Compare commits

...

247 Commits

Author SHA1 Message Date
Gerd Hoffmann
8bc8912796 inet_listen_opts: add error checking
Don't use atoi() function which doesn't detect errors, switch to
strtol and error out on failures.  Also add a range check while
being at it.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
2014-06-13 12:34:57 +02:00
Peter Maydell
2a2c4830c0 Merge remote-tracking branch 'remotes/kraxel/tags/pull-gtk-20140611-1' into staging
gtk: misc fixes & cleanups.

# gpg: Signature made Wed 11 Jun 2014 13:28:12 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-gtk-20140611-1:
  gtk: update window size after showing/hiding tabs
  gtk: factor out gtk3 grab into the new gd_grab_devices function
  gtk: cleanup backend dependencies
  gtk: factor out keycode mapping

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-12 09:51:41 +01:00
Peter Maydell
05fedeef83 Merge remote-tracking branch 'remotes/qmp-unstable/queue/qmp' into staging
* remotes/qmp-unstable/queue/qmp:
  json-parser: drop superfluous assignment for token variable
  readline: Clear screen on form feed.
  monitor: Add delvm and loadvm argument completion
  monitor: Add host_net_remove arguments completion
  readline: Make completion strings always unique
  monitor: Add host_net_add device argument completion
  net: Export valid host network devices list
  monitor: Add migrate_set_capability completion
  monitor: Add watchdog_action argument completion
  monitor: Add ringbuf_write and ringbuf_read argument completion
  dump: simplify get_len_buf_out()
  dump: hoist lzo_init() from get_len_buf_out() to dump_init()
  dump: select header bitness based on ELF class, not ELF architecture
  dump: eliminate DumpState.page_size ("guest's page size")
  dump: eliminate DumpState.page_shift ("guest's page shift")
  dump: simplify write_start_flat_header()
  dump: fill in the flat header signature more pleasingly to the eye

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 21:34:08 +01:00
Peter Maydell
706808585a Merge remote-tracking branch 'remotes/pmaydell/tags/pull-bsd-user-20140611' into staging
bsd-user queue:
 * build fixes
 * improvements to strace

# gpg: Signature made Wed 11 Jun 2014 15:23:40 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-bsd-user-20140611:
  bsd-user: Fix syscall format, add strace support for more syscalls
  bsd-user: Implement strace support for thr_* syscalls
  bsd-user: Implement strace support for extattr_* syscalls
  bsd-user: Implement strace support for __acl_* syscalls
  bsd-user: Implement strace support for print_ioctl syscall
  bsd-user: Implement strace support for print_sysctl syscall
  bsd-user: GPL v2 attribution update and style
  bsd-user: add HOST_VARIANT_DIR for various *BSD dependent code
  exec: replace ffsl with ctzl
  vhost: replace ffsl with ctzl
  xen: replace ffsl with ctzl
  util/qemu-openpty: fix build with musl libc by include termios.h as fallback
  bsd-user/mmap.c: Don't try to override g_malloc/g_free
  util/hbitmap.c: Use ctpopl rather than reimplementing a local equivalent
  bsd-user: refresh freebsd system call numbers

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 18:05:21 +01:00
Peter Maydell
c5cb1afc46 Merge remote-tracking branch 'remotes/bonzini/configure' into staging
* remotes/bonzini/configure:
  rules.mak: Rewrite unnest-vars
  configure: unset interfering variables
  configure: duplicate/incorrect order of -lrt
  libcacard: improve documentation
  libcacard: actually use symbols file
  libcacard: replace qemu thread primitives with glib ones
  vscclient: use glib thread primitives not qemu
  glib-compat.h: add new thread API emulation on top of pre-2.31 API

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 15:36:48 +01:00
Gonglei
a491af471b json-parser: drop superfluous assignment for token variable
Signed-off-by: ChenLiang <chenliang88@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:29 -04:00
Hani Benhabiles
075ccb6cd3 readline: Clear screen on form feed.
Signed-off-by: Hani Benhabiles <hani@linux.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:29 -04:00
Hani Benhabiles
b21631f3b5 monitor: Add delvm and loadvm argument completion
Signed-off-by: Hani Benhabiles <hani@linux.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:29 -04:00
Hani Benhabiles
ddd6b45ce2 monitor: Add host_net_remove arguments completion
Relies on readline unique completion strings patch to make the added vlan/hub
completion values unique, instead of using something like a hash table.

Signed-off-by: Hani Benhabiles <hani@linux.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:29 -04:00
Hani Benhabiles
e70871d8b5 readline: Make completion strings always unique
There is no need to clutter the user's choices with repeating the same value
multiple times.

Signed-off-by: Hani Benhabiles <hani@linux.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:29 -04:00
Hani Benhabiles
e3bb532cc7 monitor: Add host_net_add device argument completion
Also fix the parameters documentation.

Signed-off-by: Hani Benhabiles <hani@linux.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:29 -04:00
Hani Benhabiles
84007e8181 net: Export valid host network devices list
Signed-off-by: Hani Benhabiles <hani@linux.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:29 -04:00
Hani Benhabiles
c68a0409b3 monitor: Add migrate_set_capability completion
Signed-off-by: Hani Benhabiles <hani@linux.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:29 -04:00
Hani Benhabiles
d0ece345cb monitor: Add watchdog_action argument completion
Signed-off-by: Hani Benhabiles <hani@linux.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Hani Benhabiles
8e5977797d monitor: Add ringbuf_write and ringbuf_read argument completion
Export chr_is_ringbuf() function. Also remove left-over function prototypes
while at it.

Signed-off-by: Hani Benhabiles <hani@linux.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Laszlo Ersek
b87ef3518b dump: simplify get_len_buf_out()
We can (and should) rely on the fact that s->flag_compress is exactly one
of DUMP_DH_COMPRESSED_ZLIB, DUMP_DH_COMPRESSED_LZO, and
DUMP_DH_COMPRESSED_SNAPPY.

This is ensured by the QMP schema and dump_init() in combination.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Laszlo Ersek
c998acb03d dump: hoist lzo_init() from get_len_buf_out() to dump_init()
qmp_dump_guest_memory()
  dump_init()
    lzo_init() <---------+
  create_kdump_vmcore()  |
    write_dump_pages()   |
      get_len_buf_out()  |
        lzo_init() ------+

This patch doesn't change the fact that lzo_init() is called for every
LZO-compressed dump, but it makes get_len_buf_out() more focused (single
responsibility).

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Laszlo Ersek
24aeeace7a dump: select header bitness based on ELF class, not ELF architecture
The specific ELF architecture (d_machine) carries Too Much Information
(TM) for deciding between create_header32() and create_header64(), use
"d_class" instead (ELFCLASS32 vs. ELFCLASS64).

This change adapts write_dump_header() to write_elf_loads(), dump_begin()
etc. that also rely on the ELF class of the target for bitness selection.

Considering the current targets that support dumping, cpu_get_dump_info()
works as follows:
- target-s390x/arch_dump.c: (EM_S390, ELFCLASS64) only
- target-ppc/arch_dump.c (EM_PPC64, ELFCLASS64) only
- target-i386/arch_dump.c: sets (EM_X86_64, ELFCLASS64) vs. (EM_386,
  ELFCLASS32) keying off the same Long Mode Active flag.

Hence no observable change.

Approximately-suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Laszlo Ersek
2f859f80c2 dump: eliminate DumpState.page_size ("guest's page size")
Use TARGET_PAGE_SIZE and ~TARGET_PAGE_MASK instead.

"DumpState.page_size" has type "size_t", whereas TARGET_PAGE_SIZE has type
"int". TARGET_PAGE_MASK is of type "int" and has negative value. The patch
affects the implicit type conversions as follows:

- create_header32() and create_header64(): assigned to "block_size", which
  has type "uint32_t". No change.

- get_next_page(): "block->target_start", "block->target_end" and "addr"
  have type "hwaddr" (uint64_t).

  Before the patch,
  - if "size_t" was "uint64_t", then no additional conversion was done as
    part of the usual arithmetic conversions,
  - If "size_t" was "uint32_t", then it was widened to uint64_t as part of
    the usual arithmetic conversions,
  for the remainder and addition operators.

  After the patch,
  - "~TARGET_PAGE_MASK" expands to  ~~((1 << TARGET_PAGE_BITS) - 1). It
    has type "int" and positive value (only least significant bits set).
    That's converted (widened) to "uint64_t" for the bit-ands. No visible
    change.
  - The same holds for the (addr + TARGET_PAGE_SIZE) addition.

- write_dump_pages():
  - TARGET_PAGE_SIZE passed as argument to a bunch of functions that all
    have prototypes. No change.

  - When incrementing "offset_data" (of type "off_t"): given that we never
    build for ILP32_OFF32 (see "-D_FILE_OFFSET_BITS=64" in configure),
    "off_t" is always "int64_t", and we only need to consider:
    - ILP32_OFFBIG: "size_t" is "uint32_t".
      - before: int64_t += uint32_t. Page size converted to int64_t for
        the addition.
      - after:  int64_t += int32_t. No change.
    - LP64_OFF64: "size_t" is "uint64_t".
      - before: int64_t += uint64_t. Offset converted to uint64_t for the
        addition, then the uint64_t result is converted to int64_t for
        storage.
      - after:  int64_t += int32_t. Same as the ILP32_OFFBIG/after case.
        No visible change.

  - (size_out < s->page_size) comparisons, and (size_out = s->page_size)
    assignment:
    - before: "size_out" is of type "size_t", no implicit conversion for
              either operator.
    - after: TARGET_PAGE_SIZE (of type "int" and positive value) is
             converted to "size_t" (for the relop because the latter is
             one of "uint32_t" and "uint64_t"). No visible change.

- dump_init():
  - DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), s->page_size): The
    innermost "DumpState.max_mapnr" field has type uint64_t, which
    propagates through all implicit conversions at hand:

    #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))

    regardless of the page size macro argument's type. In the outer macro
    replacement, the page size is converted from uint32_t and int32_t
    alike to uint64_t.

  - (tmp * s->page_size) multiplication: "tmp" has size "uint64_t"; the
    RHS is converted to that type from uint32_t and int32_t just the same
    if it's not uint64_t to begin with.

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Laszlo Ersek
22227f121b dump: eliminate DumpState.page_shift ("guest's page shift")
Just use TARGET_PAGE_BITS.

"DumpState.page_shift" used to have type "uint32_t", while the replacement
TARGET_PAGE_BITS has type "int". Since "DumpState.page_shift" was only
used as bit shift counts in the paddr_to_pfn() and pfn_to_paddr() macros,
this is safe.

Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Laszlo Ersek
92ba1401e0 dump: simplify write_start_flat_header()
Currently, the function
- defines and populates an auto variable of type MakedumpfileHeader
- allocates and zeroes a buffer of size MAX_SIZE_MDF_HEADER (4096)
- copies the former into the latter (covering an initial portion of the
  latter)

Fill in the MakedumpfileHeader structure in its final place (the alignment
is OK because the structure lives at the address returned by g_malloc0()).

Approximately-suggested-by: Luiz Capitulino <lcapitulino@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Laszlo Ersek
ae3f88f60f dump: fill in the flat header signature more pleasingly to the eye
The "mh.signature" array field has size 16, and is zeroed by the preceding
memset(). MAKEDUMPFILE_SIGNATURE expands to a string literal with string
length 12 (size 13). There's no need to measure the length of
MAKEDUMPFILE_SIGNATURE at runtime, nor for the extra zero-filling of
"mh.signature" with strncpy().

Use memcpy() with MIN(sizeof, sizeof) for robustness (which is an integer
constant expression, evaluable at compile time.)

Approximately-suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-11 10:10:28 -04:00
Gerd Hoffmann
fa7a1e5219 gtk: update window size after showing/hiding tabs
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-06-11 14:26:49 +02:00
Gerd Hoffmann
f50def915e gtk: factor out gtk3 grab into the new gd_grab_devices function
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-06-11 14:26:49 +02:00
Gerd Hoffmann
0a337ed067 gtk: cleanup backend dependencies
Make configure detect gtk x11 backend and link libX11 then.  Make
gtk backend specific code properly #ifdef'ed on the GTK_WINDOWING_*
backends at runtime).  Our gtk ui code should build and run fine on
any platform now.

This also fixes the linker failute due to the new XkbGetKeyboard call
added by commit 3158a3482b.

Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
2014-06-11 14:26:49 +02:00
Gerd Hoffmann
932f2d7e0f gtk: factor out keycode mapping
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-06-11 14:26:49 +02:00
Sean Bruno
c4af6d4b13 bsd-user: Fix syscall format, add strace support for more syscalls
Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1402246651-71099-10-git-send-email-sbruno@freebsd.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Sean Bruno
f35f961ac9 bsd-user: Implement strace support for thr_* syscalls
Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1402246651-71099-9-git-send-email-sbruno@freebsd.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Sean Bruno
1e501653ab bsd-user: Implement strace support for extattr_* syscalls
Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1402246651-71099-8-git-send-email-sbruno@freebsd.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Sean Bruno
605474815d bsd-user: Implement strace support for __acl_* syscalls
Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1402246651-71099-7-git-send-email-sbruno@freebsd.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Sean Bruno
b85159a3a3 bsd-user: Implement strace support for print_ioctl syscall
Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1402246651-71099-5-git-send-email-sbruno@freebsd.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Sean Bruno
80b346040d bsd-user: Implement strace support for print_sysctl syscall
Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1402246651-71099-4-git-send-email-sbruno@freebsd.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Sean Bruno
88dae46d18 bsd-user: GPL v2 attribution update and style
Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1402246651-71099-3-git-send-email-sbruno@freebsd.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Stacey Son
adfc3e91e2 bsd-user: add HOST_VARIANT_DIR for various *BSD dependent code
This change adds HOST_VARIANT_DIR so the various BSD OS dependent
code can be separated into its own directories rather than
using #ifdef's.

This may also allow an BSD variant OS to host another BSD variant's
executable as a target.

Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1402246651-71099-2-git-send-email-sbruno@freebsd.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Natanael Copa
7224f66ec3 exec: replace ffsl with ctzl
See commit fbeadf50 (bitops: unify bitops_ffsl with the one in
host-utils.h, call it bitops_ctzl) on why ctzl should be used instead
of ffsl.

This is also needed for musl libc which does not implement ffsl.

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Natanael Copa
747eb78baa vhost: replace ffsl with ctzl
Avoid using the GNU extesion ffsl which is not implemented in musl libc.

The atomic_xchg() means we know that vhost_log_chunk_t will never be
larger than the 'long' type, so ctzl() is always sufficient.

See also commit fbeadf50 (bitops: unify bitops_ffsl with the one in
host-utils.h, call it bitops_ctzl) on why ctzl should be used instead
of ffsl.

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Natanael Copa
adf9d70b0d xen: replace ffsl with ctzl
ffsl is a GNU extension and not available in musl libc.

See also commit fbeadf50 (bitops: unify bitops_ffsl with the one in
host-utils.h, call it bitops_ctzl) on why ctzl should be used instead
of ffsl.

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
[PMM: rebased to accommodate file rename to xen-hvm.c]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Natanael Copa
6ad3f09bd4 util/qemu-openpty: fix build with musl libc by include termios.h as fallback
Include termios.h as POSIX fallback when not glibc, bsd or solaris.
POSIX says that termios.h should define struct termios and TCAFLUSH.
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html

This fixes the following compile errors with musl libc:

util/qemu-openpty.c: In function 'qemu_openpty_raw':
util/qemu-openpty.c:112:20: error: storage size of 'tty' isn't known
     struct termios tty;
                    ^
...
util/qemu-openpty.c:128:24: error: 'TCSAFLUSH' undeclared (first use in this function)
     tcsetattr(*aslave, TCSAFLUSH, &tty);
                        ^

Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Peter Maydell
b7b5233ad7 bsd-user/mmap.c: Don't try to override g_malloc/g_free
Trying to override the implementations of g_malloc and g_free is
a really bad idea -- it means statically linked builds fail to
link (because of the multiple definitions provided by this file
and by glib), and non-statically linked builds segfault as soon
as they try to do anything more complicated than printing the
usage message. Remove these overridden versions and just use
the glib ones.

This is sufficient that bsd-user can run basic x86-64
binaries on OpenBSD again; FreeBSD and NetBSD seem to have
further issues.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Sean Bruno <sbruno@freebsd.org>
Reviewed-by: Ed Maste <emaste@freebsd.org>
2014-06-11 00:25:06 +01:00
Peter Maydell
591b320ad0 util/hbitmap.c: Use ctpopl rather than reimplementing a local equivalent
The function popcountl() in hbitmap.c is effectively a reimplementation
of what host-utils.h provides as ctpopl(). Use ctpopl() directly; this fixes
a failure to compile on NetBSD (whose strings.h erroneously exposes a
system popcountl() which clashes with this one).

Reported-by: Martin Husemann <martin@duskware.de>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Stacey Son
6b24119b7f bsd-user: refresh freebsd system call numbers
Update FreeBSD system call numbers in freebsd/syscall_nr.h.


Signed-off-by: Stacey Son <sson@FreeBSD.org>
Reviewed-by: Ed Maste <emaste@freebsd.org>
Signed-off-by: Sean Bruno <sbruno@freebsd.org>
Message-id: 1401220104-7147-2-git-send-email-sbruno@freebsd.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-11 00:25:06 +01:00
Peter Maydell
b780bf8eff Merge remote-tracking branch 'remotes/mjt/tags/trivial-patches-2014-06-10' into staging
trivial patches for 2014-06-10

# gpg: Signature made Tue 10 Jun 2014 17:07:19 BST using RSA key ID A4C3D7DB
# gpg: Good signature from "Michael Tokarev <mjt@tls.msk.ru>"
# gpg:                 aka "Michael Tokarev <mjt@corpit.ru>"
# gpg:                 aka "Michael Tokarev <mjt@debian.org>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6EE1 95D1 886E 8FFB 810D  4324 457C E0A0 8044 65C5
#      Subkey fingerprint: 6F67 E18E 7C91 C5B1 5514  66A7 BEE5 9D74 A4C3 D7DB

* remotes/mjt/tags/trivial-patches-2014-06-10: (25 commits)
  virtio.c: fix error message
  hw: vmware_vga: don't return cursorx when the driver asks for cursory register
  migration: Plug memory leak in migrate-set-cache-size command
  libcacard: Clean up dead stores before g_free()
  libcacard: Drop superfluous conditionals around g_free()
  cpu/x86: correctly set errors in x86_cpu_parse_featurestr
  smbios: use g_free directly on NULL pointers
  vdi: remove double conversion
  apb: Fix compiler warnings (large constants)
  hw/net/ne2000-isa: Register vmstate struct
  target-microblaze: Delete unused sign_extend() function
  hw/misc/milkymist-softusb: Remove unused softusb_{read, write}_pmem()
  target-i386/translate.c: Remove unused tcg_gen_lshift()
  hw/isa/pc87312: Remove unused function is_parallel_epp()
  hw/intc/openpic: Remove unused function IRQ_testbit()
  hw/dma/xilinx_axidma: Remove unused stream_halted() function
  util/qemu-sockets.c: Avoid unused variable warnings
  hw/sd/sd.c: Drop unused sd_acmd_type[] array
  hw/i386/pc.c: Remove unused parallel_io and parallel_irq variables
  slirp: Remove unused zero_ethaddr[] variable
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-10 17:16:03 +01:00
Michael Tokarev
1a2858995d virtio.c: fix error message
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 20:07:01 +04:00
Nicolas Owens
e2bb4ae746 hw: vmware_vga: don't return cursorx when the driver asks for cursory register
hello qemu-*@nongnu.org, this is my first contribution. apologies if
something is incorrect.

this patch fixes vmware_vga.c so that it actually returns the cursory
register when asked for, instead of cursorx.

Signed-off-by: Nicolas Owens <mischief@offblast.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 20:06:48 +04:00
Chen Gang
4380be0e99 migration: Plug memory leak in migrate-set-cache-size command
We call g_free() after cache_fini() in migration_end(), but we don't
call it after cache_fini() in xbzrle_cache_resize(), leaking the
memory.

cache_init() and cache_fini() are a pair.  Since cache_init()
allocates the cache, let cache_fini() free it.  This plugs the leak.

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:54:43 +04:00
Markus Armbruster
fec0da9cbf libcacard: Clean up dead stores before g_free()
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Markus Armbruster
ec15993d9d libcacard: Drop superfluous conditionals around g_free()
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Paolo Bonzini
6b1dd54b6a cpu/x86: correctly set errors in x86_cpu_parse_featurestr
Because of the "goto out", the contents of local_err are leaked
and lost.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Paolo Bonzini
a10678b08e smbios: use g_free directly on NULL pointers
No need to wrap it with an if.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Paolo Bonzini
6998b6c11b vdi: remove double conversion
This should be a problem when running on big-endian machines.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Stefan Weil
d1180c1e57 apb: Fix compiler warnings (large constants)
Both constants need more than 32 bit.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
89218c218f hw/net/ne2000-isa: Register vmstate struct
The ne2000-isa device defines a VMState struct for migration, but
we forgot to actually register it. Correct this deficiency by
setting dc->vmsd.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
fc4bde9025 target-microblaze: Delete unused sign_extend() function
The sign_extend() function is unused; delete it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
029ad4bcf3 hw/misc/milkymist-softusb: Remove unused softusb_{read, write}_pmem()
The functions softusb_read_pmem() and softusb_write_pmem() are unused;
remove them.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
e3a17ef6cc target-i386/translate.c: Remove unused tcg_gen_lshift()
The function tcg_gen_lshift() is unused; remove it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
f46b9cc71c hw/isa/pc87312: Remove unused function is_parallel_epp()
The function is_parallel_epp() is unused; remove it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
c1d7572793 hw/intc/openpic: Remove unused function IRQ_testbit()
The IRQ_testbit() function is never used; remove it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
a1fa7992a9 hw/dma/xilinx_axidma: Remove unused stream_halted() function
The stream_halted() function is never used; remove it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
f9b5426fd5 util/qemu-sockets.c: Avoid unused variable warnings
The 'on' variable is never used, and 'off' is only used
if IPV6_V6ONLY is defined; delete 'on' and move 'off' to
the point where it is used. This avoids warnings from
clang 3.4.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
7179585688 hw/sd/sd.c: Drop unused sd_acmd_type[] array
Drop the sd_acmd_type[] array: it is never used. (The equivalent
sd_cmd_type[] array for normal commands is used to identify
those commands whose argument includes the card address in the
top 16 bits; but for app commands the card address is passed
with the APP_CMD prefix, not with the argument to the app command
itself.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
831f4d27b6 hw/i386/pc.c: Remove unused parallel_io and parallel_irq variables
The variables parallel_io and parallel_irq are unused; delete them.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Maydell
49bba868df slirp: Remove unused zero_ethaddr[] variable
The zero_ethaddr[] array is never used; delete it.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Sergey Fedorov
2a802aaf63 qtest: fix hex2nib for capital characters
Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Crosthwaite
ef18c2f54e net: cadence_gem: Remove &desc[0] usages
Just use desc instead.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Crosthwaite
3048ed6aac net: cadence_gem: Comment spelling sweep
Fix some typos in comments.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Crosthwaite
fa15286a75 net: cadence_gem: Add Tx descriptor fetch printf
Add a debug printf for TX descriptor fetching. This is helpful to anyone
needing to debug TX ring buffer traversal. It is also now consistent with
the RX code which has a similar printf.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Peter Crosthwaite
6ab57a6b80 net: cadence_gem: Fix Tx descriptor update
The local variable "desc" was being used to read-modify-write the
first descriptor (of a multi-desc packet) upon packet completion.
desc however continues to be used by the code as the current
descriptor. Give this first desc RMW it's own local variable to
avoid trampling.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2014-06-10 19:39:34 +04:00
Fam Zheng
1c33ac5716 rules.mak: Rewrite unnest-vars
The macro unnest-vars is the most important, complicated but hard to
track magic in QEMU's build system.

Rewrite it in a (hopefully) clearer way, with more comments, to make it
easier to understand and maintain.

Remove DSO_CFLAGS and module-objs-m that are not used.

A bonus fix of this version is, per object variables are properly
protected in save-objs and load-objs, before including sub-dir
Makefile.objs, just as nested variables are. So the occasional same
object name from different directory levels won't step on each other's
foot.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-10 13:59:02 +02:00
Peter Maydell
3334e929ae Merge remote-tracking branch 'remotes/kraxel/tags/pull-console-20140610-1' into staging
console: two little bugfixes.

# gpg: Signature made Tue 10 Jun 2014 12:01:07 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-console-20140610-1:
  console: fix -vga none -sdl crash
  console: kill MAX_CONSOLES, alloc consoles dynamically

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-10 12:06:17 +01:00
Gerd Hoffmann
333cb18ff4 console: fix -vga none -sdl crash
Call get_alloc_displaystate() for proper initialization
instead of allocating with g_new().

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-06-10 12:36:36 +02:00
Gerd Hoffmann
a1d2db08d8 console: kill MAX_CONSOLES, alloc consoles dynamically
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-06-10 12:36:36 +02:00
Cornelia Huck
99519e677b configure: unset interfering variables
The check for big or little endianness relies on grep reporting
match/non-match on the generated binary. If the user specified
--binary-files=without-match in their GREP_OPTIONS, this will fail.

Let's follow what autoconf does and unset GREP_OPTIONS and CLICOLOR_FORCE
at the beginning of the script.

Reported-by: Eugene (jno) Dvurechenski <jno@linux.vnet.ibm.com>
Suggested-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-10 12:34:37 +02:00
Rick Liu
18e588b197 configure: duplicate/incorrect order of -lrt
'-lrt' flag duplication/incorrect order
would cause 'undefined reference to clock_gettime' error during compilation time.

Before fix:
... -o qemu-bridge-helper qemu-bridge-helper.o    -lrt -pthread -lgthread-2.0 -lrt -lglib-2.0
After fix:
... -o qemu-bridge-helper qemu-bridge-helper.o    -pthread -lgthread-2.0 -lrt -lglib-2.0

Reference:
http://hi.baidu.com/sanitywolf/item/7a8b69c1e76dd220a0b50ab1

Signed-off-by: Rick Liu <yrliu.ca@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-10 12:34:37 +02:00
Peter Maydell
7b0140e49b Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20140610' into staging
Several patches for s390:

- bugfixes: A fix for a long-standing bug in the css code as well as
  a fixup for the recent I/O adapter support.
- Exploitation of the userspace cmma enablement/reset interface, if
  it is present.
- Some debuggability improvements by logging unmanageable conditions.
- virtio-ccw finally gets migration support for its structures.
- Some cleanup as to how floating interrupts are injected.

# gpg: Signature made Tue 10 Jun 2014 08:57:56 BST using RSA key ID C6F02FAF
# gpg: Can't check signature: public key not found

* remotes/cohuck/tags/s390x-20140610:
  s390x/kvm: inject via flic
  s390x: cleanup interrupt injection
  s390x/kvm: add alternative injection interface
  s390x: consolidate floating interrupts
  s390/virtio-ccw: migration support
  s390x/kvm: Log unmanageable program interruptions
  s390x/kvm: Log unmanageable external interruptions
  s390x/kvm: enable/reset cmma via vm attributes
  s390x/kvm: make flic play well with old kernels
  s390x/css: handle emw correctly for tsch

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-10 10:59:26 +01:00
Cornelia Huck
bbd8bb8e32 s390x/kvm: inject via flic
Try to inject floating interrupts via the flic if it is available.
This allows us to inject the full range of floating interrupts.

Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:27 +02:00
Cornelia Huck
de13d21614 s390x: cleanup interrupt injection
Remove the need for a cpu to inject a floating interrupt on kvm.

Acked-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:27 +02:00
Cornelia Huck
66ad0893f0 s390x/kvm: add alternative injection interface
Add kvm_s390_{vcpu,floating}_interrupt, which offer the possibility
to inject interrupts with larger payloads (when a kvm backend becomes
available).

Moreover, kvm_s390_floating_interrupt() does no longer have the bogus
requirement for a vcpu.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:27 +02:00
Cornelia Huck
79afc36d91 s390x: consolidate floating interrupts
Move the injection code for all floating interrupts to interrupt.c
and add a comment.

Also get rid of the #ifdef CONFIG_KVM for the service interrupt.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:27 +02:00
Jens Freimann
bcb2b582f3 s390/virtio-ccw: migration support
This patch adds live migration support for virtio-ccw devices.
It's not done with vmstate because virtio itself is not yet ported
to vmstate either.

Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:27 +02:00
Thomas Huth
6449a41a4d s390x/kvm: Log unmanageable program interruptions
The kernel only drops to userspace if an endless program interrupt loop
has been detected. Let's print an error message in this case to inform
the user about the crash and stop the affected CPU with a panic event,
just like it is already done for the external interruption loop detection.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:27 +02:00
Thomas Huth
a2689242b1 s390x/kvm: Log unmanageable external interruptions
Interception code 0x14 only drops to userspace when an unmanageable
external interruption interception occured (e.g. if the External New
PSW does not disable external interruptions). Instead of bailing out
via the default handler, it is better to inform the user with a
proper error message that also includes the bad PSW, and to stop
the affected CPU with a panic event instead.

Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:27 +02:00
Dominik Dingel
4cb88c3c37 s390x/kvm: enable/reset cmma via vm attributes
Exploit the new api for userspace-controlled cmma. If supported, enable
cmma during kvm initialization and register a reset handler for cmma,
which is also called directly from the load IPL code.

The reset functionality is needed to reset the cmma state of the guest
pages, e.g. if a system reset is triggered via qemu monitor; otherwise
this could result in data corruption.

A guest triggered reboot may now lead to multiple cmma resets; this is
OK, however, as this is slowpath anyway and the simplest way to achieve
the intended effects.

Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:27 +02:00
Cornelia Huck
08da527fd0 s390x/kvm: make flic play well with old kernels
If we run with an old kernel that does not support KVM_CAP_IRQ_ROUTING,
we don't have to do anything in the ->register_io_adapter and
->io_adapter_map callbacks and therefore should return 0 instead of
-ENOSYS (just as the non-kvm flic does).

This fixes using adapter interrupts when running under an older kernel,
which broke with "s390x: add I/O adapter registration".

Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:26 +02:00
Cornelia Huck
f068d320de s390x/css: handle emw correctly for tsch
We should not try to store the emw portion of the irb if extended
measurements are not applicable. In particular, we should not surprise
the guest by storing a larger irb if it did not enable extended
measurements.

Cc: qemu-stable@nongnu.org
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
2014-06-10 09:50:26 +02:00
Paolo Bonzini
471f7e30a4 libcacard: improve documentation
Using the file-backed smartcard backend is black magic, but it can
be useful if your only smartcard bricks itself if it is accessed
the wrong way too many times.

Complete the documentation to include the art of creating certificates
and using them with QEMU, based on Ray Strode's useful tutorial at
https://blogs.gnome.org/halfline/2013/09/08/another-smartcard-post/
but with ccid-card-emulated or vscclient instead of SPICE.

Cc: Ray Strode <rstrode@redhat.com>
Reviewed-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-10 07:44:01 +02:00
Michael Tokarev
ae9b65e873 libcacard: actually use symbols file
libtool has an argument for .syms file, which is -export-symbols.
There's no argument `-export-syms', and it looks like at least on
linux, -export-syms is just ignored.  Use the correct argument,
-export-symbols, to actually get the right export list.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Alon Levy <alevy@redhat.com>
Tested-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-10 07:44:01 +02:00
Michael Tokarev
fd25c0e6dd libcacard: replace qemu thread primitives with glib ones
Replace QemuMutex with GMutex and QemuCond with GCond
(with corresponding function changes), to make libcacard
independent of qemu internal functions.

After this step, none of libcacard internals use any
qemu-provided symbols.  Maybe it's a good idea to
stop including qemu-common.h internally too.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Alon Levy <alevy@redhat.com>
Tested-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-10 07:44:01 +02:00
Michael Tokarev
2a0c46da96 vscclient: use glib thread primitives not qemu
Use glib-provided thread primitives in vscclient instead of
qemu ones, and do not use qemu sockets in there (open-code
call to WSAStartup() for windows to initialize things).

This way, vscclient becomes more stand-alone, independent on
qemu internals.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Alon Levy <alevy@redhat.com>
Tested-by: Alon Levy <alevy@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-10 07:44:01 +02:00
Michael Tokarev
86946a2d83 glib-compat.h: add new thread API emulation on top of pre-2.31 API
Thread API changed in glib-2.31 significantly.  Before that version,
conditionals and mutexes were only allocated dynamically, using
_new()/_free() interface.  in 2.31 and up, they're allocated statically
as regular variables, and old interface is deprecated.

(Note: glib docs says the new interface is available since version
2.32, but it was actually introduced in version 2.31).

Create the new interface using old primitives, by providing non-opaque
definitions of the base types (GCond and GMutex) using GOnces.

Replace #ifdeffery around GCond and GMutex in trace/simple.c and
coroutine-gthread.c too because it does not work anymore with the new
glib-compat.h.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
[Use GOnce to support lazy initialization; introduce CompatGMutex
 and CompatGCond.  - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-10 07:44:01 +02:00
Peter Maydell
7721a30442 Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140609-1' into staging
----------------------------------------------------------------
target-arm queue:
 * support -bios option in vexpress boards
 * register the Cortex-A57 impdef system registers
 * fix handling of UXN bit in ARMv8 page tables
 * complete support of crypto insns in A32/T32
 * implement CRC and crypto insns in A64
 * fix bugs in generic timer control register

----------------------------------------------------------------

# gpg: Signature made Mon 09 Jun 2014 16:08:26 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20140609-1:
  target-arm: Delete unused iwmmxt_msadb helper
  target-arm: Fix errors in writes to generic timer control registers
  target-arm: A64: Implement two-register SHA instructions
  target-arm: A64: Implement 3-register SHA instructions
  target-arm: A64: Implement AES instructions
  target-arm: A32/T32: Mask CRC value in calling code, not helper
  target-arm: A64: Implement CRC instructions
  target-arm: VFPv4 implies half-precision extension
  target-arm: Clean up handling of ARMv8 optional feature bits
  target-arm: Remove unnecessary setting of feature bits
  target-arm: arm_any_initfn() should never set ARM_FEATURE_AARCH64
  target-arm: A64: Use PMULL feature bit for PMULL
  target-arm: add support for v8 VMULL.P64 instruction
  target-arm: Allow 3reg_wide undefreq to encode more bad size options
  target-arm: add support for v8 SHA1 and SHA256 instructions
  target-arm: Correct handling of UXN bit in ARMv8 LPAE page tables
  target-arm: Prepare cpreg writefns/readfns for EL3/SecExt
  target-arm/cpu64.c: Actually register Cortex-A57 impdef registers
  vexpress: Add support for the -bios flag to provide firmware

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 17:04:13 +01:00
Peter Maydell
14ac573392 Merge remote-tracking branch 'remotes/stefanha/tags/tracing-pull-request' into staging
Tracing pull request

# gpg: Signature made Mon 09 Jun 2014 14:44:18 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/tracing-pull-request:
  trace: Replace fprintf with error_report and print location
  trace: Multi-backend tracing
  trace: Replace error with warning if event is not defined
  simpletrace: add support for trace record pid field
  trace: add pid field to simpletrace record

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 16:25:34 +01:00
Peter Maydell
3b1a413812 target-arm: Delete unused iwmmxt_msadb helper
The iwmmxt_msadb helper and its corresponding gen function are unused;
delete them. (This function appears to have never been used right back
to the initial implementation of iwMMXt; it is identical to iwmmxt_madduq,
and is presumably an accidental remnant from the initial development.)

Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401822125-1822-1-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:12 +01:00
Peter Maydell
d3afacc726 target-arm: Fix errors in writes to generic timer control registers
The code for handling writes to the generic timer control registers
had several bugs:
 * ISTATUS (bit 2) is read-only but we forced it to zero on any write
 * the check for "was IMASK (bit 1) toggled?" incorrectly used '&' where
   it should be '^'
 * the handling of IMASK was inverted: we should set the IRQ if
   ISTATUS is set and IMASK is clear, not if both are set

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

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401803208-1281-1-git-send-email-peter.maydell@linaro.org
Cc: qemu-stable@nongnu.org
2014-06-09 16:06:12 +01:00
Peter Maydell
f6fe04d566 target-arm: A64: Implement two-register SHA instructions
Implement the two-register SHA instruction group from the optional
Crypto Extensions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-10-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:12 +01:00
Peter Maydell
be56f04eea target-arm: A64: Implement 3-register SHA instructions
Implement the 3-register SHA instruction group from the optional
Crypto Extensions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-9-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:12 +01:00
Peter Maydell
5acc765c04 target-arm: A64: Implement AES instructions
Implement the AES instructions from the optional Crypto Extensions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-8-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:12 +01:00
Peter Maydell
aa633469ed target-arm: A32/T32: Mask CRC value in calling code, not helper
Bring the 32-bit CRC helper functions into line with the A64 ones,
by masking the high bytes of the value in the calling code rather
than the helper. This is more efficient since we can determine the
mask at translation time.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-7-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:12 +01:00
Peter Maydell
130f2e7dcb target-arm: A64: Implement CRC instructions
Implement the optional A64 CRC instructions.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-6-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:12 +01:00
Peter Maydell
da5141fc45 target-arm: VFPv4 implies half-precision extension
VFPv4 implies the presence of the half-precision floating point
extension (which is optional in VFPv3). Add this implied rule
to arm_cpu_realizefn() and remove some no-longer-needed explicit
setting of the bit in initfns.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-5-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:11 +01:00
Peter Maydell
25f748e37a target-arm: Clean up handling of ARMv8 optional feature bits
CRC and crypto are both optional v8 extensions, so FEATURE_V8
should not imply them. Instead we should set these bits in the
initfns for the 32-bit and 64-bit "cpu any" and for the Cortex-A57.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-4-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:11 +01:00
Peter Maydell
fb8ad9f2c1 target-arm: Remove unnecessary setting of feature bits
FEATURE_V8 implies both FEATURE_V7MP and FEATURE_ARM_DIV, so
we don't need to set them explicitly in initfns which set the
V8 feature bit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-3-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:11 +01:00
Peter Maydell
46d9dfdad6 target-arm: arm_any_initfn() should never set ARM_FEATURE_AARCH64
The arm_any_initfn() is used only for the 32-bit linux-user "cpu any",
so it only gets called in builds where TARGET_AARCH64 is not defined.
Remove the unreachable line which sets ARM_FEATURE_AARCH64.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401458125-27977-2-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:11 +01:00
Peter Maydell
411bdc7837 target-arm: A64: Use PMULL feature bit for PMULL
Now that we have a separate ARM_FEATURE_V8_PMULL bit, use it for
the A64 PMULL, not the AES feature bit.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 16:06:11 +01:00
Peter Maydell
4e624edaeb target-arm: add support for v8 VMULL.P64 instruction
Add support for the VMULL.P64 polynomial 64x64 to 128 bit multiplication
instruction in the A32/T32 instruction sets; this is part of the v8
Crypto Extensions.

To do this we have to move the neon_pmull_64_{lo,hi} helpers from
helper-a64.c into neon_helper.c so they can be used by the AArch32
translator.

Inspired-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401386724-26529-4-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:11 +01:00
Peter Maydell
526d0096e5 target-arm: Allow 3reg_wide undefreq to encode more bad size options
The current undefreq field in the neon_3reg_wide handling allows us
to encode "UNDEF if size != 0" and "UNDEF if size == 0". This is
no longer sufficient with the advent of 64-bit polynomial VMULL,
which means we want to UNDEF if size == 1. Change the undefreq
encoding to use separate bits for all of "UNDEF if size == 0",
"UNDEF if size == 1" and "UNDEF if size == 2".

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401386724-26529-3-git-send-email-peter.maydell@linaro.org
2014-06-09 16:06:11 +01:00
Ard Biesheuvel
f1ecb913d8 target-arm: add support for v8 SHA1 and SHA256 instructions
This adds support for the SHA1 and SHA256 instructions that are available
on some v8 implementations of Aarch32.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1401386724-26529-2-git-send-email-peter.maydell@linaro.org
[PMM:
 * rebase
 * fix bad indent
 * add a missing UNDEF check for Q!=1 in the 3-reg SHA1/SHA256 case
 * use g_assert_not_reached()
 * don't re-extract bit 6 for the 2-reg-misc encodings
 * set the ELF HWCAP2 bits for the new features
]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 16:06:11 +01:00
Ian Campbell
d615efac7c target-arm: Correct handling of UXN bit in ARMv8 LPAE page tables
In v8 page tables bit 54 in the PTE is UXN in the EL0/EL1 translation regimes
and XN elsewhere. In v7 the bit is always XN. Since we only emulate EL0/EL1 we
can just treat this bit as UXN whenever we are in v8 mode.

Also correctly extract the upper attributes from the PTE entry, the v8 version
tried to avoid extracting the CONTIG bit and ended up with the upper bits being
off-by-one. Instead behave the same as v7 and extract (but ignore) the CONTIG
bit.

This fixes "Bad mode in Synchronous Abort handler detected, code 0x8400000f"
seen when modprobing modules under Linux.

Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Claudio Fontana <claudio.fontana@huawei.com>
Cc: Rob Herring <robherring2@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 16:06:11 +01:00
Fabian Aggeler
8d5c773e32 target-arm: Prepare cpreg writefns/readfns for EL3/SecExt
This patch changes some readfns/writefns to use raw_write
and raw_read functions, which use the fieldoffset specified
in ARMCPRegInfo instead of directly accessing the field.
This will simplify patches for EL3 & Security Extensions.

Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Fabian Aggeler <aggelerf@ethz.ch>
Message-id: 1401962428-14749-1-git-send-email-aggelerf@ethz.ch
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 15:43:22 +01:00
Peter Maydell
bf01601764 target-arm/cpu64.c: Actually register Cortex-A57 impdef registers
cpu64.c contains a reginfo list for the impdef registers on
the Cortex-A57; however we forgot to actually call define_arm_cp_regs(),
so it was sitting there doing nothing. Remedy this omission.

Message-id: 1401226259-23121-1-git-send-email-peter.maydell@linaro.org
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Tested-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 15:43:22 +01:00
Grant Likely
61e9924149 vexpress: Add support for the -bios flag to provide firmware
Right now to run firmware inside the QEMU VExpress model requires
padding out the firmware image to the size of the virtual flash and
passing it in via the -pflash argument. If the firmware image is passed
without padding, then QEMU will fail. Also, when passed as a -pflash
argument, QEMU treats the file as persistent storage and will modify the
file.

The -bios flag provides the semantics that we want for providing a
firmware image. This patch maps the contents of the -bios file into the
address space at the boot flash location.

Tested with the vexpress-a15 model and the Tianocore port.

Signed-off-by: Grant Likely <grant.likely@linaro.org>
Tested-by: Roy Franz <roy.franz@linaro.org>
[PMM: folded long line, removed stray \n from error message,
 use correct variable for printing image name, exit(1) rather than 0]
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 15:43:22 +01:00
Peter Maydell
4a331bb33b Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request' into staging
Net patches

# gpg: Signature made Mon 09 Jun 2014 14:41:34 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/net-pull-request:
  e1000: remove broken support for 82573L
  tests: e1000: test additional device IDs
  e1000: allow command-line selection of card model
  vmxnet3: fix msix vectors unuse
  net: xilinx_ethlite: Fix Rx-pong interrupt

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 15:00:21 +01:00
Alexey Kardashevskiy
a35d9be622 trace: Replace fprintf with error_report and print location
This replaces fprintf(stderr) with error_report.

This moves local variables to the beginning of the function to comply
with QEMU's coding style.

Suggested-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:43:40 +02:00
Lluís Vilanova
5b808275f3 trace: Multi-backend tracing
Adds support to compile QEMU with multiple tracing backends at the same time.

For example, you can compile QEMU with:

  $ ./configure --enable-trace-backends=ftrace,dtrace

Where 'ftrace' can be handy for having an in-flight record of events, and 'dtrace' can be later used to extract more information from the system.

This patch allows having both available without recompiling QEMU.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:43:40 +02:00
Alexey Kardashevskiy
82432638eb trace: Replace error with warning if event is not defined
At the moment QEMU exits if trace point is not defined which makes
a developer life harder if he has to switch between branches with
different traces implemented.

This replaces error+exit wit WARNING if the tracepoint does not exist or
not traceable.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:43:40 +02:00
Stefan Hajnoczi
80ff35cd3f simpletrace: add support for trace record pid field
Extract the pid field from the trace record and print it.

Change the trace record tuple from:
  (event_num, timestamp, arg1, ..., arg6)
to:
  (event_num, timestamp, pid, arg1, ..., arg6)

Trace event methods now support 3 prototypes:
1. <event-name>(arg1, arg2, arg3)
2. <event-name>(timestamp, arg1, arg2, arg3)
3. <event-name>(timestamp, pid, arg1, arg2, arg3)

Existing script continue to work without changes, they only know about
prototypes 1 and 2.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:43:40 +02:00
Stefan Hajnoczi
26896cbf35 trace: add pid field to simpletrace record
It is useful to know the QEMU process ID when working with traces from
multiple VMs.  Although the trace filename may contain the pid, tools
that aggregate traces or even trace globally need somewhere to record
the pid.

There is a reserved field in the trace event header struct that we can
use.

It is not necessary to bump the simpletrace file format version number
because it has already been incremented for the QEMU 2.1 release cycle
in commit "trace: [simple] Bump up log version number".

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:43:40 +02:00
Gabriel L. Somlo
7efea76377 e1000: remove broken support for 82573L
Currently, e1000 support is based on the manual for the 8254xx
model series. 82573x models are documented in a separate manual
(see http://www.intel.com/content/dam/www/public/us/en/documents/manuals/pcie-gbe-controllers-open-source-manual.pdf)
and the 82573L device ID no longer works correctly on either Linux
(3.14.*) or Windows 7.

This patch removes stale code claiming to support 82573L, cleaning
up the code base for the remaining 8254xx model series.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:38:58 +02:00
Gabriel L. Somlo
b167383ffb tests: e1000: test additional device IDs
Update e1000-test.c to check all currently supported devices.

Suggested-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:38:58 +02:00
Gabriel L. Somlo
8597f2e19e e1000: allow command-line selection of card model
Allow selection of different card models from the qemu
command line, to better accomodate a wider range of guests.

Signed-off-by: Romain Dolbeau <romain@dolbeau.org>
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:38:58 +02:00
Jiri Pirko
b44672849a vmxnet3: fix msix vectors unuse
In vmxnet3_cleanup_msix(), there is called msix_vector_unuse() with
VMXNET3_MAX_INTRS. That is not correct since vector of
value VMXNET3_MAX_INTRS was never used. Also all the used vectors
are not un-used. So call vmxnet3_unuse_msix_vectors() instead which
does the correct job.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Dmitry Fleytman <dmitry@daynix.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:38:58 +02:00
Peter Crosthwaite
40e76f736d net: xilinx_ethlite: Fix Rx-pong interrupt
There is no CTRL_I bit in the pong buffer control register. The
CTRL_I bit from the ping buffer masks both ping and pong buffers.
Fix.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-09 15:38:58 +02:00
Peter Maydell
5dfc05cb1d Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Block pull request

# gpg: Signature made Fri 06 Jun 2014 17:08:50 BST using RSA key ID 81AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>"
# gpg:                 aka "Stefan Hajnoczi <stefanha@gmail.com>"

* remotes/stefanha/tags/block-pull-request: (42 commits)
  qapi: Extract qapi/block.json definitions
  qapi: Extract qapi/block-core.json definitions
  qapi: create two block related json modules
  qapi: Extract qapi/common.json definitions
  sheepdog: reload only header in a case of live snapshot
  sheepdog: fix vdi object update after live snapshot
  rbd: Fix leaks in rbd_start_aio() error path
  qemu-img: Document check exit codes
  block: fix wrong order in live block migration setup
  blockdev: acquire AioContext in block_set_io_throttle
  throttle: add detach/attach test case
  throttle: add throttle_detach/attach_aio_context()
  dataplane: Support VIRTIO_BLK_T_SCSI_CMD
  virtio-blk: Factor out virtio_blk_handle_scsi_req from virtio_blk_handle_scsi
  virtio-blk: Allow config-wce in dataplane
  block: Move declaration of bdrv_get_aio_context to block.h
  raw-posix: drop raw_get_aio_fd() since it is no longer used
  dataplane: implement async flush
  dataplane: delete IOQueue since it is no longer used
  dataplane: use the QEMU block layer for I/O
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-09 11:54:22 +01:00
Samuel Thibault
959e41473f slirp/arp: do not special-case bogus IP addresses
Do not special-case addresses with zero host part, as we do not
necessarily know how big it is, and the guest can fake them anyway.
Silently avoid having 0.0.0.0 as a destination, however.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
[Edgar: Minor change to subject]
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2014-06-09 01:49:28 +02:00
Peter Maydell
37654d9e6a target-cris/translate.c: Remove _t_gen_mov_TN_env and _t_gen_mov_env_TN
The wrapper functions _t_gen_mov_TN_env and _t_gen_mov_env_TN are only
used via their accompanying non-underscore macros. The check they add
on offset is thus pointless, since the compiler will complain if the
struct field passed to the macro is not part of the struct. Remove the
functions and make the macros directly expand to the appropriate
tcg_gen_{ld,st}_tl calls.

This conveniently avoids a warning due to _t_gen_mov_TN_env() being
unused.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2014-06-09 01:04:44 +02:00
Peter Maydell
08397c4b29 target-cris/translate.c: Remove t_gen_mov_TN_reg and t_gen_mov_reg_TN
Remove the t_gen_mov_TN_reg and t_gen_mov_reg_TN wrappers: the
latter is completely unused, and the former only used in a few
places (which are thus inconsistent with the rest of the decoder
which directly accesses cpu_R[]).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2014-06-09 01:04:44 +02:00
Peter Crosthwaite
a373cdb5ce intc: xilinx_uartlite: Convert SBD::init -> instance_init
SysBusDevice::init is depracated. Convert to Object::init
as prescribed by QOM conventions.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2014-06-09 00:33:03 +02:00
Peter Crosthwaite
aa0f607f61 char: xilinx_uartlite: Convert to realize()
SysBusDevice::init is depracated. Convert to Object::init and
Device::realize as prescribed by QOM conventions.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2014-06-09 00:33:03 +02:00
Peter Crosthwaite
95faaa73df char: xilinx_uartlite: Don't reset from init
This refresh of the device state is intended to be a reset side
effect. Move it to a proper reset handler rather than do it at
init time.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2014-06-09 00:33:03 +02:00
Peter Crosthwaite
e8198f6ea0 net: xilinx_ethlite: Convert to realize()
SysBusDevice::init is depracated. Convert to Object::init and
Device::realize as prescribed by QOM conventions.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2014-06-09 00:33:03 +02:00
Peter Crosthwaite
8c6d96728d net: xilinx_ethlite: Don't reset from init
This zeroing-out of the rxbuf variable (ping pong state) is a reset
side effect. Extract into a proper reset.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2014-06-09 00:33:03 +02:00
Peter Crosthwaite
04bb4d86f1 timer: xilinx_timer: Convert to realize()
SysBusDevice::init is depracated. Convert to Object::init and
Device::realize as prescribed by QOM conventions.

Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
2014-06-09 00:33:02 +02:00
Benoît Canet
2e95fa1719 qapi: Extract qapi/block.json definitions
Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-06 16:25:48 +02:00
Benoît Canet
1ad166b612 qapi: Extract qapi/block-core.json definitions
Signed-off-by: Benoit Canet <benoit@irqsave.net
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-06 16:25:48 +02:00
Benoît Canet
5db15096d0 qapi: create two block related json modules
qapi/block-core.json contains block definitions unrelated to emulation.

qapi/block.json is a superset of the previous and contains definitions related
to emulation.

The purpose of these extractions is to be able to hook qapi/block-core.json
generated code on qemu-nbd.

Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-06 16:25:48 +02:00
Benoît Canet
d34bda716a qapi: Extract qapi/common.json definitions
Signed-off-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-06 16:25:48 +02:00
Hitoshi Mitake
5d039baba4 sheepdog: reload only header in a case of live snapshot
sheepdog driver doesn't need to read data_vdi_id[] when a live snapshot is
created.

Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Liu Yuan <namei.unix@gmail.com>
Cc: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Hitoshi Mitake <mitake.hitoshi@lab.ntt.co.jp>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-06 14:54:43 +02:00
Hitoshi Mitake
b544c1aba8 sheepdog: fix vdi object update after live snapshot
sheepdog driver should decide a write request is COW or not based on inode
object which is active when the write request is issued.

Example of wrong inode update path in the previous driver:
1. drier issues an ordinal write request to an existing object
2. user creates a snapshot of the VDI before the write request is completed
3. the respones for the request is RDONLY, because the VDI is already a snapshot
4. the driver reload an inode object of the new active VDI, then issues a write
   request again
5. the second write request can be completed
6. driver decide the request is COW or not with the below conditional branch:
   	  if (s->inode.data_vdi_id[idx] != s->inode.vdi_id) {
7. the ID of the written object and VID of the new active VDI is different, so
   the driver updates data_vdi_id[idx] and writes inode object
8. the existing object cannot be seen by the new active VDI, it results object
   leaking

Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Liu Yuan <namei.unix@gmail.com>
Cc: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Signed-off-by: Hitoshi Mitake <mitake.hitoshi@lab.ntt.co.jp>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-06 14:53:55 +02:00
Kevin Wolf
405a27640b rbd: Fix leaks in rbd_start_aio() error path
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-06 11:05:04 +02:00
Peter Maydell
50809c8b92 Merge remote-tracking branch 'remotes/mcayland/qemu-sparc' into staging
* remotes/mcayland/qemu-sparc:
  apb: implement IOMMU translation for PCI host bridge
  apb: handle reading/writing of IOMMU control registers
  apb: fix IOMMU register sizes
  apb: Move IOMMU registers into a separate IOMMUState struct
  tcx: move initialisation from realizefn to initfn
  tcx: move initialisation from SysBusDevice class to TCX class realizefn
  cg3: add extra check to prevent CG3 register array overflow
  cg3: move initialisation from realizefn to initfn

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-05 23:05:07 +01:00
Peter Maydell
4e627aeef8 Merge remote-tracking branch 'remotes/mdroth/qga-pull-2014-06-05' into staging
* remotes/mdroth/qga-pull-2014-06-05:
  qga: Fix handle fd leak in acquire_privilege()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-05 22:40:44 +01:00
Peter Maydell
26edf8cc08 Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc,pci,virtio,qdev fixes, tests

new tests for SMBIOS
SMBIOS fixes
pc, pci fixes
qdev patches stayed on list for a month with no review,
as I told people on KVM forum I'm merging stuch patches
if they look fine.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

* remotes/mst/tags/for_upstream:
  qdev: Add test of qdev_prop_check_global
  qdev: Display warning about unused -global
  tests: add smbios testing
  tests: rename acpi-test to bios-tables-test
  virtio-balloon: return empty data when no stats are available
  pcie_host: Turn pcie_host_init() into an instance_init
  SMBIOS: Fix type 17 field sizes
  SMBIOS: Update Type 0 struct generator for machines >= 2.1
  SMBIOS: Fix endian-ness when populating multi-byte fields
  serial-pci: Set prog interface field of pci config to 16550 compatible

Conflicts:
	include/hw/i386/pc.h
[PMM: fixed trivial conflict in pc.h]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-05 21:52:37 +01:00
Peter Maydell
31e25e3e57 Merge remote-tracking branch 'remotes/bonzini/softmmu-smap' into staging
* remotes/bonzini/softmmu-smap: (33 commits)
  target-i386: cleanup x86_cpu_get_phys_page_debug
  target-i386: fix protection bits in the TLB for SMEP
  target-i386: support long addresses for 4MB pages (PSE-36)
  target-i386: raise page fault for reserved bits in large pages
  target-i386: unify reserved bits and NX bit check
  target-i386: simplify pte/vaddr calculation
  target-i386: raise page fault for reserved physical address bits
  target-i386: test reserved PS bit on PML4Es
  target-i386: set correct error code for reserved bit access
  target-i386: introduce support for 1 GB pages
  target-i386: introduce do_check_protect label
  target-i386: tweak handling of PG_NX_MASK
  target-i386: commonize checks for PAE and non-PAE
  target-i386: commonize checks for 4MB and 4KB pages
  target-i386: commonize checks for 2MB and 4KB pages
  target-i386: fix coding standards in x86_cpu_handle_mmu_fault
  target-i386: simplify SMAP handling in MMU_KSMAP_IDX
  target-i386: fix kernel accesses with SMAP and CPL = 3
  target-i386: move check_io helpers to seg_helper.c
  target-i386: rename KSMAP to KNOSMAP
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-05 21:06:14 +01:00
Mark Cave-Ayland
ae74bbe7c5 apb: implement IOMMU translation for PCI host bridge
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2014-06-05 21:00:22 +01:00
Mark Cave-Ayland
f38b161203 apb: handle reading/writing of IOMMU control registers
While the registers are documented as being 64-bit, Linux seems to access
them in two halves as 2 x 32-bit accesses. Make sure that we can correctly
handle this case.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2014-06-05 21:00:12 +01:00
Mark Cave-Ayland
fd7fbc8ff7 apb: fix IOMMU register sizes
According to the referenced documentation, the IOMMU has 3 64-bit registers
consisting of a control register, base register and flush register.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2014-06-05 21:00:03 +01:00
Mark Cave-Ayland
ea9a6606b1 apb: Move IOMMU registers into a separate IOMMUState struct
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2014-06-05 20:59:53 +01:00
Mark Cave-Ayland
01b91ac2be tcx: move initialisation from realizefn to initfn
Initialisation cleanup as suggested by Andreas.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
CC: Andreas Färber <afaerber@suse.de>
2014-06-05 20:51:57 +01:00
Mark Cave-Ayland
d4ad9dec14 tcx: move initialisation from SysBusDevice class to TCX class realizefn
This is an intermediate step to bring TCX in line with CG3.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
CC: Andreas Färber <afaerber@suse.de>
2014-06-05 20:51:45 +01:00
Mark Cave-Ayland
366d4f7e00 cg3: add extra check to prevent CG3 register array overflow
The case statements in the CG3 read and write register routines have a maximum
value of CG3_REG_SIZE, so if a value were written to this offset then it
would overflow the register array.

Currently this cannot be exploited since the MemoryRegion restricts accesses
to the range 0 ... CG3_REG_SIZE - 1, but it seems worth clarifying this for
future review and/or static analysis.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
CC: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 20:51:30 +01:00
Mark Cave-Ayland
e09c49f40d cg3: move initialisation from realizefn to initfn
Initialisation cleanup as suggested by Andreas.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
CC: Andreas Färber <afaerber@suse.de>
2014-06-05 20:51:19 +01:00
Peter Maydell
9d48d3f01c Merge remote-tracking branch 'remotes/rth/tcg-next' into staging
* remotes/rth/tcg-next:
  TCG: Fix tcg_gen_extr_i64_tl for 32bit
  tcg: Remove TCG_TARGET_HAS_new_ldst
  tci: Convert to new ldst opcodes
  tcg-i386: Fix win64 qemu store

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-05 20:11:50 +01:00
Peter Maydell
9f0355b590 Merge remote-tracking branch 'remotes/kvm/uq/master' into staging
* remotes/kvm/uq/master:
  kvm: Fix eax for cpuid leaf 0x40000000
  kvmclock: Ensure proper env->tsc value for kvmclock_current_nsec calculation
  kvm: Enable -cpu option to hide KVM
  kvm: Ensure negative return value on kvm_init() error handling path
  target-i386: set CC_OP to CC_OP_EFLAGS in cpu_load_eflags
  target-i386: get CPL from SS.DPL
  target-i386: rework CPL checks during task switch, preparing for next patch
  target-i386: fix segment flags for SMM and VM86 mode
  target-i386: Fix vm86 mode regression introduced in fd460606fd.
  kvm_stat: allow choosing between tracepoints and old stats
  kvmclock: Ensure time in migration never goes backward

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-05 19:16:28 +01:00
Peter Maydell
d4f005db9b Merge remote-tracking branch 'remotes/kraxel/tags/pull-input-10' into staging
updates for docs/multiseat.txt
input: add support for kbd delays

# gpg: Signature made Wed 04 Jun 2014 08:22:39 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-input-10:
  docs/multiseat.txt: add note about spice
  docs/multiseat.txt: gtk joined the party
  docs/multiseat.txt: use autoseat
  input/vnc: use kbd delays in press_key
  input/curses: add kbd delay between keydown and keyup events
  input: use kbd delays for send_key monitor command
  input: add support for kbd delays

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2014-06-05 18:58:53 +01:00
Don Slutz
711e2f1e9e qdev: Add test of qdev_prop_check_global
This will generate a warning from "make check":

...
GTESTER tests/test-qdev-global-props
Warning: "-global dynamic-prop-type-bad.prop3=103" not used
GTESTER tests/check-qom-interface
...

If the warning is not generated, the test will fail.

Signed-off-by: Don Slutz <dslutz@verizon.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
2014-06-05 19:20:38 +03:00
Don Slutz
9f9260a3be qdev: Display warning about unused -global
This can help a user understand why -global was ignored.

For example: with "-vga cirrus"; "-global vga.vgamem_mb=16" is just
ignored when "-global cirrus-vga.vgamem_mb=16" is not.

This is currently clear when the wrong property is provided:

out/x86_64-softmmu/qemu-system-x86_64 -global cirrus-vga.vram_size_mb=16 -monitor pty -vga cirrus
char device redirected to /dev/pts/20 (label compat_monitor0)
qemu-system-x86_64: Property '.vram_size_mb' not found
Aborted (core dumped)

vs

out/x86_64-softmmu/qemu-system-x86_64 -global vga.vram_size_mb=16 -monitor pty -vga cirrus
char device redirected to /dev/pts/20 (label compat_monitor0)
VNC server running on `::1:5900'
^Cqemu: terminating on signal 2

Signed-off-by: Don Slutz <dslutz@verizon.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
2014-06-05 19:20:37 +03:00
Paolo Bonzini
16b96f82cd target-i386: cleanup x86_cpu_get_phys_page_debug
Make the code a bit more similar to x86_cpu_handle_mmu_fault.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:35 +02:00
Paolo Bonzini
b09481de91 target-i386: fix protection bits in the TLB for SMEP
User pages must be marked as non-executable when running under SMEP;
otherwise, fetching the page first and then calling it will fail.

With this patch, all SMEP testcases in kvm-unit-tests now pass.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:35 +02:00
Paolo Bonzini
de431a655a target-i386: support long addresses for 4MB pages (PSE-36)
4MB pages can use 40-bit addresses by putting the higher 8 bits in bits
20-13 of the PDE.  Bit 21 is reserved.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:35 +02:00
Paolo Bonzini
eaad03e472 target-i386: raise page fault for reserved bits in large pages
In large pages, bit 12 is for PAT, but bits starting at 13 are reserved.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:35 +02:00
Paolo Bonzini
e2a32ebbfe target-i386: unify reserved bits and NX bit check
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
e7e898a76a target-i386: simplify pte/vaddr calculation
They can moved to after the dirty bit processing, and unified between
CR0.PG=1 and CR0.PG=0.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
e8f6d00c30 target-i386: raise page fault for reserved physical address bits
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
b728464ae8 target-i386: test reserved PS bit on PML4Es
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
c1eb2fa3fd target-i386: set correct error code for reserved bit access
The correct error code is 9 (present, reserved), not 8.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
77549a7809 target-i386: introduce support for 1 GB pages
Given the simplifications to the code in the previous patches, this
is now very simple to do.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
b052e4509b target-i386: introduce do_check_protect label
This will help adding 1GB page support in the next patch.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
870a706735 target-i386: tweak handling of PG_NX_MASK
Remove the tail of the PAE case, so that we can use "goto" in the
next patch to jump to the protection checks.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
7c82256006 target-i386: commonize checks for PAE and non-PAE
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
487cad8853 target-i386: commonize checks for 4MB and 4KB pages
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
00cc3e1d70 target-i386: commonize checks for 2MB and 4KB pages
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
843408b3cf target-i386: fix coding standards in x86_cpu_handle_mmu_fault
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
f57584dc87 target-i386: simplify SMAP handling in MMU_KSMAP_IDX
Do not use this MMU index at all if CR4.SMAP is false, and drop
the SMAP check from x86_cpu_handle_mmu_fault.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
8a201bd47e target-i386: fix kernel accesses with SMAP and CPL = 3
With SMAP, implicit kernel accesses from user mode always behave as
if AC=0.  To do this, kernel mode is not anymore a separate MMU mode.
Instead, KERNEL_IDX is renamed to KSMAP_IDX and the kernel mode accessors
wrap KSMAP_IDX and KNOSMAP_IDX.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
81cf8d8adc target-i386: move check_io helpers to seg_helper.c
Prepare for adding _kernel accessors there in the next patch.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
43773ed369 target-i386: rename KSMAP to KNOSMAP
This is the mode where SMAP is overridden, put "NO" in its name.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:34 +02:00
Paolo Bonzini
c773828aa9 softmmu: move all load/store functions to cpu_ldst.h
Unify pieces of cpu-all.h, exec-all.h, softmmu_exec.h and tcg/tcg.h
into a single new header file with all helpers.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:33 +02:00
Paolo Bonzini
f08b617018 softmmu: introduce cpu_ldst.h
This will collect all load and store helpers soon.  For now
it is just a replacement for softmmu_exec.h, which this patch
stops including directly, but we also include it where this will
be necessary in order to simplify the next patch.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:33 +02:00
Paolo Bonzini
1d854765df target-arm: move arm_*_code to a separate file
These will soon require cpu_ldst.h, so move them out of cpu.h.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:33 +02:00
Paolo Bonzini
58ed270df9 softmmu: move softmmu_template.h out of include/
It is only included in cputlb.c now.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:33 +02:00
Paolo Bonzini
0f590e749f softmmu: commonize helper definitions
They do not need to be in op_helper.c.  Because cputlb.c now includes
softmmu_template.h twice for each size, io_readX must be elided the
second time through.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:33 +02:00
Paolo Bonzini
d94f0a8ecb softmmu: move ALIGNED_ONLY to cpu.h
Prepare for moving softmmu_header.h inclusion out of .c files

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:33 +02:00
Paolo Bonzini
93e22326d6 softmmu: make do_unaligned_access a method of CPU
We will reference it from more files in the next patch.  To avoid
ruining the small steps we're making towards multi-target, make
it a method of CPU rather than just a global.

Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:10:31 +02:00
Paolo Bonzini
ca0aa40816 softmmu: move definition of CPU_MMU_INDEX to inclusion site, drop ACCESS_TYPE
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:05:52 +02:00
Paolo Bonzini
a6c9eac0d5 softmmu: move MMUSUFFIX under SOFTMMU_CODE_ACCESS
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:05:47 +02:00
Paolo Bonzini
859d76120b softmmu: start introducing SOFTMMU_CODE_ACCESS in softmmu_header.h
This preprocessor symbol is already used in softmmu_template.h.  We
will use it to distinguish the two "fake" ACCESS_TYPEs
NB_MMU_MODES and NB_MMU_MODES + 1.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:05:27 +02:00
Paolo Bonzini
0983979b3a hw: use ld_p/st_p instead of ld_raw/st_raw
The ld_raw and st_raw definitions are only needed in code that
must compile for both user-mode and softmmu emulation.  Device
models can use the equivalent ld_p/st_p which are simple
pointer accessors.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:04:17 +02:00
Paolo Bonzini
fddbd80cc9 nseries: clean up coding style
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:03:53 +02:00
Stefan Weil
7e4e88656c cputlb: Fix regression with TCG interpreter (bug 1310324)
Commit 0f842f8a24 replaced GETPC_EXT() which
was derived from GETPC() by GETRA_EXT() without fixing cputlb.c. A later
patch replaced GETRA_EXT() by GETRA() in exec/softmmu_template.h which
is included in cputlb.c.

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

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

Cc: qemu-stable@nongnu.org
Reported-by: Giovanni Mascellani <gio@debian.org>
Signed-off-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-05 16:03:37 +02:00
Alexander Graf
e3eb9806c7 TCG: Fix tcg_gen_extr_i64_tl for 32bit
We expose a generic helper "tcg_gen_extr_i64_tl" for 64bit targets, but the
same function for 32bit targets is a misnomer and refers to an invalid function
name.

Fix up the definition to point to the correct internal helper names instead.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-06-04 14:11:45 -07:00
Richard Henderson
3d1b2ff62c tcg: Remove TCG_TARGET_HAS_new_ldst
Since all backends have been converted, remove the compatibility code.

Acked-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-06-04 14:10:26 -07:00
Richard Henderson
76782fab1c tci: Convert to new ldst opcodes
Tested-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-06-04 14:10:16 -07:00
Richard Henderson
0b91966730 tcg-i386: Fix win64 qemu store
The first non-register argument isn't placed at offset 0.

Cc: qemu-stable@nongnu.org
Reviewed-by: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2014-06-04 13:58:39 -07:00
Max Reitz
d6635c4dbb qemu-img: Document check exit codes
The exit code 63 (check not supported by image format) was not even
documented in the comment above the check command in the source code;
add it, as it does indeed seem useful.

Also, document all of check's exit codes in the manpage.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reported-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 11:30:32 +02:00
chai wen
1ac362cdbd block: fix wrong order in live block migration setup
The function init_blk_migration is better to be called before
set_dirty_tracking as the reasons below.

If we want to track dirty blocks via dirty_maps on a BlockDriverState
when doing live block-migration, its correspoding 'BlkMigDevState' should be
added to block_mig_state.bmds_list first for subsequent processing.
Otherwise set_dirty_tracking will do nothing on an empty list than allocating
dirty_bitmaps for them. And bdrv_get_dirty_count will access the
bmds->dirty_maps directly, then there would be a segfault triggered.

If the set_dirty_tracking fails, qemu_savevm_state_cancel will handle
the cleanup of init_blk_migration automatically.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: chai wen <chaiw.fnst@cn.fujitsu.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 11:22:39 +02:00
Stefan Hajnoczi
b15446fdbf blockdev: acquire AioContext in block_set_io_throttle
The block_set_io_throttle QMP and HMP commands modify I/O throttling
limits for block devices.

Acquire the BlockDriverState's AioContext to protect against race
conditions with an IOThread that is running I/O for this device.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
22524f7262 throttle: add detach/attach test case
Add a test case that checks the timer is really removed/added by the
detach/attach functions.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
13af91ebf0 throttle: add throttle_detach/attach_aio_context()
Block I/O throttling uses timers and currently always adds them to the
main loop.  Throttling will break if bdrv_set_aio_context() is used to
move a BlockDriverState to a different AioContext.

This patch adds throttle_detach/attach_aio_context() interfaces so the
throttling timers and uses them to move timers to the new AioContext.
Note that bdrv_set_aio_context() already drains all requests so we're
sure no throttled requests are pending.

The test cases need to be updated since the throttle_init() interface
has changed.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Benoit Canet <benoit@irqsave.net>
2014-06-04 09:56:12 +02:00
Fam Zheng
c9f87b20b9 dataplane: Support VIRTIO_BLK_T_SCSI_CMD
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Fam Zheng
5a05cbeeaa virtio-blk: Factor out virtio_blk_handle_scsi_req from virtio_blk_handle_scsi
The common logic to process a scsi request in a VirtQueueElement is
extracted to a function to share with dataplane.

This makes VirtIOBlockReq.scsi unused, so drop it.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Fam Zheng
6d7e73d62f virtio-blk: Allow config-wce in dataplane
Dataplane now uses block layer. Protect bdrv_set_enable_write_cache with
aio_context_acquire and aio_context_release, so we can enable config-wce
to allow guest to modify the write cache online.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Fam Zheng
db519cba87 block: Move declaration of bdrv_get_aio_context to block.h
block_int.h is for block layer and block drivers, other code shouldn't
include it. But similar to bdrv_set_aio_context, bdrv_get_aio_context
should also be accessible from outside of block layer.

Move it.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
76ef2cf549 raw-posix: drop raw_get_aio_fd() since it is no longer used
virtio-blk data-plane now uses the QEMU block layer for I/O.  We do not
need raw_get_aio_fd() anymore.  It was a layering violation anyway, so
let's get rid of it.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
8d242f0ed5 dataplane: implement async flush
Stop using the raw-posix file descriptor for synchronous
qemu_fdatasync().  Use bdrv_aio_flush() instead and drop the
VirtIOBlockDataPlane->fd field.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
0d6ecec252 dataplane: delete IOQueue since it is no longer used
This custom Linux AIO request queue is no longer used by virtio-blk
data-plane.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
580b6b2aa2 dataplane: use the QEMU block layer for I/O
Stop using a custom Linux AIO request queue from ioq.h and instead use
the QEMU block layer for I/O.

This patch adjusts the VirtIOBlockRequest struct with fields needed for
bdrv_aio_readv()/bdrv_aio_writev().  ioq.h used struct iovec and struct
iocb, which we don't need directly anymore.

Modify dataplane start/stop to set the AioContext on the
BlockDriverState.  We also no longer need to get the raw-posix file
descriptor.  This means image formats are now supported with dataplane!

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
c75f3bdf46 vmdk: implement .bdrv_detach/attach_aio_context()
Implement .bdrv_detach/attach_aio_context() interfaces to propagate
detach/attach to BDRVVmdkState->extents[].file.  The block layer takes
care of ->file and ->backing_hd but doesn't know about our extents
BlockDriverStates, which is also part of the graph.

Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
2af0b20056 ssh: use BlockDriverState's AioContext
Drop the assumption that we're using the main AioContext.  Use
bdrv_get_aio_context() to register fd handlers in the right AioContext
for this BlockDriverState.

The .bdrv_detach_aio_context() and .bdrv_attach_aio_context() interfaces
are not needed since no fd handlers, timers, or BHs stay registered when
requests have been drained.

For now this doesn't make much difference but will allow ssh to work in
IOThread instances in the future.

Acked-by: Richard W.M. Jones <rjones@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
84390bed59 sheepdog: implement .bdrv_detach/attach_aio_context()
Drop the assumption that we're using the main AioContext.  Convert
qemu_aio_set_fd_handler() to aio_set_fd_handler() and qemu_aio_wait() to
aio_poll().

The .bdrv_detach/attach_aio_context() interfaces also need to be
implemented to move the socket fd handler from the old to the new
AioContext.

Cc: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Acked-by: Liu Yuan <namei.unix@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
ea80019149 rbd: use BlockDriverState's AioContext
Drop the assumption that we're using the main AioContext.  Convert
qemu_bh_new() to aio_bh_new() and qemu_aio_wait() to aio_poll().

The .bdrv_detach_aio_context() and .bdrv_attach_aio_context() interfaces
are not needed since no fd handlers, timers, or BHs stay registered when
requests have been drained.

Cc: Josh Durgin <josh.durgin@inktank.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
85ebd381fd block/raw-win32: implement .bdrv_detach/attach_aio_context()
Drop the assumption that we're using the main AioContext for raw-win32.
Convert the aio-win32 code to support detach/attach and replace
qemu_aio_wait() with aio_poll().

The .bdrv_detach/attach_aio_context() interfaces move the aio-win32
event notifier from the old to the new AioContext.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
99cc598924 block/raw-win32: create one QEMUWin32AIOState per BDRVRawState
Each QEMUWin32AIOState event notifier is associated with an AioContext.
Since BlockDriverState instances can use different AioContexts we cannot
continue to use a global QEMUWin32AIOState.

Let each BDRVRawState have its own QEMUWin32AIOState and free it when
BDRVRawState is closed.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:12 +02:00
Stefan Hajnoczi
abd269b7cf block/linux-aio: fix memory and fd leak
Hot unplugging -drive aio=native,file=test.img,format=raw images leaves
the Linux AIO event notifier and struct qemu_laio_state allocated.
Luckily nothing will use the event notifier after the BlockDriverState
has been closed so the handler function is never called.

It's still worth fixing this resource leak.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
c2f3426c9b block/raw-posix: implement .bdrv_detach/attach_aio_context()
Drop the assumption that we're using the main AioContext for Linux AIO.
Convert the Linux AIO event notifier to use aio_set_event_notifier().

The .bdrv_detach/attach_aio_context() interfaces also need to be
implemented to move the event notifier handler from the old to the new
AioContext.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
e3625d3d6a quorum: implement .bdrv_detach/attach_aio_context()
Implement .bdrv_detach/attach_aio_context() interfaces to propagate
detach/attach to BDRVQuorumState->bs[] children.  The block layer takes
care of ->file and ->backing_hd but doesn't know about our ->bs[]
BlockDriverStates, which is also part of the graph.

Reviewed-by: Benoît Canet <benoit.canet@irqsave.net>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
a8c868c386 qed: use BlockDriverState's AioContext
Drop the assumption that we're using the main AioContext.  Convert
qemu_bh_new() to aio_bh_new() and qemu_aio_wait() to aio_poll() so we're
using the BlockDriverState's AioContext.

Implement .bdrv_detach/attach_aio_context() interfaces to move the
QED_F_NEED_CHECK timer from the old AioContext to the new one.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
471799d135 nfs: implement .bdrv_detach/attach_aio_context()
Drop the assumption that we're using the main AioContext.  The following
functions need to be converted:
 * qemu_bh_new() -> aio_bh_new()
 * qemu_aio_set_fd_handler() -> aio_set_fd_handler()
 * qemu_aio_wait() -> aio_poll()

The .bdrv_detach/attach_aio_context() interfaces also need to be
implemented to move the fd handler from the old to the new AioContext.

Cc: Peter Lieven <pl@kamp.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Lieven <pl@kamp.de>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
69447cd8f3 nbd: implement .bdrv_detach/attach_aio_context()
Drop the assumption that we're using the main AioContext.  Convert
qemu_aio_set_fd_handler() calls to aio_set_fd_handler().

The .bdrv_detach/attach_aio_context() interfaces also need to be
implemented to move the socket fd handler from the old to the new
AioContext.

Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
80cf625766 iscsi: implement .bdrv_detach/attach_aio_context()
Drop the assumption that we're using the main AioContext for Linux
AIO.  Convert qemu_aio_set_fd_handler() to aio_set_fd_handler() and
timer_new_ms() to aio_timer_new().

The .bdrv_detach/attach_aio_context() interfaces also need to be
implemented to move the fd and timer from the old to the new AioContext.

Cc: Peter Lieven <pl@kamp.de>
Cc: Ronnie Sahlberg <ronniesahlberg@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Peter Lieven <pl@kamp.de>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
6ee50af24b gluster: use BlockDriverState's AioContext
Drop the assumption that we're using the main AioContext.  Use
aio_bh_new() instead of qemu_bh_new().

The .bdrv_detach_aio_context() and .bdrv_attach_aio_context() interfaces
are not needed since no fd handlers, timers, or BHs stay registered when
requests have been drained.

Cc: Bharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
63f0f45f2e curl: implement .bdrv_detach/attach_aio_context()
The curl block driver uses fd handlers, timers, and BHs.  The fd
handlers and timers are managed on behalf of libcurl, which controls
them using callback functions that the block driver implements.

The simplest way to implement .bdrv_detach/attach_aio_context() is to
clean up libcurl in the old event loop and initialize it again in the
new event loop.  We do not need to keep track of anything since there
are no pending requests when the AioContext is changed.

Also make sure to use aio_set_fd_handler() instead of
qemu_aio_set_fd_handler() and aio_bh_new() instead of qemu_bh_new() so
the current AioContext is passed in.

Cc: Alexander Graf <agraf@suse.de>
Cc: Fam Zheng <famz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
9d94020bc6 blkverify: implement .bdrv_detach/attach_aio_context()
Drop the assumption that we're using the main AioContext.  Convert
qemu_bh_new() to aio_bh_new() and qemu_aio_wait() to aio_poll() so we
use the BlockDriverState's AioContext.

Implement .bdrv_detach/attach_aio_context() interfaces to propagate
detach/attach to BDRVBlkverifyState->test_file.  The block layer takes
care of ->file and ->backing_hd but doesn't know about our ->test_file
BlockDriverState, which is also part of the graph.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
7e1efdf0a3 blkdebug: use BlockDriverState's AioContext
Drop the assumption that we're using the main AioContext.  Convert
qemu_bh_new() to aio_bh_new() so we use the BlockDriverState's
AioContext.

The .bdrv_detach_aio_context() and .bdrv_attach_aio_context() interfaces
are not needed since no fd handlers, timers, or BHs stay registered when
requests have been drained.

Cc: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
dcd042282d block: add bdrv_set_aio_context()
Up until now all BlockDriverState instances have used the QEMU main loop
for fd handlers, timers, and BHs.  This is not scalable on SMP guests
and hosts so we need to move to a model with multiple event loops on
different host CPUs.

bdrv_set_aio_context() assigns the AioContext event loop to use for a
particular BlockDriverState.  It first detaches the entire
BlockDriverState graph from the current AioContext and then attaches to
the new AioContext.

This function will be used by virtio-blk data-plane to assign a
BlockDriverState to its IOThread AioContext.  Make
bdrv_aio_set_context() public since data-plane should not include
block_int.h.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
9b536adcbe block: acquire AioContext in bdrv_drain_all()
Modify bdrv_drain_all() to take into account that BlockDriverState
instances may be running in different AioContexts.

This patch changes the implementation of bdrv_drain_all() while
preserving the semantics.  Previously kicking throttled requests and
checking for pending requests were done across all BlockDriverState
instances in sequence.  Now we process each BlockDriverState in turn,
making sure to acquire and release its AioContext.

This prevents race conditions between the thread executing
bdrv_drain_all() and the thread running the AioContext.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
ed78cda3de block: acquire AioContext in bdrv_*_all()
bdrv_close_all(), bdrv_commit_all(), bdrv_flush_all(),
bdrv_invalidate_cache_all(), and bdrv_clear_incoming_migration_all() are
called by main loop code and touch all BlockDriverState instances.

Some BlockDriverState instances may be running in another AioContext.
Make sure to acquire the AioContext before closing the BlockDriverState.

This will protect against race conditions once virtio-blk data-plane is
using the BlockDriverState from another AioContext event loop.

Note that this patch does not convert bdrv_drain_all() yet since that
conversion is non-trivial.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
2572b37a47 block: use BlockDriverState AioContext
Drop the assumption that we're using the main AioContext.  Convert
qemu_aio_wait() to aio_poll() and qemu_bh_new() to aio_bh_new() so the
BlockDriverState AioContext is used.

Note there is still one qemu_aio_wait() left in bdrv_create() but we do
not have a BlockDriverState there and only main loop code invokes this
function.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2014-06-04 09:56:11 +02:00
Stefan Hajnoczi
924fe1293c aio: fix qemu_bh_schedule() bh->ctx race condition
qemu_bh_schedule() is supposed to be thread-safe at least the first time
it is called.  Unfortunately this is not quite true:

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

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

Reported-by: Stefan Priebe <s.priebe@profihost.ag>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Tested-by: Stefan Priebe <s.priebe@profihost.ag>
2014-06-04 09:56:06 +02:00
Jidong Xiao
79b6f2f651 kvm: Fix eax for cpuid leaf 0x40000000
Since Linux kernel 3.5, KVM has documented eax for leaf 0x40000000
to be KVM_CPUID_FEATURES:

57c22e5f35

But qemu still tries to set it to 0. It would be better to make qemu
and kvm consistent. This patch just fixes this issue.

Signed-off-by: Jidong Xiao <jidong.xiao@gmail.com>
[Include kvm_base in the value. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-04 09:12:04 +02:00
Gonglei
374044f08f qga: Fix handle fd leak in acquire_privilege()
token should be closed in all conditions.
So move CloseHandle(token) to "out" branch.

Signed-off-by: Wang Rui <moon.wangrui@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2014-06-03 15:07:59 -05:00
Marcelo Tosatti
9b1786829a kvmclock: Ensure proper env->tsc value for kvmclock_current_nsec calculation
Ensure proper env->tsc value for kvmclock_current_nsec calculation.

Reported-by: Marcin Gibuła <m.gibula@beyond.pl>
Cc: qemu-stable@nongnu.org
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-03 18:40:48 +02:00
Alex Williamson
f522d2acc5 kvm: Enable -cpu option to hide KVM
The latest Nvidia driver (337.88) specifically checks for KVM as the
hypervisor and reports Code 43 for the driver in a Windows guest when
found.  Removing or changing the KVM signature is sufficient for the
driver to load and work.  This patch adds an option to easily allow
the KVM hypervisor signature to be hidden using '-cpu kvm=off'.  We
continue to expose KVM via the cpuid value by default.  The state of
this option does not supercede or replace -enable-kvm or the accel=kvm
machine option.  This only changes the visibility of KVM to the guest
and paravirtual features specifically tied to the KVM cpuid.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-06-03 18:40:48 +02:00
Eduardo Habkost
0e1dac6c41 kvm: Ensure negative return value on kvm_init() error handling path
We need to ensure ret < 0 when going through the error path, or QEMU may
try to run the half-initialized VM and crash.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-05-30 22:28:55 +02:00
Gabriel L. Somlo
eb386aaccc tests: add smbios testing
Add tests to find and verify the smbios entry point structure,
and to walk and perform checks on the actual smbios tables.

Suggested-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2014-05-27 23:42:16 +03:00
Gabriel L. Somlo
501f28ca9d tests: rename acpi-test to bios-tables-test
The test harness for acpi (generating a boot disk, starting qemu,
waiting for the BIOS to finish booting before examining guest
memory, etc.) is perfectly suited for testing other bios tables
beside acpi, such as e.g., smbios.

This patch renames acpi-test to bios-tables-test to reflect that,
and in preparation for adding smbios tests.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2014-05-27 23:42:16 +03:00
Ján Tomko
38dbd48b24 virtio-balloon: return empty data when no stats are available
If the guest hasn't updated the stats yet, instead of returning
an error, return '-1' for the stats and '0' as 'last-update'.

This lets applications ignore this without parsing the error message.

Related libvirt patch and discussion:
https://www.redhat.com/archives/libvir-list/2014-May/msg00460.html

Tested against current upstream libvirt - stat reporting works and
it no longer logs errors when the stats are queried on domain startup.
(Note: libvirt doesn't use the last-update field for anything yet)

Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2014-05-25 12:46:58 +03:00
Paolo Bonzini
28fb26f19f target-i386: set CC_OP to CC_OP_EFLAGS in cpu_load_eflags
There is no reason to keep that out of the function.  The comment refers
to the disassembler's cc_op state rather than the CPUState field.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-05-21 18:02:08 +02:00
Paolo Bonzini
7125c937c9 target-i386: get CPL from SS.DPL
CS.RPL is not equal to the CPL in the few instructions between
setting CR0.PE and reloading CS.  We get this right in the common
case, because writes to CR0 do not modify the CPL, but it would
not be enough if an SMI comes exactly during that brief period.
Were this to happen, the RSM instruction would erroneously set
CPL to the low two bits of the real-mode selector; and if they are
not 00, the next instruction fetch cannot access the code segment
and causes a triple fault.

However, SS.DPL *is* always equal to the CPL.  In real processors
(AMD only) there is a weird case of SYSRET setting SS.DPL=SS.RPL
from the STAR register while forcing CPL=3, but we do not emulate
that.

Tested-by: Kevin O'Connor <kevin@koconnor.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-05-21 18:02:08 +02:00
Paolo Bonzini
d3b5491897 target-i386: rework CPL checks during task switch, preparing for next patch
During task switch, all of CS.DPL, CS.RPL, SS.DPL must match (in addition
to all the other requirements) and will be the new CPL.  So far this worked
by carefully setting the CS selector and flags before doing the task
switch; but this will not work once we get the CPL from SS.DPL.

Temporarily assume that the CPL comes from CS.RPL during task switch
to a protected-mode task, until the descriptor of SS is loaded.

Tested-by: Kevin O'Connor <kevin@koconnor.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-05-21 18:02:08 +02:00
Paolo Bonzini
b98dbc9095 target-i386: fix segment flags for SMM and VM86 mode
With the next patch, these need to be correct or VM86 tasks
have the wrong CPL.  The flags are basically what the Intel VMX
documentation say is mandatory for entry into a VM86 guest.

For consistency, SMM ought to have the same flags except with
CPL=0.

Tested-by: Kevin O'Connor <kevin@koconnor.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-05-21 18:02:08 +02:00
Kevin O'Connor
87446327cc target-i386: Fix vm86 mode regression introduced in fd460606fd.
Commit fd460606fd moved setting of eflags above calls to
cpu_x86_load_seg_cache() in seg_helper.c.  Unfortunately, in
do_interrupt_protected() this moved the clearing of VM_MASK above a
test for it.

Fix this regression by storing the value of VM_MASK at the start of
do_interrupt_protected().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-05-21 18:02:08 +02:00
Paolo Bonzini
b763adf1a6 kvm_stat: allow choosing between tracepoints and old stats
The old stats contain information not available in the tracepoints.
By default, keep the old behavior, but allow choosing which set of stats
to present, or even both.

Inspired by a patch from Marcelo Tosatti.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-05-21 17:56:37 +02:00
Andreas Färber
7c8b724826 pcie_host: Turn pcie_host_init() into an instance_init
This assures the trivial field initialization is applied for any derived
type - currently only Q35PCIHost.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2014-05-21 15:47:50 +03:00
Gabriel L. Somlo
0d73394ad9 SMBIOS: Fix type 17 field sizes
Fields for configured_clock_speed and various voltage values
introduced in spec v2.7+ should be "word", i.e. 16 bits.

Reported-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2014-05-21 15:47:50 +03:00
Gabriel L. Somlo
84351843eb SMBIOS: Update Type 0 struct generator for machines >= 2.1
Update how type 0 (bios info) structures are generated, as follows:

  - convert bios_characteristics field to uin64_t (instead of
    uint8_t[8]), as described in the current smbios spec (v2.8)

  - enable "virtual machine" bit in bios_characteristics_extension_bits

  - add command line option to enable "uefi supported" bit in
    bios_characteristics_extension_bits

These updates should make this optional structure more useful when
used with edk2/ovmf. Only pc machines >= 2.1 are affected, and only
when a type 0 structure is explicitly specified on the command line.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2014-05-21 15:47:50 +03:00
Gabriel L. Somlo
fb5be2e833 SMBIOS: Fix endian-ness when populating multi-byte fields
When i386 guests are emulated on big endian hosts, make sure
multi-byte fields are populated safely via cpu_to_le*().

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2014-05-21 15:47:50 +03:00
BALATON Zoltan
13cc2c3e86 serial-pci: Set prog interface field of pci config to 16550 compatible
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
2014-05-21 15:47:50 +03:00
Alexander Graf
a096b3a673 kvmclock: Ensure time in migration never goes backward
When we migrate we ask the kernel about its current belief on what the guest
time would be. However, I've seen cases where the kvmclock guest structure
indicates a time more recent than the kvm returned time.

To make sure we never go backwards, calculate what the guest would have seen
as time at the point of migration and use that value instead of the kernel
returned one when it's more recent.  This bases the view of the kvmclock
after migration on the same foundation in host as well as guest.

Signed-off-by: Alexander Graf <agraf@suse.de>
Cc: qemu-stable@nongnu.org
Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2014-05-21 12:01:45 +02:00
273 changed files with 8227 additions and 6129 deletions

View File

@@ -66,16 +66,16 @@ matrix:
compiler: gcc
# All the trace backends (apart from dtrace)
- env: TARGETS=i386-softmmu,x86_64-softmmu
EXTRA_CONFIG="--enable-trace-backend=stderr"
EXTRA_CONFIG="--enable-trace-backends=stderr"
compiler: gcc
- env: TARGETS=i386-softmmu,x86_64-softmmu
EXTRA_CONFIG="--enable-trace-backend=simple"
EXTRA_CONFIG="--enable-trace-backends=simple"
compiler: gcc
- env: TARGETS=i386-softmmu,x86_64-softmmu
EXTRA_CONFIG="--enable-trace-backend=ftrace"
EXTRA_CONFIG="--enable-trace-backends=ftrace"
TEST_CMD=""
compiler: gcc
- env: TARGETS=i386-softmmu,x86_64-softmmu
EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
EXTRA_CONFIG="--enable-trace-backend=ust"
EXTRA_CONFIG="--enable-trace-backends=ust"
compiler: gcc

View File

@@ -52,12 +52,12 @@ GENERATED_HEADERS += trace/generated-events.h
GENERATED_SOURCES += trace/generated-events.c
GENERATED_HEADERS += trace/generated-tracers.h
ifeq ($(TRACE_BACKEND),dtrace)
ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
GENERATED_HEADERS += trace/generated-tracers-dtrace.h
endif
GENERATED_SOURCES += trace/generated-tracers.c
ifeq ($(TRACE_BACKEND),ust)
ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
GENERATED_HEADERS += trace/generated-ust-provider.h
GENERATED_SOURCES += trace/generated-ust.c
endif

View File

@@ -49,7 +49,7 @@ endif
$(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \
--format=stap \
--backend=$(TRACE_BACKEND) \
--backends=$(TRACE_BACKENDS) \
--binary=$(bindir)/$(QEMU_PROG) \
--target-name=$(TARGET_NAME) \
--target-type=$(TARGET_TYPE) \
@@ -58,7 +58,7 @@ $(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
$(QEMU_PROG).stp: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \
--format=stap \
--backend=$(TRACE_BACKEND) \
--backends=$(TRACE_BACKENDS) \
--binary=$(realpath .)/$(QEMU_PROG) \
--target-name=$(TARGET_NAME) \
--target-type=$(TARGET_TYPE) \
@@ -102,7 +102,8 @@ endif #CONFIG_LINUX_USER
ifdef CONFIG_BSD_USER
QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR)
QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR) \
-I$(SRC_PATH)/bsd-user/$(HOST_VARIANT_DIR)
obj-y += bsd-user/
obj-y += gdbstub.o user-exec.o

View File

@@ -739,7 +739,6 @@ static void migration_end(void)
XBZRLE_cache_lock();
if (XBZRLE.cache) {
cache_fini(XBZRLE.cache);
g_free(XBZRLE.cache);
g_free(XBZRLE.encoded_buf);
g_free(XBZRLE.current_buf);
XBZRLE.cache = NULL;

14
async.c
View File

@@ -117,15 +117,21 @@ void qemu_bh_schedule_idle(QEMUBH *bh)
void qemu_bh_schedule(QEMUBH *bh)
{
AioContext *ctx;
if (bh->scheduled)
return;
ctx = bh->ctx;
bh->idle = 0;
/* Make sure that idle & any writes needed by the callback are done
* before the locations are read in the aio_bh_poll.
/* Make sure that:
* 1. idle & any writes needed by the callback are done before the
* locations are read in the aio_bh_poll.
* 2. ctx is loaded before scheduled is set and the callback has a chance
* to execute.
*/
smp_wmb();
smp_mb();
bh->scheduled = 1;
aio_notify(bh->ctx);
aio_notify(ctx);
}

View File

@@ -629,6 +629,7 @@ static int block_save_setup(QEMUFile *f, void *opaque)
block_mig_state.submitted, block_mig_state.transferred);
qemu_mutex_lock_iothread();
init_blk_migration(f);
/* start track dirty blocks */
ret = set_dirty_tracking();
@@ -638,8 +639,6 @@ static int block_save_setup(QEMUFile *f, void *opaque)
return ret;
}
init_blk_migration(f);
qemu_mutex_unlock_iothread();
ret = flush_blks(f);

144
block.c
View File

@@ -179,6 +179,7 @@ void bdrv_io_limits_enable(BlockDriverState *bs)
{
assert(!bs->io_limits_enabled);
throttle_init(&bs->throttle_state,
bdrv_get_aio_context(bs),
QEMU_CLOCK_VIRTUAL,
bdrv_throttle_read_timer_cb,
bdrv_throttle_write_timer_cb,
@@ -363,6 +364,7 @@ BlockDriverState *bdrv_new(const char *device_name, Error **errp)
qemu_co_queue_init(&bs->throttled_reqs[0]);
qemu_co_queue_init(&bs->throttled_reqs[1]);
bs->refcnt = 1;
bs->aio_context = qemu_get_aio_context();
return bs;
}
@@ -1856,7 +1858,11 @@ void bdrv_close_all(void)
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
AioContext *aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
bdrv_close(bs);
aio_context_release(aio_context);
}
}
@@ -1881,17 +1887,6 @@ static bool bdrv_requests_pending(BlockDriverState *bs)
return false;
}
static bool bdrv_requests_pending_all(void)
{
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
if (bdrv_requests_pending(bs)) {
return true;
}
}
return false;
}
/*
* Wait for pending requests to complete across all BlockDriverStates
*
@@ -1911,12 +1906,20 @@ void bdrv_drain_all(void)
BlockDriverState *bs;
while (busy) {
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
bdrv_start_throttled_reqs(bs);
}
busy = false;
busy = bdrv_requests_pending_all();
busy |= aio_poll(qemu_get_aio_context(), busy);
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
AioContext *aio_context = bdrv_get_aio_context(bs);
bool bs_busy;
aio_context_acquire(aio_context);
bdrv_start_throttled_reqs(bs);
bs_busy = bdrv_requests_pending(bs);
bs_busy |= aio_poll(aio_context, bs_busy);
aio_context_release(aio_context);
busy |= bs_busy;
}
}
}
@@ -2352,12 +2355,17 @@ int bdrv_commit_all(void)
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
AioContext *aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
if (bs->drv && bs->backing_hd) {
int ret = bdrv_commit(bs);
if (ret < 0) {
aio_context_release(aio_context);
return ret;
}
}
aio_context_release(aio_context);
}
return 0;
}
@@ -2775,10 +2783,12 @@ static int bdrv_prwv_co(BlockDriverState *bs, int64_t offset,
/* Fast-path if already in coroutine context */
bdrv_rw_co_entry(&rwco);
} else {
AioContext *aio_context = bdrv_get_aio_context(bs);
co = qemu_coroutine_create(bdrv_rw_co_entry);
qemu_coroutine_enter(co, &rwco);
while (rwco.ret == NOT_DONE) {
qemu_aio_wait();
aio_poll(aio_context, true);
}
}
return rwco.ret;
@@ -3831,10 +3841,15 @@ int bdrv_flush_all(void)
int result = 0;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
int ret = bdrv_flush(bs);
AioContext *aio_context = bdrv_get_aio_context(bs);
int ret;
aio_context_acquire(aio_context);
ret = bdrv_flush(bs);
if (ret < 0 && !result) {
result = ret;
}
aio_context_release(aio_context);
}
return result;
@@ -4025,10 +4040,12 @@ int64_t bdrv_get_block_status(BlockDriverState *bs, int64_t sector_num,
/* Fast-path if already in coroutine context */
bdrv_get_block_status_co_entry(&data);
} else {
AioContext *aio_context = bdrv_get_aio_context(bs);
co = qemu_coroutine_create(bdrv_get_block_status_co_entry);
qemu_coroutine_enter(co, &data);
while (!data.done) {
qemu_aio_wait();
aio_poll(aio_context, true);
}
}
return data.ret;
@@ -4621,7 +4638,7 @@ static BlockDriverAIOCB *bdrv_aio_rw_vector(BlockDriverState *bs,
acb->is_write = is_write;
acb->qiov = qiov;
acb->bounce = qemu_blockalign(bs, qiov->size);
acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_aio_bh_cb, acb);
if (is_write) {
qemu_iovec_to_buf(acb->qiov, 0, acb->bounce, qiov->size);
@@ -4660,13 +4677,14 @@ typedef struct BlockDriverAIOCBCoroutine {
static void bdrv_aio_co_cancel_em(BlockDriverAIOCB *blockacb)
{
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
BlockDriverAIOCBCoroutine *acb =
container_of(blockacb, BlockDriverAIOCBCoroutine, common);
bool done = false;
acb->done = &done;
while (!done) {
qemu_aio_wait();
aio_poll(aio_context, true);
}
}
@@ -4703,7 +4721,7 @@ static void coroutine_fn bdrv_co_do_rw(void *opaque)
acb->req.nb_sectors, acb->req.qiov, acb->req.flags);
}
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
qemu_bh_schedule(acb->bh);
}
@@ -4739,7 +4757,7 @@ static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
BlockDriverState *bs = acb->common.bs;
acb->req.error = bdrv_co_flush(bs);
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
qemu_bh_schedule(acb->bh);
}
@@ -4766,7 +4784,7 @@ static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
BlockDriverState *bs = acb->common.bs;
acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors);
acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), bdrv_co_em_bh, acb);
qemu_bh_schedule(acb->bh);
}
@@ -4977,7 +4995,11 @@ void bdrv_invalidate_cache_all(Error **errp)
Error *local_err = NULL;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
AioContext *aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
bdrv_invalidate_cache(bs, &local_err);
aio_context_release(aio_context);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -4990,7 +5012,11 @@ void bdrv_clear_incoming_migration_all(void)
BlockDriverState *bs;
QTAILQ_FOREACH(bs, &bdrv_states, device_list) {
AioContext *aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
bs->open_flags = bs->open_flags & ~(BDRV_O_INCOMING);
aio_context_release(aio_context);
}
}
@@ -5006,10 +5032,12 @@ int bdrv_flush(BlockDriverState *bs)
/* Fast-path if already in coroutine context */
bdrv_flush_co_entry(&rwco);
} else {
AioContext *aio_context = bdrv_get_aio_context(bs);
co = qemu_coroutine_create(bdrv_flush_co_entry);
qemu_coroutine_enter(co, &rwco);
while (rwco.ret == NOT_DONE) {
qemu_aio_wait();
aio_poll(aio_context, true);
}
}
@@ -5119,10 +5147,12 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
/* Fast-path if already in coroutine context */
bdrv_discard_co_entry(&rwco);
} else {
AioContext *aio_context = bdrv_get_aio_context(bs);
co = qemu_coroutine_create(bdrv_discard_co_entry);
qemu_coroutine_enter(co, &rwco);
while (rwco.ret == NOT_DONE) {
qemu_aio_wait();
aio_poll(aio_context, true);
}
}
@@ -5633,8 +5663,66 @@ out:
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
{
/* Currently BlockDriverState always uses the main loop AioContext */
return qemu_get_aio_context();
return bs->aio_context;
}
void bdrv_detach_aio_context(BlockDriverState *bs)
{
if (!bs->drv) {
return;
}
if (bs->io_limits_enabled) {
throttle_detach_aio_context(&bs->throttle_state);
}
if (bs->drv->bdrv_detach_aio_context) {
bs->drv->bdrv_detach_aio_context(bs);
}
if (bs->file) {
bdrv_detach_aio_context(bs->file);
}
if (bs->backing_hd) {
bdrv_detach_aio_context(bs->backing_hd);
}
bs->aio_context = NULL;
}
void bdrv_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
if (!bs->drv) {
return;
}
bs->aio_context = new_context;
if (bs->backing_hd) {
bdrv_attach_aio_context(bs->backing_hd, new_context);
}
if (bs->file) {
bdrv_attach_aio_context(bs->file, new_context);
}
if (bs->drv->bdrv_attach_aio_context) {
bs->drv->bdrv_attach_aio_context(bs, new_context);
}
if (bs->io_limits_enabled) {
throttle_attach_aio_context(&bs->throttle_state, new_context);
}
}
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
{
bdrv_drain_all(); /* ensure there are no in-flight requests */
bdrv_detach_aio_context(bs);
/* This function executes in the old AioContext so acquire the new one in
* case it runs in a different thread.
*/
aio_context_acquire(new_context);
bdrv_attach_aio_context(bs, new_context);
aio_context_release(new_context);
}
void bdrv_add_before_write_notifier(BlockDriverState *bs,

View File

@@ -471,7 +471,7 @@ static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque);
acb->ret = -error;
bh = qemu_bh_new(error_callback_bh, acb);
bh = aio_bh_new(bdrv_get_aio_context(bs), error_callback_bh, acb);
acb->bh = bh;
qemu_bh_schedule(bh);

View File

@@ -39,12 +39,13 @@ struct BlkverifyAIOCB {
static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb)
{
BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb;
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
bool finished = false;
/* Wait until request completes, invokes its callback, and frees itself */
acb->finished = &finished;
while (!finished) {
qemu_aio_wait();
aio_poll(aio_context, true);
}
}
@@ -228,7 +229,8 @@ static void blkverify_aio_cb(void *opaque, int ret)
acb->verify(acb);
}
acb->bh = qemu_bh_new(blkverify_aio_bh, acb);
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
blkverify_aio_bh, acb);
qemu_bh_schedule(acb->bh);
break;
}
@@ -302,6 +304,22 @@ static bool blkverify_recurse_is_first_non_filter(BlockDriverState *bs,
return bdrv_recurse_is_first_non_filter(s->test_file, candidate);
}
/* Propagate AioContext changes to ->test_file */
static void blkverify_detach_aio_context(BlockDriverState *bs)
{
BDRVBlkverifyState *s = bs->opaque;
bdrv_detach_aio_context(s->test_file);
}
static void blkverify_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVBlkverifyState *s = bs->opaque;
bdrv_attach_aio_context(s->test_file, new_context);
}
static BlockDriver bdrv_blkverify = {
.format_name = "blkverify",
.protocol_name = "blkverify",
@@ -316,6 +334,9 @@ static BlockDriver bdrv_blkverify = {
.bdrv_aio_writev = blkverify_aio_writev,
.bdrv_aio_flush = blkverify_aio_flush,
.bdrv_attach_aio_context = blkverify_attach_aio_context,
.bdrv_detach_aio_context = blkverify_detach_aio_context,
.is_filter = true,
.bdrv_recurse_is_first_non_filter = blkverify_recurse_is_first_non_filter,
};

View File

@@ -110,6 +110,7 @@ typedef struct BDRVCURLState {
size_t readahead_size;
bool sslverify;
bool accept_range;
AioContext *aio_context;
} BDRVCURLState;
static void curl_clean_state(CURLState *s);
@@ -134,25 +135,29 @@ static int curl_timer_cb(CURLM *multi, long timeout_ms, void *opaque)
#endif
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
void *s, void *sp)
void *userp, void *sp)
{
BDRVCURLState *s;
CURLState *state = NULL;
curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state);
state->sock_fd = fd;
s = state->s;
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
switch (action) {
case CURL_POLL_IN:
qemu_aio_set_fd_handler(fd, curl_multi_read, NULL, state);
aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
NULL, state);
break;
case CURL_POLL_OUT:
qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, state);
aio_set_fd_handler(s->aio_context, fd, NULL, curl_multi_do, state);
break;
case CURL_POLL_INOUT:
qemu_aio_set_fd_handler(fd, curl_multi_read, curl_multi_do, state);
aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
curl_multi_do, state);
break;
case CURL_POLL_REMOVE:
qemu_aio_set_fd_handler(fd, NULL, NULL, NULL);
aio_set_fd_handler(s->aio_context, fd, NULL, NULL, NULL);
break;
}
@@ -365,7 +370,7 @@ static CURLState *curl_init_state(BDRVCURLState *s)
break;
}
if (!state) {
qemu_aio_wait();
aio_poll(state->s->aio_context, true);
}
} while(!state);
@@ -422,6 +427,51 @@ static void curl_parse_filename(const char *filename, QDict *options,
qdict_put(options, CURL_BLOCK_OPT_URL, qstring_from_str(filename));
}
static void curl_detach_aio_context(BlockDriverState *bs)
{
BDRVCURLState *s = bs->opaque;
int i;
for (i = 0; i < CURL_NUM_STATES; i++) {
if (s->states[i].in_use) {
curl_clean_state(&s->states[i]);
}
if (s->states[i].curl) {
curl_easy_cleanup(s->states[i].curl);
s->states[i].curl = NULL;
}
if (s->states[i].orig_buf) {
g_free(s->states[i].orig_buf);
s->states[i].orig_buf = NULL;
}
}
if (s->multi) {
curl_multi_cleanup(s->multi);
s->multi = NULL;
}
timer_del(&s->timer);
}
static void curl_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVCURLState *s = bs->opaque;
aio_timer_init(new_context, &s->timer,
QEMU_CLOCK_REALTIME, SCALE_NS,
curl_multi_timeout_do, s);
assert(!s->multi);
s->multi = curl_multi_init();
s->aio_context = new_context;
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
#ifdef NEED_CURL_TIMER_CALLBACK
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
#endif
}
static QemuOptsList runtime_opts = {
.name = "curl",
.head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
@@ -491,6 +541,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
}
DPRINTF("CURL: Opening %s\n", file);
s->aio_context = bdrv_get_aio_context(bs);
s->url = g_strdup(file);
state = curl_init_state(s);
if (!state)
@@ -523,19 +574,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
curl_easy_cleanup(state->curl);
state->curl = NULL;
aio_timer_init(bdrv_get_aio_context(bs), &s->timer,
QEMU_CLOCK_REALTIME, SCALE_NS,
curl_multi_timeout_do, s);
// Now we know the file exists and its size, so let's
// initialize the multi interface!
s->multi = curl_multi_init();
curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb);
#ifdef NEED_CURL_TIMER_CALLBACK
curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s);
curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb);
#endif
curl_attach_aio_context(bs, bdrv_get_aio_context(bs));
qemu_opts_del(opts);
return 0;
@@ -630,7 +669,7 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
acb->sector_num = sector_num;
acb->nb_sectors = nb_sectors;
acb->bh = qemu_bh_new(curl_readv_bh_cb, acb);
acb->bh = aio_bh_new(bdrv_get_aio_context(bs), curl_readv_bh_cb, acb);
qemu_bh_schedule(acb->bh);
return &acb->common;
}
@@ -638,25 +677,9 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
static void curl_close(BlockDriverState *bs)
{
BDRVCURLState *s = bs->opaque;
int i;
DPRINTF("CURL: Close\n");
for (i=0; i<CURL_NUM_STATES; i++) {
if (s->states[i].in_use)
curl_clean_state(&s->states[i]);
if (s->states[i].curl) {
curl_easy_cleanup(s->states[i].curl);
s->states[i].curl = NULL;
}
if (s->states[i].orig_buf) {
g_free(s->states[i].orig_buf);
s->states[i].orig_buf = NULL;
}
}
if (s->multi)
curl_multi_cleanup(s->multi);
timer_del(&s->timer);
curl_detach_aio_context(bs);
g_free(s->url);
}
@@ -678,6 +701,9 @@ static BlockDriver bdrv_http = {
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
};
static BlockDriver bdrv_https = {
@@ -691,6 +717,9 @@ static BlockDriver bdrv_https = {
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
};
static BlockDriver bdrv_ftp = {
@@ -704,6 +733,9 @@ static BlockDriver bdrv_ftp = {
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
};
static BlockDriver bdrv_ftps = {
@@ -717,6 +749,9 @@ static BlockDriver bdrv_ftps = {
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
};
static BlockDriver bdrv_tftp = {
@@ -730,6 +765,9 @@ static BlockDriver bdrv_tftp = {
.bdrv_getlength = curl_getlength,
.bdrv_aio_readv = curl_aio_readv,
.bdrv_detach_aio_context = curl_detach_aio_context,
.bdrv_attach_aio_context = curl_attach_aio_context,
};
static void curl_block_init(void)

View File

@@ -16,6 +16,7 @@ typedef struct GlusterAIOCB {
int ret;
QEMUBH *bh;
Coroutine *coroutine;
AioContext *aio_context;
} GlusterAIOCB;
typedef struct BDRVGlusterState {
@@ -249,7 +250,7 @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
acb->ret = -EIO; /* Partial read/write - fail it */
}
acb->bh = qemu_bh_new(qemu_gluster_complete_aio, acb);
acb->bh = aio_bh_new(acb->aio_context, qemu_gluster_complete_aio, acb);
qemu_bh_schedule(acb->bh);
}
@@ -436,6 +437,7 @@ static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs,
acb->size = size;
acb->ret = 0;
acb->coroutine = qemu_coroutine_self();
acb->aio_context = bdrv_get_aio_context(bs);
ret = glfs_zerofill_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
if (ret < 0) {
@@ -549,6 +551,7 @@ static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
acb->size = size;
acb->ret = 0;
acb->coroutine = qemu_coroutine_self();
acb->aio_context = bdrv_get_aio_context(bs);
if (write) {
ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
@@ -605,6 +608,7 @@ static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
acb->size = 0;
acb->ret = 0;
acb->coroutine = qemu_coroutine_self();
acb->aio_context = bdrv_get_aio_context(bs);
ret = glfs_fsync_async(s->fd, &gluster_finish_aiocb, acb);
if (ret < 0) {
@@ -633,6 +637,7 @@ static coroutine_fn int qemu_gluster_co_discard(BlockDriverState *bs,
acb->size = 0;
acb->ret = 0;
acb->coroutine = qemu_coroutine_self();
acb->aio_context = bdrv_get_aio_context(bs);
ret = glfs_discard_async(s->fd, offset, size, &gluster_finish_aiocb, acb);
if (ret < 0) {

View File

@@ -49,6 +49,7 @@
typedef struct IscsiLun {
struct iscsi_context *iscsi;
AioContext *aio_context;
int lun;
enum scsi_inquiry_peripheral_device_type type;
int block_size;
@@ -73,6 +74,7 @@ typedef struct IscsiTask {
struct scsi_task *task;
Coroutine *co;
QEMUBH *bh;
IscsiLun *iscsilun;
} IscsiTask;
typedef struct IscsiAIOCB {
@@ -133,7 +135,7 @@ iscsi_schedule_bh(IscsiAIOCB *acb)
if (acb->bh) {
return;
}
acb->bh = qemu_bh_new(iscsi_bh_cb, acb);
acb->bh = aio_bh_new(acb->iscsilun->aio_context, iscsi_bh_cb, acb);
qemu_bh_schedule(acb->bh);
}
@@ -169,7 +171,8 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status,
out:
if (iTask->co) {
iTask->bh = qemu_bh_new(iscsi_co_generic_bh_cb, iTask);
iTask->bh = aio_bh_new(iTask->iscsilun->aio_context,
iscsi_co_generic_bh_cb, iTask);
qemu_bh_schedule(iTask->bh);
}
}
@@ -179,6 +182,7 @@ static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask)
*iTask = (struct IscsiTask) {
.co = qemu_coroutine_self(),
.retries = ISCSI_CMD_RETRIES,
.iscsilun = iscsilun,
};
}
@@ -209,7 +213,7 @@ iscsi_aio_cancel(BlockDriverAIOCB *blockacb)
iscsi_abort_task_cb, acb);
while (acb->status == -EINPROGRESS) {
qemu_aio_wait();
aio_poll(iscsilun->aio_context, true);
}
}
@@ -232,7 +236,8 @@ iscsi_set_events(IscsiLun *iscsilun)
ev = POLLIN;
ev |= iscsi_which_events(iscsi);
if (ev != iscsilun->events) {
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi),
aio_set_fd_handler(iscsilun->aio_context,
iscsi_get_fd(iscsi),
iscsi_process_read,
(ev & POLLOUT) ? iscsi_process_write : NULL,
iscsilun);
@@ -791,7 +796,7 @@ static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status);
while (status == -EINPROGRESS) {
qemu_aio_wait();
aio_poll(iscsilun->aio_context, true);
}
return 0;
@@ -1195,6 +1200,40 @@ fail_with_err:
return NULL;
}
static void iscsi_detach_aio_context(BlockDriverState *bs)
{
IscsiLun *iscsilun = bs->opaque;
aio_set_fd_handler(iscsilun->aio_context,
iscsi_get_fd(iscsilun->iscsi),
NULL, NULL, NULL);
iscsilun->events = 0;
if (iscsilun->nop_timer) {
timer_del(iscsilun->nop_timer);
timer_free(iscsilun->nop_timer);
iscsilun->nop_timer = NULL;
}
}
static void iscsi_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
IscsiLun *iscsilun = bs->opaque;
iscsilun->aio_context = new_context;
iscsi_set_events(iscsilun);
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
/* Set up a timer for sending out iSCSI NOPs */
iscsilun->nop_timer = aio_timer_new(iscsilun->aio_context,
QEMU_CLOCK_REALTIME, SCALE_MS,
iscsi_nop_timed_event, iscsilun);
timer_mod(iscsilun->nop_timer,
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
#endif
}
/*
* We support iscsi url's on the form
* iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
@@ -1301,6 +1340,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
}
iscsilun->iscsi = iscsi;
iscsilun->aio_context = bdrv_get_aio_context(bs);
iscsilun->lun = iscsi_url->lun;
iscsilun->has_write_same = true;
@@ -1374,11 +1414,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
scsi_free_scsi_task(task);
task = NULL;
#if defined(LIBISCSI_FEATURE_NOP_COUNTER)
/* Set up a timer for sending out iSCSI NOPs */
iscsilun->nop_timer = timer_new_ms(QEMU_CLOCK_REALTIME, iscsi_nop_timed_event, iscsilun);
timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
#endif
iscsi_attach_aio_context(bs, iscsilun->aio_context);
/* Guess the internal cluster (page) size of the iscsi target by the means
* of opt_unmap_gran. Transfer the unmap granularity only if it has a
@@ -1422,11 +1458,7 @@ static void iscsi_close(BlockDriverState *bs)
IscsiLun *iscsilun = bs->opaque;
struct iscsi_context *iscsi = iscsilun->iscsi;
if (iscsilun->nop_timer) {
timer_del(iscsilun->nop_timer);
timer_free(iscsilun->nop_timer);
}
qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL);
iscsi_detach_aio_context(bs);
iscsi_destroy_context(iscsi);
g_free(iscsilun->zeroblock);
g_free(iscsilun->allocationmap);
@@ -1530,10 +1562,7 @@ static int iscsi_create(const char *filename, QEMUOptionParameter *options,
if (ret != 0) {
goto out;
}
if (iscsilun->nop_timer) {
timer_del(iscsilun->nop_timer);
timer_free(iscsilun->nop_timer);
}
iscsi_detach_aio_context(bs);
if (iscsilun->type != TYPE_DISK) {
ret = -ENODEV;
goto out;
@@ -1604,6 +1633,9 @@ static BlockDriver bdrv_iscsi = {
.bdrv_ioctl = iscsi_ioctl,
.bdrv_aio_ioctl = iscsi_aio_ioctl,
#endif
.bdrv_detach_aio_context = iscsi_detach_aio_context,
.bdrv_attach_aio_context = iscsi_attach_aio_context,
};
static QemuOptsList qemu_iscsi_opts = {

View File

@@ -177,6 +177,20 @@ out_free_aiocb:
return NULL;
}
void laio_detach_aio_context(void *s_, AioContext *old_context)
{
struct qemu_laio_state *s = s_;
aio_set_event_notifier(old_context, &s->e, NULL);
}
void laio_attach_aio_context(void *s_, AioContext *new_context)
{
struct qemu_laio_state *s = s_;
aio_set_event_notifier(new_context, &s->e, qemu_laio_completion_cb);
}
void *laio_init(void)
{
struct qemu_laio_state *s;
@@ -190,8 +204,6 @@ void *laio_init(void)
goto out_close_efd;
}
qemu_aio_set_event_notifier(&s->e, qemu_laio_completion_cb);
return s;
out_close_efd:
@@ -200,3 +212,11 @@ out_free_state:
g_free(s);
return NULL;
}
void laio_cleanup(void *s_)
{
struct qemu_laio_state *s = s_;
event_notifier_cleanup(&s->e);
g_free(s);
}

View File

@@ -49,7 +49,7 @@ static void nbd_teardown_connection(NbdClientSession *client)
shutdown(client->sock, 2);
nbd_recv_coroutines_enter_all(client);
qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL);
nbd_client_session_detach_aio_context(client);
closesocket(client->sock);
client->sock = -1;
}
@@ -103,11 +103,14 @@ static int nbd_co_send_request(NbdClientSession *s,
struct nbd_request *request,
QEMUIOVector *qiov, int offset)
{
AioContext *aio_context;
int rc, ret;
qemu_co_mutex_lock(&s->send_mutex);
s->send_coroutine = qemu_coroutine_self();
qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, s);
aio_context = bdrv_get_aio_context(s->bs);
aio_set_fd_handler(aio_context, s->sock,
nbd_reply_ready, nbd_restart_write, s);
if (qiov) {
if (!s->is_unix) {
socket_set_cork(s->sock, 1);
@@ -126,7 +129,7 @@ static int nbd_co_send_request(NbdClientSession *s,
} else {
rc = nbd_send_request(s->sock, request);
}
qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, s);
aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, s);
s->send_coroutine = NULL;
qemu_co_mutex_unlock(&s->send_mutex);
return rc;
@@ -335,6 +338,19 @@ int nbd_client_session_co_discard(NbdClientSession *client, int64_t sector_num,
}
void nbd_client_session_detach_aio_context(NbdClientSession *client)
{
aio_set_fd_handler(bdrv_get_aio_context(client->bs), client->sock,
NULL, NULL, NULL);
}
void nbd_client_session_attach_aio_context(NbdClientSession *client,
AioContext *new_context)
{
aio_set_fd_handler(new_context, client->sock,
nbd_reply_ready, NULL, client);
}
void nbd_client_session_close(NbdClientSession *client)
{
struct nbd_request request = {
@@ -381,7 +397,7 @@ int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs,
/* Now that we're connected, set the socket to be non-blocking and
* kick the reply mechanism. */
qemu_set_nonblock(sock);
qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, client);
nbd_client_session_attach_aio_context(client, bdrv_get_aio_context(bs));
logout("Established connection with NBD server\n");
return 0;

View File

@@ -47,4 +47,8 @@ int nbd_client_session_co_writev(NbdClientSession *client, int64_t sector_num,
int nbd_client_session_co_readv(NbdClientSession *client, int64_t sector_num,
int nb_sectors, QEMUIOVector *qiov);
void nbd_client_session_detach_aio_context(NbdClientSession *client);
void nbd_client_session_attach_aio_context(NbdClientSession *client,
AioContext *new_context);
#endif /* NBD_CLIENT_H */

View File

@@ -323,6 +323,21 @@ static int64_t nbd_getlength(BlockDriverState *bs)
return s->client.size;
}
static void nbd_detach_aio_context(BlockDriverState *bs)
{
BDRVNBDState *s = bs->opaque;
nbd_client_session_detach_aio_context(&s->client);
}
static void nbd_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVNBDState *s = bs->opaque;
nbd_client_session_attach_aio_context(&s->client, new_context);
}
static BlockDriver bdrv_nbd = {
.format_name = "nbd",
.protocol_name = "nbd",
@@ -335,6 +350,8 @@ static BlockDriver bdrv_nbd = {
.bdrv_co_flush_to_os = nbd_co_flush,
.bdrv_co_discard = nbd_co_discard,
.bdrv_getlength = nbd_getlength,
.bdrv_detach_aio_context = nbd_detach_aio_context,
.bdrv_attach_aio_context = nbd_attach_aio_context,
};
static BlockDriver bdrv_nbd_tcp = {
@@ -349,6 +366,8 @@ static BlockDriver bdrv_nbd_tcp = {
.bdrv_co_flush_to_os = nbd_co_flush,
.bdrv_co_discard = nbd_co_discard,
.bdrv_getlength = nbd_getlength,
.bdrv_detach_aio_context = nbd_detach_aio_context,
.bdrv_attach_aio_context = nbd_attach_aio_context,
};
static BlockDriver bdrv_nbd_unix = {
@@ -363,6 +382,8 @@ static BlockDriver bdrv_nbd_unix = {
.bdrv_co_flush_to_os = nbd_co_flush,
.bdrv_co_discard = nbd_co_discard,
.bdrv_getlength = nbd_getlength,
.bdrv_detach_aio_context = nbd_detach_aio_context,
.bdrv_attach_aio_context = nbd_attach_aio_context,
};
static void bdrv_nbd_init(void)

View File

@@ -40,6 +40,7 @@ typedef struct NFSClient {
struct nfsfh *fh;
int events;
bool has_zero_init;
AioContext *aio_context;
} NFSClient;
typedef struct NFSRPC {
@@ -49,6 +50,7 @@ typedef struct NFSRPC {
struct stat *st;
Coroutine *co;
QEMUBH *bh;
NFSClient *client;
} NFSRPC;
static void nfs_process_read(void *arg);
@@ -58,7 +60,8 @@ static void nfs_set_events(NFSClient *client)
{
int ev = nfs_which_events(client->context);
if (ev != client->events) {
qemu_aio_set_fd_handler(nfs_get_fd(client->context),
aio_set_fd_handler(client->aio_context,
nfs_get_fd(client->context),
(ev & POLLIN) ? nfs_process_read : NULL,
(ev & POLLOUT) ? nfs_process_write : NULL,
client);
@@ -85,6 +88,7 @@ static void nfs_co_init_task(NFSClient *client, NFSRPC *task)
{
*task = (NFSRPC) {
.co = qemu_coroutine_self(),
.client = client,
};
}
@@ -116,7 +120,8 @@ nfs_co_generic_cb(int ret, struct nfs_context *nfs, void *data,
error_report("NFS Error: %s", nfs_get_error(nfs));
}
if (task->co) {
task->bh = qemu_bh_new(nfs_co_generic_bh_cb, task);
task->bh = aio_bh_new(task->client->aio_context,
nfs_co_generic_bh_cb, task);
qemu_bh_schedule(task->bh);
}
}
@@ -224,13 +229,34 @@ static QemuOptsList runtime_opts = {
},
};
static void nfs_detach_aio_context(BlockDriverState *bs)
{
NFSClient *client = bs->opaque;
aio_set_fd_handler(client->aio_context,
nfs_get_fd(client->context),
NULL, NULL, NULL);
client->events = 0;
}
static void nfs_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
NFSClient *client = bs->opaque;
client->aio_context = new_context;
nfs_set_events(client);
}
static void nfs_client_close(NFSClient *client)
{
if (client->context) {
if (client->fh) {
nfs_close(client->context, client->fh);
}
qemu_aio_set_fd_handler(nfs_get_fd(client->context), NULL, NULL, NULL);
aio_set_fd_handler(client->aio_context,
nfs_get_fd(client->context),
NULL, NULL, NULL);
nfs_destroy_context(client->context);
}
memset(client, 0, sizeof(NFSClient));
@@ -345,6 +371,8 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
QemuOpts *opts;
Error *local_err = NULL;
client->aio_context = bdrv_get_aio_context(bs);
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) {
@@ -368,6 +396,8 @@ static int nfs_file_create(const char *url, QEMUOptionParameter *options,
int64_t total_size = 0;
NFSClient *client = g_malloc0(sizeof(NFSClient));
client->aio_context = qemu_get_aio_context();
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, "size")) {
@@ -407,7 +437,7 @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
while (!task.complete) {
nfs_set_events(client);
qemu_aio_wait();
aio_poll(client->aio_context, true);
}
return (task.ret < 0 ? task.ret : st.st_blocks * st.st_blksize);
@@ -436,6 +466,9 @@ static BlockDriver bdrv_nfs = {
.bdrv_co_readv = nfs_co_readv,
.bdrv_co_writev = nfs_co_writev,
.bdrv_co_flush_to_disk = nfs_co_flush,
.bdrv_detach_aio_context = nfs_detach_aio_context,
.bdrv_attach_aio_context = nfs_attach_aio_context,
};
static void nfs_block_init(void)

View File

@@ -173,7 +173,7 @@ int qed_read_l1_table_sync(BDRVQEDState *s)
qed_read_table(s, s->header.l1_table_offset,
s->l1_table, qed_sync_cb, &ret);
while (ret == -EINPROGRESS) {
qemu_aio_wait();
aio_poll(bdrv_get_aio_context(s->bs), true);
}
return ret;
@@ -194,7 +194,7 @@ int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index,
qed_write_l1_table(s, index, n, qed_sync_cb, &ret);
while (ret == -EINPROGRESS) {
qemu_aio_wait();
aio_poll(bdrv_get_aio_context(s->bs), true);
}
return ret;
@@ -267,7 +267,7 @@ int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset
qed_read_l2_table(s, request, offset, qed_sync_cb, &ret);
while (ret == -EINPROGRESS) {
qemu_aio_wait();
aio_poll(bdrv_get_aio_context(s->bs), true);
}
return ret;
@@ -289,7 +289,7 @@ int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request,
qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret);
while (ret == -EINPROGRESS) {
qemu_aio_wait();
aio_poll(bdrv_get_aio_context(s->bs), true);
}
return ret;

View File

@@ -21,12 +21,13 @@
static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
{
QEDAIOCB *acb = (QEDAIOCB *)blockacb;
AioContext *aio_context = bdrv_get_aio_context(blockacb->bs);
bool finished = false;
/* Wait for the request to finish */
acb->finished = &finished;
while (!finished) {
qemu_aio_wait();
aio_poll(aio_context, true);
}
}
@@ -373,6 +374,27 @@ static void bdrv_qed_rebind(BlockDriverState *bs)
s->bs = bs;
}
static void bdrv_qed_detach_aio_context(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
qed_cancel_need_check_timer(s);
timer_free(s->need_check_timer);
}
static void bdrv_qed_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVQEDState *s = bs->opaque;
s->need_check_timer = aio_timer_new(new_context,
QEMU_CLOCK_VIRTUAL, SCALE_NS,
qed_need_check_timer_cb, s);
if (s->header.features & QED_F_NEED_CHECK) {
qed_start_need_check_timer(s);
}
}
static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
@@ -496,8 +518,7 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
}
}
s->need_check_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
qed_need_check_timer_cb, s);
bdrv_qed_attach_aio_context(bs, bdrv_get_aio_context(bs));
out:
if (ret) {
@@ -528,8 +549,7 @@ static void bdrv_qed_close(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
qed_cancel_need_check_timer(s);
timer_free(s->need_check_timer);
bdrv_qed_detach_aio_context(bs);
/* Ensure writes reach stable storage */
bdrv_flush(bs->file);
@@ -919,7 +939,8 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
/* Arrange for a bh to invoke the completion function */
acb->bh_ret = ret;
acb->bh = qemu_bh_new(qed_aio_complete_bh, acb);
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
qed_aio_complete_bh, acb);
qemu_bh_schedule(acb->bh);
/* Start next allocating write request waiting behind this one. Note that
@@ -1644,6 +1665,8 @@ static BlockDriver bdrv_qed = {
.bdrv_change_backing_file = bdrv_qed_change_backing_file,
.bdrv_invalidate_cache = bdrv_qed_invalidate_cache,
.bdrv_check = bdrv_qed_check,
.bdrv_detach_aio_context = bdrv_qed_detach_aio_context,
.bdrv_attach_aio_context = bdrv_qed_attach_aio_context,
};
static void bdrv_qed_init(void)

View File

@@ -848,6 +848,27 @@ static void quorum_close(BlockDriverState *bs)
g_free(s->bs);
}
static void quorum_detach_aio_context(BlockDriverState *bs)
{
BDRVQuorumState *s = bs->opaque;
int i;
for (i = 0; i < s->num_children; i++) {
bdrv_detach_aio_context(s->bs[i]);
}
}
static void quorum_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVQuorumState *s = bs->opaque;
int i;
for (i = 0; i < s->num_children; i++) {
bdrv_attach_aio_context(s->bs[i], new_context);
}
}
static BlockDriver bdrv_quorum = {
.format_name = "quorum",
.protocol_name = "quorum",
@@ -865,6 +886,9 @@ static BlockDriver bdrv_quorum = {
.bdrv_aio_writev = quorum_aio_writev,
.bdrv_invalidate_cache = quorum_invalidate_cache,
.bdrv_detach_aio_context = quorum_detach_aio_context,
.bdrv_attach_aio_context = quorum_attach_aio_context,
.is_filter = true,
.bdrv_recurse_is_first_non_filter = quorum_recurse_is_first_non_filter,
};

View File

@@ -34,19 +34,27 @@
/* linux-aio.c - Linux native implementation */
#ifdef CONFIG_LINUX_AIO
void *laio_init(void);
void laio_cleanup(void *s);
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);
void laio_detach_aio_context(void *s, AioContext *old_context);
void laio_attach_aio_context(void *s, AioContext *new_context);
#endif
#ifdef _WIN32
typedef struct QEMUWin32AIOState QEMUWin32AIOState;
QEMUWin32AIOState *win32_aio_init(void);
void win32_aio_cleanup(QEMUWin32AIOState *aio);
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);
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
AioContext *old_context);
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
AioContext *new_context);
#endif
#endif /* QEMU_RAW_AIO_H */

View File

@@ -307,6 +307,29 @@ static void raw_parse_flags(int bdrv_flags, int *open_flags)
}
}
static void raw_detach_aio_context(BlockDriverState *bs)
{
#ifdef CONFIG_LINUX_AIO
BDRVRawState *s = bs->opaque;
if (s->use_aio) {
laio_detach_aio_context(s->aio_ctx, bdrv_get_aio_context(bs));
}
#endif
}
static void raw_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
#ifdef CONFIG_LINUX_AIO
BDRVRawState *s = bs->opaque;
if (s->use_aio) {
laio_attach_aio_context(s->aio_ctx, new_context);
}
#endif
}
#ifdef CONFIG_LINUX_AIO
static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags)
{
@@ -447,6 +470,8 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
}
#endif
raw_attach_aio_context(bs, bdrv_get_aio_context(bs));
ret = 0;
fail:
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
@@ -1059,6 +1084,14 @@ static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
static void raw_close(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
raw_detach_aio_context(bs);
#ifdef CONFIG_LINUX_AIO
if (s->use_aio) {
laio_cleanup(s->aio_ctx);
}
#endif
if (s->fd >= 0) {
qemu_close(s->fd);
s->fd = -1;
@@ -1478,6 +1511,9 @@ static BlockDriver bdrv_file = {
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
.bdrv_detach_aio_context = raw_detach_aio_context,
.bdrv_attach_aio_context = raw_attach_aio_context,
.create_options = raw_create_options,
};
@@ -1878,6 +1914,9 @@ static BlockDriver bdrv_host_device = {
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
.bdrv_detach_aio_context = raw_detach_aio_context,
.bdrv_attach_aio_context = raw_attach_aio_context,
/* generic scsi device */
#ifdef __linux__
.bdrv_ioctl = hdev_ioctl,
@@ -2020,6 +2059,9 @@ static BlockDriver bdrv_host_floppy = {
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
.bdrv_detach_aio_context = raw_detach_aio_context,
.bdrv_attach_aio_context = raw_attach_aio_context,
/* removable device support */
.bdrv_is_inserted = floppy_is_inserted,
.bdrv_media_changed = floppy_media_changed,
@@ -2145,6 +2187,9 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
.bdrv_detach_aio_context = raw_detach_aio_context,
.bdrv_attach_aio_context = raw_attach_aio_context,
/* removable device support */
.bdrv_is_inserted = cdrom_is_inserted,
.bdrv_eject = cdrom_eject,
@@ -2276,6 +2321,9 @@ static BlockDriver bdrv_host_cdrom = {
.bdrv_get_allocated_file_size
= raw_get_allocated_file_size,
.bdrv_detach_aio_context = raw_detach_aio_context,
.bdrv_attach_aio_context = raw_attach_aio_context,
/* removable device support */
.bdrv_is_inserted = cdrom_is_inserted,
.bdrv_eject = cdrom_eject,
@@ -2283,40 +2331,6 @@ static BlockDriver bdrv_host_cdrom = {
};
#endif /* __FreeBSD__ */
#ifdef CONFIG_LINUX_AIO
/**
* Return the file descriptor for Linux AIO
*
* This function is a layering violation and should be removed when it becomes
* possible to call the block layer outside the global mutex. It allows the
* caller to hijack the file descriptor so I/O can be performed outside the
* block layer.
*/
int raw_get_aio_fd(BlockDriverState *bs)
{
BDRVRawState *s;
if (!bs->drv) {
return -ENOMEDIUM;
}
if (bs->drv == bdrv_find_format("raw")) {
bs = bs->file;
}
/* raw-posix has several protocols so just check for raw_aio_readv */
if (bs->drv->bdrv_aio_readv != raw_aio_readv) {
return -ENOTSUP;
}
s = bs->opaque;
if (!s->use_aio) {
return -ENOTSUP;
}
return s->fd;
}
#endif /* CONFIG_LINUX_AIO */
static void bdrv_file_init(void)
{
/*

View File

@@ -36,8 +36,6 @@
#define FTYPE_CD 1
#define FTYPE_HARDDISK 2
static QEMUWin32AIOState *aio;
typedef struct RawWin32AIOData {
BlockDriverState *bs;
HANDLE hfile;
@@ -202,6 +200,25 @@ static int set_sparse(int fd)
NULL, 0, NULL, 0, &returned, NULL);
}
static void raw_detach_aio_context(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
if (s->aio) {
win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
}
}
static void raw_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVRawState *s = bs->opaque;
if (s->aio) {
win32_aio_attach_aio_context(s->aio, new_context);
}
}
static void raw_probe_alignment(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
@@ -300,15 +317,6 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
raw_parse_flags(flags, &access_flags, &overlapped);
if ((flags & BDRV_O_NATIVE_AIO) && aio == NULL) {
aio = win32_aio_init();
if (aio == NULL) {
error_setg(errp, "Could not initialize AIO");
ret = -EINVAL;
goto fail;
}
}
if (filename[0] && filename[1] == ':') {
snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]);
} else if (filename[0] == '\\' && filename[1] == '\\') {
@@ -335,13 +343,23 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
}
if (flags & BDRV_O_NATIVE_AIO) {
ret = win32_aio_attach(aio, s->hfile);
s->aio = win32_aio_init();
if (s->aio == NULL) {
CloseHandle(s->hfile);
error_setg(errp, "Could not initialize AIO");
ret = -EINVAL;
goto fail;
}
ret = win32_aio_attach(s->aio, s->hfile);
if (ret < 0) {
win32_aio_cleanup(s->aio);
CloseHandle(s->hfile);
error_setg_errno(errp, -ret, "Could not enable AIO");
goto fail;
}
s->aio = aio;
win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs));
}
raw_probe_alignment(bs);
@@ -389,6 +407,13 @@ static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
static void raw_close(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
if (s->aio) {
win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs));
win32_aio_cleanup(s->aio);
s->aio = NULL;
}
CloseHandle(s->hfile);
if (bs->open_flags & BDRV_O_TEMPORARY) {
unlink(bs->filename);
@@ -684,6 +709,9 @@ static BlockDriver bdrv_host_device = {
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_detach_aio_context = raw_detach_aio_context,
.bdrv_attach_aio_context = raw_attach_aio_context,
.bdrv_getlength = raw_getlength,
.has_variable_length = true,

View File

@@ -555,7 +555,7 @@ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb)
acb->cancelled = 1;
while (acb->status == -EINPROGRESS) {
qemu_aio_wait();
aio_poll(bdrv_get_aio_context(acb->common.bs), true);
}
qemu_aio_release(acb);
@@ -588,7 +588,8 @@ static void rbd_finish_aiocb(rbd_completion_t c, RADOSCB *rcb)
rcb->ret = rbd_aio_get_return_value(c);
rbd_aio_release(c);
acb->bh = qemu_bh_new(rbd_finish_bh, rcb);
acb->bh = aio_bh_new(bdrv_get_aio_context(acb->common.bs),
rbd_finish_bh, rcb);
qemu_bh_schedule(acb->bh);
}
@@ -684,13 +685,16 @@ static BlockDriverAIOCB *rbd_start_aio(BlockDriverState *bs,
}
if (r < 0) {
goto failed;
goto failed_completion;
}
return &acb->common;
failed_completion:
rbd_aio_release(c);
failed:
g_free(rcb);
qemu_vfree(acb->bounce);
qemu_aio_release(acb);
return NULL;
}

View File

@@ -200,6 +200,8 @@ typedef struct SheepdogInode {
uint32_t data_vdi_id[MAX_DATA_OBJS];
} SheepdogInode;
#define SD_INODE_HEADER_SIZE offsetof(SheepdogInode, data_vdi_id)
/*
* 64 bit FNV-1a non-zero initial basis
*/
@@ -282,6 +284,7 @@ typedef struct AIOReq {
unsigned int data_len;
uint8_t flags;
uint32_t id;
bool create;
QLIST_ENTRY(AIOReq) aio_siblings;
} AIOReq;
@@ -314,6 +317,7 @@ struct SheepdogAIOCB {
typedef struct BDRVSheepdogState {
BlockDriverState *bs;
AioContext *aio_context;
SheepdogInode inode;
@@ -404,7 +408,7 @@ static const char * sd_strerror(int err)
static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
uint64_t oid, unsigned int data_len,
uint64_t offset, uint8_t flags,
uint64_t offset, uint8_t flags, bool create,
uint64_t base_oid, unsigned int iov_offset)
{
AIOReq *aio_req;
@@ -418,6 +422,7 @@ static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
aio_req->data_len = data_len;
aio_req->flags = flags;
aio_req->id = s->aioreq_seq_num++;
aio_req->create = create;
acb->nr_pending++;
return aio_req;
@@ -496,7 +501,7 @@ static void sd_aio_cancel(BlockDriverAIOCB *blockacb)
sd_finish_aiocb(acb);
return;
}
qemu_aio_wait();
aio_poll(s->aio_context, true);
}
}
@@ -578,6 +583,7 @@ static void restart_co_req(void *opaque)
typedef struct SheepdogReqCo {
int sockfd;
AioContext *aio_context;
SheepdogReq *hdr;
void *data;
unsigned int *wlen;
@@ -598,14 +604,14 @@ static coroutine_fn void do_co_req(void *opaque)
unsigned int *rlen = srco->rlen;
co = qemu_coroutine_self();
qemu_aio_set_fd_handler(sockfd, NULL, restart_co_req, co);
aio_set_fd_handler(srco->aio_context, sockfd, NULL, restart_co_req, co);
ret = send_co_req(sockfd, hdr, data, wlen);
if (ret < 0) {
goto out;
}
qemu_aio_set_fd_handler(sockfd, restart_co_req, NULL, co);
aio_set_fd_handler(srco->aio_context, sockfd, restart_co_req, NULL, co);
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
if (ret != sizeof(*hdr)) {
@@ -630,18 +636,19 @@ static coroutine_fn void do_co_req(void *opaque)
out:
/* there is at most one request for this sockfd, so it is safe to
* set each handler to NULL. */
qemu_aio_set_fd_handler(sockfd, NULL, NULL, NULL);
aio_set_fd_handler(srco->aio_context, sockfd, NULL, NULL, NULL);
srco->ret = ret;
srco->finished = true;
}
static int do_req(int sockfd, SheepdogReq *hdr, void *data,
unsigned int *wlen, unsigned int *rlen)
static int do_req(int sockfd, AioContext *aio_context, SheepdogReq *hdr,
void *data, unsigned int *wlen, unsigned int *rlen)
{
Coroutine *co;
SheepdogReqCo srco = {
.sockfd = sockfd,
.aio_context = aio_context,
.hdr = hdr,
.data = data,
.wlen = wlen,
@@ -656,7 +663,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
co = qemu_coroutine_create(do_co_req);
qemu_coroutine_enter(co, &srco);
while (!srco.finished) {
qemu_aio_wait();
aio_poll(aio_context, true);
}
}
@@ -664,7 +671,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
}
static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
struct iovec *iov, int niov, bool create,
struct iovec *iov, int niov,
enum AIOCBState aiocb_type);
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req);
static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag);
@@ -698,7 +705,7 @@ static void coroutine_fn send_pending_req(BDRVSheepdogState *s, uint64_t oid)
/* move aio_req from pending list to inflight one */
QLIST_REMOVE(aio_req, aio_siblings);
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, false,
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
acb->aiocb_type);
}
}
@@ -709,7 +716,7 @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
BDRVSheepdogState *s = opaque;
AIOReq *aio_req, *next;
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
close(s->fd);
s->fd = -1;
@@ -797,7 +804,7 @@ static void coroutine_fn aio_read_response(void *opaque)
}
idx = data_oid_to_idx(aio_req->oid);
if (s->inode.data_vdi_id[idx] != s->inode.vdi_id) {
if (aio_req->create) {
/*
* If the object is newly created one, we need to update
* the vdi object (metadata object). min_dirty_data_idx
@@ -922,7 +929,7 @@ static int get_sheep_fd(BDRVSheepdogState *s, Error **errp)
return fd;
}
qemu_aio_set_fd_handler(fd, co_read_response, NULL, s);
aio_set_fd_handler(s->aio_context, fd, co_read_response, NULL, s);
return fd;
}
@@ -1092,7 +1099,7 @@ static int find_vdi_name(BDRVSheepdogState *s, const char *filename,
hdr.snapid = snapid;
hdr.flags = SD_FLAG_CMD_WRITE;
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
if (ret) {
error_setg_errno(errp, -ret, "cannot get vdi info");
goto out;
@@ -1117,7 +1124,7 @@ out:
}
static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
struct iovec *iov, int niov, bool create,
struct iovec *iov, int niov,
enum AIOCBState aiocb_type)
{
int nr_copies = s->inode.nr_copies;
@@ -1129,6 +1136,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
uint64_t offset = aio_req->offset;
uint8_t flags = aio_req->flags;
uint64_t old_oid = aio_req->base_oid;
bool create = aio_req->create;
if (!nr_copies) {
error_report("bug");
@@ -1173,7 +1181,8 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
qemu_co_mutex_lock(&s->lock);
s->co_send = qemu_coroutine_self();
qemu_aio_set_fd_handler(s->fd, co_read_response, co_write_request, s);
aio_set_fd_handler(s->aio_context, s->fd,
co_read_response, co_write_request, s);
socket_set_cork(s->fd, 1);
/* send a header */
@@ -1191,12 +1200,13 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
}
out:
socket_set_cork(s->fd, 0);
qemu_aio_set_fd_handler(s->fd, co_read_response, NULL, s);
aio_set_fd_handler(s->aio_context, s->fd, co_read_response, NULL, s);
s->co_send = NULL;
qemu_co_mutex_unlock(&s->lock);
}
static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
static int read_write_object(int fd, AioContext *aio_context, char *buf,
uint64_t oid, uint8_t copies,
unsigned int datalen, uint64_t offset,
bool write, bool create, uint32_t cache_flags)
{
@@ -1229,7 +1239,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
hdr.offset = offset;
hdr.copies = copies;
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
ret = do_req(fd, aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
if (ret) {
error_report("failed to send a request to the sheep");
return ret;
@@ -1244,19 +1254,23 @@ static int read_write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
}
}
static int read_object(int fd, char *buf, uint64_t oid, uint8_t copies,
static int read_object(int fd, AioContext *aio_context, char *buf,
uint64_t oid, uint8_t copies,
unsigned int datalen, uint64_t offset,
uint32_t cache_flags)
{
return read_write_object(fd, buf, oid, copies, datalen, offset, false,
return read_write_object(fd, aio_context, buf, oid, copies,
datalen, offset, false,
false, cache_flags);
}
static int write_object(int fd, char *buf, uint64_t oid, uint8_t copies,
static int write_object(int fd, AioContext *aio_context, char *buf,
uint64_t oid, uint8_t copies,
unsigned int datalen, uint64_t offset, bool create,
uint32_t cache_flags)
{
return read_write_object(fd, buf, oid, copies, datalen, offset, true,
return read_write_object(fd, aio_context, buf, oid, copies,
datalen, offset, true,
create, cache_flags);
}
@@ -1275,7 +1289,7 @@ static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag)
return -EIO;
}
inode = g_malloc(sizeof(s->inode));
inode = g_malloc(SD_INODE_HEADER_SIZE);
ret = find_vdi_name(s, s->name, snapid, tag, &vid, false, &local_err);
if (ret) {
@@ -1284,14 +1298,15 @@ static int reload_inode(BDRVSheepdogState *s, uint32_t snapid, const char *tag)
goto out;
}
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(vid),
s->inode.nr_copies, sizeof(*inode), 0, s->cache_flags);
ret = read_object(fd, s->aio_context, (char *)inode, vid_to_vdi_oid(vid),
s->inode.nr_copies, SD_INODE_HEADER_SIZE, 0,
s->cache_flags);
if (ret < 0) {
goto out;
}
if (inode->vdi_id != s->inode.vdi_id) {
memcpy(&s->inode, inode, sizeof(s->inode));
memcpy(&s->inode, inode, SD_INODE_HEADER_SIZE);
}
out:
@@ -1315,6 +1330,7 @@ static bool check_simultaneous_create(BDRVSheepdogState *s, AIOReq *aio_req)
DPRINTF("simultaneous create to %" PRIx64 "\n", aio_req->oid);
aio_req->flags = 0;
aio_req->base_oid = 0;
aio_req->create = false;
QLIST_REMOVE(aio_req, aio_siblings);
QLIST_INSERT_HEAD(&s->pending_aio_head, aio_req, aio_siblings);
return true;
@@ -1327,7 +1343,8 @@ static bool check_simultaneous_create(BDRVSheepdogState *s, AIOReq *aio_req)
static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
{
SheepdogAIOCB *acb = aio_req->aiocb;
bool create = false;
aio_req->create = false;
/* check whether this request becomes a CoW one */
if (acb->aiocb_type == AIOCB_WRITE_UDATA && is_data_obj(aio_req->oid)) {
@@ -1345,20 +1362,36 @@ static void coroutine_fn resend_aioreq(BDRVSheepdogState *s, AIOReq *aio_req)
aio_req->base_oid = vid_to_data_oid(s->inode.data_vdi_id[idx], idx);
aio_req->flags |= SD_FLAG_CMD_COW;
}
create = true;
aio_req->create = true;
}
out:
if (is_data_obj(aio_req->oid)) {
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
acb->aiocb_type);
} else {
struct iovec iov;
iov.iov_base = &s->inode;
iov.iov_len = sizeof(s->inode);
add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
}
}
static void sd_detach_aio_context(BlockDriverState *bs)
{
BDRVSheepdogState *s = bs->opaque;
aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
}
static void sd_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVSheepdogState *s = bs->opaque;
s->aio_context = new_context;
aio_set_fd_handler(new_context, s->fd, co_read_response, NULL, s);
}
/* TODO Convert to fine grained options */
static QemuOptsList runtime_opts = {
.name = "sheepdog",
@@ -1387,6 +1420,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
const char *filename;
s->bs = bs;
s->aio_context = bdrv_get_aio_context(bs);
opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
@@ -1448,8 +1482,8 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
}
buf = g_malloc(SD_INODE_SIZE);
ret = read_object(fd, buf, vid_to_vdi_oid(vid), 0, SD_INODE_SIZE, 0,
s->cache_flags);
ret = read_object(fd, s->aio_context, buf, vid_to_vdi_oid(vid),
0, SD_INODE_SIZE, 0, s->cache_flags);
closesocket(fd);
@@ -1469,7 +1503,7 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
g_free(buf);
return 0;
out:
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL);
if (s->fd >= 0) {
closesocket(s->fd);
}
@@ -1512,7 +1546,7 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot,
hdr.copy_policy = s->inode.copy_policy;
hdr.copies = s->inode.nr_copies;
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
closesocket(fd);
@@ -1766,7 +1800,8 @@ static void sd_close(BlockDriverState *bs)
hdr.data_length = wlen;
hdr.flags = SD_FLAG_CMD_WRITE;
ret = do_req(fd, (SheepdogReq *)&hdr, s->name, &wlen, &rlen);
ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr,
s->name, &wlen, &rlen);
closesocket(fd);
@@ -1775,7 +1810,7 @@ static void sd_close(BlockDriverState *bs)
error_report("%s, %s", sd_strerror(rsp->result), s->name);
}
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL);
closesocket(s->fd);
g_free(s->host_spec);
}
@@ -1812,8 +1847,9 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
/* we don't need to update entire object */
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_flags);
ret = write_object(fd, s->aio_context, (char *)&s->inode,
vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies,
datalen, 0, false, s->cache_flags);
close(fd);
if (ret < 0) {
@@ -1849,9 +1885,9 @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
iov.iov_base = &s->inode;
iov.iov_len = sizeof(s->inode);
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
data_len, offset, 0, 0, offset);
data_len, offset, 0, false, 0, offset);
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
add_aio_request(s, aio_req, &iov, 1, false, AIOCB_WRITE_UDATA);
add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
acb->aio_done_func = sd_finish_aiocb;
acb->aiocb_type = AIOCB_WRITE_UDATA;
@@ -1882,7 +1918,8 @@ static bool sd_delete(BDRVSheepdogState *s)
return false;
}
ret = do_req(fd, (SheepdogReq *)&hdr, s->name, &wlen, &rlen);
ret = do_req(fd, s->aio_context, (SheepdogReq *)&hdr,
s->name, &wlen, &rlen);
closesocket(fd);
if (ret) {
return false;
@@ -1939,8 +1976,8 @@ static int sd_create_branch(BDRVSheepdogState *s)
goto out;
}
ret = read_object(fd, buf, vid_to_vdi_oid(vid), s->inode.nr_copies,
SD_INODE_SIZE, 0, s->cache_flags);
ret = read_object(fd, s->aio_context, buf, vid_to_vdi_oid(vid),
s->inode.nr_copies, SD_INODE_SIZE, 0, s->cache_flags);
closesocket(fd);
@@ -2049,7 +2086,8 @@ static int coroutine_fn sd_co_rw_vector(void *p)
DPRINTF("new oid %" PRIx64 "\n", oid);
}
aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, old_oid, done);
aio_req = alloc_aio_req(s, acb, oid, len, offset, flags, create,
old_oid, done);
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
if (create) {
@@ -2058,7 +2096,7 @@ static int coroutine_fn sd_co_rw_vector(void *p)
}
}
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov, create,
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
acb->aiocb_type);
done:
offset = 0;
@@ -2138,9 +2176,9 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
acb->aio_done_func = sd_finish_aiocb;
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
0, 0, 0, 0, 0);
0, 0, 0, false, 0, 0);
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
add_aio_request(s, aio_req, NULL, 0, false, acb->aiocb_type);
add_aio_request(s, aio_req, NULL, 0, acb->aiocb_type);
qemu_coroutine_yield();
return acb->ret;
@@ -2187,8 +2225,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
goto cleanup;
}
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
s->inode.nr_copies, datalen, 0, false, s->cache_flags);
ret = write_object(fd, s->aio_context, (char *)&s->inode,
vid_to_vdi_oid(s->inode.vdi_id), s->inode.nr_copies,
datalen, 0, false, s->cache_flags);
if (ret < 0) {
error_report("failed to write snapshot's inode.");
goto cleanup;
@@ -2203,8 +2242,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
goto cleanup;
}
ret = read_object(fd, (char *)inode, vid_to_vdi_oid(new_vid),
s->inode.nr_copies, datalen, 0, s->cache_flags);
ret = read_object(fd, s->aio_context, (char *)inode,
vid_to_vdi_oid(new_vid), s->inode.nr_copies, datalen, 0,
s->cache_flags);
if (ret < 0) {
error_report("failed to read new inode info. %s", strerror(errno));
@@ -2311,7 +2351,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
req.opcode = SD_OP_READ_VDIS;
req.data_length = max;
ret = do_req(fd, (SheepdogReq *)&req, vdi_inuse, &wlen, &rlen);
ret = do_req(fd, s->aio_context, (SheepdogReq *)&req,
vdi_inuse, &wlen, &rlen);
closesocket(fd);
if (ret) {
@@ -2338,7 +2379,8 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
}
/* we don't need to read entire object */
ret = read_object(fd, (char *)&inode, vid_to_vdi_oid(vid),
ret = read_object(fd, s->aio_context, (char *)&inode,
vid_to_vdi_oid(vid),
0, SD_INODE_SIZE - sizeof(inode.data_vdi_id), 0,
s->cache_flags);
@@ -2403,11 +2445,11 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
create = (offset == 0);
if (load) {
ret = read_object(fd, (char *)data, vmstate_oid,
ret = read_object(fd, s->aio_context, (char *)data, vmstate_oid,
s->inode.nr_copies, data_len, offset,
s->cache_flags);
} else {
ret = write_object(fd, (char *)data, vmstate_oid,
ret = write_object(fd, s->aio_context, (char *)data, vmstate_oid,
s->inode.nr_copies, data_len, offset, create,
s->cache_flags);
}
@@ -2580,6 +2622,9 @@ static BlockDriver bdrv_sheepdog = {
.bdrv_save_vmstate = sd_save_vmstate,
.bdrv_load_vmstate = sd_load_vmstate,
.bdrv_detach_aio_context = sd_detach_aio_context,
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_options = sd_create_options,
};
@@ -2610,6 +2655,9 @@ static BlockDriver bdrv_sheepdog_tcp = {
.bdrv_save_vmstate = sd_save_vmstate,
.bdrv_load_vmstate = sd_load_vmstate,
.bdrv_detach_aio_context = sd_detach_aio_context,
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_options = sd_create_options,
};
@@ -2640,6 +2688,9 @@ static BlockDriver bdrv_sheepdog_unix = {
.bdrv_save_vmstate = sd_save_vmstate,
.bdrv_load_vmstate = sd_load_vmstate,
.bdrv_detach_aio_context = sd_detach_aio_context,
.bdrv_attach_aio_context = sd_attach_aio_context,
.create_options = sd_create_options,
};

View File

@@ -773,7 +773,7 @@ static void restart_coroutine(void *opaque)
qemu_coroutine_enter(co, NULL);
}
static coroutine_fn void set_fd_handler(BDRVSSHState *s)
static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs)
{
int r;
IOHandler *rd_handler = NULL, *wr_handler = NULL;
@@ -791,24 +791,26 @@ static coroutine_fn void set_fd_handler(BDRVSSHState *s)
DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock,
rd_handler, wr_handler);
qemu_aio_set_fd_handler(s->sock, rd_handler, wr_handler, co);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
rd_handler, wr_handler, co);
}
static coroutine_fn void clear_fd_handler(BDRVSSHState *s)
static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
BlockDriverState *bs)
{
DPRINTF("s->sock=%d", s->sock);
qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, NULL, NULL, NULL);
}
/* A non-blocking call returned EAGAIN, so yield, ensuring the
* handlers are set up so that we'll be rescheduled when there is an
* interesting event on the socket.
*/
static coroutine_fn void co_yield(BDRVSSHState *s)
static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
{
set_fd_handler(s);
set_fd_handler(s, bs);
qemu_coroutine_yield();
clear_fd_handler(s);
clear_fd_handler(s, bs);
}
/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position
@@ -838,7 +840,7 @@ static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags)
}
}
static coroutine_fn int ssh_read(BDRVSSHState *s,
static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs,
int64_t offset, size_t size,
QEMUIOVector *qiov)
{
@@ -871,7 +873,7 @@ static coroutine_fn int ssh_read(BDRVSSHState *s,
DPRINTF("sftp_read returned %zd", r);
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
co_yield(s);
co_yield(s, bs);
goto again;
}
if (r < 0) {
@@ -906,14 +908,14 @@ static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
int ret;
qemu_co_mutex_lock(&s->lock);
ret = ssh_read(s, sector_num * BDRV_SECTOR_SIZE,
ret = ssh_read(s, bs, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE, qiov);
qemu_co_mutex_unlock(&s->lock);
return ret;
}
static int ssh_write(BDRVSSHState *s,
static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
int64_t offset, size_t size,
QEMUIOVector *qiov)
{
@@ -941,7 +943,7 @@ static int ssh_write(BDRVSSHState *s,
DPRINTF("sftp_write returned %zd", r);
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
co_yield(s);
co_yield(s, bs);
goto again;
}
if (r < 0) {
@@ -960,7 +962,7 @@ static int ssh_write(BDRVSSHState *s,
*/
if (r == 0) {
ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE);
co_yield(s);
co_yield(s, bs);
goto again;
}
@@ -988,7 +990,7 @@ static coroutine_fn int ssh_co_writev(BlockDriverState *bs,
int ret;
qemu_co_mutex_lock(&s->lock);
ret = ssh_write(s, sector_num * BDRV_SECTOR_SIZE,
ret = ssh_write(s, bs, sector_num * BDRV_SECTOR_SIZE,
nb_sectors * BDRV_SECTOR_SIZE, qiov);
qemu_co_mutex_unlock(&s->lock);
@@ -1009,7 +1011,7 @@ static void unsafe_flush_warning(BDRVSSHState *s, const char *what)
#ifdef HAS_LIBSSH2_SFTP_FSYNC
static coroutine_fn int ssh_flush(BDRVSSHState *s)
static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs)
{
int r;
@@ -1017,7 +1019,7 @@ static coroutine_fn int ssh_flush(BDRVSSHState *s)
again:
r = libssh2_sftp_fsync(s->sftp_handle);
if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) {
co_yield(s);
co_yield(s, bs);
goto again;
}
if (r == LIBSSH2_ERROR_SFTP_PROTOCOL &&
@@ -1039,7 +1041,7 @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs)
int ret;
qemu_co_mutex_lock(&s->lock);
ret = ssh_flush(s);
ret = ssh_flush(s, bs);
qemu_co_mutex_unlock(&s->lock);
return ret;

View File

@@ -239,7 +239,6 @@ static void vdi_header_to_le(VdiHeader *header)
cpu_to_le32s(&header->block_extra);
cpu_to_le32s(&header->blocks_in_image);
cpu_to_le32s(&header->blocks_allocated);
cpu_to_le32s(&header->blocks_allocated);
uuid_convert(header->uuid_image);
uuid_convert(header->uuid_last_snap);
uuid_convert(header->uuid_link);

View File

@@ -2096,6 +2096,27 @@ static int vmdk_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
return 0;
}
static void vmdk_detach_aio_context(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
int i;
for (i = 0; i < s->num_extents; i++) {
bdrv_detach_aio_context(s->extents[i].file);
}
}
static void vmdk_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
BDRVVmdkState *s = bs->opaque;
int i;
for (i = 0; i < s->num_extents; i++) {
bdrv_attach_aio_context(s->extents[i].file, new_context);
}
}
static QEMUOptionParameter vmdk_create_options[] = {
{
.name = BLOCK_OPT_SIZE,
@@ -2153,6 +2174,8 @@ static BlockDriver bdrv_vmdk = {
.bdrv_get_specific_info = vmdk_get_specific_info,
.bdrv_refresh_limits = vmdk_refresh_limits,
.bdrv_get_info = vmdk_get_info,
.bdrv_detach_aio_context = vmdk_detach_aio_context,
.bdrv_attach_aio_context = vmdk_attach_aio_context,
.create_options = vmdk_create_options,
};

View File

@@ -40,6 +40,7 @@ struct QEMUWin32AIOState {
HANDLE hIOCP;
EventNotifier e;
int count;
bool is_aio_context_attached;
};
typedef struct QEMUWin32AIOCB {
@@ -114,7 +115,7 @@ static void win32_aio_cancel(BlockDriverAIOCB *blockacb)
* wait for completion.
*/
while (!HasOverlappedIoCompleted(&waiocb->ov)) {
qemu_aio_wait();
aio_poll(bdrv_get_aio_context(blockacb->bs), true);
}
}
@@ -180,6 +181,20 @@ int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile)
}
}
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
AioContext *old_context)
{
aio_set_event_notifier(old_context, &aio->e, NULL);
aio->is_aio_context_attached = false;
}
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
AioContext *new_context)
{
aio->is_aio_context_attached = true;
aio_set_event_notifier(new_context, &aio->e, win32_aio_completion_cb);
}
QEMUWin32AIOState *win32_aio_init(void)
{
QEMUWin32AIOState *s;
@@ -194,8 +209,6 @@ QEMUWin32AIOState *win32_aio_init(void)
goto out_close_efd;
}
qemu_aio_set_event_notifier(&s->e, win32_aio_completion_cb);
return s;
out_close_efd:
@@ -204,3 +217,11 @@ out_free_state:
g_free(s);
return NULL;
}
void win32_aio_cleanup(QEMUWin32AIOState *aio)
{
assert(!aio->is_aio_context_attached);
CloseHandle(aio->hIOCP);
event_notifier_cleanup(&aio->e);
g_free(aio);
}

View File

@@ -1703,6 +1703,7 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
{
ThrottleConfig cfg;
BlockDriverState *bs;
AioContext *aio_context;
bs = bdrv_find(device);
if (!bs) {
@@ -1746,6 +1747,9 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
return;
}
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
if (!bs->io_limits_enabled && throttle_enabled(&cfg)) {
bdrv_io_limits_enable(bs);
} else if (bs->io_limits_enabled && !throttle_enabled(&cfg)) {
@@ -1755,6 +1759,8 @@ void qmp_block_set_io_throttle(const char *device, int64_t bps, int64_t bps_rd,
if (bs->io_limits_enabled) {
bdrv_set_io_limits(bs, &cfg);
}
aio_context_release(aio_context);
}
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)

View File

@@ -1,7 +1,37 @@
{ TARGET_FREEBSD_NR___getcwd, "__getcwd", NULL, NULL, NULL },
/*
* FreeBSD strace list
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
{ TARGET_FREEBSD_NR___acl_aclcheck_fd, "__acl_aclcheck_fd", "%s(%d, %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_aclcheck_file, "__acl_aclcheck_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_aclcheck_link, "__acl_aclcheck_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_delete_fd, "__acl_delete_fd", "%s(%d, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_delete_file, "__acl_delete_file", "%s(\"%s\", %d)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_delete_link, "__acl_delete_link", "%s(\"%s\", %d)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_get_fd, "__acl_get_fd", "%s(%d, %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_get_file, "__acl_get_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_get_link, "__acl_get_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_set_fd, "__acl_set_fd", "%s(%d, %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_set_file, "__acl_set_file", "%s(\"%s\", %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___acl_set_link, "__acl_set_link", "%s(\"%s\", %d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR___semctl, "__semctl", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR___syscall, "__syscall", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR___sysctl, "__sysctl", NULL, print_sysctl, NULL },
{ TARGET_FREEBSD_NR__umtx_op, "_umtx_op", "%s(%#x, %d, %d, %#x, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_accept, "accept", "%s(%d,%#x,%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_access, "access", "%s(\"%s\",%#o)", NULL, NULL },
{ TARGET_FREEBSD_NR_acct, "acct", NULL, NULL, NULL },
@@ -20,24 +50,41 @@
{ TARGET_FREEBSD_NR_connect, "connect", "%s(%d,%#x,%d)", NULL, NULL },
{ TARGET_FREEBSD_NR_dup, "dup", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_dup2, "dup2", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_eaccess, "eaccess", "%s(\"%s\",%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_execve, "execve", NULL, print_execve, NULL },
{ TARGET_FREEBSD_NR_exit, "exit", "%s(%d)\n", NULL, NULL },
{ TARGET_FREEBSD_NR_extattrctl, "extattrctl", "%s(\"%s\", %d, \"%s\", %d, \"%s\"", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_delete_fd, "extattr_delete_fd", "%s(%d, %d, \"%s\")", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_delete_file, "extattr_delete_file", "%s(\"%s\", %d, \"%s\")", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_delete_link, "extattr_delete_link", "%s(\"%s\", %d, \"%s\")", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_get_fd, "extattr_get_fd", "%s(%d, %d, \"%s\", %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_get_file, "extattr_get_file", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_get_file, "extattr_get_link", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_list_fd, "extattr_list_fd", "%s(%d, %d, %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_list_file, "extattr_list_file", "%s(\"%s\", %d, %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_list_link, "extattr_list_link", "%s(\"%s\", %d, %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_set_fd, "extattr_set_fd", "%s(%d, %d, \"%s\", %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_set_file, "extattr_set_file", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_extattr_set_link, "extattr_set_link", "%s(\"%s\", %d, \"%s\", %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_fchdir, "fchdir", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fchflags, "fchflags", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fchmod, "fchmod", "%s(%d,%#o)", NULL, NULL },
{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(\"%s\",%d,%d)", NULL, NULL },
{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(%d,%d,%d)", NULL, NULL },
{ TARGET_FREEBSD_NR_fcntl, "fcntl", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fexecve, "fexecve", NULL, print_execve, NULL },
{ TARGET_FREEBSD_NR_fhopen, "fhopen", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fhstat, "fhstat", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fhstatfs, "fhstatfs", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_flock, "flock", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fork, "fork", "%s()", NULL, NULL },
{ TARGET_FREEBSD_NR_fpathconf, "fpathconf", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fstat, "fstat", "%s(%d,%p)", NULL, NULL },
{ TARGET_FREEBSD_NR_fstatfs, "fstatfs", "%s(%d,%p)", NULL, NULL },
{ TARGET_FREEBSD_NR_fstat, "fstat", "%s(%d,%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_fstatat, "fstatat", "%s(%d,\"%s\", %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_fstatfs, "fstatfs", "%s(%d,%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_fsync, "fsync", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_getcontext, "getcontext", "%s(%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_getdirentries, "getdirentries", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_freebsd6_mmap, "freebsd6_mmap", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_getegid, "getegid", "%s()", NULL, NULL },
@@ -63,7 +110,7 @@
{ TARGET_FREEBSD_NR_getsockopt, "getsockopt", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_gettimeofday, "gettimeofday", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_getuid, "getuid", "%s()", NULL, NULL },
{ TARGET_FREEBSD_NR_ioctl, "ioctl", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_ioctl, "ioctl", NULL, print_ioctl, NULL },
{ TARGET_FREEBSD_NR_issetugid, "issetugid", "%s()", NULL, NULL },
{ TARGET_FREEBSD_NR_kevent, "kevent", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_kill, "kill", NULL, NULL, NULL },
@@ -72,6 +119,7 @@
{ TARGET_FREEBSD_NR_lchown, "lchown", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_link, "link", "%s(\"%s\",\"%s\")", NULL, NULL },
{ TARGET_FREEBSD_NR_listen, "listen", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_lpathconf, "lpathconf", "%s(\"%s\", %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_lseek, "lseek", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_lstat, "lstat", "%s(\"%s\",%p)", NULL, NULL },
{ TARGET_FREEBSD_NR_madvise, "madvise", NULL, NULL, NULL },
@@ -96,7 +144,8 @@
{ TARGET_FREEBSD_NR_nanosleep, "nanosleep", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_nfssvc, "nfssvc", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_open, "open", "%s(\"%s\",%#x,%#o)", NULL, NULL },
{ TARGET_FREEBSD_NR_pathconf, "pathconf", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_openat, "openat", "%s(%d, \"%s\",%#x,%#o)", NULL, NULL },
{ TARGET_FREEBSD_NR_pathconf, "pathconf", "%s(\"%s\", %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_pipe, "pipe", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_poll, "poll", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_pread, "pread", NULL, NULL, NULL },
@@ -116,6 +165,7 @@
{ TARGET_FREEBSD_NR_revoke, "revoke", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_rfork, "rfork", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_rmdir, "rmdir", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_rtprio_thread, "rtprio_thread", "%s(%d, %d, %p)", NULL, NULL },
{ TARGET_FREEBSD_NR_sbrk, "sbrk", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sched_yield, "sched_yield", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_select, "select", NULL, NULL, NULL },
@@ -123,6 +173,7 @@
{ TARGET_FREEBSD_NR_semop, "semop", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sendmsg, "sendmsg", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sendto, "sendto", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_setcontext, "setcontext", "%s(%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_setegid, "setegid", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_seteuid, "seteuid", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_setgid, "setgid", NULL, NULL, NULL },
@@ -151,7 +202,7 @@
{ TARGET_FREEBSD_NR_sigprocmask, "sigprocmask", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sigreturn, "sigreturn", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sigsuspend, "sigsuspend", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_socket, "socket", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_socket, "socket", "%s(%d,%d,%d)", NULL, NULL },
{ TARGET_FREEBSD_NR_socketpair, "socketpair", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sstk, "sstk", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_stat, "stat", "%s(\"%s\",%p)", NULL, NULL },
@@ -160,6 +211,15 @@
{ TARGET_FREEBSD_NR_sync, "sync", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sysarch, "sysarch", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_syscall, "syscall", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_thr_create, "thr_create", "%s(%#x, %#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_thr_exit, "thr_exit", "%s(%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_thr_kill, "thr_kill", "%s(%d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_thr_kill2, "thr_kill2", "%s(%d, %d, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_thr_new, "thr_new", "%s(%#x, %d)", NULL, NULL },
{ TARGET_FREEBSD_NR_thr_self, "thr_self", "%s(%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_thr_set_name, "thr_set_name", "%s(%d, \"%s\")", NULL, NULL },
{ TARGET_FREEBSD_NR_thr_suspend, "thr_suspend", "%s(%d, %#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_thr_wake, "thr_wake", "%s(%d)", NULL, NULL },
{ TARGET_FREEBSD_NR_truncate, "truncate", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_umask, "umask", "%s(%#o)", NULL, NULL },
{ TARGET_FREEBSD_NR_unlink, "unlink", "%s(\"%s\")", NULL, NULL },

View File

@@ -1,8 +1,8 @@
/*
* System call numbers.
*
* $FreeBSD: src/sys/sys/syscall.h,v 1.224 2008/08/24 21:23:08 rwatson Exp $
* created from FreeBSD: head/sys/kern/syscalls.master 182123 2008-08-24 21:20:35Z rwatson
* created from FreeBSD: releng/9.1/sys/kern/syscalls.master 229723
* 2012-01-06 19:29:16Z jhb
*/
#define TARGET_FREEBSD_NR_syscall 0
@@ -13,8 +13,10 @@
#define TARGET_FREEBSD_NR_open 5
#define TARGET_FREEBSD_NR_close 6
#define TARGET_FREEBSD_NR_wait4 7
/* 8 is old creat */
#define TARGET_FREEBSD_NR_link 9
#define TARGET_FREEBSD_NR_unlink 10
/* 11 is obsolete execv */
#define TARGET_FREEBSD_NR_chdir 12
#define TARGET_FREEBSD_NR_fchdir 13
#define TARGET_FREEBSD_NR_mknod 14
@@ -22,6 +24,7 @@
#define TARGET_FREEBSD_NR_chown 16
#define TARGET_FREEBSD_NR_break 17
#define TARGET_FREEBSD_NR_freebsd4_getfsstat 18
/* 19 is old lseek */
#define TARGET_FREEBSD_NR_getpid 20
#define TARGET_FREEBSD_NR_mount 21
#define TARGET_FREEBSD_NR_unmount 22
@@ -40,16 +43,21 @@
#define TARGET_FREEBSD_NR_fchflags 35
#define TARGET_FREEBSD_NR_sync 36
#define TARGET_FREEBSD_NR_kill 37
/* 38 is old stat */
#define TARGET_FREEBSD_NR_getppid 39
/* 40 is old lstat */
#define TARGET_FREEBSD_NR_dup 41
#define TARGET_FREEBSD_NR_pipe 42
#define TARGET_FREEBSD_NR_getegid 43
#define TARGET_FREEBSD_NR_profil 44
#define TARGET_FREEBSD_NR_ktrace 45
/* 46 is old sigaction */
#define TARGET_FREEBSD_NR_getgid 47
/* 48 is old sigprocmask */
#define TARGET_FREEBSD_NR_getlogin 49
#define TARGET_FREEBSD_NR_setlogin 50
#define TARGET_FREEBSD_NR_acct 51
/* 52 is old sigpending */
#define TARGET_FREEBSD_NR_sigaltstack 53
#define TARGET_FREEBSD_NR_ioctl 54
#define TARGET_FREEBSD_NR_reboot 55
@@ -59,22 +67,33 @@
#define TARGET_FREEBSD_NR_execve 59
#define TARGET_FREEBSD_NR_umask 60
#define TARGET_FREEBSD_NR_chroot 61
/* 62 is old fstat */
/* 63 is old getkerninfo */
/* 64 is old getpagesize */
#define TARGET_FREEBSD_NR_msync 65
#define TARGET_FREEBSD_NR_vfork 66
/* 67 is obsolete vread */
/* 68 is obsolete vwrite */
#define TARGET_FREEBSD_NR_sbrk 69
#define TARGET_FREEBSD_NR_sstk 70
/* 71 is old mmap */
#define TARGET_FREEBSD_NR_vadvise 72
#define TARGET_FREEBSD_NR_munmap 73
#define TARGET_FREEBSD_NR_mprotect 74
#define TARGET_FREEBSD_NR_madvise 75
/* 76 is obsolete vhangup */
/* 77 is obsolete vlimit */
#define TARGET_FREEBSD_NR_mincore 78
#define TARGET_FREEBSD_NR_getgroups 79
#define TARGET_FREEBSD_NR_setgroups 80
#define TARGET_FREEBSD_NR_getpgrp 81
#define TARGET_FREEBSD_NR_setpgid 82
#define TARGET_FREEBSD_NR_setitimer 83
/* 84 is old wait */
#define TARGET_FREEBSD_NR_swapon 85
#define TARGET_FREEBSD_NR_getitimer 86
/* 87 is old gethostname */
/* 88 is old sethostname */
#define TARGET_FREEBSD_NR_getdtablesize 89
#define TARGET_FREEBSD_NR_dup2 90
#define TARGET_FREEBSD_NR_fcntl 92
@@ -83,10 +102,23 @@
#define TARGET_FREEBSD_NR_setpriority 96
#define TARGET_FREEBSD_NR_socket 97
#define TARGET_FREEBSD_NR_connect 98
/* 99 is old accept */
#define TARGET_FREEBSD_NR_getpriority 100
/* 101 is old send */
/* 102 is old recv */
/* 103 is old sigreturn */
#define TARGET_FREEBSD_NR_bind 104
#define TARGET_FREEBSD_NR_setsockopt 105
#define TARGET_FREEBSD_NR_listen 106
/* 107 is obsolete vtimes */
/* 108 is old sigvec */
/* 109 is old sigblock */
/* 110 is old sigsetmask */
/* 111 is old sigsuspend */
/* 112 is old sigstack */
/* 113 is old recvmsg */
/* 114 is old sendmsg */
/* 115 is obsolete vtrace */
#define TARGET_FREEBSD_NR_gettimeofday 116
#define TARGET_FREEBSD_NR_getrusage 117
#define TARGET_FREEBSD_NR_getsockopt 118
@@ -95,9 +127,12 @@
#define TARGET_FREEBSD_NR_settimeofday 122
#define TARGET_FREEBSD_NR_fchown 123
#define TARGET_FREEBSD_NR_fchmod 124
/* 125 is old recvfrom */
#define TARGET_FREEBSD_NR_setreuid 126
#define TARGET_FREEBSD_NR_setregid 127
#define TARGET_FREEBSD_NR_rename 128
/* 129 is old truncate */
/* 130 is old ftruncate */
#define TARGET_FREEBSD_NR_flock 131
#define TARGET_FREEBSD_NR_mkfifo 132
#define TARGET_FREEBSD_NR_sendto 133
@@ -106,18 +141,29 @@
#define TARGET_FREEBSD_NR_mkdir 136
#define TARGET_FREEBSD_NR_rmdir 137
#define TARGET_FREEBSD_NR_utimes 138
/* 139 is obsolete 4.2 sigreturn */
#define TARGET_FREEBSD_NR_adjtime 140
/* 141 is old getpeername */
/* 142 is old gethostid */
/* 143 is old sethostid */
/* 144 is old getrlimit */
/* 145 is old setrlimit */
/* 146 is old killpg */
#define TARGET_FREEBSD_NR_killpg 146 /* COMPAT */
#define TARGET_FREEBSD_NR_setsid 147
#define TARGET_FREEBSD_NR_quotactl 148
/* 149 is old quota */
/* 150 is old getsockname */
#define TARGET_FREEBSD_NR_nlm_syscall 154
#define TARGET_FREEBSD_NR_nfssvc 155
/* 156 is old getdirentries */
#define TARGET_FREEBSD_NR_freebsd4_statfs 157
#define TARGET_FREEBSD_NR_freebsd4_fstatfs 158
#define TARGET_FREEBSD_NR_lgetfh 160
#define TARGET_FREEBSD_NR_getfh 161
#define TARGET_FREEBSD_NR_getdomainname 162
#define TARGET_FREEBSD_NR_setdomainname 163
#define TARGET_FREEBSD_NR_uname 164
#define TARGET_FREEBSD_NR_freebsd4_getdomainname 162
#define TARGET_FREEBSD_NR_freebsd4_setdomainname 163
#define TARGET_FREEBSD_NR_freebsd4_uname 164
#define TARGET_FREEBSD_NR_sysarch 165
#define TARGET_FREEBSD_NR_rtprio 166
#define TARGET_FREEBSD_NR_semsys 169
@@ -150,15 +196,15 @@
#define TARGET_FREEBSD_NR_futimes 206
#define TARGET_FREEBSD_NR_getpgid 207
#define TARGET_FREEBSD_NR_poll 209
#define TARGET_FREEBSD_NR___semctl 220
#define TARGET_FREEBSD_NR_freebsd7___semctl 220
#define TARGET_FREEBSD_NR_semget 221
#define TARGET_FREEBSD_NR_semop 222
#define TARGET_FREEBSD_NR_msgctl 224
#define TARGET_FREEBSD_NR_freebsd7_msgctl 224
#define TARGET_FREEBSD_NR_msgget 225
#define TARGET_FREEBSD_NR_msgsnd 226
#define TARGET_FREEBSD_NR_msgrcv 227
#define TARGET_FREEBSD_NR_shmat 228
#define TARGET_FREEBSD_NR_shmctl 229
#define TARGET_FREEBSD_NR_freebsd7_shmctl 229
#define TARGET_FREEBSD_NR_shmdt 230
#define TARGET_FREEBSD_NR_shmget 231
#define TARGET_FREEBSD_NR_clock_gettime 232
@@ -205,6 +251,7 @@
#define TARGET_FREEBSD_NR_getsid 310
#define TARGET_FREEBSD_NR_setresuid 311
#define TARGET_FREEBSD_NR_setresgid 312
/* 313 is obsolete signanosleep */
#define TARGET_FREEBSD_NR_aio_return 314
#define TARGET_FREEBSD_NR_aio_suspend 315
#define TARGET_FREEBSD_NR_aio_cancel 316
@@ -213,6 +260,8 @@
#define TARGET_FREEBSD_NR_oaio_write 319
#define TARGET_FREEBSD_NR_olio_listio 320
#define TARGET_FREEBSD_NR_yield 321
/* 322 is obsolete thr_sleep */
/* 323 is obsolete thr_wakeup */
#define TARGET_FREEBSD_NR_mlockall 324
#define TARGET_FREEBSD_NR_munlockall 325
#define TARGET_FREEBSD_NR___getcwd 326
@@ -228,6 +277,7 @@
#define TARGET_FREEBSD_NR_freebsd4_sendfile 336
#define TARGET_FREEBSD_NR_kldsym 337
#define TARGET_FREEBSD_NR_jail 338
#define TARGET_FREEBSD_NR_nnpfs_syscall 339
#define TARGET_FREEBSD_NR_sigprocmask 340
#define TARGET_FREEBSD_NR_sigsuspend 341
#define TARGET_FREEBSD_NR_freebsd4_sigaction 342
@@ -256,8 +306,8 @@
#define TARGET_FREEBSD_NR_extattr_get_fd 372
#define TARGET_FREEBSD_NR_extattr_delete_fd 373
#define TARGET_FREEBSD_NR___setugid 374
#define TARGET_FREEBSD_NR_nfsclnt 375
#define TARGET_FREEBSD_NR_eaccess 376
#define TARGET_FREEBSD_NR_afs3_syscall 377
#define TARGET_FREEBSD_NR_nmount 378
#define TARGET_FREEBSD_NR___mac_get_proc 384
#define TARGET_FREEBSD_NR___mac_set_proc 385
@@ -371,3 +421,30 @@
#define TARGET_FREEBSD_NR_symlinkat 502
#define TARGET_FREEBSD_NR_unlinkat 503
#define TARGET_FREEBSD_NR_posix_openpt 504
#define TARGET_FREEBSD_NR_gssd_syscall 505
#define TARGET_FREEBSD_NR_jail_get 506
#define TARGET_FREEBSD_NR_jail_set 507
#define TARGET_FREEBSD_NR_jail_remove 508
#define TARGET_FREEBSD_NR_closefrom 509
#define TARGET_FREEBSD_NR___semctl 510
#define TARGET_FREEBSD_NR_msgctl 511
#define TARGET_FREEBSD_NR_shmctl 512
#define TARGET_FREEBSD_NR_lpathconf 513
#define TARGET_FREEBSD_NR_cap_new 514
#define TARGET_FREEBSD_NR_cap_getrights 515
#define TARGET_FREEBSD_NR_cap_enter 516
#define TARGET_FREEBSD_NR_cap_getmode 517
#define TARGET_FREEBSD_NR_pdfork 518
#define TARGET_FREEBSD_NR_pdkill 519
#define TARGET_FREEBSD_NR_pdgetpid 520
#define TARGET_FREEBSD_NR_pselect 522
#define TARGET_FREEBSD_NR_getloginclass 523
#define TARGET_FREEBSD_NR_setloginclass 524
#define TARGET_FREEBSD_NR_rctl_get_racct 525
#define TARGET_FREEBSD_NR_rctl_get_rules 526
#define TARGET_FREEBSD_NR_rctl_get_limits 527
#define TARGET_FREEBSD_NR_rctl_add_rule 528
#define TARGET_FREEBSD_NR_rctl_remove_rule 529
#define TARGET_FREEBSD_NR_posix_fallocate 530
#define TARGET_FREEBSD_NR_posix_fadvise 531
#define TARGET_FREEBSD_NR_MAXSYSCALL 532

View File

@@ -1004,7 +1004,7 @@ int main(int argc, char **argv)
#if defined(TARGET_I386)
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK;
env->hflags |= HF_PE_MASK | HF_CPL_MASK;
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
env->cr[4] |= CR4_OSFXSR_MASK;
env->hflags |= HF_OSFXSR_MASK;

View File

@@ -74,66 +74,6 @@ void mmap_unlock(void)
}
#endif
static void *bsd_vmalloc(size_t size)
{
void *p;
mmap_lock();
/* Use map and mark the pages as used. */
p = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (h2g_valid(p)) {
/* Allocated region overlaps guest address space.
This may recurse. */
abi_ulong addr = h2g(p);
page_set_flags(addr & TARGET_PAGE_MASK, TARGET_PAGE_ALIGN(addr + size),
PAGE_RESERVED);
}
mmap_unlock();
return p;
}
void *g_malloc(size_t size)
{
char * p;
size += 16;
p = bsd_vmalloc(size);
*(size_t *)p = size;
return p + 16;
}
/* We use map, which is always zero initialized. */
void * g_malloc0(size_t size)
{
return g_malloc(size);
}
void g_free(void *ptr)
{
/* FIXME: We should unmark the reserved pages here. However this gets
complicated when one target page spans multiple host pages, so we
don't bother. */
size_t *p;
p = (size_t *)((char *)ptr - 16);
munmap(p, *p);
}
void *g_realloc(void *ptr, size_t size)
{
size_t old_size, copy;
void *new_ptr;
if (!ptr)
return g_malloc(size);
old_size = *(size_t *)((char *)ptr - 16);
copy = old_size < size ? old_size : size;
new_ptr = g_malloc(size);
memcpy(new_ptr, ptr, copy);
g_free(ptr);
return new_ptr;
}
/* NOTE: all the constants are the HOST ones, but addresses are target. */
int target_mprotect(abi_ulong start, abi_ulong len, int prot)
{

View File

@@ -1,3 +1,19 @@
/*
* qemu bsd user mode definition
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QEMU_H
#define QEMU_H
@@ -5,6 +21,7 @@
#include <string.h>
#include "cpu.h"
#include "exec/cpu_ldst.h"
#undef DEBUG_REMAP
#ifdef DEBUG_REMAP
@@ -149,6 +166,16 @@ void fork_end(int child);
#include "qemu/log.h"
/* strace.c */
struct syscallname {
int nr;
const char *name;
const char *format;
void (*call)(const struct syscallname *,
abi_long, abi_long, abi_long,
abi_long, abi_long, abi_long);
void (*result)(const struct syscallname *, abi_long);
};
void
print_freebsd_syscall(int num,
abi_long arg1, abi_long arg2, abi_long arg3,

View File

@@ -1,37 +1,71 @@
/*
* System call tracing and debugging
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/ioccom.h>
#include <ctype.h>
#include "qemu.h"
int do_strace=0;
struct syscallname {
int nr;
const char *name;
const char *format;
void (*call)(const struct syscallname *,
abi_long, abi_long, abi_long,
abi_long, abi_long, abi_long);
void (*result)(const struct syscallname *, abi_long);
};
int do_strace;
/*
* Utility functions
*/
static void
print_execve(const struct syscallname *name,
abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6)
static void print_sysctl(const struct syscallname *name, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
abi_long arg6)
{
uint32_t i;
int32_t *namep;
gemu_log("%s({ ", name->name);
namep = lock_user(VERIFY_READ, arg1, sizeof(int32_t) * arg2, 1);
if (namep) {
int32_t *p = namep;
for (i = 0; i < (uint32_t)arg2; i++) {
gemu_log("%d ", tswap32(*p++));
}
unlock_user(namep, arg1, 0);
}
gemu_log("}, %u, 0x" TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ", 0x"
TARGET_ABI_FMT_lx ", 0x" TARGET_ABI_FMT_lx ")",
(uint32_t)arg2, arg3, arg4, arg5, arg6);
}
static void print_execve(const struct syscallname *name, abi_long arg1,
abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5,
abi_long arg6)
{
abi_ulong arg_ptr_addr;
char *s;
if (!(s = lock_user_string(arg1)))
s = lock_user_string(arg1);
if (s == NULL) {
return;
}
gemu_log("%s(\"%s\",{", name->name, s);
unlock_user(s, arg1, 0);
@@ -39,29 +73,48 @@ print_execve(const struct syscallname *name,
abi_ulong *arg_ptr, arg_addr;
arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
if (!arg_ptr)
if (!arg_ptr) {
return;
}
arg_addr = tswapl(*arg_ptr);
unlock_user(arg_ptr, arg_ptr_addr, 0);
if (!arg_addr)
if (!arg_addr) {
break;
}
if ((s = lock_user_string(arg_addr))) {
gemu_log("\"%s\",", s);
unlock_user(s, arg_addr, 0);
}
}
gemu_log("NULL})");
}
static void print_ioctl(const struct syscallname *name,
abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4,
abi_long arg5, abi_long arg6)
{
/* Decode the ioctl request */
gemu_log("%s(%d, 0x%0lx { IO%s%s GRP:0x%x('%c') CMD:%d LEN:%d }, 0x"
TARGET_ABI_FMT_lx ", ...)",
name->name,
(int)arg1,
(unsigned long)arg2,
arg2 & IOC_OUT ? "R" : "",
arg2 & IOC_IN ? "W" : "",
(unsigned)IOCGROUP(arg2),
isprint(IOCGROUP(arg2)) ? (char)IOCGROUP(arg2) : '?',
(int)arg2 & 0xFF,
(int)IOCPARM_LEN(arg2),
arg3);
}
/*
* Variants for the return value output function
*/
static void
print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
static void print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
{
if( ret == -1 ) {
if (ret == -1) {
gemu_log(" = -1 errno=%d (%s)\n", errno, strerror(errno));
} else {
gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
@@ -90,9 +143,8 @@ static const struct syscallname openbsd_scnames[] = {
#include "openbsd/strace.list"
};
static void
print_syscall(int num, const struct syscallname *scnames, unsigned int nscnames,
abi_long arg1, abi_long arg2, abi_long arg3,
static void print_syscall(int num, const struct syscallname *scnames,
unsigned int nscnames, abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6)
{
unsigned int i;
@@ -102,7 +154,7 @@ print_syscall(int num, const struct syscallname *scnames, unsigned int nscnames,
gemu_log("%d ", getpid() );
for (i = 0; i < nscnames; i++)
for (i = 0; i < nscnames; i++) {
if (scnames[i].nr == num) {
if (scnames[i].call != NULL) {
scnames[i].call(&scnames[i], arg1, arg2, arg3, arg4, arg5,
@@ -110,28 +162,29 @@ print_syscall(int num, const struct syscallname *scnames, unsigned int nscnames,
} else {
/* XXX: this format system is broken because it uses
host types and host pointers for strings */
if (scnames[i].format != NULL)
if (scnames[i].format != NULL) {
format = scnames[i].format;
gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4,
arg5, arg6);
}
gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4, arg5,
arg6);
}
return;
}
}
gemu_log("Unknown syscall %d\n", num);
}
static void
print_syscall_ret(int num, abi_long ret, const struct syscallname *scnames,
unsigned int nscnames)
static void print_syscall_ret(int num, abi_long ret,
const struct syscallname *scnames, unsigned int nscnames)
{
unsigned int i;
for (i = 0; i < nscnames; i++)
for (i = 0; i < nscnames; i++) {
if (scnames[i].nr == num) {
if (scnames[i].result != NULL) {
scnames[i].result(&scnames[i], ret);
} else {
if( ret < 0 ) {
if (ret < 0) {
gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret,
strerror(-ret));
} else {
@@ -140,52 +193,50 @@ print_syscall_ret(int num, abi_long ret, const struct syscallname *scnames,
}
break;
}
}
}
/*
* The public interface to this module.
*/
void
print_freebsd_syscall(int num,
abi_long arg1, abi_long arg2, abi_long arg3,
void print_freebsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6)
{
print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames),
arg1, arg2, arg3, arg4, arg5, arg6);
print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames), arg1, arg2,
arg3, arg4, arg5, arg6);
}
void
print_freebsd_syscall_ret(int num, abi_long ret)
void print_freebsd_syscall_ret(int num, abi_long ret)
{
print_syscall_ret(num, ret, freebsd_scnames, ARRAY_SIZE(freebsd_scnames));
}
void
print_netbsd_syscall(int num,
abi_long arg1, abi_long arg2, abi_long arg3,
void print_netbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6)
{
print_syscall(num, netbsd_scnames, ARRAY_SIZE(netbsd_scnames),
arg1, arg2, arg3, arg4, arg5, arg6);
}
void
print_netbsd_syscall_ret(int num, abi_long ret)
void print_netbsd_syscall_ret(int num, abi_long ret)
{
print_syscall_ret(num, ret, netbsd_scnames, ARRAY_SIZE(netbsd_scnames));
}
void
print_openbsd_syscall(int num,
abi_long arg1, abi_long arg2, abi_long arg3,
void print_openbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
abi_long arg4, abi_long arg5, abi_long arg6)
{
print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames),
arg1, arg2, arg3, arg4, arg5, arg6);
print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames), arg1, arg2,
arg3, arg4, arg5, arg6);
}
void
print_openbsd_syscall_ret(int num, abi_long ret)
void print_openbsd_syscall_ret(int num, abi_long ret)
{
print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames));
}

73
configure vendored
View File

@@ -3,6 +3,11 @@
# qemu configure script (c) 2003 Fabrice Bellard
#
# Unset some variables known to interfere with behavior of common tools,
# just as autoconf does.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS
# Temporary directory used for files created while
# configure runs. Since it is in the build directory
# we can safely blow away any previous version of it
@@ -182,6 +187,10 @@ path_of() {
return 1
}
have_backend () {
echo "$trace_backends" | grep "$1" >/dev/null
}
# default parameters
source_path=`dirname "$0"`
cpu=""
@@ -293,7 +302,7 @@ pkgversion=""
pie=""
zero_malloc=""
qom_cast_debug="yes"
trace_backend="nop"
trace_backends="nop"
trace_file="trace"
spice=""
rbd=""
@@ -537,6 +546,9 @@ fi
# OS specific
# host *BSD for user mode
HOST_VARIANT_DIR=""
case $targetos in
CYGWIN*)
mingw32="yes"
@@ -562,12 +574,14 @@ FreeBSD)
# needed for kinfo_getvmmap(3) in libutil.h
LIBS="-lutil $LIBS"
netmap="" # enable netmap autodetect
HOST_VARIANT_DIR="freebsd"
;;
DragonFly)
bsd="yes"
make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd pa"
HOST_VARIANT_DIR="dragonfly"
;;
NetBSD)
bsd="yes"
@@ -575,12 +589,14 @@ NetBSD)
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd"
oss_lib="-lossaudio"
HOST_VARIANT_DIR="netbsd"
;;
OpenBSD)
bsd="yes"
make="${MAKE-gmake}"
audio_drv_list="sdl"
audio_possible_drivers="sdl esd"
HOST_VARIANT_DIR="openbsd"
;;
Darwin)
bsd="yes"
@@ -598,6 +614,7 @@ Darwin)
# Disable attempts to use ObjectiveC features in os/object.h since they
# won't work when we're compiling with gcc as a C compiler.
QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
HOST_VARIANT_DIR="darwin"
;;
SunOS)
solaris="yes"
@@ -753,7 +770,10 @@ for opt do
;;
--target-list=*) target_list="$optarg"
;;
--enable-trace-backend=*) trace_backend="$optarg"
--enable-trace-backends=*) trace_backends="$optarg"
;;
# XXX: backwards compatibility
--enable-trace-backend=*) trace_backends="$optarg"
;;
--with-trace-file=*) trace_file="$optarg"
;;
@@ -1320,7 +1340,7 @@ Advanced options (experts only):
--disable-docs disable documentation build
--disable-vhost-net disable vhost-net acceleration support
--enable-vhost-net enable vhost-net acceleration support
--enable-trace-backend=B Set trace backend
--enable-trace-backends=B Set trace backend
Available backends: $($python $source_path/scripts/tracetool.py --list-backends)
--with-trace-file=NAME Full PATH,NAME of file to store traces
Default:trace-<pid>
@@ -1986,6 +2006,7 @@ fi
if test "$gtk" != "no"; then
gtkpackage="gtk+-$gtkabi"
gtkx11package="gtk+-x11-$gtkabi"
if test "$gtkabi" = "3.0" ; then
gtkversion="3.0.0"
else
@@ -1994,6 +2015,9 @@ if test "$gtk" != "no"; then
if $pkg_config --exists "$gtkpackage >= $gtkversion"; then
gtk_cflags=`$pkg_config --cflags $gtkpackage`
gtk_libs=`$pkg_config --libs $gtkpackage`
if $pkg_config --exists "$gtkx11package >= $gtkversion"; then
gtk_libs="$gtk_libs -lX11"
fi
libs_softmmu="$gtk_libs $libs_softmmu"
gtk="yes"
elif test "$gtk" = "yes"; then
@@ -3445,9 +3469,9 @@ EOF
if compile_prog "" "" ; then
:
# we need pthread for static linking. use previous pthread test result
elif compile_prog "" "-lrt $pthread_lib" ; then
LIBS="-lrt $LIBS"
libs_qga="-lrt $libs_qga"
elif compile_prog "" "$pthread_lib -lrt" ; then
LIBS="$LIBS -lrt"
libs_qga="$libs_qga -lrt"
fi
if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \
@@ -3666,15 +3690,15 @@ fi
##########################################
# check if trace backend exists
$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend > /dev/null 2> /dev/null
$python "$source_path/scripts/tracetool.py" "--backends=$trace_backends" --check-backends > /dev/null 2> /dev/null
if test "$?" -ne 0 ; then
error_exit "invalid trace backend" \
"Please choose a supported trace backend."
error_exit "invalid trace backends" \
"Please choose supported trace backends."
fi
##########################################
# For 'ust' backend, test if ust headers are present
if test "$trace_backend" = "ust"; then
if have_backend "ust"; then
cat > $TMPC << EOF
#include <lttng/tracepoint.h>
int main(void) { return 0; }
@@ -3700,7 +3724,7 @@ fi
##########################################
# For 'dtrace' backend, test if 'dtrace' command is present
if test "$trace_backend" = "dtrace"; then
if have_backend "dtrace"; then
if ! has 'dtrace' ; then
error_exit "dtrace command is not found in PATH $PATH"
fi
@@ -4170,7 +4194,7 @@ echo "uuid support $uuid"
echo "libcap-ng support $cap_ng"
echo "vhost-net support $vhost_net"
echo "vhost-scsi support $vhost_scsi"
echo "Trace backend $trace_backend"
echo "Trace backends $trace_backends"
if test "$trace_backend" = "simple"; then
echo "Trace output file $trace_file-<pid>"
fi
@@ -4664,43 +4688,35 @@ if test "$tpm" = "yes"; then
fi
fi
# use default implementation for tracing backend-specific routines
trace_default=yes
echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
if test "$trace_backend" = "nop"; then
echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
if have_backend "nop"; then
echo "CONFIG_TRACE_NOP=y" >> $config_host_mak
fi
if test "$trace_backend" = "simple"; then
if have_backend "simple"; then
echo "CONFIG_TRACE_SIMPLE=y" >> $config_host_mak
trace_default=no
# Set the appropriate trace file.
trace_file="\"$trace_file-\" FMT_pid"
fi
if test "$trace_backend" = "stderr"; then
if have_backend "stderr"; then
echo "CONFIG_TRACE_STDERR=y" >> $config_host_mak
trace_default=no
fi
if test "$trace_backend" = "ust"; then
if have_backend "ust"; then
echo "CONFIG_TRACE_UST=y" >> $config_host_mak
fi
if test "$trace_backend" = "dtrace"; then
if have_backend "dtrace"; then
echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak
if test "$trace_backend_stap" = "yes" ; then
echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak
fi
fi
if test "$trace_backend" = "ftrace"; then
if have_backend "ftrace"; then
if test "$linux" = "yes" ; then
echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak
trace_default=no
else
feature_not_found "ftrace(trace backend)" "ftrace requires Linux"
fi
fi
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
if test "$trace_default" = "yes"; then
echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak
fi
if test "$rdma" = "yes" ; then
echo "CONFIG_RDMA=y" >> $config_host_mak
@@ -4982,6 +4998,9 @@ if [ "$TARGET_ABI_DIR" = "" ]; then
TARGET_ABI_DIR=$TARGET_ARCH
fi
echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak
if [ "$HOST_VARIANT_DIR" != "" ]; then
echo "HOST_VARIANT_DIR=$HOST_VARIANT_DIR" >> $config_target_mak
fi
case "$target_name" in
i386|x86_64)
if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then

View File

@@ -30,20 +30,14 @@ typedef struct {
CoroutineAction action;
} CoroutineGThread;
static GStaticMutex coroutine_lock = G_STATIC_MUTEX_INIT;
static CompatGMutex coroutine_lock;
static CompatGCond coroutine_cond;
/* GLib 2.31 and beyond deprecated various parts of the thread API,
* but the new interfaces are not available in older GLib versions
* so we have to cope with both.
*/
#if GLIB_CHECK_VERSION(2, 31, 0)
/* Default zero-initialisation is sufficient for 2.31+ GCond */
static GCond the_coroutine_cond;
static GCond *coroutine_cond = &the_coroutine_cond;
static inline void init_coroutine_cond(void)
{
}
/* Awkwardly, the GPrivate API doesn't provide a way to update the
* GDestroyNotify handler for the coroutine key dynamically. So instead
* we track whether or not the CoroutineGThread should be freed on
@@ -84,11 +78,6 @@ static inline GThread *create_thread(GThreadFunc func, gpointer data)
#else
/* Handle older GLib versions */
static GCond *coroutine_cond;
static inline void init_coroutine_cond(void)
{
coroutine_cond = g_cond_new();
}
static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT;
@@ -120,22 +109,20 @@ static void __attribute__((constructor)) coroutine_init(void)
g_thread_init(NULL);
}
#endif
init_coroutine_cond();
}
static void coroutine_wait_runnable_locked(CoroutineGThread *co)
{
while (!co->runnable) {
g_cond_wait(coroutine_cond, g_static_mutex_get_mutex(&coroutine_lock));
g_cond_wait(&coroutine_cond, &coroutine_lock);
}
}
static void coroutine_wait_runnable(CoroutineGThread *co)
{
g_static_mutex_lock(&coroutine_lock);
g_mutex_lock(&coroutine_lock);
coroutine_wait_runnable_locked(co);
g_static_mutex_unlock(&coroutine_lock);
g_mutex_unlock(&coroutine_lock);
}
static gpointer coroutine_thread(gpointer opaque)
@@ -177,17 +164,17 @@ CoroutineAction qemu_coroutine_switch(Coroutine *from_,
CoroutineGThread *from = DO_UPCAST(CoroutineGThread, base, from_);
CoroutineGThread *to = DO_UPCAST(CoroutineGThread, base, to_);
g_static_mutex_lock(&coroutine_lock);
g_mutex_lock(&coroutine_lock);
from->runnable = false;
from->action = action;
to->runnable = true;
to->action = action;
g_cond_broadcast(coroutine_cond);
g_cond_broadcast(&coroutine_cond);
if (action != COROUTINE_TERMINATE) {
coroutine_wait_runnable_locked(from);
}
g_static_mutex_unlock(&coroutine_lock);
g_mutex_unlock(&coroutine_lock);
return from->action;
}

View File

@@ -22,11 +22,13 @@
#include "exec/exec-all.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
#include "exec/cpu_ldst.h"
#include "exec/cputlb.h"
#include "exec/memory-internal.h"
#include "exec/ram_addr.h"
#include "tcg/tcg.h"
//#define DEBUG_TLB
//#define DEBUG_TLB_CHECK
@@ -330,21 +332,36 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
return qemu_ram_addr_from_host_nofail(p);
}
#define MMUSUFFIX _mmu
#define SHIFT 0
#include "softmmu_template.h"
#define SHIFT 1
#include "softmmu_template.h"
#define SHIFT 2
#include "softmmu_template.h"
#define SHIFT 3
#include "softmmu_template.h"
#undef MMUSUFFIX
#define MMUSUFFIX _cmmu
#undef GETPC
#define GETPC() ((uintptr_t)0)
#undef GETPC_ADJ
#define GETPC_ADJ 0
#undef GETRA
#define GETRA() ((uintptr_t)0)
#define SOFTMMU_CODE_ACCESS
#define SHIFT 0
#include "exec/softmmu_template.h"
#include "softmmu_template.h"
#define SHIFT 1
#include "exec/softmmu_template.h"
#include "softmmu_template.h"
#define SHIFT 2
#include "exec/softmmu_template.h"
#include "softmmu_template.h"
#define SHIFT 3
#include "exec/softmmu_template.h"
#undef env
#include "softmmu_template.h"

View File

@@ -47,6 +47,7 @@ In ubuntu/debian:
Configuring and building:
./configure --enable-smartcard && make
3. Using ccid-card-emulated with hardware
Assuming you have a working smartcard on the host with the current
@@ -54,19 +55,55 @@ user, using NSS, qemu acts as another NSS client using ccid-card-emulated:
qemu -usb -device usb-ccid -device ccid-card-emulated
4. Using ccid-card-emulated with certificates
You must create the certificates. This is a one time process. We use NSS
certificates:
4. Using ccid-card-emulated with certificates stored in files
certutil -d /etc/pki/nssdb -x -t "CT,CT,CT" -S -s "CN=cert1" -n cert1
You must create the CA and card certificates. This is a one time process.
We use NSS certificates:
mkdir fake-smartcard
cd fake-smartcard
certutil -N -d sql:$PWD
certutil -S -d sql:$PWD -s "CN=Fake Smart Card CA" -x -t TC,TC,TC -n fake-smartcard-ca
certutil -S -d sql:$PWD -t ,, -s "CN=John Doe" -n id-cert -c fake-smartcard-ca
certutil -S -d sql:$PWD -t ,, -s "CN=John Doe (signing)" --nsCertType smime -n signing-cert -c fake-smartcard-ca
certutil -S -d sql:$PWD -t ,, -s "CN=John Doe (encryption)" --nsCertType sslClient -n encryption-cert -c fake-smartcard-ca
Note: you must have exactly three certificates.
Assuming the current user can access the certificates (use certutil -L to
verify), you can use the emulated card type with the certificates backend:
You can use the emulated card type with the certificates backend:
qemu -usb -device usb-ccid -device ccid-card-emulated,backend=certificates,db=sql:$PWD,cert1=id-cert,cert2=signing-cert,cert3=encryption-cert
To use the certificates in the guest, export the CA certificate:
certutil -L -r -d sql:$PWD -o fake-smartcard-ca.cer -n fake-smartcard-ca
and import it in the guest:
certutil -A -d /etc/pki/nssdb -i fake-smartcard-ca.cer -t TC,TC,TC -n fake-smartcard-ca
In a Linux guest you can then use the CoolKey PKCS #11 module to access
the card:
certutil -d /etc/pki/nssdb -L -h all
It will prompt you for the PIN (which is the password you assigned to the
certificate database early on), and then show you all three certificates
together with the manually imported CA cert:
Certificate Nickname Trust Attributes
fake-smartcard-ca CT,C,C
John Doe:CAC ID Certificate u,u,u
John Doe:CAC Email Signature Certificate u,u,u
John Doe:CAC Email Encryption Certificate u,u,u
If this does not happen, CoolKey is not installed or not registered with
NSS. Registration can be done from Firefox or the command line:
modutil -dbdir /etc/pki/nssdb -add "CAC Module" -libfile /usr/lib64/pkcs11/libcoolkeypk11.so
modutil -dbdir /etc/pki/nssdb -list
qemu -usb -device usb-ccid -device ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3
5. Using ccid-card-passthru with client side hardware
@@ -74,15 +111,23 @@ on the host specify the ccid-card-passthru device with a suitable chardev:
qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
on the client run vscclient, built when you built the libcacard library:
libcacard/vscclient <qemu-host> 2001
on the client run vscclient, built when you built QEMU:
vscclient <qemu-host> 2001
6. Using ccid-card-passthru with client side certificates
Run qemu as per #5, and run vscclient as follows:
(Note: vscclient command line interface is in a state of change)
This case is not particularly useful, but you can use it to debug
your setup if #4 works but #5 does not.
Follow instructions as per #4, except run QEMU and vscclient as follows:
Run qemu as per #5, and run vscclient from the "fake-smartcard"
directory as follows:
qemu -chardev socket,server,host=0.0.0.0,port=2001,id=ccid,nowait -usb -device usb-ccid -device ccid-card-passthru,chardev=ccid
vscclient -e "db=\"sql:$PWD\" use_hw=no soft=(,Test,CAC,,id-cert,signing-cert,encryption-cert)" <qemu-host> 2001
libcacard/vscclient -e "db=\"/etc/pki/nssdb\" use_hw=no soft=(,Test,CAC,,cert1,cert2,cert3)" <qemu-host> 2001
7. Passthrough protocol scenario
@@ -126,10 +171,11 @@ kill/quit | | | |
8. libcacard
ccid-card-passthru and vscclient use libcacard as the card emulator.
libcacard implements a completely virtual CAC (DoD standard for smart cards)
compliant card and uses NSS to actually retrive certificates and do any
encryption using the backend (real reader + card or file backed certificates).
Both ccid-card-emulated and vscclient use libcacard as the card emulator.
libcacard implements a completely virtual CAC (DoD standard for smart
cards) compliant card and uses NSS to retrieve certificates and do
any encryption. The backend can then be a real reader and card, or
certificates stored in files.
For documentation of cac_card see README in libcacard subdirectory.
For documentation of the library see docs/libcacard.txt.

View File

@@ -9,7 +9,7 @@ for debugging, profiling, and observing execution.
1. Build with the 'simple' trace backend:
./configure --enable-trace-backend=simple
./configure --enable-trace-backends=simple
make
2. Create a file with the events you want to trace:
@@ -142,7 +142,7 @@ script.
The trace backend is chosen at configure time and only one trace backend can
be built into the binary:
./configure --trace-backend=simple
./configure --trace-backends=simple
For a list of supported trace backends, try ./configure --help or see below.

View File

@@ -35,7 +35,8 @@ which will return a dictionary containing:
o A key named last-update, which contains the last stats update
timestamp in seconds. Since this timestamp is generated by the host,
a buggy guest can't influence its value
a buggy guest can't influence its value. The value is 0 if the guest
has not updated the stats (yet).
It's also important to note the following:
@@ -49,7 +50,7 @@ It's also important to note the following:
- Polling can be enabled even if the guest doesn't have stats support
or the balloon driver wasn't loaded in the guest. If this is the case
and stats are queried, an error will be returned
and stats are queried, last-update will be 0.
- The polling timer is only re-armed when the guest responds to the
statistics request. This means that if a (buggy) guest doesn't ever

134
dump.c
View File

@@ -90,8 +90,6 @@ typedef struct DumpState {
uint8_t *note_buf; /* buffer for notes */
size_t note_buf_offset; /* the writing place in note_buf */
uint32_t nr_cpus; /* number of guest's cpu */
size_t page_size; /* guest's page size */
uint32_t page_shift; /* guest's page shift */
uint64_t max_mapnr; /* the biggest guest's phys-mem's number */
size_t len_dump_bitmap; /* the size of the place used to store
dump_bitmap in vmcore */
@@ -711,27 +709,25 @@ static int create_vmcore(DumpState *s)
static int write_start_flat_header(int fd)
{
uint8_t *buf;
MakedumpfileHeader mh;
MakedumpfileHeader *mh;
int ret = 0;
memset(&mh, 0, sizeof(mh));
strncpy(mh.signature, MAKEDUMPFILE_SIGNATURE,
strlen(MAKEDUMPFILE_SIGNATURE));
QEMU_BUILD_BUG_ON(sizeof *mh > MAX_SIZE_MDF_HEADER);
mh = g_malloc0(MAX_SIZE_MDF_HEADER);
mh.type = cpu_to_be64(TYPE_FLAT_HEADER);
mh.version = cpu_to_be64(VERSION_FLAT_HEADER);
memcpy(mh->signature, MAKEDUMPFILE_SIGNATURE,
MIN(sizeof mh->signature, sizeof MAKEDUMPFILE_SIGNATURE));
buf = g_malloc0(MAX_SIZE_MDF_HEADER);
memcpy(buf, &mh, sizeof(mh));
mh->type = cpu_to_be64(TYPE_FLAT_HEADER);
mh->version = cpu_to_be64(VERSION_FLAT_HEADER);
size_t written_size;
written_size = qemu_write_full(fd, buf, MAX_SIZE_MDF_HEADER);
written_size = qemu_write_full(fd, mh, MAX_SIZE_MDF_HEADER);
if (written_size != MAX_SIZE_MDF_HEADER) {
ret = -1;
}
g_free(buf);
g_free(mh);
return ret;
}
@@ -808,7 +804,7 @@ static int create_header32(DumpState *s)
strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
dh->header_version = cpu_convert_to_target32(6, endian);
block_size = s->page_size;
block_size = TARGET_PAGE_SIZE;
dh->block_size = cpu_convert_to_target32(block_size, endian);
sub_hdr_size = sizeof(struct KdumpSubHeader32) + s->note_size;
sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, block_size);
@@ -915,7 +911,7 @@ static int create_header64(DumpState *s)
strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
dh->header_version = cpu_convert_to_target32(6, endian);
block_size = s->page_size;
block_size = TARGET_PAGE_SIZE;
dh->block_size = cpu_convert_to_target32(block_size, endian);
sub_hdr_size = sizeof(struct KdumpSubHeader64) + s->note_size;
sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, block_size);
@@ -1004,7 +1000,7 @@ out:
static int write_dump_header(DumpState *s)
{
if (s->dump_info.d_machine == EM_386) {
if (s->dump_info.d_class == ELFCLASS32) {
return create_header32(s);
} else {
return create_header64(s);
@@ -1086,9 +1082,9 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
if (!block) {
block = QTAILQ_FIRST(&s->guest_phys_blocks.head);
*blockptr = block;
assert(block->target_start % s->page_size == 0);
assert(block->target_end % s->page_size == 0);
*pfnptr = paddr_to_pfn(block->target_start, s->page_shift);
assert((block->target_start & ~TARGET_PAGE_MASK) == 0);
assert((block->target_end & ~TARGET_PAGE_MASK) == 0);
*pfnptr = paddr_to_pfn(block->target_start);
if (bufptr) {
*bufptr = block->host_addr;
}
@@ -1096,10 +1092,10 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
}
*pfnptr = *pfnptr + 1;
addr = pfn_to_paddr(*pfnptr, s->page_shift);
addr = pfn_to_paddr(*pfnptr);
if ((addr >= block->target_start) &&
(addr + s->page_size <= block->target_end)) {
(addr + TARGET_PAGE_SIZE <= block->target_end)) {
buf = block->host_addr + (addr - block->target_start);
} else {
/* the next page is in the next block */
@@ -1108,9 +1104,9 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr,
if (!block) {
return false;
}
assert(block->target_start % s->page_size == 0);
assert(block->target_end % s->page_size == 0);
*pfnptr = paddr_to_pfn(block->target_start, s->page_shift);
assert((block->target_start & ~TARGET_PAGE_MASK) == 0);
assert((block->target_end & ~TARGET_PAGE_MASK) == 0);
*pfnptr = paddr_to_pfn(block->target_start);
buf = block->host_addr;
}
@@ -1224,42 +1220,24 @@ static void free_data_cache(DataCache *data_cache)
static size_t get_len_buf_out(size_t page_size, uint32_t flag_compress)
{
size_t len_buf_out_zlib, len_buf_out_lzo, len_buf_out_snappy;
size_t len_buf_out;
/* init buf_out */
len_buf_out_zlib = len_buf_out_lzo = len_buf_out_snappy = 0;
/* buf size for zlib */
len_buf_out_zlib = compressBound(page_size);
/* buf size for lzo */
#ifdef CONFIG_LZO
if (flag_compress & DUMP_DH_COMPRESSED_LZO) {
if (lzo_init() != LZO_E_OK) {
/* return 0 to indicate lzo is unavailable */
return 0;
}
}
switch (flag_compress) {
case DUMP_DH_COMPRESSED_ZLIB:
return compressBound(page_size);
case DUMP_DH_COMPRESSED_LZO:
/*
* LZO will expand incompressible data by a little amount. please check the
* following URL to see the expansion calculation:
* LZO will expand incompressible data by a little amount. Please check
* the following URL to see the expansion calculation:
* http://www.oberhumer.com/opensource/lzo/lzofaq.php
*/
len_buf_out_lzo = page_size + page_size / 16 + 64 + 3;
#endif
return page_size + page_size / 16 + 64 + 3;
#ifdef CONFIG_SNAPPY
/* buf size for snappy */
len_buf_out_snappy = snappy_max_compressed_length(page_size);
case DUMP_DH_COMPRESSED_SNAPPY:
return snappy_max_compressed_length(page_size);
#endif
/* get the biggest that can store all kinds of compressed page */
len_buf_out = MAX(len_buf_out_zlib,
MAX(len_buf_out_lzo, len_buf_out_snappy));
return len_buf_out;
}
return 0;
}
/*
@@ -1294,11 +1272,8 @@ static int write_dump_pages(DumpState *s)
prepare_data_cache(&page_data, s, offset_data);
/* prepare buffer to store compressed data */
len_buf_out = get_len_buf_out(s->page_size, s->flag_compress);
if (len_buf_out == 0) {
dump_error(s, "dump: failed to get length of output buffer.\n");
goto out;
}
len_buf_out = get_len_buf_out(TARGET_PAGE_SIZE, s->flag_compress);
assert(len_buf_out != 0);
#ifdef CONFIG_LZO
wrkmem = g_malloc(LZO1X_1_MEM_COMPRESS);
@@ -1310,19 +1285,19 @@ static int write_dump_pages(DumpState *s)
* init zero page's page_desc and page_data, because every zero page
* uses the same page_data
*/
pd_zero.size = cpu_convert_to_target32(s->page_size, endian);
pd_zero.size = cpu_convert_to_target32(TARGET_PAGE_SIZE, endian);
pd_zero.flags = cpu_convert_to_target32(0, endian);
pd_zero.offset = cpu_convert_to_target64(offset_data, endian);
pd_zero.page_flags = cpu_convert_to_target64(0, endian);
buf = g_malloc0(s->page_size);
ret = write_cache(&page_data, buf, s->page_size, false);
buf = g_malloc0(TARGET_PAGE_SIZE);
ret = write_cache(&page_data, buf, TARGET_PAGE_SIZE, false);
g_free(buf);
if (ret < 0) {
dump_error(s, "dump: failed to write page data(zero page).\n");
goto out;
}
offset_data += s->page_size;
offset_data += TARGET_PAGE_SIZE;
/*
* dump memory to vmcore page by page. zero page will all be resided in the
@@ -1330,7 +1305,7 @@ static int write_dump_pages(DumpState *s)
*/
while (get_next_page(&block_iter, &pfn_iter, &buf, s)) {
/* check zero page */
if (is_zero_page(buf, s->page_size)) {
if (is_zero_page(buf, TARGET_PAGE_SIZE)) {
ret = write_cache(&page_desc, &pd_zero, sizeof(PageDescriptor),
false);
if (ret < 0) {
@@ -1351,8 +1326,9 @@ static int write_dump_pages(DumpState *s)
*/
size_out = len_buf_out;
if ((s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) &&
(compress2(buf_out, (uLongf *)&size_out, buf, s->page_size,
Z_BEST_SPEED) == Z_OK) && (size_out < s->page_size)) {
(compress2(buf_out, (uLongf *)&size_out, buf,
TARGET_PAGE_SIZE, Z_BEST_SPEED) == Z_OK) &&
(size_out < TARGET_PAGE_SIZE)) {
pd.flags = cpu_convert_to_target32(DUMP_DH_COMPRESSED_ZLIB,
endian);
pd.size = cpu_convert_to_target32(size_out, endian);
@@ -1364,9 +1340,9 @@ static int write_dump_pages(DumpState *s)
}
#ifdef CONFIG_LZO
} else if ((s->flag_compress & DUMP_DH_COMPRESSED_LZO) &&
(lzo1x_1_compress(buf, s->page_size, buf_out,
(lzo1x_1_compress(buf, TARGET_PAGE_SIZE, buf_out,
(lzo_uint *)&size_out, wrkmem) == LZO_E_OK) &&
(size_out < s->page_size)) {
(size_out < TARGET_PAGE_SIZE)) {
pd.flags = cpu_convert_to_target32(DUMP_DH_COMPRESSED_LZO,
endian);
pd.size = cpu_convert_to_target32(size_out, endian);
@@ -1379,9 +1355,9 @@ static int write_dump_pages(DumpState *s)
#endif
#ifdef CONFIG_SNAPPY
} else if ((s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) &&
(snappy_compress((char *)buf, s->page_size,
(snappy_compress((char *)buf, TARGET_PAGE_SIZE,
(char *)buf_out, &size_out) == SNAPPY_OK) &&
(size_out < s->page_size)) {
(size_out < TARGET_PAGE_SIZE)) {
pd.flags = cpu_convert_to_target32(
DUMP_DH_COMPRESSED_SNAPPY, endian);
pd.size = cpu_convert_to_target32(size_out, endian);
@@ -1395,13 +1371,13 @@ static int write_dump_pages(DumpState *s)
} else {
/*
* fall back to save in plaintext, size_out should be
* assigned to s->page_size
* assigned TARGET_PAGE_SIZE
*/
pd.flags = cpu_convert_to_target32(0, endian);
size_out = s->page_size;
size_out = TARGET_PAGE_SIZE;
pd.size = cpu_convert_to_target32(size_out, endian);
ret = write_cache(&page_data, buf, s->page_size, false);
ret = write_cache(&page_data, buf, TARGET_PAGE_SIZE, false);
if (ret < 0) {
dump_error(s, "dump: failed to write page data.\n");
goto out;
@@ -1536,7 +1512,7 @@ static void get_max_mapnr(DumpState *s)
GuestPhysBlock *last_block;
last_block = QTAILQ_LAST(&s->guest_phys_blocks.head, GuestPhysBlockHead);
s->max_mapnr = paddr_to_pfn(last_block->target_end, s->page_shift);
s->max_mapnr = paddr_to_pfn(last_block->target_end);
}
static int dump_init(DumpState *s, int fd, bool has_format,
@@ -1613,14 +1589,12 @@ static int dump_init(DumpState *s, int fd, bool has_format,
}
s->nr_cpus = nr_cpus;
s->page_size = TARGET_PAGE_SIZE;
s->page_shift = ffs(s->page_size) - 1;
get_max_mapnr(s);
uint64_t tmp;
tmp = DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), s->page_size);
s->len_dump_bitmap = tmp * s->page_size;
tmp = DIV_ROUND_UP(DIV_ROUND_UP(s->max_mapnr, CHAR_BIT), TARGET_PAGE_SIZE);
s->len_dump_bitmap = tmp * TARGET_PAGE_SIZE;
/* init for kdump-compressed format */
if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
@@ -1630,6 +1604,12 @@ static int dump_init(DumpState *s, int fd, bool has_format,
break;
case DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO:
#ifdef CONFIG_LZO
if (lzo_init() != LZO_E_OK) {
error_setg(errp, "failed to initialize the LZO library");
goto cleanup;
}
#endif
s->flag_compress = DUMP_DH_COMPRESSED_LZO;
break;

View File

@@ -335,6 +335,7 @@ ETEXI
.params = "tag|id",
.help = "restore a VM snapshot from its tag or id",
.mhandler.cmd = do_loadvm,
.command_completion = loadvm_completion,
},
STEXI
@@ -350,6 +351,7 @@ ETEXI
.params = "tag|id",
.help = "delete a VM snapshot from its tag or id",
.mhandler.cmd = do_delvm,
.command_completion = delvm_completion,
},
STEXI
@@ -852,6 +854,7 @@ ETEXI
.params = "device data",
.help = "Write to a ring buffer character device",
.mhandler.cmd = hmp_ringbuf_write,
.command_completion = ringbuf_write_completion,
},
STEXI
@@ -868,6 +871,7 @@ ETEXI
.params = "device size",
.help = "Read from a ring buffer character device",
.mhandler.cmd = hmp_ringbuf_read,
.command_completion = ringbuf_write_completion,
},
STEXI
@@ -973,6 +977,7 @@ ETEXI
.params = "capability state",
.help = "Enable/Disable the usage of a capability for migration",
.mhandler.cmd = hmp_migrate_set_capability,
.command_completion = migrate_set_capability_completion,
},
STEXI
@@ -1206,9 +1211,10 @@ ETEXI
{
.name = "host_net_add",
.args_type = "device:s,opts:s?",
.params = "tap|user|socket|vde|netmap|dump [options]",
.params = "tap|user|socket|vde|netmap|bridge|dump [options]",
.help = "add host VLAN client",
.mhandler.cmd = net_host_device_add,
.command_completion = host_net_add_completion,
},
STEXI
@@ -1223,6 +1229,7 @@ ETEXI
.params = "vlan_id name",
.help = "remove host VLAN client",
.mhandler.cmd = net_host_device_remove,
.command_completion = host_net_remove_completion,
},
STEXI
@@ -1357,6 +1364,7 @@ ETEXI
.params = "[reset|shutdown|poweroff|pause|debug|none]",
.help = "change watchdog action",
.mhandler.cmd = do_watchdog_action,
.command_completion = watchdog_action_completion,
},
STEXI

11
hmp.h
View File

@@ -103,5 +103,16 @@ void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str);
void set_link_completion(ReadLineState *rs, int nb_args, const char *str);
void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str);
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str);
void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str);
void ringbuf_read_completion(ReadLineState *rs, int nb_args, const char *str);
void watchdog_action_completion(ReadLineState *rs, int nb_args,
const char *str);
void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
const char *str);
void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str);
void host_net_remove_completion(ReadLineState *rs, int nb_args,
const char *str);
void delvm_completion(ReadLineState *rs, int nb_args, const char *str);
void loadvm_completion(ReadLineState *rs, int nb_args, const char *str);
#endif

View File

@@ -34,7 +34,7 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
len = strlen(s->tag);
cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
stw_raw(&cfg->tag_len, len);
stw_p(&cfg->tag_len, len);
/* We don't copy the terminating null to config space */
memcpy(cfg->tag, s->tag, len);
memcpy(config, cfg, s->config_size);

View File

@@ -239,8 +239,9 @@ static void n800_key_event(void *opaque, int keycode)
int code = s->keymap[keycode & 0x7f];
if (code == -1) {
if ((keycode & 0x7f) == RETU_KEYCODE)
if ((keycode & 0x7f) == RETU_KEYCODE) {
retu_key_event(s->retu, !(keycode & 0x80));
}
return;
}
@@ -280,11 +281,14 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
s->ts.opaque = s->ts.chip->opaque;
s->ts.txrx = tsc210x_txrx;
for (i = 0; i < 0x80; i ++)
for (i = 0; i < 0x80; i++) {
s->keymap[i] = -1;
for (i = 0; i < 0x10; i ++)
if (n800_keys[i] >= 0)
}
for (i = 0; i < 0x10; i++) {
if (n800_keys[i] >= 0) {
s->keymap[n800_keys[i]] = i;
}
}
qemu_add_kbd_event_handler(n800_key_event, s);
@@ -308,8 +312,9 @@ static void n810_key_event(void *opaque, int keycode)
int code = s->keymap[keycode & 0x7f];
if (code == -1) {
if ((keycode & 0x7f) == RETU_KEYCODE)
if ((keycode & 0x7f) == RETU_KEYCODE) {
retu_key_event(s->retu, !(keycode & 0x80));
}
return;
}
@@ -388,11 +393,14 @@ static void n810_kbd_setup(struct n800_s *s)
qemu_irq kbd_irq = qdev_get_gpio_in(s->mpu->gpio, N810_KEYBOARD_GPIO);
int i;
for (i = 0; i < 0x80; i ++)
for (i = 0; i < 0x80; i++) {
s->keymap[i] = -1;
for (i = 0; i < 0x80; i ++)
if (n810_keys[i] > 0)
}
for (i = 0; i < 0x80; i++) {
if (n810_keys[i] > 0) {
s->keymap[n810_keys[i]] = i;
}
}
qemu_add_kbd_event_handler(n810_key_event, s);
@@ -449,17 +457,20 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
struct mipid_s *s = (struct mipid_s *) opaque;
uint8_t ret;
if (len > 9)
if (len > 9) {
hw_error("%s: FIXME: bad SPI word width %i\n", __FUNCTION__, len);
}
if (s->p >= ARRAY_SIZE(s->resp))
if (s->p >= ARRAY_SIZE(s->resp)) {
ret = 0;
else
ret = s->resp[s->p ++];
if (s->pm --> 0)
} else {
ret = s->resp[s->p++];
}
if (s->pm-- > 0) {
s->param[s->pm] = cmd;
else
} else {
s->cmd = cmd;
}
switch (s->cmd) {
case 0x00: /* NOP */
@@ -560,15 +571,17 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
goto bad_cmd;
case 0x25: /* WRCNTR */
if (s->pm < 0)
if (s->pm < 0) {
s->pm = 1;
}
goto bad_cmd;
case 0x26: /* GAMSET */
if (!s->pm)
if (!s->pm) {
s->gamma = ffs(s->param[0] & 0xf) - 1;
else if (s->pm < 0)
} else if (s->pm < 0) {
s->pm = 1;
}
break;
case 0x28: /* DISPOFF */
@@ -591,10 +604,11 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
s->te = 0;
break;
case 0x35: /* TEON */
if (!s->pm)
if (!s->pm) {
s->te = 1;
else if (s->pm < 0)
} else if (s->pm < 0) {
s->pm = 1;
}
break;
case 0x36: /* MADCTR */
@@ -613,8 +627,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
case 0xb0: /* CLKINT / DISCTL */
case 0xb1: /* CLKEXT */
if (s->pm < 0)
if (s->pm < 0) {
s->pm = 2;
}
break;
case 0xb4: /* FRMSEL */
@@ -635,8 +650,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len)
break;
case 0xc2: /* IFMOD */
if (s->pm < 0)
if (s->pm < 0) {
s->pm = 2;
}
break;
case 0xc6: /* PWRCTL */
@@ -834,118 +850,119 @@ static void n800_setup_nolo_tags(void *sram_base)
strcpy((void *) (p + 8), "F5");
stl_raw(p + 10, 0x04f70000);
stl_p(p + 10, 0x04f70000);
strcpy((void *) (p + 9), "RX-34");
/* RAM size in MB? */
stl_raw(p + 12, 0x80);
stl_p(p + 12, 0x80);
/* Pointer to the list of tags */
stl_raw(p + 13, OMAP2_SRAM_BASE + 0x9000);
stl_p(p + 13, OMAP2_SRAM_BASE + 0x9000);
/* The NOLO tags start here */
p = sram_base + 0x9000;
#define ADD_TAG(tag, len) \
stw_raw((uint16_t *) p + 0, tag); \
stw_raw((uint16_t *) p + 1, len); p ++; \
stl_raw(p ++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
stw_p((uint16_t *) p + 0, tag); \
stw_p((uint16_t *) p + 1, len); p++; \
stl_p(p++, OMAP2_SRAM_BASE | (((void *) v - sram_base) & 0xffff));
/* OMAP STI console? Pin out settings? */
ADD_TAG(0x6e01, 414);
for (i = 0; i < ARRAY_SIZE(n800_pinout); i ++)
stl_raw(v ++, n800_pinout[i]);
for (i = 0; i < ARRAY_SIZE(n800_pinout); i++) {
stl_p(v++, n800_pinout[i]);
}
/* Kernel memsize? */
ADD_TAG(0x6e05, 1);
stl_raw(v ++, 2);
stl_p(v++, 2);
/* NOLO serial console */
ADD_TAG(0x6e02, 4);
stl_raw(v ++, XLDR_LL_UART); /* UART number (1 - 3) */
stl_p(v++, XLDR_LL_UART); /* UART number (1 - 3) */
#if 0
/* CBUS settings (Retu/AVilma) */
ADD_TAG(0x6e03, 6);
stw_raw((uint16_t *) v + 0, 65); /* CBUS GPIO0 */
stw_raw((uint16_t *) v + 1, 66); /* CBUS GPIO1 */
stw_raw((uint16_t *) v + 2, 64); /* CBUS GPIO2 */
stw_p((uint16_t *) v + 0, 65); /* CBUS GPIO0 */
stw_p((uint16_t *) v + 1, 66); /* CBUS GPIO1 */
stw_p((uint16_t *) v + 2, 64); /* CBUS GPIO2 */
v += 2;
#endif
/* Nokia ASIC BB5 (Retu/Tahvo) */
ADD_TAG(0x6e0a, 4);
stw_raw((uint16_t *) v + 0, 111); /* "Retu" interrupt GPIO */
stw_raw((uint16_t *) v + 1, 108); /* "Tahvo" interrupt GPIO */
v ++;
stw_p((uint16_t *) v + 0, 111); /* "Retu" interrupt GPIO */
stw_p((uint16_t *) v + 1, 108); /* "Tahvo" interrupt GPIO */
v++;
/* LCD console? */
ADD_TAG(0x6e04, 4);
stw_raw((uint16_t *) v + 0, 30); /* ??? */
stw_raw((uint16_t *) v + 1, 24); /* ??? */
v ++;
stw_p((uint16_t *) v + 0, 30); /* ??? */
stw_p((uint16_t *) v + 1, 24); /* ??? */
v++;
#if 0
/* LCD settings */
ADD_TAG(0x6e06, 2);
stw_raw((uint16_t *) (v ++), 15); /* ??? */
stw_p((uint16_t *) (v++), 15); /* ??? */
#endif
/* I^2C (Menelaus) */
ADD_TAG(0x6e07, 4);
stl_raw(v ++, 0x00720000); /* ??? */
stl_p(v++, 0x00720000); /* ??? */
/* Unknown */
ADD_TAG(0x6e0b, 6);
stw_raw((uint16_t *) v + 0, 94); /* ??? */
stw_raw((uint16_t *) v + 1, 23); /* ??? */
stw_raw((uint16_t *) v + 2, 0); /* ??? */
stw_p((uint16_t *) v + 0, 94); /* ??? */
stw_p((uint16_t *) v + 1, 23); /* ??? */
stw_p((uint16_t *) v + 2, 0); /* ??? */
v += 2;
/* OMAP gpio switch info */
ADD_TAG(0x6e0c, 80);
strcpy((void *) v, "bat_cover"); v += 3;
stw_raw((uint16_t *) v + 0, 110); /* GPIO num ??? */
stw_raw((uint16_t *) v + 1, 1); /* GPIO num ??? */
stw_p((uint16_t *) v + 0, 110); /* GPIO num ??? */
stw_p((uint16_t *) v + 1, 1); /* GPIO num ??? */
v += 2;
strcpy((void *) v, "cam_act"); v += 3;
stw_raw((uint16_t *) v + 0, 95); /* GPIO num ??? */
stw_raw((uint16_t *) v + 1, 32); /* GPIO num ??? */
stw_p((uint16_t *) v + 0, 95); /* GPIO num ??? */
stw_p((uint16_t *) v + 1, 32); /* GPIO num ??? */
v += 2;
strcpy((void *) v, "cam_turn"); v += 3;
stw_raw((uint16_t *) v + 0, 12); /* GPIO num ??? */
stw_raw((uint16_t *) v + 1, 33); /* GPIO num ??? */
stw_p((uint16_t *) v + 0, 12); /* GPIO num ??? */
stw_p((uint16_t *) v + 1, 33); /* GPIO num ??? */
v += 2;
strcpy((void *) v, "headphone"); v += 3;
stw_raw((uint16_t *) v + 0, 107); /* GPIO num ??? */
stw_raw((uint16_t *) v + 1, 17); /* GPIO num ??? */
stw_p((uint16_t *) v + 0, 107); /* GPIO num ??? */
stw_p((uint16_t *) v + 1, 17); /* GPIO num ??? */
v += 2;
/* Bluetooth */
ADD_TAG(0x6e0e, 12);
stl_raw(v ++, 0x5c623d01); /* ??? */
stl_raw(v ++, 0x00000201); /* ??? */
stl_raw(v ++, 0x00000000); /* ??? */
stl_p(v++, 0x5c623d01); /* ??? */
stl_p(v++, 0x00000201); /* ??? */
stl_p(v++, 0x00000000); /* ??? */
/* CX3110x WLAN settings */
ADD_TAG(0x6e0f, 8);
stl_raw(v ++, 0x00610025); /* ??? */
stl_raw(v ++, 0xffff0057); /* ??? */
stl_p(v++, 0x00610025); /* ??? */
stl_p(v++, 0xffff0057); /* ??? */
/* MMC host settings */
ADD_TAG(0x6e10, 12);
stl_raw(v ++, 0xffff000f); /* ??? */
stl_raw(v ++, 0xffffffff); /* ??? */
stl_raw(v ++, 0x00000060); /* ??? */
stl_p(v++, 0xffff000f); /* ??? */
stl_p(v++, 0xffffffff); /* ??? */
stl_p(v++, 0x00000060); /* ??? */
/* OneNAND chip select */
ADD_TAG(0x6e11, 10);
stl_raw(v ++, 0x00000401); /* ??? */
stl_raw(v ++, 0x0002003a); /* ??? */
stl_raw(v ++, 0x00000002); /* ??? */
stl_p(v++, 0x00000401); /* ??? */
stl_p(v++, 0x0002003a); /* ??? */
stl_p(v++, 0x00000002); /* ??? */
/* TEA5761 sensor settings */
ADD_TAG(0x6e12, 2);
stl_raw(v ++, 93); /* GPIO num ??? */
stl_p(v++, 93); /* GPIO num ??? */
#if 0
/* Unknown tag */
@@ -956,8 +973,8 @@ static void n800_setup_nolo_tags(void *sram_base)
#endif
/* End of the list */
stl_raw(p ++, 0x00000000);
stl_raw(p ++, 0x00000000);
stl_p(p++, 0x00000000);
stl_p(p++, 0x00000000);
}
/* This task is normally performed by the bootloader. If we're loading
@@ -1032,8 +1049,9 @@ static void n8x0_boot_init(void *opaque)
s->mpu->cpu->env.GE = 0x5;
/* If the machine has a slided keyboard, open it */
if (s->kbd)
if (s->kbd) {
qemu_irq_raise(qdev_get_gpio_in(s->mpu->gpio, N810_SLIDE_GPIO));
}
}
#define OMAP_TAG_NOKIA_BT 0x4e01
@@ -1119,112 +1137,112 @@ static int n8x0_atag_setup(void *p, int model)
w = p;
stw_raw(w ++, OMAP_TAG_UART); /* u16 tag */
stw_raw(w ++, 4); /* u16 len */
stw_raw(w ++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
w ++;
stw_p(w++, OMAP_TAG_UART); /* u16 tag */
stw_p(w++, 4); /* u16 len */
stw_p(w++, (1 << 2) | (1 << 1) | (1 << 0)); /* uint enabled_uarts */
w++;
#if 0
stw_raw(w ++, OMAP_TAG_SERIAL_CONSOLE); /* u16 tag */
stw_raw(w ++, 4); /* u16 len */
stw_raw(w ++, XLDR_LL_UART + 1); /* u8 console_uart */
stw_raw(w ++, 115200); /* u32 console_speed */
stw_p(w++, OMAP_TAG_SERIAL_CONSOLE); /* u16 tag */
stw_p(w++, 4); /* u16 len */
stw_p(w++, XLDR_LL_UART + 1); /* u8 console_uart */
stw_p(w++, 115200); /* u32 console_speed */
#endif
stw_raw(w ++, OMAP_TAG_LCD); /* u16 tag */
stw_raw(w ++, 36); /* u16 len */
stw_p(w++, OMAP_TAG_LCD); /* u16 tag */
stw_p(w++, 36); /* u16 len */
strcpy((void *) w, "QEMU LCD panel"); /* char panel_name[16] */
w += 8;
strcpy((void *) w, "blizzard"); /* char ctrl_name[16] */
w += 8;
stw_raw(w ++, N810_BLIZZARD_RESET_GPIO); /* TODO: n800 s16 nreset_gpio */
stw_raw(w ++, 24); /* u8 data_lines */
stw_p(w++, N810_BLIZZARD_RESET_GPIO); /* TODO: n800 s16 nreset_gpio */
stw_p(w++, 24); /* u8 data_lines */
stw_raw(w ++, OMAP_TAG_CBUS); /* u16 tag */
stw_raw(w ++, 8); /* u16 len */
stw_raw(w ++, N8X0_CBUS_CLK_GPIO); /* s16 clk_gpio */
stw_raw(w ++, N8X0_CBUS_DAT_GPIO); /* s16 dat_gpio */
stw_raw(w ++, N8X0_CBUS_SEL_GPIO); /* s16 sel_gpio */
w ++;
stw_p(w++, OMAP_TAG_CBUS); /* u16 tag */
stw_p(w++, 8); /* u16 len */
stw_p(w++, N8X0_CBUS_CLK_GPIO); /* s16 clk_gpio */
stw_p(w++, N8X0_CBUS_DAT_GPIO); /* s16 dat_gpio */
stw_p(w++, N8X0_CBUS_SEL_GPIO); /* s16 sel_gpio */
w++;
stw_raw(w ++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */
stw_raw(w ++, 4); /* u16 len */
stw_raw(w ++, N8X0_RETU_GPIO); /* s16 retu_irq_gpio */
stw_raw(w ++, N8X0_TAHVO_GPIO); /* s16 tahvo_irq_gpio */
stw_p(w++, OMAP_TAG_EM_ASIC_BB5); /* u16 tag */
stw_p(w++, 4); /* u16 len */
stw_p(w++, N8X0_RETU_GPIO); /* s16 retu_irq_gpio */
stw_p(w++, N8X0_TAHVO_GPIO); /* s16 tahvo_irq_gpio */
gpiosw = (model == 810) ? n810_gpiosw_info : n800_gpiosw_info;
for (; gpiosw->name; gpiosw ++) {
stw_raw(w ++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
stw_raw(w ++, 20); /* u16 len */
for (; gpiosw->name; gpiosw++) {
stw_p(w++, OMAP_TAG_GPIO_SWITCH); /* u16 tag */
stw_p(w++, 20); /* u16 len */
strcpy((void *) w, gpiosw->name); /* char name[12] */
w += 6;
stw_raw(w ++, gpiosw->line); /* u16 gpio */
stw_raw(w ++, gpiosw->type);
stw_raw(w ++, 0);
stw_raw(w ++, 0);
stw_p(w++, gpiosw->line); /* u16 gpio */
stw_p(w++, gpiosw->type);
stw_p(w++, 0);
stw_p(w++, 0);
}
stw_raw(w ++, OMAP_TAG_NOKIA_BT); /* u16 tag */
stw_raw(w ++, 12); /* u16 len */
stw_p(w++, OMAP_TAG_NOKIA_BT); /* u16 tag */
stw_p(w++, 12); /* u16 len */
b = (void *) w;
stb_raw(b ++, 0x01); /* u8 chip_type (CSR) */
stb_raw(b ++, N8X0_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */
stb_raw(b ++, N8X0_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */
stb_raw(b ++, N8X0_BT_RESET_GPIO); /* u8 reset_gpio */
stb_raw(b ++, BT_UART + 1); /* u8 bt_uart */
stb_p(b++, 0x01); /* u8 chip_type (CSR) */
stb_p(b++, N8X0_BT_WKUP_GPIO); /* u8 bt_wakeup_gpio */
stb_p(b++, N8X0_BT_HOST_WKUP_GPIO); /* u8 host_wakeup_gpio */
stb_p(b++, N8X0_BT_RESET_GPIO); /* u8 reset_gpio */
stb_p(b++, BT_UART + 1); /* u8 bt_uart */
memcpy(b, &n8x0_bd_addr, 6); /* u8 bd_addr[6] */
b += 6;
stb_raw(b ++, 0x02); /* u8 bt_sysclk (38.4) */
stb_p(b++, 0x02); /* u8 bt_sysclk (38.4) */
w = (void *) b;
stw_raw(w ++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */
stw_raw(w ++, 8); /* u16 len */
stw_raw(w ++, 0x25); /* u8 chip_type */
stw_raw(w ++, N8X0_WLAN_PWR_GPIO); /* s16 power_gpio */
stw_raw(w ++, N8X0_WLAN_IRQ_GPIO); /* s16 irq_gpio */
stw_raw(w ++, -1); /* s16 spi_cs_gpio */
stw_p(w++, OMAP_TAG_WLAN_CX3110X); /* u16 tag */
stw_p(w++, 8); /* u16 len */
stw_p(w++, 0x25); /* u8 chip_type */
stw_p(w++, N8X0_WLAN_PWR_GPIO); /* s16 power_gpio */
stw_p(w++, N8X0_WLAN_IRQ_GPIO); /* s16 irq_gpio */
stw_p(w++, -1); /* s16 spi_cs_gpio */
stw_raw(w ++, OMAP_TAG_MMC); /* u16 tag */
stw_raw(w ++, 16); /* u16 len */
stw_p(w++, OMAP_TAG_MMC); /* u16 tag */
stw_p(w++, 16); /* u16 len */
if (model == 810) {
stw_raw(w ++, 0x23f); /* unsigned flags */
stw_raw(w ++, -1); /* s16 power_pin */
stw_raw(w ++, -1); /* s16 switch_pin */
stw_raw(w ++, -1); /* s16 wp_pin */
stw_raw(w ++, 0x240); /* unsigned flags */
stw_raw(w ++, 0xc000); /* s16 power_pin */
stw_raw(w ++, 0x0248); /* s16 switch_pin */
stw_raw(w ++, 0xc000); /* s16 wp_pin */
stw_p(w++, 0x23f); /* unsigned flags */
stw_p(w++, -1); /* s16 power_pin */
stw_p(w++, -1); /* s16 switch_pin */
stw_p(w++, -1); /* s16 wp_pin */
stw_p(w++, 0x240); /* unsigned flags */
stw_p(w++, 0xc000); /* s16 power_pin */
stw_p(w++, 0x0248); /* s16 switch_pin */
stw_p(w++, 0xc000); /* s16 wp_pin */
} else {
stw_raw(w ++, 0xf); /* unsigned flags */
stw_raw(w ++, -1); /* s16 power_pin */
stw_raw(w ++, -1); /* s16 switch_pin */
stw_raw(w ++, -1); /* s16 wp_pin */
stw_raw(w ++, 0); /* unsigned flags */
stw_raw(w ++, 0); /* s16 power_pin */
stw_raw(w ++, 0); /* s16 switch_pin */
stw_raw(w ++, 0); /* s16 wp_pin */
stw_p(w++, 0xf); /* unsigned flags */
stw_p(w++, -1); /* s16 power_pin */
stw_p(w++, -1); /* s16 switch_pin */
stw_p(w++, -1); /* s16 wp_pin */
stw_p(w++, 0); /* unsigned flags */
stw_p(w++, 0); /* s16 power_pin */
stw_p(w++, 0); /* s16 switch_pin */
stw_p(w++, 0); /* s16 wp_pin */
}
stw_raw(w ++, OMAP_TAG_TEA5761); /* u16 tag */
stw_raw(w ++, 4); /* u16 len */
stw_raw(w ++, N8X0_TEA5761_CS_GPIO); /* u16 enable_gpio */
w ++;
stw_p(w++, OMAP_TAG_TEA5761); /* u16 tag */
stw_p(w++, 4); /* u16 len */
stw_p(w++, N8X0_TEA5761_CS_GPIO); /* u16 enable_gpio */
w++;
partition = (model == 810) ? n810_part_info : n800_part_info;
for (; partition->name; partition ++) {
stw_raw(w ++, OMAP_TAG_PARTITION); /* u16 tag */
stw_raw(w ++, 28); /* u16 len */
for (; partition->name; partition++) {
stw_p(w++, OMAP_TAG_PARTITION); /* u16 tag */
stw_p(w++, 28); /* u16 len */
strcpy((void *) w, partition->name); /* char name[16] */
l = (void *) (w + 8);
stl_raw(l ++, partition->size); /* unsigned int size */
stl_raw(l ++, partition->offset); /* unsigned int offset */
stl_raw(l ++, partition->mask); /* unsigned int mask_flags */
stl_p(l++, partition->size); /* unsigned int size */
stl_p(l++, partition->offset); /* unsigned int offset */
stl_p(l++, partition->mask); /* unsigned int mask_flags */
w = (void *) l;
}
stw_raw(w ++, OMAP_TAG_BOOT_REASON); /* u16 tag */
stw_raw(w ++, 12); /* u16 len */
stw_p(w++, OMAP_TAG_BOOT_REASON); /* u16 tag */
stw_p(w++, 12); /* u16 len */
#if 0
strcpy((void *) w, "por"); /* char reason_str[12] */
strcpy((void *) w, "charger"); /* char reason_str[12] */
@@ -1242,15 +1260,15 @@ static int n8x0_atag_setup(void *p, int model)
w += 6;
tag = (model == 810) ? "RX-44" : "RX-34";
stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
stw_raw(w ++, 24); /* u16 len */
stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
stw_p(w++, 24); /* u16 len */
strcpy((void *) w, "product"); /* char component[12] */
w += 6;
strcpy((void *) w, tag); /* char version[12] */
w += 6;
stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
stw_raw(w ++, 24); /* u16 len */
stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
stw_p(w++, 24); /* u16 len */
strcpy((void *) w, "hw-build"); /* char component[12] */
w += 6;
strcpy((void *) w, "QEMU ");
@@ -1258,8 +1276,8 @@ static int n8x0_atag_setup(void *p, int model)
w += 6;
tag = (model == 810) ? "1.1.10-qemu" : "1.1.6-qemu";
stw_raw(w ++, OMAP_TAG_VERSION_STR); /* u16 tag */
stw_raw(w ++, 24); /* u16 len */
stw_p(w++, OMAP_TAG_VERSION_STR); /* u16 tag */
stw_p(w++, 24); /* u16 len */
strcpy((void *) w, "nolo"); /* char component[12] */
w += 6;
strcpy((void *) w, tag); /* char version[12] */
@@ -1315,9 +1333,9 @@ static void n8x0_init(MachineState *machine,
n8x0_gpio_setup(s);
n8x0_nand_setup(s);
n8x0_i2c_setup(s);
if (model == 800)
if (model == 800) {
n800_tsc_kbd_setup(s);
else if (model == 810) {
} else if (model == 810) {
n810_tsc_setup(s);
n810_kbd_setup(s);
}

View File

@@ -28,6 +28,7 @@
#include "net/net.h"
#include "sysemu/sysemu.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "exec/address-spaces.h"
#include "sysemu/blockdev.h"
#include "hw/block/flash.h"
@@ -528,6 +529,18 @@ static void vexpress_common_init(VEDBoardInfo *daughterboard,
daughterboard->init(daughterboard, machine->ram_size, machine->cpu_model,
pic);
/*
* If a bios file was provided, attempt to map it into memory
*/
if (bios_name) {
const char *fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (!fn || load_image_targphys(fn, map[VE_NORFLASH0],
VEXPRESS_FLASH_SIZE) < 0) {
error_report("Could not load ROM image '%s'", bios_name);
exit(1);
}
}
/* Motherboard peripherals: the wiring is the same but the
* addresses vary between the legacy and A-Series memory maps.
*/

View File

@@ -1 +1 @@
obj-y += ioq.o virtio-blk.o
obj-y += virtio-blk.o

View File

@@ -1,117 +0,0 @@
/*
* Linux AIO request queue
*
* Copyright 2012 IBM, Corp.
* Copyright 2012 Red Hat, Inc. and/or its affiliates
*
* Authors:
* Stefan Hajnoczi <stefanha@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 "ioq.h"
void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs)
{
int rc;
ioq->fd = fd;
ioq->max_reqs = max_reqs;
memset(&ioq->io_ctx, 0, sizeof ioq->io_ctx);
rc = io_setup(max_reqs, &ioq->io_ctx);
if (rc != 0) {
fprintf(stderr, "ioq io_setup failed %d\n", rc);
exit(1);
}
rc = event_notifier_init(&ioq->io_notifier, 0);
if (rc != 0) {
fprintf(stderr, "ioq io event notifier creation failed %d\n", rc);
exit(1);
}
ioq->freelist = g_malloc0(sizeof ioq->freelist[0] * max_reqs);
ioq->freelist_idx = 0;
ioq->queue = g_malloc0(sizeof ioq->queue[0] * max_reqs);
ioq->queue_idx = 0;
}
void ioq_cleanup(IOQueue *ioq)
{
g_free(ioq->freelist);
g_free(ioq->queue);
event_notifier_cleanup(&ioq->io_notifier);
io_destroy(ioq->io_ctx);
}
EventNotifier *ioq_get_notifier(IOQueue *ioq)
{
return &ioq->io_notifier;
}
struct iocb *ioq_get_iocb(IOQueue *ioq)
{
/* Underflow cannot happen since ioq is sized for max_reqs */
assert(ioq->freelist_idx != 0);
struct iocb *iocb = ioq->freelist[--ioq->freelist_idx];
ioq->queue[ioq->queue_idx++] = iocb;
return iocb;
}
void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb)
{
/* Overflow cannot happen since ioq is sized for max_reqs */
assert(ioq->freelist_idx != ioq->max_reqs);
ioq->freelist[ioq->freelist_idx++] = iocb;
}
struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov,
unsigned int count, long long offset)
{
struct iocb *iocb = ioq_get_iocb(ioq);
if (read) {
io_prep_preadv(iocb, ioq->fd, iov, count, offset);
} else {
io_prep_pwritev(iocb, ioq->fd, iov, count, offset);
}
io_set_eventfd(iocb, event_notifier_get_fd(&ioq->io_notifier));
return iocb;
}
int ioq_submit(IOQueue *ioq)
{
int rc = io_submit(ioq->io_ctx, ioq->queue_idx, ioq->queue);
ioq->queue_idx = 0; /* reset */
return rc;
}
int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion,
void *opaque)
{
struct io_event events[ioq->max_reqs];
int nevents, i;
do {
nevents = io_getevents(ioq->io_ctx, 0, ioq->max_reqs, events, NULL);
} while (nevents < 0 && errno == EINTR);
if (nevents < 0) {
return nevents;
}
for (i = 0; i < nevents; i++) {
ssize_t ret = ((uint64_t)events[i].res2 << 32) | events[i].res;
completion(events[i].obj, ret, opaque);
ioq_put_iocb(ioq, events[i].obj);
}
return nevents;
}

View File

@@ -1,57 +0,0 @@
/*
* Linux AIO request queue
*
* Copyright 2012 IBM, Corp.
* Copyright 2012 Red Hat, Inc. and/or its affiliates
*
* Authors:
* Stefan Hajnoczi <stefanha@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.
*
*/
#ifndef IOQ_H
#define IOQ_H
#include <libaio.h>
#include "qemu/event_notifier.h"
typedef struct {
int fd; /* file descriptor */
unsigned int max_reqs; /* max length of freelist and queue */
io_context_t io_ctx; /* Linux AIO context */
EventNotifier io_notifier; /* Linux AIO eventfd */
/* Requests can complete in any order so a free list is necessary to manage
* available iocbs.
*/
struct iocb **freelist; /* free iocbs */
unsigned int freelist_idx;
/* Multiple requests are queued up before submitting them all in one go */
struct iocb **queue; /* queued iocbs */
unsigned int queue_idx;
} IOQueue;
void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs);
void ioq_cleanup(IOQueue *ioq);
EventNotifier *ioq_get_notifier(IOQueue *ioq);
struct iocb *ioq_get_iocb(IOQueue *ioq);
void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb);
struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov,
unsigned int count, long long offset);
int ioq_submit(IOQueue *ioq);
static inline unsigned int ioq_num_queued(IOQueue *ioq)
{
return ioq->queue_idx;
}
typedef void IOQueueCompletion(struct iocb *iocb, ssize_t ret, void *opaque);
int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion,
void *opaque);
#endif /* IOQ_H */

View File

@@ -17,7 +17,6 @@
#include "qemu/thread.h"
#include "qemu/error-report.h"
#include "hw/virtio/dataplane/vring.h"
#include "ioq.h"
#include "block/block.h"
#include "hw/virtio/virtio-blk.h"
#include "virtio-blk.h"
@@ -25,20 +24,14 @@
#include "hw/virtio/virtio-bus.h"
#include "qom/object_interfaces.h"
enum {
SEG_MAX = 126, /* maximum number of I/O segments */
VRING_MAX = SEG_MAX + 2, /* maximum number of vring descriptors */
REQ_MAX = VRING_MAX, /* maximum number of requests in the vring,
* is VRING_MAX / 2 with traditional and
* VRING_MAX with indirect descriptors */
};
typedef struct {
struct iocb iocb; /* Linux AIO control block */
VirtIOBlockDataPlane *s;
QEMUIOVector *inhdr; /* iovecs for virtio_blk_inhdr */
VirtQueueElement *elem; /* saved data from the virtqueue */
struct iovec *bounce_iov; /* used if guest buffers are unaligned */
QEMUIOVector *read_qiov; /* for read completion /w bounce buffer */
QEMUIOVector qiov; /* original request iovecs */
struct iovec bounce_iov; /* used if guest buffers are unaligned */
QEMUIOVector bounce_qiov; /* bounce buffer iovecs */
bool read; /* read or write? */
} VirtIOBlockRequest;
struct VirtIOBlockDataPlane {
@@ -47,7 +40,6 @@ struct VirtIOBlockDataPlane {
bool stopping;
VirtIOBlkConf *blk;
int fd; /* image file descriptor */
VirtIODevice *vdev;
Vring vring; /* virtqueue vring */
@@ -61,16 +53,8 @@ struct VirtIOBlockDataPlane {
IOThread *iothread;
IOThread internal_iothread_obj;
AioContext *ctx;
EventNotifier io_notifier; /* Linux AIO completion */
EventNotifier host_notifier; /* doorbell */
IOQueue ioqueue; /* Linux AIO queue (should really be per
IOThread) */
VirtIOBlockRequest requests[REQ_MAX]; /* pool of requests, managed by the
queue */
unsigned int num_reqs;
/* Operation blocker on BDS */
Error *blocker;
};
@@ -85,33 +69,28 @@ static void notify_guest(VirtIOBlockDataPlane *s)
event_notifier_set(s->guest_notifier);
}
static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque)
static void complete_rdwr(void *opaque, int ret)
{
VirtIOBlockDataPlane *s = opaque;
VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb);
VirtIOBlockRequest *req = opaque;
struct virtio_blk_inhdr hdr;
int len;
if (likely(ret >= 0)) {
if (likely(ret == 0)) {
hdr.status = VIRTIO_BLK_S_OK;
len = ret;
len = req->qiov.size;
} else {
hdr.status = VIRTIO_BLK_S_IOERR;
len = 0;
}
trace_virtio_blk_data_plane_complete_request(s, req->elem->index, ret);
trace_virtio_blk_data_plane_complete_request(req->s, req->elem->index, ret);
if (req->read_qiov) {
assert(req->bounce_iov);
qemu_iovec_from_buf(req->read_qiov, 0, req->bounce_iov->iov_base, len);
qemu_iovec_destroy(req->read_qiov);
g_slice_free(QEMUIOVector, req->read_qiov);
if (req->read && req->bounce_iov.iov_base) {
qemu_iovec_from_buf(&req->qiov, 0, req->bounce_iov.iov_base, len);
}
if (req->bounce_iov) {
qemu_vfree(req->bounce_iov->iov_base);
g_slice_free(struct iovec, req->bounce_iov);
if (req->bounce_iov.iov_base) {
qemu_vfree(req->bounce_iov.iov_base);
}
qemu_iovec_from_buf(req->inhdr, 0, &hdr, sizeof(hdr));
@@ -122,9 +101,9 @@ static void complete_request(struct iocb *iocb, ssize_t ret, void *opaque)
* written to, but for virtio-blk it seems to be the number of bytes
* transferred plus the status bytes.
*/
vring_push(&s->vring, req->elem, len + sizeof(hdr));
req->elem = NULL;
s->num_reqs--;
vring_push(&req->s->vring, req->elem, len + sizeof(hdr));
notify_guest(req->s);
g_slice_free(VirtIOBlockRequest, req);
}
static void complete_request_early(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
@@ -155,51 +134,87 @@ static void do_get_id_cmd(VirtIOBlockDataPlane *s,
complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_OK);
}
static int do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read,
static void do_rdwr_cmd(VirtIOBlockDataPlane *s, bool read,
struct iovec *iov, unsigned iov_cnt,
long long offset, VirtQueueElement *elem,
int64_t sector_num, VirtQueueElement *elem,
QEMUIOVector *inhdr)
{
struct iocb *iocb;
QEMUIOVector qiov;
struct iovec *bounce_iov = NULL;
QEMUIOVector *read_qiov = NULL;
VirtIOBlockRequest *req = g_slice_new0(VirtIOBlockRequest);
QEMUIOVector *qiov;
int nb_sectors;
qemu_iovec_init_external(&qiov, iov, iov_cnt);
if (!bdrv_qiov_is_aligned(s->blk->conf.bs, &qiov)) {
void *bounce_buffer = qemu_blockalign(s->blk->conf.bs, qiov.size);
/* Fill in virtio block metadata needed for completion */
req->s = s;
req->elem = elem;
req->inhdr = inhdr;
req->read = read;
qemu_iovec_init_external(&req->qiov, iov, iov_cnt);
if (read) {
/* Need to copy back from bounce buffer on completion */
read_qiov = g_slice_new(QEMUIOVector);
qemu_iovec_init(read_qiov, iov_cnt);
qemu_iovec_concat_iov(read_qiov, iov, iov_cnt, 0, qiov.size);
} else {
qemu_iovec_to_buf(&qiov, 0, bounce_buffer, qiov.size);
qiov = &req->qiov;
if (!bdrv_qiov_is_aligned(s->blk->conf.bs, qiov)) {
void *bounce_buffer = qemu_blockalign(s->blk->conf.bs, qiov->size);
/* Populate bounce buffer with data for writes */
if (!read) {
qemu_iovec_to_buf(qiov, 0, bounce_buffer, qiov->size);
}
/* Redirect I/O to aligned bounce buffer */
bounce_iov = g_slice_new(struct iovec);
bounce_iov->iov_base = bounce_buffer;
bounce_iov->iov_len = qiov.size;
iov = bounce_iov;
iov_cnt = 1;
req->bounce_iov.iov_base = bounce_buffer;
req->bounce_iov.iov_len = qiov->size;
qemu_iovec_init_external(&req->bounce_qiov, &req->bounce_iov, 1);
qiov = &req->bounce_qiov;
}
iocb = ioq_rdwr(&s->ioqueue, read, iov, iov_cnt, offset);
nb_sectors = qiov->size / BDRV_SECTOR_SIZE;
/* Fill in virtio block metadata needed for completion */
VirtIOBlockRequest *req = container_of(iocb, VirtIOBlockRequest, iocb);
req->elem = elem;
req->inhdr = inhdr;
req->bounce_iov = bounce_iov;
req->read_qiov = read_qiov;
return 0;
if (read) {
bdrv_aio_readv(s->blk->conf.bs, sector_num, qiov, nb_sectors,
complete_rdwr, req);
} else {
bdrv_aio_writev(s->blk->conf.bs, sector_num, qiov, nb_sectors,
complete_rdwr, req);
}
}
static int process_request(IOQueue *ioq, VirtQueueElement *elem)
static void complete_flush(void *opaque, int ret)
{
VirtIOBlockRequest *req = opaque;
unsigned char status;
if (ret == 0) {
status = VIRTIO_BLK_S_OK;
} else {
status = VIRTIO_BLK_S_IOERR;
}
complete_request_early(req->s, req->elem, req->inhdr, status);
g_slice_free(VirtIOBlockRequest, req);
}
static void do_flush_cmd(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
QEMUIOVector *inhdr)
{
VirtIOBlockRequest *req = g_slice_new(VirtIOBlockRequest);
req->s = s;
req->elem = elem;
req->inhdr = inhdr;
bdrv_aio_flush(s->blk->conf.bs, complete_flush, req);
}
static void do_scsi_cmd(VirtIOBlockDataPlane *s, VirtQueueElement *elem,
QEMUIOVector *inhdr)
{
int status;
status = virtio_blk_handle_scsi_req(VIRTIO_BLK(s->vdev), elem);
complete_request_early(s, elem, inhdr, status);
}
static int process_request(VirtIOBlockDataPlane *s, VirtQueueElement *elem)
{
VirtIOBlockDataPlane *s = container_of(ioq, VirtIOBlockDataPlane, ioqueue);
struct iovec *iov = elem->out_sg;
struct iovec *in_iov = elem->in_sg;
unsigned out_num = elem->out_num;
@@ -234,25 +249,23 @@ static int process_request(IOQueue *ioq, VirtQueueElement *elem)
switch (outhdr.type) {
case VIRTIO_BLK_T_IN:
do_rdwr_cmd(s, true, in_iov, in_num, outhdr.sector * 512, elem, inhdr);
do_rdwr_cmd(s, true, in_iov, in_num,
outhdr.sector * 512 / BDRV_SECTOR_SIZE,
elem, inhdr);
return 0;
case VIRTIO_BLK_T_OUT:
do_rdwr_cmd(s, false, iov, out_num, outhdr.sector * 512, elem, inhdr);
do_rdwr_cmd(s, false, iov, out_num,
outhdr.sector * 512 / BDRV_SECTOR_SIZE,
elem, inhdr);
return 0;
case VIRTIO_BLK_T_SCSI_CMD:
/* TODO support SCSI commands */
complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_UNSUPP);
do_scsi_cmd(s, elem, inhdr);
return 0;
case VIRTIO_BLK_T_FLUSH:
/* TODO fdsync not supported by Linux AIO, do it synchronously here! */
if (qemu_fdatasync(s->fd) < 0) {
complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_IOERR);
} else {
complete_request_early(s, elem, inhdr, VIRTIO_BLK_S_OK);
}
do_flush_cmd(s, elem, inhdr);
return 0;
case VIRTIO_BLK_T_GET_ID:
@@ -274,7 +287,6 @@ static void handle_notify(EventNotifier *e)
VirtQueueElement *elem;
int ret;
unsigned int num_queued;
event_notifier_test_and_clear(&s->host_notifier);
for (;;) {
@@ -291,7 +303,7 @@ static void handle_notify(EventNotifier *e)
trace_virtio_blk_data_plane_process_request(s, elem->out_num,
elem->in_num, elem->index);
if (process_request(&s->ioqueue, elem) < 0) {
if (process_request(s, elem) < 0) {
vring_set_broken(&s->vring);
vring_free_element(elem);
ret = -EFAULT;
@@ -306,44 +318,10 @@ static void handle_notify(EventNotifier *e)
if (vring_enable_notification(s->vdev, &s->vring)) {
break;
}
} else { /* ret == -ENOBUFS or fatal error, iovecs[] is depleted */
/* Since there are no iovecs[] left, stop processing for now. Do
* not re-enable guest->host notifies since the I/O completion
* handler knows to check for more vring descriptors anyway.
*/
} else { /* fatal error */
break;
}
}
num_queued = ioq_num_queued(&s->ioqueue);
if (num_queued > 0) {
s->num_reqs += num_queued;
int rc = ioq_submit(&s->ioqueue);
if (unlikely(rc < 0)) {
fprintf(stderr, "ioq_submit failed %d\n", rc);
exit(1);
}
}
}
static void handle_io(EventNotifier *e)
{
VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
io_notifier);
event_notifier_test_and_clear(&s->io_notifier);
if (ioq_run_completion(&s->ioqueue, complete_request, s) > 0) {
notify_guest(s);
}
/* If there were more requests than iovecs, the vring will not be empty yet
* so check again. There should now be enough resources to process more
* requests.
*/
if (unlikely(vring_more_avail(&s->vring))) {
handle_notify(&s->host_notifier);
}
}
/* Context: QEMU global mutex held */
@@ -352,7 +330,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
Error **errp)
{
VirtIOBlockDataPlane *s;
int fd;
Error *local_err = NULL;
*dataplane = NULL;
@@ -361,18 +338,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
return;
}
if (blk->scsi) {
error_setg(errp,
"device is incompatible with x-data-plane, use scsi=off");
return;
}
if (blk->config_wce) {
error_setg(errp, "device is incompatible with x-data-plane, "
"use config-wce=off");
return;
}
/* If dataplane is (re-)enabled while the guest is running there could be
* block jobs that can conflict.
*/
@@ -383,16 +348,8 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *blk,
return;
}
fd = raw_get_aio_fd(blk->conf.bs);
if (fd < 0) {
error_setg(errp, "drive is incompatible with x-data-plane, "
"use format=raw,cache=none,aio=native");
return;
}
s = g_new0(VirtIOBlockDataPlane, 1);
s->vdev = vdev;
s->fd = fd;
s->blk = blk;
if (blk->iothread) {
@@ -437,7 +394,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
VirtQueue *vq;
int i;
if (s->started) {
return;
@@ -470,24 +426,18 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
}
s->host_notifier = *virtio_queue_get_host_notifier(vq);
/* Set up ioqueue */
ioq_init(&s->ioqueue, s->fd, REQ_MAX);
for (i = 0; i < ARRAY_SIZE(s->requests); i++) {
ioq_put_iocb(&s->ioqueue, &s->requests[i].iocb);
}
s->io_notifier = *ioq_get_notifier(&s->ioqueue);
s->starting = false;
s->started = true;
trace_virtio_blk_data_plane_start(s);
bdrv_set_aio_context(s->blk->conf.bs, s->ctx);
/* Kick right away to begin processing requests already in vring */
event_notifier_set(virtio_queue_get_host_notifier(vq));
/* Get this show started by hooking up our callbacks */
aio_context_acquire(s->ctx);
aio_set_event_notifier(s->ctx, &s->host_notifier, handle_notify);
aio_set_event_notifier(s->ctx, &s->io_notifier, handle_io);
aio_context_release(s->ctx);
}
@@ -507,13 +457,8 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
/* Stop notifications for new requests from guest */
aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
/* Complete pending requests */
while (s->num_reqs > 0) {
aio_poll(s->ctx, true);
}
/* Stop ioq callbacks (there are no pending requests left) */
aio_set_event_notifier(s->ctx, &s->io_notifier, NULL);
/* Drain and switch bs back to the QEMU main loop */
bdrv_set_aio_context(s->blk->conf.bs, qemu_get_aio_context());
aio_context_release(s->ctx);
@@ -522,7 +467,6 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
*/
vring_teardown(&s->vring, s->vdev, 0);
ioq_cleanup(&s->ioqueue);
k->set_host_notifier(qbus->parent, 0, false);
/* Clean up guest notifier (irq) */

View File

@@ -33,7 +33,6 @@ typedef struct VirtIOBlockReq
VirtQueueElement elem;
struct virtio_blk_inhdr *in;
struct virtio_blk_outhdr *out;
struct virtio_scsi_inhdr *scsi;
QEMUIOVector qiov;
struct VirtIOBlockReq *next;
BlockAcctCookie acct;
@@ -125,13 +124,15 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
return req;
}
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
VirtQueueElement *elem)
{
#ifdef __linux__
int ret;
int i;
#endif
int status = VIRTIO_BLK_S_OK;
struct virtio_scsi_inhdr *scsi = NULL;
#ifdef __linux__
int i;
struct sg_io_hdr hdr;
#endif
/*
* We require at least one output segment each for the virtio_blk_outhdr
@@ -140,19 +141,18 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
* We also at least require the virtio_blk_inhdr, the virtio_scsi_inhdr
* and the sense buffer pointer in the input segments.
*/
if (req->elem.out_num < 2 || req->elem.in_num < 3) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
g_free(req);
return;
if (elem->out_num < 2 || elem->in_num < 3) {
status = VIRTIO_BLK_S_IOERR;
goto fail;
}
/*
* The scsi inhdr is placed in the second-to-last input segment, just
* before the regular inhdr.
*/
req->scsi = (void *)req->elem.in_sg[req->elem.in_num - 2].iov_base;
scsi = (void *)elem->in_sg[elem->in_num - 2].iov_base;
if (!req->dev->blk.scsi) {
if (!blk->blk.scsi) {
status = VIRTIO_BLK_S_UNSUPP;
goto fail;
}
@@ -160,43 +160,42 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
/*
* No support for bidirection commands yet.
*/
if (req->elem.out_num > 2 && req->elem.in_num > 3) {
if (elem->out_num > 2 && elem->in_num > 3) {
status = VIRTIO_BLK_S_UNSUPP;
goto fail;
}
#ifdef __linux__
struct sg_io_hdr hdr;
memset(&hdr, 0, sizeof(struct sg_io_hdr));
hdr.interface_id = 'S';
hdr.cmd_len = req->elem.out_sg[1].iov_len;
hdr.cmdp = req->elem.out_sg[1].iov_base;
hdr.cmd_len = elem->out_sg[1].iov_len;
hdr.cmdp = elem->out_sg[1].iov_base;
hdr.dxfer_len = 0;
if (req->elem.out_num > 2) {
if (elem->out_num > 2) {
/*
* If there are more than the minimally required 2 output segments
* there is write payload starting from the third iovec.
*/
hdr.dxfer_direction = SG_DXFER_TO_DEV;
hdr.iovec_count = req->elem.out_num - 2;
hdr.iovec_count = elem->out_num - 2;
for (i = 0; i < hdr.iovec_count; i++)
hdr.dxfer_len += req->elem.out_sg[i + 2].iov_len;
hdr.dxfer_len += elem->out_sg[i + 2].iov_len;
hdr.dxferp = req->elem.out_sg + 2;
hdr.dxferp = elem->out_sg + 2;
} else if (req->elem.in_num > 3) {
} else if (elem->in_num > 3) {
/*
* If we have more than 3 input segments the guest wants to actually
* read data.
*/
hdr.dxfer_direction = SG_DXFER_FROM_DEV;
hdr.iovec_count = req->elem.in_num - 3;
hdr.iovec_count = elem->in_num - 3;
for (i = 0; i < hdr.iovec_count; i++)
hdr.dxfer_len += req->elem.in_sg[i].iov_len;
hdr.dxfer_len += elem->in_sg[i].iov_len;
hdr.dxferp = req->elem.in_sg;
hdr.dxferp = elem->in_sg;
} else {
/*
* Some SCSI commands don't actually transfer any data.
@@ -204,11 +203,11 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
hdr.dxfer_direction = SG_DXFER_NONE;
}
hdr.sbp = req->elem.in_sg[req->elem.in_num - 3].iov_base;
hdr.mx_sb_len = req->elem.in_sg[req->elem.in_num - 3].iov_len;
hdr.sbp = elem->in_sg[elem->in_num - 3].iov_base;
hdr.mx_sb_len = elem->in_sg[elem->in_num - 3].iov_len;
ret = bdrv_ioctl(req->dev->bs, SG_IO, &hdr);
if (ret) {
status = bdrv_ioctl(blk->bs, SG_IO, &hdr);
if (status) {
status = VIRTIO_BLK_S_UNSUPP;
goto fail;
}
@@ -224,23 +223,31 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
hdr.status = CHECK_CONDITION;
}
stl_p(&req->scsi->errors,
stl_p(&scsi->errors,
hdr.status | (hdr.msg_status << 8) |
(hdr.host_status << 16) | (hdr.driver_status << 24));
stl_p(&req->scsi->residual, hdr.resid);
stl_p(&req->scsi->sense_len, hdr.sb_len_wr);
stl_p(&req->scsi->data_len, hdr.dxfer_len);
stl_p(&scsi->residual, hdr.resid);
stl_p(&scsi->sense_len, hdr.sb_len_wr);
stl_p(&scsi->data_len, hdr.dxfer_len);
virtio_blk_req_complete(req, status);
g_free(req);
return;
return status;
#else
abort();
#endif
fail:
/* Just put anything nonzero so that the ioctl fails in the guest. */
stl_p(&req->scsi->errors, 255);
if (scsi) {
stl_p(&scsi->errors, 255);
}
return status;
}
static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
{
int status;
status = virtio_blk_handle_scsi_req(req->dev, &req->elem);
virtio_blk_req_complete(req, status);
g_free(req);
}
@@ -487,12 +494,12 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
bdrv_get_geometry(s->bs, &capacity);
memset(&blkcfg, 0, sizeof(blkcfg));
stq_raw(&blkcfg.capacity, capacity);
stl_raw(&blkcfg.seg_max, 128 - 2);
stw_raw(&blkcfg.cylinders, s->conf->cyls);
stl_raw(&blkcfg.blk_size, blk_size);
stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
stq_p(&blkcfg.capacity, capacity);
stl_p(&blkcfg.seg_max, 128 - 2);
stw_p(&blkcfg.cylinders, s->conf->cyls);
stl_p(&blkcfg.blk_size, blk_size);
stw_p(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
stw_p(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
blkcfg.heads = s->conf->heads;
/*
* We must ensure that the block device capacity is a multiple of
@@ -523,7 +530,10 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
struct virtio_blk_config blkcfg;
memcpy(&blkcfg, config, sizeof(blkcfg));
aio_context_acquire(bdrv_get_aio_context(s->bs));
bdrv_set_enable_write_cache(s->bs, blkcfg.wce != 0);
aio_context_release(bdrv_get_aio_context(s->bs));
}
static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
@@ -582,7 +592,10 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
* s->bs would erroneously be placed in writethrough mode.
*/
if (!(features & (1 << VIRTIO_BLK_F_CONFIG_WCE))) {
bdrv_set_enable_write_cache(s->bs, !!(features & (1 << VIRTIO_BLK_F_WCE)));
aio_context_acquire(bdrv_get_aio_context(s->bs));
bdrv_set_enable_write_cache(s->bs,
!!(features & (1 << VIRTIO_BLK_F_WCE)));
aio_context_release(bdrv_get_aio_context(s->bs));
}
}

View File

@@ -34,6 +34,7 @@
typedef struct PCISerialState {
PCIDevice dev;
SerialState state;
uint8_t prog_if;
} PCISerialState;
typedef struct PCIMultiSerialState {
@@ -44,6 +45,7 @@ typedef struct PCIMultiSerialState {
SerialState state[PCI_SERIAL_MAX_PORTS];
uint32_t level[PCI_SERIAL_MAX_PORTS];
qemu_irq *irqs;
uint8_t prog_if;
} PCIMultiSerialState;
static int serial_pci_init(PCIDevice *dev)
@@ -60,6 +62,7 @@ static int serial_pci_init(PCIDevice *dev)
return -1;
}
pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
s->irq = pci_allocate_irq(&pci->dev);
@@ -101,6 +104,7 @@ static int multi_serial_pci_init(PCIDevice *dev)
assert(pci->ports > 0);
assert(pci->ports <= PCI_SERIAL_MAX_PORTS);
pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * pci->ports);
pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
@@ -177,12 +181,14 @@ static const VMStateDescription vmstate_pci_multi_serial = {
static Property serial_pci_properties[] = {
DEFINE_PROP_CHR("chardev", PCISerialState, state.chr),
DEFINE_PROP_UINT8("prog_if", PCISerialState, prog_if, 0x02),
DEFINE_PROP_END_OF_LIST(),
};
static Property multi_2x_serial_pci_properties[] = {
DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr),
DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02),
DEFINE_PROP_END_OF_LIST(),
};
@@ -191,6 +197,7 @@ static Property multi_4x_serial_pci_properties[] = {
DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
DEFINE_PROP_CHR("chardev3", PCIMultiSerialState, state[2].chr),
DEFINE_PROP_CHR("chardev4", PCIMultiSerialState, state[3].chr),
DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02),
DEFINE_PROP_END_OF_LIST(),
};

View File

@@ -87,6 +87,11 @@ static void uart_update_status(XilinxUARTLite *s)
s->regs[R_STATUS] = r;
}
static void xilinx_uartlite_reset(DeviceState *dev)
{
uart_update_status(XILINX_UARTLITE(dev));
}
static uint64_t
uart_read(void *opaque, hwaddr addr, unsigned int size)
{
@@ -196,34 +201,39 @@ static void uart_event(void *opaque, int event)
}
static int xilinx_uartlite_init(SysBusDevice *dev)
static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
{
XilinxUARTLite *s = XILINX_UARTLITE(dev);
sysbus_init_irq(dev, &s->irq);
uart_update_status(s);
memory_region_init_io(&s->mmio, OBJECT(s), &uart_ops, s,
"xlnx.xps-uartlite", R_MAX * 4);
sysbus_init_mmio(dev, &s->mmio);
s->chr = qemu_char_get_next_serial();
if (s->chr)
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
return 0;
}
static void xilinx_uartlite_init(Object *obj)
{
XilinxUARTLite *s = XILINX_UARTLITE(obj);
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
memory_region_init_io(&s->mmio, obj, &uart_ops, s,
"xlnx.xps-uartlite", R_MAX * 4);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
}
static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
sdc->init = xilinx_uartlite_init;
dc->reset = xilinx_uartlite_reset;
dc->realize = xilinx_uartlite_realize;
}
static const TypeInfo xilinx_uartlite_info = {
.name = TYPE_XILINX_UARTLITE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(XilinxUARTLite),
.instance_init = xilinx_uartlite_init,
.class_init = xilinx_uartlite_class_init,
};

View File

@@ -439,11 +439,27 @@ PropertyInfo qdev_prop_iothread = {
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
{
GlobalProperty *g;
ObjectClass *oc;
g = g_malloc0(sizeof(*g));
g->driver = qemu_opt_get(opts, "driver");
g->property = qemu_opt_get(opts, "property");
g->value = qemu_opt_get(opts, "value");
oc = object_class_by_name(g->driver);
if (oc) {
DeviceClass *dc = DEVICE_CLASS(oc);
if (dc->hotpluggable) {
/* If hotpluggable then skip not_used checking. */
g->not_used = false;
} else {
/* Maybe a typo. */
g->not_used = true;
}
} else {
/* Maybe a typo. */
g->not_used = true;
}
qdev_prop_register_global(g);
return 0;
}

View File

@@ -955,6 +955,23 @@ void qdev_prop_register_global_list(GlobalProperty *props)
}
}
int qdev_prop_check_global(void)
{
GlobalProperty *prop;
int ret = 0;
QTAILQ_FOREACH(prop, &global_props, next) {
if (!prop->not_used) {
continue;
}
ret = 1;
error_report("Warning: \"-global %s.%s=%s\" not used",
prop->driver, prop->property, prop->value);
}
return ret;
}
void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
Error **errp)
{
@@ -966,6 +983,7 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
if (strcmp(typename, prop->driver) != 0) {
continue;
}
prop->not_used = false;
object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
if (err != NULL) {
error_propagate(errp, err);

View File

@@ -177,7 +177,7 @@ static uint64_t cg3_reg_read(void *opaque, hwaddr addr, unsigned size)
/* monitor ID 6, board type = 1 (color) */
val = s->regs[1] | CG3_SR_1152_900_76_B | CG3_SR_ID_COLOR;
break;
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1:
val = s->regs[addr - 0x10];
break;
default:
@@ -247,7 +247,7 @@ static void cg3_reg_write(void *opaque, hwaddr addr, uint64_t val,
qemu_irq_lower(s->irq);
}
break;
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE:
case CG3_REG_FBC_CURSTART ... CG3_REG_SIZE - 1:
s->regs[addr - 0x10] = val;
break;
default:
@@ -274,6 +274,20 @@ static const GraphicHwOps cg3_ops = {
.gfx_update = cg3_update_display,
};
static void cg3_initfn(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
CG3State *s = CG3(obj);
memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(sbd, &s->rom);
memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
CG3_REG_SIZE);
sysbus_init_mmio(sbd, &s->reg);
}
static void cg3_realizefn(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
@@ -282,11 +296,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
char *fcode_filename;
/* FCode ROM */
memory_region_init_ram(&s->rom, NULL, "cg3.prom", FCODE_MAX_ROM_SIZE);
vmstate_register_ram_global(&s->rom);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(sbd, &s->rom);
fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, CG3_ROM_FILE);
if (fcode_filename) {
ret = load_image_targphys(fcode_filename, s->prom_addr,
@@ -296,10 +306,6 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
}
}
memory_region_init_io(&s->reg, NULL, &cg3_reg_ops, s, "cg3.reg",
CG3_REG_SIZE);
sysbus_init_mmio(sbd, &s->reg);
memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size);
vmstate_register_ram_global(&s->vram_mem);
sysbus_init_mmio(sbd, &s->vram_mem);
@@ -374,6 +380,7 @@ static const TypeInfo cg3_info = {
.name = TYPE_CG3,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CG3State),
.instance_init = cg3_initfn,
.class_init = cg3_class_init,
};

View File

@@ -50,7 +50,7 @@ static void glue(draw_line2_, DEPTH)(void *opaque,
uint8_t v, r, g, b;
do {
v = ldub_raw((void *) s);
v = ldub_p((void *) s);
r = (pal[v & 3] >> 4) & 0xf0;
g = pal[v & 3] & 0xf0;
b = (pal[v & 3] << 4) & 0xf0;
@@ -89,7 +89,7 @@ static void glue(draw_line4_, DEPTH)(void *opaque,
uint8_t v, r, g, b;
do {
v = ldub_raw((void *) s);
v = ldub_p((void *) s);
r = (pal[v & 0xf] >> 4) & 0xf0;
g = pal[v & 0xf] & 0xf0;
b = (pal[v & 0xf] << 4) & 0xf0;
@@ -116,7 +116,7 @@ static void glue(draw_line8_, DEPTH)(void *opaque,
uint8_t v, r, g, b;
do {
v = ldub_raw((void *) s);
v = ldub_p((void *) s);
r = (pal[v] >> 4) & 0xf0;
g = pal[v] & 0xf0;
b = (pal[v] << 4) & 0xf0;
@@ -136,7 +136,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque,
uint8_t r, g, b;
do {
v = lduw_raw((void *) s);
v = lduw_p((void *) s);
r = (v >> 4) & 0xf0;
g = v & 0xf0;
b = (v << 4) & 0xf0;
@@ -159,7 +159,7 @@ static void glue(draw_line16_, DEPTH)(void *opaque,
uint8_t r, g, b;
do {
v = lduw_raw((void *) s);
v = lduw_p((void *) s);
r = (v >> 8) & 0xf8;
g = (v >> 3) & 0xfc;
b = (v << 3) & 0xf8;

View File

@@ -47,7 +47,7 @@ static void glue(draw_line8_, PIXEL_NAME)(
{
uint8_t v, r, g, b;
do {
v = ldub_raw(s);
v = ldub_p(s);
r = (pal[v] >> 16) & 0xff;
g = (pal[v] >> 8) & 0xff;
b = (pal[v] >> 0) & 0xff;
@@ -64,7 +64,7 @@ static void glue(draw_line16_, PIXEL_NAME)(
uint8_t r, g, b;
do {
rgb565 = lduw_raw(s);
rgb565 = lduw_p(s);
r = ((rgb565 >> 11) & 0x1f) << 3;
g = ((rgb565 >> 5) & 0x3f) << 2;
b = ((rgb565 >> 0) & 0x1f) << 3;
@@ -80,7 +80,7 @@ static void glue(draw_line32_, PIXEL_NAME)(
uint8_t r, g, b;
do {
ldub_raw(s);
ldub_p(s);
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[1];
g = s[2];

View File

@@ -530,8 +530,36 @@ static const GraphicHwOps tcx24_ops = {
.gfx_update = tcx24_update_display,
};
static int tcx_init1(SysBusDevice *dev)
static void tcx_initfn(Object *obj)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
TCXState *s = TCX(obj);
memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(sbd, &s->rom);
/* DAC */
memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
"tcx.dac", TCX_DAC_NREGS);
sysbus_init_mmio(sbd, &s->dac);
/* TEC (dummy) */
memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
"tcx.tec", TCX_TEC_NREGS);
sysbus_init_mmio(sbd, &s->tec);
/* THC: NetBSD writes here even with 8-bit display: dummy */
memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
TCX_THC_NREGS_24);
sysbus_init_mmio(sbd, &s->thc24);
return;
}
static void tcx_realizefn(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
TCXState *s = TCX(dev);
ram_addr_t vram_offset = 0;
int size, ret;
@@ -544,18 +572,13 @@ static int tcx_init1(SysBusDevice *dev)
vram_base = memory_region_get_ram_ptr(&s->vram_mem);
/* FCode ROM */
memory_region_init_ram(&s->rom, NULL, "tcx.prom", FCODE_MAX_ROM_SIZE);
vmstate_register_ram_global(&s->rom);
memory_region_set_readonly(&s->rom, true);
sysbus_init_mmio(dev, &s->rom);
fcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, TCX_ROM_FILE);
if (fcode_filename) {
ret = load_image_targphys(fcode_filename, s->prom_addr,
FCODE_MAX_ROM_SIZE);
if (ret < 0 || ret > FCODE_MAX_ROM_SIZE) {
fprintf(stderr, "tcx: could not load prom '%s'\n", TCX_ROM_FILE);
return -1;
error_report("tcx: could not load prom '%s'", TCX_ROM_FILE);
}
}
@@ -564,24 +587,10 @@ static int tcx_init1(SysBusDevice *dev)
size = s->vram_size;
memory_region_init_alias(&s->vram_8bit, OBJECT(s), "tcx.vram.8bit",
&s->vram_mem, vram_offset, size);
sysbus_init_mmio(dev, &s->vram_8bit);
sysbus_init_mmio(sbd, &s->vram_8bit);
vram_offset += size;
vram_base += size;
/* DAC */
memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s,
"tcx.dac", TCX_DAC_NREGS);
sysbus_init_mmio(dev, &s->dac);
/* TEC (dummy) */
memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s,
"tcx.tec", TCX_TEC_NREGS);
sysbus_init_mmio(dev, &s->tec);
/* THC: NetBSD writes here even with 8-bit display: dummy */
memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24",
TCX_THC_NREGS_24);
sysbus_init_mmio(dev, &s->thc24);
if (s->depth == 24) {
/* 24-bit plane */
size = s->vram_size * 4;
@@ -589,7 +598,7 @@ static int tcx_init1(SysBusDevice *dev)
s->vram24_offset = vram_offset;
memory_region_init_alias(&s->vram_24bit, OBJECT(s), "tcx.vram.24bit",
&s->vram_mem, vram_offset, size);
sysbus_init_mmio(dev, &s->vram_24bit);
sysbus_init_mmio(sbd, &s->vram_24bit);
vram_offset += size;
vram_base += size;
@@ -599,20 +608,19 @@ static int tcx_init1(SysBusDevice *dev)
s->cplane_offset = vram_offset;
memory_region_init_alias(&s->vram_cplane, OBJECT(s), "tcx.vram.cplane",
&s->vram_mem, vram_offset, size);
sysbus_init_mmio(dev, &s->vram_cplane);
sysbus_init_mmio(sbd, &s->vram_cplane);
s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s);
} else {
/* THC 8 bit (dummy) */
memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8",
TCX_THC_NREGS_8);
sysbus_init_mmio(dev, &s->thc8);
sysbus_init_mmio(sbd, &s->thc8);
s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s);
}
qemu_console_resize(s->con, s->width, s->height);
return 0;
}
static Property tcx_properties[] = {
@@ -627,9 +635,8 @@ static Property tcx_properties[] = {
static void tcx_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = tcx_init1;
dc->realize = tcx_realizefn;
dc->reset = tcx_reset;
dc->vmsd = &vmstate_tcx;
dc->props = tcx_properties;
@@ -639,6 +646,7 @@ static const TypeInfo tcx_info = {
.name = TYPE_TCX,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(TCXState),
.instance_init = tcx_initfn,
.class_init = tcx_class_init,
};

View File

@@ -361,7 +361,7 @@ static void glue(vga_draw_line15_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
w = width;
do {
v = lduw_raw((void *)s);
v = lduw_p((void *)s);
r = (v >> 7) & 0xf8;
g = (v >> 2) & 0xf8;
b = (v << 3) & 0xf8;
@@ -386,7 +386,7 @@ static void glue(vga_draw_line16_, PIXEL_NAME)(VGACommonState *s1, uint8_t *d,
w = width;
do {
v = lduw_raw((void *)s);
v = lduw_p((void *)s);
r = (v >> 8) & 0xf8;
g = (v >> 3) & 0xfc;
b = (v << 3) & 0xf8;

View File

@@ -863,7 +863,7 @@ static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
break;
case SVGA_REG_CURSOR_Y:
ret = s->cursor.x;
ret = s->cursor.y;
break;
case SVGA_REG_CURSOR_ON:

View File

@@ -157,11 +157,6 @@ static inline int stream_running(struct Stream *s)
return s->regs[R_DMACR] & DMACR_RUNSTOP;
}
static inline int stream_halted(struct Stream *s)
{
return s->regs[R_DMASR] & DMASR_HALTED;
}
static inline int stream_idle(struct Stream *s)
{
return !!(s->regs[R_DMASR] & DMASR_IDLE);

View File

@@ -14,8 +14,10 @@
*/
#include "qemu-common.h"
#include "qemu/host-utils.h"
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
#include "sysemu/cpus.h"
#include "hw/sysbus.h"
#include "hw/kvm/clock.h"
@@ -34,6 +36,48 @@ typedef struct KVMClockState {
bool clock_valid;
} KVMClockState;
struct pvclock_vcpu_time_info {
uint32_t version;
uint32_t pad0;
uint64_t tsc_timestamp;
uint64_t system_time;
uint32_t tsc_to_system_mul;
int8_t tsc_shift;
uint8_t flags;
uint8_t pad[2];
} __attribute__((__packed__)); /* 32 bytes */
static uint64_t kvmclock_current_nsec(KVMClockState *s)
{
CPUState *cpu = first_cpu;
CPUX86State *env = cpu->env_ptr;
hwaddr kvmclock_struct_pa = env->system_time_msr & ~1ULL;
uint64_t migration_tsc = env->tsc;
struct pvclock_vcpu_time_info time;
uint64_t delta;
uint64_t nsec_lo;
uint64_t nsec_hi;
uint64_t nsec;
if (!(env->system_time_msr & 1ULL)) {
/* KVM clock not active */
return 0;
}
cpu_physical_memory_read(kvmclock_struct_pa, &time, sizeof(time));
assert(time.tsc_timestamp <= migration_tsc);
delta = migration_tsc - time.tsc_timestamp;
if (time.tsc_shift < 0) {
delta >>= -time.tsc_shift;
} else {
delta <<= time.tsc_shift;
}
mulu64(&nsec_lo, &nsec_hi, delta, time.tsc_to_system_mul);
nsec = (nsec_lo >> 32) | (nsec_hi << 32);
return nsec + time.system_time;
}
static void kvmclock_vm_state_change(void *opaque, int running,
RunState state)
@@ -45,9 +89,15 @@ static void kvmclock_vm_state_change(void *opaque, int running,
if (running) {
struct kvm_clock_data data;
uint64_t time_at_migration = kvmclock_current_nsec(s);
s->clock_valid = false;
/* We can't rely on the migrated clock value, just discard it */
if (time_at_migration) {
s->clock = time_at_migration;
}
data.clock = s->clock;
data.flags = 0;
ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
@@ -75,6 +125,8 @@ static void kvmclock_vm_state_change(void *opaque, int running,
if (s->clock_valid) {
return;
}
cpu_synchronize_all_states();
ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data);
if (ret < 0) {
fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret));

View File

@@ -922,9 +922,6 @@ static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
0x280, 0x380 };
static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
{
static int nb_ne2k = 0;

View File

@@ -67,7 +67,7 @@ static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
static struct {
const char *vendor, *version, *date;
bool have_major_minor;
bool have_major_minor, uefi;
uint8_t major, minor;
} type0;
@@ -134,6 +134,10 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
.name = "release",
.type = QEMU_OPT_STRING,
.help = "revision number",
},{
.name = "uefi",
.type = QEMU_OPT_BOOL,
.help = "uefi support",
},
{ /* end of list */ }
};
@@ -444,7 +448,7 @@ static bool smbios_skip_table(uint8_t type, bool required_table)
\
t->header.type = tbl_type; \
t->header.length = sizeof(*t); \
t->header.handle = tbl_handle; \
t->header.handle = cpu_to_le16(tbl_handle); \
} while (0)
#define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \
@@ -491,19 +495,18 @@ static void smbios_build_type_0_table(void)
SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor);
SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version);
t->bios_starting_address_segment = 0xE800; /* hardcoded in SeaBIOS */
t->bios_starting_address_segment = cpu_to_le16(0xE800); /* from SeaBIOS */
SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date);
t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */
/* BIOS characteristics not supported */
memset(t->bios_characteristics, 0, 8);
t->bios_characteristics[0] = 0x08;
/* Enable targeted content distribution (needed for SVVP, per SeaBIOS) */
t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
t->bios_characteristics_extension_bytes[0] = 0;
t->bios_characteristics_extension_bytes[1] = 4;
t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
if (type0.uefi) {
t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
}
if (type0.have_major_minor) {
t->system_bios_major_release = type0.major;
@@ -551,7 +554,7 @@ static void smbios_build_type_2_table(void)
SMBIOS_TABLE_SET_STR(2, asset_tag_number_str, type2.asset);
t->feature_flags = 0x01; /* Motherboard */
SMBIOS_TABLE_SET_STR(2, location_str, type2.location);
t->chassis_handle = 0x300; /* Type 3 (System enclosure) */
t->chassis_handle = cpu_to_le16(0x300); /* Type 3 (System enclosure) */
t->board_type = 0x0A; /* Motherboard */
t->contained_element_count = 0;
@@ -571,7 +574,7 @@ static void smbios_build_type_3_table(void)
t->power_supply_state = 0x03; /* Safe */
t->thermal_state = 0x03; /* Safe */
t->security_status = 0x02; /* Unknown */
t->oem_defined = 0;
t->oem_defined = cpu_to_le32(0);
t->height = 0;
t->number_of_power_cords = 0;
t->contained_element_count = 0;
@@ -589,26 +592,27 @@ static void smbios_build_type_4_table(unsigned instance)
snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance);
SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str);
t->processor_type = 0x03; /* CPU */
t->processor_family = 0x01; /* Other */
SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer);
t->processor_id[0] = smbios_cpuid_version;
t->processor_id[1] = smbios_cpuid_features;
t->processor_id[0] = cpu_to_le32(smbios_cpuid_version);
t->processor_id[1] = cpu_to_le32(smbios_cpuid_features);
SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
t->voltage = 0;
t->external_clock = 0; /* Unknown */
t->max_speed = 0; /* Unknown */
t->current_speed = 0; /* Unknown */
t->external_clock = cpu_to_le16(0); /* Unknown */
t->max_speed = cpu_to_le16(0); /* Unknown */
t->current_speed = cpu_to_le16(0); /* Unknown */
t->status = 0x41; /* Socket populated, CPU enabled */
t->processor_upgrade = 0x01; /* Other */
t->l1_cache_handle = 0xFFFF; /* N/A */
t->l2_cache_handle = 0xFFFF; /* N/A */
t->l3_cache_handle = 0xFFFF; /* N/A */
t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
t->l2_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
t->l3_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial);
SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
t->core_count = t->core_enabled = smp_cores;
t->thread_count = smp_threads;
t->processor_characteristics = 0x02; /* Unknown */
t->processor_family = t->processor_family2 = 0x01; /* Other */
t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
t->processor_family2 = cpu_to_le16(0x01); /* Other */
SMBIOS_BUILD_TABLE_POST;
smbios_type4_count++;
@@ -631,14 +635,14 @@ static void smbios_build_type_16_table(unsigned dimm_cnt)
t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */
size_kb = QEMU_ALIGN_UP(ram_size, ONE_KB) / ONE_KB;
if (size_kb < MAX_T16_STD_SZ) {
t->maximum_capacity = size_kb;
t->extended_maximum_capacity = 0;
t->maximum_capacity = cpu_to_le32(size_kb);
t->extended_maximum_capacity = cpu_to_le64(0);
} else {
t->maximum_capacity = MAX_T16_STD_SZ;
t->extended_maximum_capacity = ram_size;
t->maximum_capacity = cpu_to_le32(MAX_T16_STD_SZ);
t->extended_maximum_capacity = cpu_to_le64(ram_size);
}
t->memory_error_information_handle = 0xFFFE; /* Not provided */
t->number_of_memory_devices = dimm_cnt;
t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
t->number_of_memory_devices = cpu_to_le16(dimm_cnt);
SMBIOS_BUILD_TABLE_POST;
}
@@ -653,18 +657,18 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
t->physical_memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
t->memory_error_information_handle = 0xFFFE; /* Not provided */
t->total_width = 0xFFFF; /* Unknown */
t->data_width = 0xFFFF; /* Unknown */
t->physical_memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
t->total_width = cpu_to_le16(0xFFFF); /* Unknown */
t->data_width = cpu_to_le16(0xFFFF); /* Unknown */
size_mb = QEMU_ALIGN_UP(size, ONE_MB) / ONE_MB;
if (size_mb < MAX_T17_STD_SZ) {
t->size = size_mb;
t->extended_size = 0;
t->size = cpu_to_le16(size_mb);
t->extended_size = cpu_to_le32(0);
} else {
assert(size_mb < MAX_T17_EXT_SZ);
t->size = MAX_T17_STD_SZ;
t->extended_size = size_mb;
t->size = cpu_to_le16(MAX_T17_STD_SZ);
t->extended_size = cpu_to_le32(size_mb);
}
t->form_factor = 0x09; /* DIMM */
t->device_set = 0; /* Not in a set */
@@ -672,17 +676,17 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
SMBIOS_TABLE_SET_STR(17, device_locator_str, loc_str);
SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank);
t->memory_type = 0x07; /* RAM */
t->type_detail = 0x02; /* Other */
t->speed = 0; /* Unknown */
t->type_detail = cpu_to_le16(0x02); /* Other */
t->speed = cpu_to_le16(0); /* Unknown */
SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer);
SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial);
SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset);
SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part);
t->attributes = 0; /* Unknown */
t->configured_clock_speed = 0; /* Unknown */
t->minimum_voltage = 0; /* Unknown */
t->maximum_voltage = 0; /* Unknown */
t->configured_voltage = 0; /* Unknown */
t->configured_clock_speed = cpu_to_le16(0); /* Unknown */
t->minimum_voltage = cpu_to_le16(0); /* Unknown */
t->maximum_voltage = cpu_to_le16(0); /* Unknown */
t->configured_voltage = cpu_to_le16(0); /* Unknown */
SMBIOS_BUILD_TABLE_POST;
}
@@ -699,15 +703,16 @@ static void smbios_build_type_19_table(unsigned instance,
start_kb = start / ONE_KB;
end_kb = end / ONE_KB;
if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) {
t->starting_address = start_kb;
t->ending_address = end_kb;
t->extended_starting_address = t->extended_ending_address = 0;
t->starting_address = cpu_to_le32(start_kb);
t->ending_address = cpu_to_le32(end_kb);
t->extended_starting_address =
t->extended_ending_address = cpu_to_le64(0);
} else {
t->starting_address = t->ending_address = UINT32_MAX;
t->extended_starting_address = start;
t->extended_ending_address = end;
t->starting_address = t->ending_address = cpu_to_le32(UINT32_MAX);
t->extended_starting_address = cpu_to_le64(start);
t->extended_ending_address = cpu_to_le64(end);
}
t->memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
t->memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
t->partition_width = 1; /* One device per row */
SMBIOS_BUILD_TABLE_POST;
@@ -740,11 +745,6 @@ void smbios_set_cpuid(uint32_t version, uint32_t features)
field = value; \
}
#define G_FREE_UNLESS_NULL(ptr) \
if (ptr != NULL) { \
g_free(ptr); \
}
void smbios_set_defaults(const char *manufacturer, const char *product,
const char *version, bool legacy_mode)
{
@@ -753,7 +753,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product,
/* drop unwanted version of command-line file blob(s) */
if (smbios_legacy) {
G_FREE_UNLESS_NULL(smbios_tables);
g_free(smbios_tables);
/* in legacy mode, also complain if fields were given for types > 1 */
if (find_next_bit(have_fields_bitmap,
SMBIOS_MAX_TYPE+1, 2) < SMBIOS_MAX_TYPE+1) {
@@ -762,7 +762,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product,
exit(1);
}
} else {
G_FREE_UNLESS_NULL(smbios_entries);
g_free(smbios_entries);
}
SMBIOS_SET_DEFAULT(type1.manufacturer, manufacturer);
@@ -794,14 +794,14 @@ static void smbios_entry_point_setup(void)
ep.smbios_bcd_revision = 0x28;
/* set during table construction, but BIOS may override: */
ep.structure_table_length = smbios_tables_len;
ep.max_structure_size = smbios_table_max;
ep.number_of_structures = smbios_table_cnt;
ep.structure_table_length = cpu_to_le16(smbios_tables_len);
ep.max_structure_size = cpu_to_le16(smbios_table_max);
ep.number_of_structures = cpu_to_le16(smbios_table_cnt);
/* BIOS must recalculate: */
ep.checksum = 0;
ep.intermediate_checksum = 0;
ep.structure_table_address = 0; /* where BIOS has copied smbios_tables */
ep.structure_table_address = cpu_to_le32(0);
}
void smbios_get_tables(uint8_t **tables, size_t *tables_len,
@@ -977,6 +977,7 @@ void smbios_entry_add(QemuOpts *opts)
save_opt(&type0.vendor, opts, "vendor");
save_opt(&type0.version, opts, "version");
save_opt(&type0.date, opts, "date");
type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
val = qemu_opt_get(opts, "release");
if (val) {

View File

@@ -156,31 +156,6 @@ static inline void softusb_write_dmem(MilkymistSoftUsbState *s,
memcpy(s->dmem_ptr + offset, buf, len);
}
static inline void softusb_read_pmem(MilkymistSoftUsbState *s,
uint32_t offset, uint8_t *buf, uint32_t len)
{
if (offset + len >= s->pmem_size) {
error_report("milkymist_softusb: read pmem out of bounds "
"at offset 0x%x, len %d", offset, len);
memset(buf, 0, len);
return;
}
memcpy(buf, s->pmem_ptr + offset, len);
}
static inline void softusb_write_pmem(MilkymistSoftUsbState *s,
uint32_t offset, uint8_t *buf, uint32_t len)
{
if (offset + len >= s->pmem_size) {
error_report("milkymist_softusb: write pmem out of bounds "
"at offset 0x%x, len %d", offset, len);
return;
}
memcpy(s->pmem_ptr + offset, buf, len);
}
static void softusb_mouse_changed(MilkymistSoftUsbState *s)
{
uint8_t m;

View File

@@ -311,11 +311,6 @@ static inline void IRQ_resetbit(IRQQueue *q, int n_IRQ)
clear_bit(n_IRQ, q->queue);
}
static inline int IRQ_testbit(IRQQueue *q, int n_IRQ)
{
return test_bit(n_IRQ, q->queue);
}
static void IRQ_check(OpenPICState *opp, IRQQueue *q)
{
int irq = -1;

View File

@@ -117,6 +117,16 @@ static int flic_enqueue_irqs(void *buf, uint64_t len,
return rc ? -errno : 0;
}
int kvm_s390_inject_flic(struct kvm_s390_irq *irq)
{
static KVMS390FLICState *flic;
if (unlikely(!flic)) {
flic = KVM_S390_FLIC(s390_get_flic());
}
return flic_enqueue_irqs(irq, sizeof(*irq), flic);
}
/**
* __get_all_irqs - store all pending irqs in buffer
* @flic: pointer to flic device state
@@ -170,7 +180,8 @@ static int kvm_s390_register_io_adapter(S390FLICState *fs, uint32_t id,
};
if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
return -ENOSYS;
/* nothing to do */
return 0;
}
r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);
@@ -195,7 +206,8 @@ static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
int r;
if (!kvm_check_extension(kvm_state, KVM_CAP_IRQ_ROUTING)) {
return -ENOSYS;
/* nothing to do */
return 0;
}
r = ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr);

View File

@@ -161,18 +161,16 @@ static void irq_handler(void *opaque, int irq, int level)
update_irq(p);
}
static int xilinx_intc_init(SysBusDevice *sbd)
static void xilinx_intc_init(Object *obj)
{
DeviceState *dev = DEVICE(sbd);
struct xlx_pic *p = XILINX_INTC(dev);
struct xlx_pic *p = XILINX_INTC(obj);
qdev_init_gpio_in(dev, irq_handler, 32);
sysbus_init_irq(sbd, &p->parent_irq);
qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq);
memory_region_init_io(&p->mmio, OBJECT(p), &pic_ops, p, "xlnx.xps-intc",
memory_region_init_io(&p->mmio, obj, &pic_ops, p, "xlnx.xps-intc",
R_MAX * 4);
sysbus_init_mmio(sbd, &p->mmio);
return 0;
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
}
static Property xilinx_intc_properties[] = {
@@ -183,9 +181,7 @@ static Property xilinx_intc_properties[] = {
static void xilinx_intc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = xilinx_intc_init;
dc->props = xilinx_intc_properties;
}
@@ -193,6 +189,7 @@ static const TypeInfo xilinx_intc_info = {
.name = TYPE_XILINX_INTC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct xlx_pic),
.instance_init = xilinx_intc_init,
.class_init = xilinx_intc_class_init,
};

View File

@@ -86,11 +86,6 @@ static inline uint32_t get_parallel_irq(PC87312State *s)
}
}
static inline bool is_parallel_epp(PC87312State *s)
{
return s->regs[REG_PTR] & PTR_EPP_MODE;
}
/* UARTs */

View File

@@ -178,24 +178,24 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base, int64_t kernel_a
/* Small bootloader */
p = (uint32_t *) base;
stl_raw(p++, 0x0bf00010); /* j 0x1fc00040 */
stl_raw(p++, 0x00000000); /* nop */
stl_p(p++, 0x0bf00010); /* j 0x1fc00040 */
stl_p(p++, 0x00000000); /* nop */
/* Second part of the bootloader */
p = (uint32_t *) (base + 0x040);
stl_raw(p++, 0x3c040000); /* lui a0, 0 */
stl_raw(p++, 0x34840002); /* ori a0, a0, 2 */
stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a0, low(ENVP_ADDR) */
stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(env->ram_size) */
stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(env->ram_size) */
stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff)); /* lui ra, high(kernel_addr) */;
stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff)); /* ori ra, ra, low(kernel_addr) */
stl_raw(p++, 0x03e00008); /* jr ra */
stl_raw(p++, 0x00000000); /* nop */
stl_p(p++, 0x3c040000); /* lui a0, 0 */
stl_p(p++, 0x34840002); /* ori a0, a0, 2 */
stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a0, low(ENVP_ADDR) */
stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(env->ram_size) */
stl_p(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(env->ram_size) */
stl_p(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff)); /* lui ra, high(kernel_addr) */;
stl_p(p++, 0x37ff0000 | (kernel_addr & 0xffff)); /* ori ra, ra, low(kernel_addr) */
stl_p(p++, 0x03e00008); /* jr ra */
stl_p(p++, 0x00000000); /* nop */
}

View File

@@ -609,136 +609,136 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
/* Small bootloader */
p = (uint32_t *)base;
stl_raw(p++, 0x0bf00160); /* j 0x1fc00580 */
stl_raw(p++, 0x00000000); /* nop */
stl_p(p++, 0x0bf00160); /* j 0x1fc00580 */
stl_p(p++, 0x00000000); /* nop */
/* YAMON service vector */
stl_raw(base + 0x500, 0xbfc00580); /* start: */
stl_raw(base + 0x504, 0xbfc0083c); /* print_count: */
stl_raw(base + 0x520, 0xbfc00580); /* start: */
stl_raw(base + 0x52c, 0xbfc00800); /* flush_cache: */
stl_raw(base + 0x534, 0xbfc00808); /* print: */
stl_raw(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */
stl_raw(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */
stl_raw(base + 0x540, 0xbfc00800); /* reg_ic_isr: */
stl_raw(base + 0x544, 0xbfc00800); /* unred_ic_isr: */
stl_raw(base + 0x548, 0xbfc00800); /* reg_esr: */
stl_raw(base + 0x54c, 0xbfc00800); /* unreg_esr: */
stl_raw(base + 0x550, 0xbfc00800); /* getchar: */
stl_raw(base + 0x554, 0xbfc00800); /* syscon_read: */
stl_p(base + 0x500, 0xbfc00580); /* start: */
stl_p(base + 0x504, 0xbfc0083c); /* print_count: */
stl_p(base + 0x520, 0xbfc00580); /* start: */
stl_p(base + 0x52c, 0xbfc00800); /* flush_cache: */
stl_p(base + 0x534, 0xbfc00808); /* print: */
stl_p(base + 0x538, 0xbfc00800); /* reg_cpu_isr: */
stl_p(base + 0x53c, 0xbfc00800); /* unred_cpu_isr: */
stl_p(base + 0x540, 0xbfc00800); /* reg_ic_isr: */
stl_p(base + 0x544, 0xbfc00800); /* unred_ic_isr: */
stl_p(base + 0x548, 0xbfc00800); /* reg_esr: */
stl_p(base + 0x54c, 0xbfc00800); /* unreg_esr: */
stl_p(base + 0x550, 0xbfc00800); /* getchar: */
stl_p(base + 0x554, 0xbfc00800); /* syscon_read: */
/* Second part of the bootloader */
p = (uint32_t *) (base + 0x580);
stl_raw(p++, 0x24040002); /* addiu a0, zero, 2 */
stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff)); /* ori sp, sp, low(ENVP_ADDR) */
stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a1, low(ENVP_ADDR) */
stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(ram_size) */
stl_raw(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(ram_size) */
stl_p(p++, 0x24040002); /* addiu a0, zero, 2 */
stl_p(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
stl_p(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff)); /* ori sp, sp, low(ENVP_ADDR) */
stl_p(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff)); /* lui a1, high(ENVP_ADDR) */
stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a1, low(ENVP_ADDR) */
stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(ram_size) */
stl_p(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(ram_size) */
/* Load BAR registers as done by YAMON */
stl_raw(p++, 0x3c09b400); /* lui t1, 0xb400 */
stl_p(p++, 0x3c09b400); /* lui t1, 0xb400 */
#ifdef TARGET_WORDS_BIGENDIAN
stl_raw(p++, 0x3c08df00); /* lui t0, 0xdf00 */
stl_p(p++, 0x3c08df00); /* lui t0, 0xdf00 */
#else
stl_raw(p++, 0x340800df); /* ori t0, r0, 0x00df */
stl_p(p++, 0x340800df); /* ori t0, r0, 0x00df */
#endif
stl_raw(p++, 0xad280068); /* sw t0, 0x0068(t1) */
stl_p(p++, 0xad280068); /* sw t0, 0x0068(t1) */
stl_raw(p++, 0x3c09bbe0); /* lui t1, 0xbbe0 */
stl_p(p++, 0x3c09bbe0); /* lui t1, 0xbbe0 */
#ifdef TARGET_WORDS_BIGENDIAN
stl_raw(p++, 0x3c08c000); /* lui t0, 0xc000 */
stl_p(p++, 0x3c08c000); /* lui t0, 0xc000 */
#else
stl_raw(p++, 0x340800c0); /* ori t0, r0, 0x00c0 */
stl_p(p++, 0x340800c0); /* ori t0, r0, 0x00c0 */
#endif
stl_raw(p++, 0xad280048); /* sw t0, 0x0048(t1) */
stl_p(p++, 0xad280048); /* sw t0, 0x0048(t1) */
#ifdef TARGET_WORDS_BIGENDIAN
stl_raw(p++, 0x3c084000); /* lui t0, 0x4000 */
stl_p(p++, 0x3c084000); /* lui t0, 0x4000 */
#else
stl_raw(p++, 0x34080040); /* ori t0, r0, 0x0040 */
stl_p(p++, 0x34080040); /* ori t0, r0, 0x0040 */
#endif
stl_raw(p++, 0xad280050); /* sw t0, 0x0050(t1) */
stl_p(p++, 0xad280050); /* sw t0, 0x0050(t1) */
#ifdef TARGET_WORDS_BIGENDIAN
stl_raw(p++, 0x3c088000); /* lui t0, 0x8000 */
stl_p(p++, 0x3c088000); /* lui t0, 0x8000 */
#else
stl_raw(p++, 0x34080080); /* ori t0, r0, 0x0080 */
stl_p(p++, 0x34080080); /* ori t0, r0, 0x0080 */
#endif
stl_raw(p++, 0xad280058); /* sw t0, 0x0058(t1) */
stl_p(p++, 0xad280058); /* sw t0, 0x0058(t1) */
#ifdef TARGET_WORDS_BIGENDIAN
stl_raw(p++, 0x3c083f00); /* lui t0, 0x3f00 */
stl_p(p++, 0x3c083f00); /* lui t0, 0x3f00 */
#else
stl_raw(p++, 0x3408003f); /* ori t0, r0, 0x003f */
stl_p(p++, 0x3408003f); /* ori t0, r0, 0x003f */
#endif
stl_raw(p++, 0xad280060); /* sw t0, 0x0060(t1) */
stl_p(p++, 0xad280060); /* sw t0, 0x0060(t1) */
#ifdef TARGET_WORDS_BIGENDIAN
stl_raw(p++, 0x3c08c100); /* lui t0, 0xc100 */
stl_p(p++, 0x3c08c100); /* lui t0, 0xc100 */
#else
stl_raw(p++, 0x340800c1); /* ori t0, r0, 0x00c1 */
stl_p(p++, 0x340800c1); /* ori t0, r0, 0x00c1 */
#endif
stl_raw(p++, 0xad280080); /* sw t0, 0x0080(t1) */
stl_p(p++, 0xad280080); /* sw t0, 0x0080(t1) */
#ifdef TARGET_WORDS_BIGENDIAN
stl_raw(p++, 0x3c085e00); /* lui t0, 0x5e00 */
stl_p(p++, 0x3c085e00); /* lui t0, 0x5e00 */
#else
stl_raw(p++, 0x3408005e); /* ori t0, r0, 0x005e */
stl_p(p++, 0x3408005e); /* ori t0, r0, 0x005e */
#endif
stl_raw(p++, 0xad280088); /* sw t0, 0x0088(t1) */
stl_p(p++, 0xad280088); /* sw t0, 0x0088(t1) */
/* Jump to kernel code */
stl_raw(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */
stl_raw(p++, 0x37ff0000 | (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */
stl_raw(p++, 0x03e00008); /* jr ra */
stl_raw(p++, 0x00000000); /* nop */
stl_p(p++, 0x3c1f0000 | ((kernel_entry >> 16) & 0xffff)); /* lui ra, high(kernel_entry) */
stl_p(p++, 0x37ff0000 | (kernel_entry & 0xffff)); /* ori ra, ra, low(kernel_entry) */
stl_p(p++, 0x03e00008); /* jr ra */
stl_p(p++, 0x00000000); /* nop */
/* YAMON subroutines */
p = (uint32_t *) (base + 0x800);
stl_raw(p++, 0x03e00008); /* jr ra */
stl_raw(p++, 0x24020000); /* li v0,0 */
stl_p(p++, 0x03e00008); /* jr ra */
stl_p(p++, 0x24020000); /* li v0,0 */
/* 808 YAMON print */
stl_raw(p++, 0x03e06821); /* move t5,ra */
stl_raw(p++, 0x00805821); /* move t3,a0 */
stl_raw(p++, 0x00a05021); /* move t2,a1 */
stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */
stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */
stl_raw(p++, 0x10800005); /* beqz a0,834 */
stl_raw(p++, 0x00000000); /* nop */
stl_raw(p++, 0x0ff0021c); /* jal 870 */
stl_raw(p++, 0x00000000); /* nop */
stl_raw(p++, 0x08000205); /* j 814 */
stl_raw(p++, 0x00000000); /* nop */
stl_raw(p++, 0x01a00008); /* jr t5 */
stl_raw(p++, 0x01602021); /* move a0,t3 */
stl_p(p++, 0x03e06821); /* move t5,ra */
stl_p(p++, 0x00805821); /* move t3,a0 */
stl_p(p++, 0x00a05021); /* move t2,a1 */
stl_p(p++, 0x91440000); /* lbu a0,0(t2) */
stl_p(p++, 0x254a0001); /* addiu t2,t2,1 */
stl_p(p++, 0x10800005); /* beqz a0,834 */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x0ff0021c); /* jal 870 */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x08000205); /* j 814 */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x01a00008); /* jr t5 */
stl_p(p++, 0x01602021); /* move a0,t3 */
/* 0x83c YAMON print_count */
stl_raw(p++, 0x03e06821); /* move t5,ra */
stl_raw(p++, 0x00805821); /* move t3,a0 */
stl_raw(p++, 0x00a05021); /* move t2,a1 */
stl_raw(p++, 0x00c06021); /* move t4,a2 */
stl_raw(p++, 0x91440000); /* lbu a0,0(t2) */
stl_raw(p++, 0x0ff0021c); /* jal 870 */
stl_raw(p++, 0x00000000); /* nop */
stl_raw(p++, 0x254a0001); /* addiu t2,t2,1 */
stl_raw(p++, 0x258cffff); /* addiu t4,t4,-1 */
stl_raw(p++, 0x1580fffa); /* bnez t4,84c */
stl_raw(p++, 0x00000000); /* nop */
stl_raw(p++, 0x01a00008); /* jr t5 */
stl_raw(p++, 0x01602021); /* move a0,t3 */
stl_p(p++, 0x03e06821); /* move t5,ra */
stl_p(p++, 0x00805821); /* move t3,a0 */
stl_p(p++, 0x00a05021); /* move t2,a1 */
stl_p(p++, 0x00c06021); /* move t4,a2 */
stl_p(p++, 0x91440000); /* lbu a0,0(t2) */
stl_p(p++, 0x0ff0021c); /* jal 870 */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x254a0001); /* addiu t2,t2,1 */
stl_p(p++, 0x258cffff); /* addiu t4,t4,-1 */
stl_p(p++, 0x1580fffa); /* bnez t4,84c */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x01a00008); /* jr t5 */
stl_p(p++, 0x01602021); /* move a0,t3 */
/* 0x870 */
stl_raw(p++, 0x3c08b800); /* lui t0,0xb400 */
stl_raw(p++, 0x350803f8); /* ori t0,t0,0x3f8 */
stl_raw(p++, 0x91090005); /* lbu t1,5(t0) */
stl_raw(p++, 0x00000000); /* nop */
stl_raw(p++, 0x31290040); /* andi t1,t1,0x40 */
stl_raw(p++, 0x1120fffc); /* beqz t1,878 <outch+0x8> */
stl_raw(p++, 0x00000000); /* nop */
stl_raw(p++, 0x03e00008); /* jr ra */
stl_raw(p++, 0xa1040000); /* sb a0,0(t0) */
stl_p(p++, 0x3c08b800); /* lui t0,0xb400 */
stl_p(p++, 0x350803f8); /* ori t0,t0,0x3f8 */
stl_p(p++, 0x91090005); /* lbu t1,5(t0) */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x31290040); /* andi t1,t1,0x40 */
stl_p(p++, 0x1120fffc); /* beqz t1,878 <outch+0x8> */
stl_p(p++, 0x00000000); /* nop */
stl_p(p++, 0x03e00008); /* jr ra */
stl_p(p++, 0xa1040000); /* sb a0,0(t0) */
}

View File

@@ -50,7 +50,7 @@
#define GEM_IER (0x00000028/4) /* Interrupt Enable reg */
#define GEM_IDR (0x0000002C/4) /* Interrupt Disable reg */
#define GEM_IMR (0x00000030/4) /* Interrupt Mask reg */
#define GEM_PHYMNTNC (0x00000034/4) /* Phy Maintaince reg */
#define GEM_PHYMNTNC (0x00000034/4) /* Phy Maintenance reg */
#define GEM_RXPAUSE (0x00000038/4) /* RX Pause Time reg */
#define GEM_TXPAUSE (0x0000003C/4) /* TX Pause Time reg */
#define GEM_TXPARTIALSF (0x00000040/4) /* TX Partial Store and Forward */
@@ -150,7 +150,7 @@
#define GEM_NWCTRL_LOCALLOOP 0x00000002 /* Local Loopback */
#define GEM_NWCFG_STRIP_FCS 0x00020000 /* Strip FCS field */
#define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with lenth err */
#define GEM_NWCFG_LERR_DISC 0x00010000 /* Discard RX frames with len err */
#define GEM_NWCFG_BUFF_OFST_M 0x0000C000 /* Receive buffer offset mask */
#define GEM_NWCFG_BUFF_OFST_S 14 /* Receive buffer offset shift */
#define GEM_NWCFG_UCAST_HASH 0x00000080 /* accept unicast if hash match */
@@ -397,7 +397,7 @@ static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
*/
static void gem_init_register_masks(GemState *s)
{
/* Mask of register bits which are read only*/
/* Mask of register bits which are read only */
memset(&s->regs_ro[0], 0, sizeof(s->regs_ro));
s->regs_ro[GEM_NWCTRL] = 0xFFF80000;
s->regs_ro[GEM_NWSTATUS] = 0xFFFFFFFF;
@@ -719,7 +719,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
unsigned crc_val;
/* The application wants the FCS field, which QEMU does not provide.
* We must try and caclculate one.
* We must try and calculate one.
*/
memcpy(rxbuf, buf, size);
@@ -871,7 +871,7 @@ static void gem_transmit(GemState *s)
DB_PRINT("\n");
/* The packet we will hand off to qemu.
/* The packet we will hand off to QEMU.
* Packets scattered across multiple descriptors are gathered to this
* one contiguous buffer first.
*/
@@ -880,8 +880,10 @@ static void gem_transmit(GemState *s)
/* read current descriptor */
packet_desc_addr = s->tx_desc_addr;
DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
cpu_physical_memory_read(packet_desc_addr,
(uint8_t *)&desc[0], sizeof(desc));
(uint8_t *)desc, sizeof(desc));
/* Handle all descriptors owned by hardware */
while (tx_desc_get_used(desc) == 0) {
@@ -911,15 +913,17 @@ static void gem_transmit(GemState *s)
/* Last descriptor for this packet; hand the whole thing off */
if (tx_desc_get_last(desc)) {
unsigned desc_first[2];
/* Modify the 1st descriptor of this packet to be owned by
* the processor.
*/
cpu_physical_memory_read(s->tx_desc_addr,
(uint8_t *)&desc[0], sizeof(desc));
tx_desc_set_used(desc);
cpu_physical_memory_write(s->tx_desc_addr,
(uint8_t *)&desc[0], sizeof(desc));
/* Advance the hardare current descriptor past this packet */
cpu_physical_memory_read(s->tx_desc_addr, (uint8_t *)desc_first,
sizeof(desc_first));
tx_desc_set_used(desc_first);
cpu_physical_memory_write(s->tx_desc_addr, (uint8_t *)desc_first,
sizeof(desc_first));
/* Advance the hardware current descriptor past this packet */
if (tx_desc_get_wrap(desc)) {
s->tx_desc_addr = s->regs[GEM_TXQBASE];
} else {
@@ -960,8 +964,9 @@ static void gem_transmit(GemState *s)
} else {
packet_desc_addr += 8;
}
DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
cpu_physical_memory_read(packet_desc_addr,
(uint8_t *)&desc[0], sizeof(desc));
(uint8_t *)desc, sizeof(desc));
}
if (tx_desc_get_used(desc)) {

View File

@@ -69,23 +69,11 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
/*
* HW models:
* E1000_DEV_ID_82540EM works with Windows and Linux
* E1000_DEV_ID_82573L OK with windoze and Linux 2.6.22,
* appears to perform better than 82540EM, but breaks with Linux 2.6.18
* E1000_DEV_ID_82540EM works with Windows, Linux, and OS X <= 10.8
* E1000_DEV_ID_82544GC_COPPER appears to work; not well tested
* E1000_DEV_ID_82545EM_COPPER works with Linux and OS X >= 10.6
* Others never tested
*/
enum { E1000_DEVID = E1000_DEV_ID_82540EM };
/*
* May need to specify additional MAC-to-PHY entries --
* Intel's Windows driver refuses to initialize unless they match
*/
enum {
PHY_ID2_INIT = E1000_DEVID == E1000_DEV_ID_82573L ? 0xcc2 :
E1000_DEVID == E1000_DEV_ID_82544GC_COPPER ? 0xc30 :
/* default to E1000_DEV_ID_82540EM */ 0xc20
};
typedef struct E1000State_st {
/*< private >*/
@@ -151,10 +139,20 @@ typedef struct E1000State_st {
uint32_t compat_flags;
} E1000State;
#define TYPE_E1000 "e1000"
typedef struct E1000BaseClass {
PCIDeviceClass parent_class;
uint16_t phy_id2;
} E1000BaseClass;
#define TYPE_E1000_BASE "e1000-base"
#define E1000(obj) \
OBJECT_CHECK(E1000State, (obj), TYPE_E1000)
OBJECT_CHECK(E1000State, (obj), TYPE_E1000_BASE)
#define E1000_DEVICE_CLASS(klass) \
OBJECT_CLASS_CHECK(E1000BaseClass, (klass), TYPE_E1000_BASE)
#define E1000_DEVICE_GET_CLASS(obj) \
OBJECT_GET_CLASS(E1000BaseClass, (obj), TYPE_E1000_BASE)
#define defreg(x) x = (E1000_##x>>2)
enum {
@@ -232,10 +230,11 @@ static const char phy_regcap[0x20] = {
[PHY_ID2] = PHY_R, [M88E1000_PHY_SPEC_STATUS] = PHY_R
};
/* PHY_ID2 documented in 8254x_GBe_SDM.pdf, pp. 250 */
static const uint16_t phy_reg_init[] = {
[PHY_CTRL] = 0x1140,
[PHY_STATUS] = 0x794d, /* link initially up with not completed autoneg */
[PHY_ID1] = 0x141, [PHY_ID2] = PHY_ID2_INIT,
[PHY_ID1] = 0x141, /* [PHY_ID2] configured per DevId, from e1000_reset() */
[PHY_1000T_CTRL] = 0x0e00, [M88E1000_PHY_SPEC_CTRL] = 0x360,
[M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60, [PHY_AUTONEG_ADV] = 0xde1,
[PHY_LP_ABILITY] = 0x1e0, [PHY_1000T_STATUS] = 0x3c00,
@@ -272,10 +271,6 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val)
uint32_t pending_ints;
uint32_t mit_delay;
if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
/* Only for 8257x */
val |= E1000_ICR_INT_ASSERTED;
}
s->mac_reg[ICR] = val;
/*
@@ -375,6 +370,7 @@ rxbufsize(uint32_t v)
static void e1000_reset(void *opaque)
{
E1000State *d = opaque;
E1000BaseClass *edc = E1000_DEVICE_GET_CLASS(d);
uint8_t *macaddr = d->conf.macaddr.a;
int i;
@@ -385,6 +381,7 @@ static void e1000_reset(void *opaque)
d->mit_ide = 0;
memset(d->phy_reg, 0, sizeof d->phy_reg);
memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
d->phy_reg[PHY_ID2] = edc->phy_id2;
memset(d->mac_reg, 0, sizeof d->mac_reg);
memmove(d->mac_reg, mac_reg_init, sizeof mac_reg_init);
d->rxbuf_min_shift = 1;
@@ -1440,9 +1437,13 @@ static const VMStateDescription vmstate_e1000 = {
}
};
/*
* EEPROM contents documented in Tables 5-2 and 5-3, pp. 98-102.
* Note: A valid DevId will be inserted during pci_e1000_init().
*/
static const uint16_t e1000_eeprom_template[64] = {
0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000,
0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
0x3000, 0x1000, 0x6403, 0 /*DevId*/, 0x8086, 0 /*DevId*/, 0x8086, 0x3040,
0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x2700,
0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x0706,
0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xffff,
@@ -1507,6 +1508,7 @@ static int pci_e1000_init(PCIDevice *pci_dev)
{
DeviceState *dev = DEVICE(pci_dev);
E1000State *d = E1000(pci_dev);
PCIDeviceClass *pdc = PCI_DEVICE_GET_CLASS(pci_dev);
uint8_t *pci_conf;
uint16_t checksum = 0;
int i;
@@ -1531,6 +1533,7 @@ static int pci_e1000_init(PCIDevice *pci_dev)
macaddr = d->conf.macaddr.a;
for (i = 0; i < 3; i++)
d->eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i];
d->eeprom_data[11] = d->eeprom_data[13] = pdc->device_id;
for (i = 0; i < EEPROM_CHECKSUM_REG; i++)
checksum += d->eeprom_data[i];
checksum = (uint16_t) EEPROM_SUM - checksum;
@@ -1564,17 +1567,27 @@ static Property e1000_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
typedef struct E1000Info {
const char *name;
uint16_t device_id;
uint8_t revision;
uint16_t phy_id2;
} E1000Info;
static void e1000_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
E1000BaseClass *e = E1000_DEVICE_CLASS(klass);
const E1000Info *info = data;
k->init = pci_e1000_init;
k->exit = pci_e1000_uninit;
k->romfile = "efi-e1000.rom";
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = E1000_DEVID;
k->revision = 0x03;
k->device_id = info->device_id;
k->revision = info->revision;
e->phy_id2 = info->phy_id2;
k->class_id = PCI_CLASS_NETWORK_ETHERNET;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
dc->desc = "Intel Gigabit Ethernet";
@@ -1583,16 +1596,57 @@ static void e1000_class_init(ObjectClass *klass, void *data)
dc->props = e1000_properties;
}
static const TypeInfo e1000_info = {
.name = TYPE_E1000,
static const TypeInfo e1000_base_info = {
.name = TYPE_E1000_BASE,
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(E1000State),
.class_init = e1000_class_init,
.class_size = sizeof(E1000BaseClass),
.abstract = true,
};
static const E1000Info e1000_devices[] = {
{
.name = "e1000-82540em",
.device_id = E1000_DEV_ID_82540EM,
.revision = 0x03,
.phy_id2 = E1000_PHY_ID2_8254xx_DEFAULT,
},
{
.name = "e1000-82544gc",
.device_id = E1000_DEV_ID_82544GC_COPPER,
.revision = 0x03,
.phy_id2 = E1000_PHY_ID2_82544x,
},
{
.name = "e1000-82545em",
.device_id = E1000_DEV_ID_82545EM_COPPER,
.revision = 0x03,
.phy_id2 = E1000_PHY_ID2_8254xx_DEFAULT,
},
};
static const TypeInfo e1000_default_info = {
.name = "e1000",
.parent = "e1000-82540em",
};
static void e1000_register_types(void)
{
type_register_static(&e1000_info);
int i;
type_register_static(&e1000_base_info);
for (i = 0; i < ARRAY_SIZE(e1000_devices); i++) {
const E1000Info *info = &e1000_devices[i];
TypeInfo type_info = {};
type_info.name = info->name;
type_info.parent = TYPE_E1000_BASE;
type_info.class_data = (void *)info;
type_info.class_init = e1000_class_init;
type_register(&type_info);
}
type_register_static(&e1000_default_info);
}
type_init(e1000_register_types)

View File

@@ -99,6 +99,12 @@
#define E1000_DEV_ID_ICH8_IFE_G 0x10C5
#define E1000_DEV_ID_ICH8_IGP_M 0x104D
/* Device Specific Register Defaults */
#define E1000_PHY_ID2_82541x 0x380
#define E1000_PHY_ID2_82544x 0xC30
#define E1000_PHY_ID2_8254xx_DEFAULT 0xC20 /* 82540x, 82545x, and 82546x */
#define E1000_PHY_ID2_82573x 0xCC0
/* Register Set. (82543, 82544)
*
* Registers are defined to be 32 bits and should be accessed as 32 bit values.

View File

@@ -98,6 +98,7 @@ static void isa_ne2000_class_initfn(ObjectClass *klass, void *data)
dc->realize = isa_ne2000_realizefn;
dc->props = ne2000_isa_properties;
dc->vmsd = &vmstate_isa_ne2000;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}

View File

@@ -2050,7 +2050,7 @@ vmxnet3_cleanup_msix(VMXNET3State *s)
PCIDevice *d = PCI_DEVICE(s);
if (s->msix_used) {
msix_vector_unuse(d, VMXNET3_MAX_INTRS);
vmxnet3_unuse_msix_vectors(s, VMXNET3_MAX_INTRS);
msix_uninit(d, &s->msix_bar, &s->msix_bar);
}
}

View File

@@ -196,14 +196,22 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);
s->regs[rxbase + R_RX_CTRL0] |= CTRL_S;
if (s->regs[rxbase + R_RX_CTRL0] & CTRL_I)
if (s->regs[R_RX_CTRL0] & CTRL_I) {
eth_pulse_irq(s);
}
/* If c_rx_pingpong was set flip buffers. */
s->rxbuf ^= s->c_rx_pingpong;
return size;
}
static void xilinx_ethlite_reset(DeviceState *dev)
{
struct xlx_ethlite *s = XILINX_ETHLITE(dev);
s->rxbuf = 0;
}
static void eth_cleanup(NetClientState *nc)
{
struct xlx_ethlite *s = qemu_get_nic_opaque(nc);
@@ -219,23 +227,25 @@ static NetClientInfo net_xilinx_ethlite_info = {
.cleanup = eth_cleanup,
};
static int xilinx_ethlite_init(SysBusDevice *sbd)
static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
{
DeviceState *dev = DEVICE(sbd);
struct xlx_ethlite *s = XILINX_ETHLITE(dev);
sysbus_init_irq(sbd, &s->irq);
s->rxbuf = 0;
memory_region_init_io(&s->mmio, OBJECT(s), &eth_ops, s,
"xlnx.xps-ethernetlite", R_MAX * 4);
sysbus_init_mmio(sbd, &s->mmio);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
return 0;
}
static void xilinx_ethlite_init(Object *obj)
{
struct xlx_ethlite *s = XILINX_ETHLITE(obj);
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
memory_region_init_io(&s->mmio, obj, &eth_ops, s,
"xlnx.xps-ethernetlite", R_MAX * 4);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
}
static Property xilinx_ethlite_properties[] = {
@@ -248,9 +258,9 @@ static Property xilinx_ethlite_properties[] = {
static void xilinx_ethlite_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = xilinx_ethlite_init;
dc->realize = xilinx_ethlite_realize;
dc->reset = xilinx_ethlite_reset;
dc->props = xilinx_ethlite_properties;
}
@@ -258,6 +268,7 @@ static const TypeInfo xilinx_ethlite_info = {
.name = TYPE_XILINX_ETHLITE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct xlx_ethlite),
.instance_init = xilinx_ethlite_init,
.class_init = xilinx_ethlite_class_init,
};

View File

@@ -46,6 +46,16 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
#define APB_DPRINTF(fmt, ...)
#endif
/* debug IOMMU */
//#define DEBUG_IOMMU
#ifdef DEBUG_IOMMU
#define IOMMU_DPRINTF(fmt, ...) \
do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
#else
#define IOMMU_DPRINTF(fmt, ...)
#endif
/*
* Chipset docs:
* PBM: "UltraSPARC IIi User's Manual",
@@ -70,6 +80,51 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
#define MAX_IVEC 0x40
#define NO_IRQ_REQUEST (MAX_IVEC + 1)
#define IOMMU_PAGE_SIZE_8K (1ULL << 13)
#define IOMMU_PAGE_MASK_8K (~(IOMMU_PAGE_SIZE_8K - 1))
#define IOMMU_PAGE_SIZE_64K (1ULL << 16)
#define IOMMU_PAGE_MASK_64K (~(IOMMU_PAGE_SIZE_64K - 1))
#define IOMMU_NREGS 3
#define IOMMU_CTRL 0x0
#define IOMMU_CTRL_TBW_SIZE (1ULL << 2)
#define IOMMU_CTRL_MMU_EN (1ULL)
#define IOMMU_CTRL_TSB_SHIFT 16
#define IOMMU_BASE 0x8
#define IOMMU_TTE_DATA_V (1ULL << 63)
#define IOMMU_TTE_DATA_SIZE (1ULL << 61)
#define IOMMU_TTE_DATA_W (1ULL << 1)
#define IOMMU_TTE_PHYS_MASK_8K 0x1ffffffe000ULL
#define IOMMU_TTE_PHYS_MASK_64K 0x1ffffff8000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_8M 0x00000000007fe000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_16M 0x0000000000ffe000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_32M 0x0000000001ffe000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_64M 0x0000000003ffe000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_128M 0x0000000007ffe000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_256M 0x000000000fffe000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_512M 0x000000001fffe000ULL
#define IOMMU_TSB_8K_OFFSET_MASK_1G 0x000000003fffe000ULL
#define IOMMU_TSB_64K_OFFSET_MASK_64M 0x0000000003ff0000ULL
#define IOMMU_TSB_64K_OFFSET_MASK_128M 0x0000000007ff0000ULL
#define IOMMU_TSB_64K_OFFSET_MASK_256M 0x000000000fff0000ULL
#define IOMMU_TSB_64K_OFFSET_MASK_512M 0x000000001fff0000ULL
#define IOMMU_TSB_64K_OFFSET_MASK_1G 0x000000003fff0000ULL
#define IOMMU_TSB_64K_OFFSET_MASK_2G 0x000000007fff0000ULL
typedef struct IOMMUState {
AddressSpace iommu_as;
MemoryRegion iommu;
uint64_t regs[IOMMU_NREGS];
} IOMMUState;
#define TYPE_APB "pbm"
#define APB_DEVICE(obj) \
@@ -83,7 +138,7 @@ typedef struct APBState {
MemoryRegion pci_mmio;
MemoryRegion pci_ioport;
uint64_t pci_irq_in;
uint32_t iommu[4];
IOMMUState iommu;
uint32_t pci_control[16];
uint32_t pci_irq_map[8];
uint32_t obio_irq_map[32];
@@ -141,10 +196,217 @@ static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
s->irq_request = NO_IRQ_REQUEST;
}
static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
{
IOMMUState *is = opaque;
return &is->iommu_as;
}
static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr)
{
IOMMUState *is = container_of(iommu, IOMMUState, iommu);
hwaddr baseaddr, offset;
uint64_t tte;
uint32_t tsbsize;
IOMMUTLBEntry ret = {
.target_as = &address_space_memory,
.iova = 0,
.translated_addr = 0,
.addr_mask = ~(hwaddr)0,
.perm = IOMMU_NONE,
};
if (!(is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_MMU_EN)) {
/* IOMMU disabled, passthrough using standard 8K page */
ret.iova = addr & IOMMU_PAGE_MASK_8K;
ret.translated_addr = addr;
ret.addr_mask = IOMMU_PAGE_MASK_8K;
ret.perm = IOMMU_RW;
return ret;
}
baseaddr = is->regs[IOMMU_BASE >> 3];
tsbsize = (is->regs[IOMMU_CTRL >> 3] >> IOMMU_CTRL_TSB_SHIFT) & 0x7;
if (is->regs[IOMMU_CTRL >> 3] & IOMMU_CTRL_TBW_SIZE) {
/* 64K */
switch (tsbsize) {
case 0:
offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_64M) >> 13;
break;
case 1:
offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_128M) >> 13;
break;
case 2:
offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_256M) >> 13;
break;
case 3:
offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_512M) >> 13;
break;
case 4:
offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_1G) >> 13;
break;
case 5:
offset = (addr & IOMMU_TSB_64K_OFFSET_MASK_2G) >> 13;
break;
default:
/* Not implemented, error */
return ret;
}
} else {
/* 8K */
switch (tsbsize) {
case 0:
offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_8M) >> 10;
break;
case 1:
offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_16M) >> 10;
break;
case 2:
offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_32M) >> 10;
break;
case 3:
offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_64M) >> 10;
break;
case 4:
offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_128M) >> 10;
break;
case 5:
offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_256M) >> 10;
break;
case 6:
offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_512M) >> 10;
break;
case 7:
offset = (addr & IOMMU_TSB_8K_OFFSET_MASK_1G) >> 10;
break;
}
}
tte = ldq_be_phys(&address_space_memory, baseaddr + offset);
if (!(tte & IOMMU_TTE_DATA_V)) {
/* Invalid mapping */
return ret;
}
if (tte & IOMMU_TTE_DATA_W) {
/* Writeable */
ret.perm = IOMMU_RW;
} else {
ret.perm = IOMMU_RO;
}
/* Extract phys */
if (tte & IOMMU_TTE_DATA_SIZE) {
/* 64K */
ret.iova = addr & IOMMU_PAGE_MASK_64K;
ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_64K;
ret.addr_mask = (IOMMU_PAGE_SIZE_64K - 1);
} else {
/* 8K */
ret.iova = addr & IOMMU_PAGE_MASK_8K;
ret.translated_addr = tte & IOMMU_TTE_PHYS_MASK_8K;
ret.addr_mask = (IOMMU_PAGE_SIZE_8K - 1);
}
return ret;
}
static MemoryRegionIOMMUOps pbm_iommu_ops = {
.translate = pbm_translate_iommu,
};
static void iommu_config_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
IOMMUState *is = opaque;
IOMMU_DPRINTF("IOMMU config write: 0x%" HWADDR_PRIx " val: %" PRIx64
" size: %d\n", addr, val, size);
switch (addr) {
case IOMMU_CTRL:
if (size == 4) {
is->regs[IOMMU_CTRL >> 3] &= 0xffffffffULL;
is->regs[IOMMU_CTRL >> 3] |= val << 32;
} else {
is->regs[IOMMU_CTRL] = val;
}
break;
case IOMMU_CTRL + 0x4:
is->regs[IOMMU_CTRL >> 3] &= 0xffffffff00000000ULL;
is->regs[IOMMU_CTRL >> 3] |= val & 0xffffffffULL;
break;
case IOMMU_BASE:
if (size == 4) {
is->regs[IOMMU_BASE >> 3] &= 0xffffffffULL;
is->regs[IOMMU_BASE >> 3] |= val << 32;
} else {
is->regs[IOMMU_BASE] = val;
}
break;
case IOMMU_BASE + 0x4:
is->regs[IOMMU_BASE >> 3] &= 0xffffffff00000000ULL;
is->regs[IOMMU_BASE >> 3] |= val & 0xffffffffULL;
break;
default:
qemu_log_mask(LOG_UNIMP,
"apb iommu: Unimplemented register write "
"reg 0x%" HWADDR_PRIx " size 0x%x value 0x%" PRIx64 "\n",
addr, size, val);
break;
}
}
static uint64_t iommu_config_read(void *opaque, hwaddr addr, unsigned size)
{
IOMMUState *is = opaque;
uint64_t val;
switch (addr) {
case IOMMU_CTRL:
if (size == 4) {
val = is->regs[IOMMU_CTRL >> 3] >> 32;
} else {
val = is->regs[IOMMU_CTRL >> 3];
}
break;
case IOMMU_CTRL + 0x4:
val = is->regs[IOMMU_CTRL >> 3] & 0xffffffffULL;
break;
case IOMMU_BASE:
if (size == 4) {
val = is->regs[IOMMU_BASE >> 3] >> 32;
} else {
val = is->regs[IOMMU_BASE >> 3];
}
break;
case IOMMU_BASE + 0x4:
val = is->regs[IOMMU_BASE >> 3] & 0xffffffffULL;
break;
default:
qemu_log_mask(LOG_UNIMP,
"apb iommu: Unimplemented register read "
"reg 0x%" HWADDR_PRIx " size 0x%x\n",
addr, size);
val = 0;
break;
}
IOMMU_DPRINTF("IOMMU config read: 0x%" HWADDR_PRIx " val: %" PRIx64
" size: %d\n", addr, val, size);
return val;
}
static void apb_config_writel (void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
APBState *s = opaque;
IOMMUState *is = &s->iommu;
APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
@@ -152,10 +414,8 @@ static void apb_config_writel (void *opaque, hwaddr addr,
case 0x30 ... 0x4f: /* DMA error registers */
/* XXX: not implemented yet */
break;
case 0x200 ... 0x20b: /* IOMMU */
s->iommu[(addr & 0xf) >> 2] = val;
break;
case 0x20c ... 0x3ff: /* IOMMU flush */
case 0x200 ... 0x217: /* IOMMU */
iommu_config_write(is, (addr & 0xf), val, size);
break;
case 0xc00 ... 0xc3f: /* PCI interrupt control */
if (addr & 4) {
@@ -228,6 +488,7 @@ static uint64_t apb_config_readl (void *opaque,
hwaddr addr, unsigned size)
{
APBState *s = opaque;
IOMMUState *is = &s->iommu;
uint32_t val;
switch (addr & 0xffff) {
@@ -235,11 +496,8 @@ static uint64_t apb_config_readl (void *opaque,
val = 0;
/* XXX: not implemented yet */
break;
case 0x200 ... 0x20b: /* IOMMU */
val = s->iommu[(addr & 0xf) >> 2];
break;
case 0x20c ... 0x3ff: /* IOMMU flush */
val = 0;
case 0x200 ... 0x217: /* IOMMU */
val = iommu_config_read(is, (addr & 0xf), size);
break;
case 0xc00 ... 0xc3f: /* PCI interrupt control */
if (addr & 4) {
@@ -390,6 +648,7 @@ PCIBus *pci_apb_init(hwaddr special_base,
SysBusDevice *s;
PCIHostState *phb;
APBState *d;
IOMMUState *is;
PCIDevice *pci_dev;
PCIBridge *br;
@@ -420,6 +679,15 @@ PCIBus *pci_apb_init(hwaddr special_base,
pci_create_simple(phb->bus, 0, "pbm-pci");
/* APB IOMMU */
is = &d->iommu;
memset(is, 0, sizeof(IOMMUState));
memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
"iommu-apb", UINT64_MAX);
address_space_init(&is->iommu_as, &is->iommu, "pbm-as");
pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
/* APB secondary busses */
pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
"pbm-bridge");

View File

@@ -47,10 +47,6 @@ static void q35_host_realize(DeviceState *dev, Error **errp)
sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
if (pcie_host_init(PCIE_HOST_BRIDGE(s)) < 0) {
error_setg(errp, "failed to initialize pcie host");
return;
}
pci->bus = pci_bus_new(DEVICE(s), "pcie.0",
s->mch.pci_address_space, s->mch.address_space_io,
0, TYPE_PCIE_BUS);

View File

@@ -83,11 +83,11 @@ static const MemoryRegionOps pcie_mmcfg_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
int pcie_host_init(PCIExpressHost *e)
static void pcie_host_init(Object *obj)
{
e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
return 0;
e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
}
void pcie_host_mmcfg_unmap(PCIExpressHost *e)
@@ -128,6 +128,7 @@ static const TypeInfo pcie_host_type_info = {
.parent = TYPE_PCI_HOST_BRIDGE,
.abstract = true,
.instance_size = sizeof(PCIExpressHost),
.instance_init = pcie_host_init,
};
static void pcie_host_register_types(void)

View File

@@ -128,13 +128,11 @@ uint16_t css_build_subchannel_id(SubchDev *sch)
static void css_inject_io_interrupt(SubchDev *sch)
{
S390CPU *cpu = s390_cpu_addr2state(0);
uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
trace_css_io_interrupt(sch->cssid, sch->ssid, sch->schid,
sch->curr_status.pmcw.intparm, isc, "");
s390_io_interrupt(cpu,
css_build_subchannel_id(sch),
s390_io_interrupt(css_build_subchannel_id(sch),
sch->schid,
sch->curr_status.pmcw.intparm,
isc << 27);
@@ -147,7 +145,6 @@ void css_conditional_io_interrupt(SubchDev *sch)
* with alert status.
*/
if (!(sch->curr_status.scsw.ctrl & SCSW_STCTL_STATUS_PEND)) {
S390CPU *cpu = s390_cpu_addr2state(0);
uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
trace_css_io_interrupt(sch->cssid, sch->ssid, sch->schid,
@@ -157,8 +154,7 @@ void css_conditional_io_interrupt(SubchDev *sch)
sch->curr_status.scsw.ctrl |=
SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
/* Inject an I/O interrupt. */
s390_io_interrupt(cpu,
css_build_subchannel_id(sch),
s390_io_interrupt(css_build_subchannel_id(sch),
sch->schid,
sch->curr_status.pmcw.intparm,
isc << 27);
@@ -167,11 +163,10 @@ void css_conditional_io_interrupt(SubchDev *sch)
void css_adapter_interrupt(uint8_t isc)
{
S390CPU *cpu = s390_cpu_addr2state(0);
uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI;
trace_css_adapter_interrupt(isc);
s390_io_interrupt(cpu, 0, 0, 0, io_int_word);
s390_io_interrupt(0, 0, 0, io_int_word);
}
static void sch_handle_clear_func(SubchDev *sch)
@@ -779,9 +774,11 @@ out:
return ret;
}
static void copy_irb_to_guest(IRB *dest, const IRB *src)
static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
{
int i;
uint16_t stctl = src->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
uint16_t actl = src->scsw.ctrl & SCSW_CTRL_MASK_ACTL;
copy_scsw_to_guest(&dest->scsw, &src->scsw);
@@ -791,9 +788,23 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src)
for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
dest->ecw[i] = cpu_to_be32(src->ecw[i]);
}
/* extended measurements enabled? */
if ((src->scsw.flags & SCSW_FLAGS_MASK_ESWF) ||
!(pmcw->flags & PMCW_FLAGS_MASK_TF) ||
!(pmcw->chars & PMCW_CHARS_MASK_XMWME)) {
return;
}
/* extended measurements pending? */
if (!(stctl & SCSW_STCTL_STATUS_PEND)) {
return;
}
if ((stctl & SCSW_STCTL_PRIMARY) ||
(stctl == SCSW_STCTL_SECONDARY) ||
((stctl & SCSW_STCTL_INTERMEDIATE) && (actl & SCSW_ACTL_SUSP))) {
for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
dest->emw[i] = cpu_to_be32(src->emw[i]);
}
}
}
int css_do_tsch(SubchDev *sch, IRB *target_irb)
@@ -838,7 +849,7 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
}
}
/* Store the irb to the guest. */
copy_irb_to_guest(target_irb, &irb);
copy_irb_to_guest(target_irb, &irb, p);
/* Clear conditions on subchannel, if applicable. */
if (stctl & SCSW_STCTL_STATUS_PEND) {
@@ -1215,11 +1226,9 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
QTAILQ_INSERT_TAIL(&channel_subsys->pending_crws, crw_cont, sibling);
if (channel_subsys->do_crw_mchk) {
S390CPU *cpu = s390_cpu_addr2state(0);
channel_subsys->do_crw_mchk = false;
/* Inject crw pending machine check. */
s390_crw_mchk(cpu);
s390_crw_mchk();
}
}
@@ -1277,6 +1286,117 @@ int css_enable_mss(void)
return 0;
}
void subch_device_save(SubchDev *s, QEMUFile *f)
{
int i;
qemu_put_byte(f, s->cssid);
qemu_put_byte(f, s->ssid);
qemu_put_be16(f, s->schid);
qemu_put_be16(f, s->devno);
qemu_put_byte(f, s->thinint_active);
/* SCHIB */
/* PMCW */
qemu_put_be32(f, s->curr_status.pmcw.intparm);
qemu_put_be16(f, s->curr_status.pmcw.flags);
qemu_put_be16(f, s->curr_status.pmcw.devno);
qemu_put_byte(f, s->curr_status.pmcw.lpm);
qemu_put_byte(f, s->curr_status.pmcw.pnom);
qemu_put_byte(f, s->curr_status.pmcw.lpum);
qemu_put_byte(f, s->curr_status.pmcw.pim);
qemu_put_be16(f, s->curr_status.pmcw.mbi);
qemu_put_byte(f, s->curr_status.pmcw.pom);
qemu_put_byte(f, s->curr_status.pmcw.pam);
qemu_put_buffer(f, s->curr_status.pmcw.chpid, 8);
qemu_put_be32(f, s->curr_status.pmcw.chars);
/* SCSW */
qemu_put_be16(f, s->curr_status.scsw.flags);
qemu_put_be16(f, s->curr_status.scsw.ctrl);
qemu_put_be32(f, s->curr_status.scsw.cpa);
qemu_put_byte(f, s->curr_status.scsw.dstat);
qemu_put_byte(f, s->curr_status.scsw.cstat);
qemu_put_be16(f, s->curr_status.scsw.count);
qemu_put_be64(f, s->curr_status.mba);
qemu_put_buffer(f, s->curr_status.mda, 4);
/* end SCHIB */
qemu_put_buffer(f, s->sense_data, 32);
qemu_put_be64(f, s->channel_prog);
/* last cmd */
qemu_put_byte(f, s->last_cmd.cmd_code);
qemu_put_byte(f, s->last_cmd.flags);
qemu_put_be16(f, s->last_cmd.count);
qemu_put_be32(f, s->last_cmd.cda);
qemu_put_byte(f, s->last_cmd_valid);
qemu_put_byte(f, s->id.reserved);
qemu_put_be16(f, s->id.cu_type);
qemu_put_byte(f, s->id.cu_model);
qemu_put_be16(f, s->id.dev_type);
qemu_put_byte(f, s->id.dev_model);
qemu_put_byte(f, s->id.unused);
for (i = 0; i < ARRAY_SIZE(s->id.ciw); i++) {
qemu_put_byte(f, s->id.ciw[i].type);
qemu_put_byte(f, s->id.ciw[i].command);
qemu_put_be16(f, s->id.ciw[i].count);
}
return;
}
int subch_device_load(SubchDev *s, QEMUFile *f)
{
int i;
s->cssid = qemu_get_byte(f);
s->ssid = qemu_get_byte(f);
s->schid = qemu_get_be16(f);
s->devno = qemu_get_be16(f);
s->thinint_active = qemu_get_byte(f);
/* SCHIB */
/* PMCW */
s->curr_status.pmcw.intparm = qemu_get_be32(f);
s->curr_status.pmcw.flags = qemu_get_be16(f);
s->curr_status.pmcw.devno = qemu_get_be16(f);
s->curr_status.pmcw.lpm = qemu_get_byte(f);
s->curr_status.pmcw.pnom = qemu_get_byte(f);
s->curr_status.pmcw.lpum = qemu_get_byte(f);
s->curr_status.pmcw.pim = qemu_get_byte(f);
s->curr_status.pmcw.mbi = qemu_get_be16(f);
s->curr_status.pmcw.pom = qemu_get_byte(f);
s->curr_status.pmcw.pam = qemu_get_byte(f);
qemu_get_buffer(f, s->curr_status.pmcw.chpid, 8);
s->curr_status.pmcw.chars = qemu_get_be32(f);
/* SCSW */
s->curr_status.scsw.flags = qemu_get_be16(f);
s->curr_status.scsw.ctrl = qemu_get_be16(f);
s->curr_status.scsw.cpa = qemu_get_be32(f);
s->curr_status.scsw.dstat = qemu_get_byte(f);
s->curr_status.scsw.cstat = qemu_get_byte(f);
s->curr_status.scsw.count = qemu_get_be16(f);
s->curr_status.mba = qemu_get_be64(f);
qemu_get_buffer(f, s->curr_status.mda, 4);
/* end SCHIB */
qemu_get_buffer(f, s->sense_data, 32);
s->channel_prog = qemu_get_be64(f);
/* last cmd */
s->last_cmd.cmd_code = qemu_get_byte(f);
s->last_cmd.flags = qemu_get_byte(f);
s->last_cmd.count = qemu_get_be16(f);
s->last_cmd.cda = qemu_get_be32(f);
s->last_cmd_valid = qemu_get_byte(f);
s->id.reserved = qemu_get_byte(f);
s->id.cu_type = qemu_get_be16(f);
s->id.cu_model = qemu_get_byte(f);
s->id.dev_type = qemu_get_be16(f);
s->id.dev_model = qemu_get_byte(f);
s->id.unused = qemu_get_byte(f);
for (i = 0; i < ARRAY_SIZE(s->id.ciw); i++) {
s->id.ciw[i].type = qemu_get_byte(f);
s->id.ciw[i].command = qemu_get_byte(f);
s->id.ciw[i].count = qemu_get_be16(f);
}
return 0;
}
static void css_init(void)
{
channel_subsys = g_malloc0(sizeof(*channel_subsys));

View File

@@ -85,6 +85,8 @@ struct SubchDev {
typedef SubchDev *(*css_subch_cb_func)(uint8_t m, uint8_t cssid, uint8_t ssid,
uint16_t schid);
void subch_device_save(SubchDev *s, QEMUFile *f);
int subch_device_load(SubchDev *s, QEMUFile *f);
int css_create_css_image(uint8_t cssid, bool default_image);
bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno);
void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,

View File

@@ -45,8 +45,6 @@
do { } while (0)
#endif
#define VIRTIO_EXT_CODE 0x2603
static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size,
VirtIOS390Device *dev);
@@ -113,15 +111,6 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
return bus;
}
static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token)
{
if (kvm_enabled()) {
kvm_s390_virtio_irq(cpu, config_change, token);
} else {
cpu_inject_ext(cpu, VIRTIO_EXT_CODE, config_change, token);
}
}
static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
{
VirtIOS390Bus *bus;
@@ -144,8 +133,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
s390_virtio_device_sync(dev);
s390_virtio_reset_idx(dev);
if (dev->qdev.hotplugged) {
S390CPU *cpu = s390_cpu_addr2state(0);
s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
s390_virtio_irq(VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
}
return 0;
@@ -489,9 +477,8 @@ static void virtio_s390_notify(DeviceState *d, uint16_t vector)
{
VirtIOS390Device *dev = to_virtio_s390_device_fast(d);
uint64_t token = s390_virtio_device_vq_token(dev, vector);
S390CPU *cpu = s390_cpu_addr2state(0);
s390_virtio_irq(cpu, 0, token);
s390_virtio_irq(0, token);
}
static unsigned virtio_s390_get_features(DeviceState *d)

View File

@@ -1275,6 +1275,97 @@ irqroute_error:
return r;
}
static void virtio_ccw_save_queue(DeviceState *d, int n, QEMUFile *f)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
qemu_put_be16(f, virtio_queue_vector(vdev, n));
}
static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
uint16_t vector;
qemu_get_be16s(f, &vector);
virtio_queue_set_vector(vdev, n , vector);
return 0;
}
static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
SubchDev *s = dev->sch;
subch_device_save(s, f);
if (dev->indicators != NULL) {
qemu_put_be32(f, dev->indicators->len);
qemu_put_be64(f, dev->indicators->addr);
} else {
qemu_put_be32(f, 0);
qemu_put_be64(f, 0UL);
}
if (dev->indicators2 != NULL) {
qemu_put_be32(f, dev->indicators2->len);
qemu_put_be64(f, dev->indicators2->addr);
} else {
qemu_put_be32(f, 0);
qemu_put_be64(f, 0UL);
}
if (dev->summary_indicator != NULL) {
qemu_put_be32(f, dev->summary_indicator->len);
qemu_put_be64(f, dev->summary_indicator->addr);
} else {
qemu_put_be32(f, 0);
qemu_put_be64(f, 0UL);
}
qemu_put_be64(f, dev->routes.adapter.ind_offset);
qemu_put_byte(f, dev->thinint_isc);
}
static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
SubchDev *s = dev->sch;
int len;
s->driver_data = dev;
subch_device_load(s, f);
len = qemu_get_be32(f);
if (len != 0) {
dev->indicators = get_indicator(qemu_get_be64(f), len);
} else {
qemu_get_be64(f);
dev->indicators = NULL;
}
len = qemu_get_be32(f);
if (len != 0) {
dev->indicators2 = get_indicator(qemu_get_be64(f), len);
} else {
qemu_get_be64(f);
dev->indicators2 = NULL;
}
len = qemu_get_be32(f);
if (len != 0) {
dev->summary_indicator = get_indicator(qemu_get_be64(f), len);
} else {
qemu_get_be64(f);
dev->summary_indicator = NULL;
}
dev->routes.adapter.ind_offset = qemu_get_be64(f);
dev->thinint_isc = qemu_get_byte(f);
if (s->thinint_active) {
return css_register_io_adapter(CSS_IO_ADAPTER_VIRTIO,
dev->thinint_isc, true, false,
&dev->routes.adapter.adapter_id);
}
return 0;
}
/**************** Virtio-ccw Bus Device Descriptions *******************/
static Property virtio_ccw_net_properties[] = {
@@ -1597,6 +1688,10 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
k->set_host_notifier = virtio_ccw_set_host_notifier;
k->set_guest_notifiers = virtio_ccw_set_guest_notifiers;
k->save_queue = virtio_ccw_save_queue;
k->load_queue = virtio_ccw_load_queue;
k->save_config = virtio_ccw_save_config;
k->load_config = virtio_ccw_load_config;
}
static const TypeInfo virtio_ccw_bus_info = {

View File

@@ -164,8 +164,8 @@ static void vhost_scsi_set_config(VirtIODevice *vdev,
VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
if ((uint32_t) ldl_raw(&scsiconf->sense_size) != vs->sense_size ||
(uint32_t) ldl_raw(&scsiconf->cdb_size) != vs->cdb_size) {
if ((uint32_t) ldl_p(&scsiconf->sense_size) != vs->sense_size ||
(uint32_t) ldl_p(&scsiconf->cdb_size) != vs->cdb_size) {
error_report("vhost-scsi does not support changing the sense data and CDB sizes");
exit(1);
}

View File

@@ -425,16 +425,16 @@ static void virtio_scsi_get_config(VirtIODevice *vdev,
VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(vdev);
stl_raw(&scsiconf->num_queues, s->conf.num_queues);
stl_raw(&scsiconf->seg_max, 128 - 2);
stl_raw(&scsiconf->max_sectors, s->conf.max_sectors);
stl_raw(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
stl_raw(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
stl_raw(&scsiconf->sense_size, s->sense_size);
stl_raw(&scsiconf->cdb_size, s->cdb_size);
stw_raw(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
stw_raw(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
stl_raw(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
stl_p(&scsiconf->num_queues, s->conf.num_queues);
stl_p(&scsiconf->seg_max, 128 - 2);
stl_p(&scsiconf->max_sectors, s->conf.max_sectors);
stl_p(&scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
stl_p(&scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
stl_p(&scsiconf->sense_size, s->sense_size);
stl_p(&scsiconf->cdb_size, s->cdb_size);
stw_p(&scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
stw_p(&scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
stl_p(&scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
}
static void virtio_scsi_set_config(VirtIODevice *vdev,
@@ -443,14 +443,14 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
if ((uint32_t) ldl_raw(&scsiconf->sense_size) >= 65536 ||
(uint32_t) ldl_raw(&scsiconf->cdb_size) >= 256) {
if ((uint32_t) ldl_p(&scsiconf->sense_size) >= 65536 ||
(uint32_t) ldl_p(&scsiconf->cdb_size) >= 256) {
error_report("bad data written to virtio-scsi configuration space");
exit(1);
}
vs->sense_size = ldl_raw(&scsiconf->sense_size);
vs->cdb_size = ldl_raw(&scsiconf->cdb_size);
vs->sense_size = ldl_p(&scsiconf->sense_size);
vs->cdb_size = ldl_p(&scsiconf->cdb_size);
}
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,

View File

@@ -151,17 +151,6 @@ static const sd_cmd_type_t sd_cmd_type[64] = {
sd_adtc, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
};
static const sd_cmd_type_t sd_acmd_type[64] = {
sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_ac, sd_none,
sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none,
sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_adtc, sd_ac,
sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
sd_none, sd_bcr, sd_ac, sd_none, sd_none, sd_none, sd_none, sd_none,
sd_none, sd_none, sd_none, sd_adtc, sd_none, sd_none, sd_none, sd_none,
sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none, sd_none,
};
static const int sd_cmd_class[64] = {
0, 0, 0, 0, 0, 9, 10, 0, 0, 0, 0, 1, 0, 0, 0, 0,
2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 6, 6, 6, 6,

View File

@@ -543,14 +543,14 @@ static void tcx_init(hwaddr addr, int vram_size, int width,
s = SYS_BUS_DEVICE(dev);
/* FCode ROM */
sysbus_mmio_map(s, 0, addr);
/* 8-bit plane */
sysbus_mmio_map(s, 1, addr + 0x00800000ULL);
/* DAC */
sysbus_mmio_map(s, 2, addr + 0x00200000ULL);
sysbus_mmio_map(s, 1, addr + 0x00200000ULL);
/* TEC (dummy) */
sysbus_mmio_map(s, 3, addr + 0x00700000ULL);
sysbus_mmio_map(s, 2, addr + 0x00700000ULL);
/* THC 24 bit: NetBSD writes here even with 8-bit display: dummy */
sysbus_mmio_map(s, 4, addr + 0x00301000ULL);
sysbus_mmio_map(s, 3, addr + 0x00301000ULL);
/* 8-bit plane */
sysbus_mmio_map(s, 4, addr + 0x00800000ULL);
if (depth == 24) {
/* 24-bit plane */
sysbus_mmio_map(s, 5, addr + 0x02000000ULL);

View File

@@ -204,14 +204,11 @@ static void timer_hit(void *opaque)
timer_update_irq(t);
}
static int xilinx_timer_init(SysBusDevice *dev)
static void xilinx_timer_realize(DeviceState *dev, Error **errp)
{
struct timerblock *t = XILINX_TIMER(dev);
unsigned int i;
/* All timers share a single irq line. */
sysbus_init_irq(dev, &t->irq);
/* Init all the ptimers. */
t->timers = g_malloc0(sizeof t->timers[0] * num_timers(t));
for (i = 0; i < num_timers(t); i++) {
@@ -226,8 +223,15 @@ static int xilinx_timer_init(SysBusDevice *dev)
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer",
R_MAX * 4 * num_timers(t));
sysbus_init_mmio(dev, &t->mmio);
return 0;
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &t->mmio);
}
static void xilinx_timer_init(Object *obj)
{
struct timerblock *t = XILINX_TIMER(obj);
/* All timers share a single irq line. */
sysbus_init_irq(SYS_BUS_DEVICE(obj), &t->irq);
}
static Property xilinx_timer_properties[] = {
@@ -240,9 +244,8 @@ static Property xilinx_timer_properties[] = {
static void xilinx_timer_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = xilinx_timer_init;
dc->realize = xilinx_timer_realize;
dc->props = xilinx_timer_properties;
}
@@ -250,6 +253,7 @@ static const TypeInfo xilinx_timer_info = {
.name = TYPE_XILINX_TIMER,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(struct timerblock),
.instance_init = xilinx_timer_init,
.class_init = xilinx_timer_class_init,
};

View File

@@ -41,7 +41,6 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
for (;from < to; ++from) {
vhost_log_chunk_t log;
int bit;
/* We first check with non-atomic: much cheaper,
* and we expect non-dirty to be the common case. */
if (!*from) {
@@ -51,12 +50,11 @@ static void vhost_dev_sync_region(struct vhost_dev *dev,
/* Data must be read atomically. We don't really need barrier semantics
* but it's easier to use atomic_* than roll our own. */
log = atomic_xchg(from, 0);
while ((bit = sizeof(log) > sizeof(int) ?
ffsll(log) : ffs(log))) {
while (log) {
int bit = ctzl(log);
hwaddr page_addr;
hwaddr section_offset;
hwaddr mr_offset;
bit -= 1;
page_addr = addr + bit * VHOST_LOG_PAGE;
section_offset = page_addr - section->offset_within_address_space;
mr_offset = section_offset + section->offset_within_region;

View File

@@ -112,11 +112,6 @@ static void balloon_stats_get_all(Object *obj, struct Visitor *v,
VirtIOBalloon *s = opaque;
int i;
if (!s->stats_last_update) {
error_setg(errp, "guest hasn't updated any stats yet");
return;
}
visit_start_struct(v, NULL, "guest-stats", name, 0, &err);
if (err) {
goto out;
@@ -378,6 +373,8 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
reset_stats(s);
register_savevm(dev, "virtio-balloon", -1, 1,
virtio_balloon_save, virtio_balloon_load, s);

View File

@@ -440,7 +440,7 @@ void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
len = sg[i].iov_len;
sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
if (sg[i].iov_base == NULL || len != sg[i].iov_len) {
error_report("virtio: trying to map MMIO memory");
error_report("virtio: error trying to map MMIO memory");
exit(1);
}
}

View File

@@ -481,15 +481,6 @@ void bdrv_op_block_all(BlockDriverState *bs, Error *reason);
void bdrv_op_unblock_all(BlockDriverState *bs, Error *reason);
bool bdrv_op_blocker_is_empty(BlockDriverState *bs);
#ifdef CONFIG_LINUX_AIO
int raw_get_aio_fd(BlockDriverState *bs);
#else
static inline int raw_get_aio_fd(BlockDriverState *bs)
{
return -ENOTSUP;
}
#endif
enum BlockAcctType {
BDRV_ACCT_READ,
BDRV_ACCT_WRITE,
@@ -574,4 +565,22 @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag);
int bdrv_debug_resume(BlockDriverState *bs, const char *tag);
bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag);
/**
* bdrv_get_aio_context:
*
* Returns: the currently bound #AioContext
*/
AioContext *bdrv_get_aio_context(BlockDriverState *bs);
/**
* bdrv_set_aio_context:
*
* Changes the #AioContext used for fd handlers, timers, and BHs by this
* BlockDriverState and all its children.
*
* This function must be called from the old #AioContext or with a lock held so
* the old #AioContext is not executing.
*/
void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context);
#endif

View File

@@ -247,6 +247,19 @@ struct BlockDriver {
*/
int (*bdrv_has_zero_init)(BlockDriverState *bs);
/* Remove fd handlers, timers, and other event loop callbacks so the event
* loop is no longer in use. Called with no in-flight requests and in
* depth-first traversal order with parents before child nodes.
*/
void (*bdrv_detach_aio_context)(BlockDriverState *bs);
/* Add fd handlers, timers, and other event loop callbacks so I/O requests
* can be processed again. Called with no in-flight requests and in
* depth-first traversal order with child nodes before parent nodes.
*/
void (*bdrv_attach_aio_context)(BlockDriverState *bs,
AioContext *new_context);
QLIST_ENTRY(BlockDriver) list;
};
@@ -297,6 +310,8 @@ struct BlockDriverState {
const BlockDevOps *dev_ops;
void *dev_opaque;
AioContext *aio_context; /* event loop used for fd handlers, timers, etc */
char filename[1024];
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
@@ -390,11 +405,25 @@ void bdrv_add_before_write_notifier(BlockDriverState *bs,
NotifierWithReturn *notifier);
/**
* bdrv_get_aio_context:
* bdrv_detach_aio_context:
*
* Returns: the currently bound #AioContext
* May be called from .bdrv_detach_aio_context() to detach children from the
* current #AioContext. This is only needed by block drivers that manage their
* own children. Both ->file and ->backing_hd are automatically handled and
* block drivers should not call this function on them explicitly.
*/
AioContext *bdrv_get_aio_context(BlockDriverState *bs);
void bdrv_detach_aio_context(BlockDriverState *bs);
/**
* bdrv_attach_aio_context:
*
* May be called from .bdrv_attach_aio_context() to attach children to the new
* #AioContext. This is only needed by block drivers that manage their own
* children. Both ->file and ->backing_hd are automatically handled and block
* drivers should not call this function on them explicitly.
*/
void bdrv_attach_aio_context(BlockDriverState *bs,
AioContext *new_context);
#ifdef _WIN32
int is_windows_drive(const char *filename);

View File

@@ -198,127 +198,8 @@ extern unsigned long reserved_va;
#define RESERVED_VA 0ul
#endif
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
#define h2g_valid(x) 1
#else
#define h2g_valid(x) ({ \
unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
(__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
(!RESERVED_VA || (__guest < RESERVED_VA)); \
})
#endif
#define h2g_nocheck(x) ({ \
unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
(abi_ulong)__ret; \
})
#define h2g(x) ({ \
/* Check if given address fits target address space */ \
assert(h2g_valid(x)); \
h2g_nocheck(x); \
})
#define saddr(x) g2h(x)
#define laddr(x) g2h(x)
#else /* !CONFIG_USER_ONLY */
/* NOTE: we use double casts if pointers and target_ulong have
different sizes */
#define saddr(x) (uint8_t *)(intptr_t)(x)
#define laddr(x) (uint8_t *)(intptr_t)(x)
#endif
#define ldub_raw(p) ldub_p(laddr((p)))
#define ldsb_raw(p) ldsb_p(laddr((p)))
#define lduw_raw(p) lduw_p(laddr((p)))
#define ldsw_raw(p) ldsw_p(laddr((p)))
#define ldl_raw(p) ldl_p(laddr((p)))
#define ldq_raw(p) ldq_p(laddr((p)))
#define ldfl_raw(p) ldfl_p(laddr((p)))
#define ldfq_raw(p) ldfq_p(laddr((p)))
#define stb_raw(p, v) stb_p(saddr((p)), v)
#define stw_raw(p, v) stw_p(saddr((p)), v)
#define stl_raw(p, v) stl_p(saddr((p)), v)
#define stq_raw(p, v) stq_p(saddr((p)), v)
#define stfl_raw(p, v) stfl_p(saddr((p)), v)
#define stfq_raw(p, v) stfq_p(saddr((p)), v)
#if defined(CONFIG_USER_ONLY)
/* if user mode, no other memory access functions */
#define ldub(p) ldub_raw(p)
#define ldsb(p) ldsb_raw(p)
#define lduw(p) lduw_raw(p)
#define ldsw(p) ldsw_raw(p)
#define ldl(p) ldl_raw(p)
#define ldq(p) ldq_raw(p)
#define ldfl(p) ldfl_raw(p)
#define ldfq(p) ldfq_raw(p)
#define stb(p, v) stb_raw(p, v)
#define stw(p, v) stw_raw(p, v)
#define stl(p, v) stl_raw(p, v)
#define stq(p, v) stq_raw(p, v)
#define stfl(p, v) stfl_raw(p, v)
#define stfq(p, v) stfq_raw(p, v)
#define cpu_ldub_code(env1, p) ldub_raw(p)
#define cpu_ldsb_code(env1, p) ldsb_raw(p)
#define cpu_lduw_code(env1, p) lduw_raw(p)
#define cpu_ldsw_code(env1, p) ldsw_raw(p)
#define cpu_ldl_code(env1, p) ldl_raw(p)
#define cpu_ldq_code(env1, p) ldq_raw(p)
#define cpu_ldub_data(env, addr) ldub_raw(addr)
#define cpu_lduw_data(env, addr) lduw_raw(addr)
#define cpu_ldsw_data(env, addr) ldsw_raw(addr)
#define cpu_ldl_data(env, addr) ldl_raw(addr)
#define cpu_ldq_data(env, addr) ldq_raw(addr)
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
#define cpu_stq_data(env, addr, data) stq_raw(addr, data)
#define cpu_ldub_kernel(env, addr) ldub_raw(addr)
#define cpu_lduw_kernel(env, addr) lduw_raw(addr)
#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr)
#define cpu_ldl_kernel(env, addr) ldl_raw(addr)
#define cpu_ldq_kernel(env, addr) ldq_raw(addr)
#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data)
#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data)
#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data)
#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data)
#define ldub_kernel(p) ldub_raw(p)
#define ldsb_kernel(p) ldsb_raw(p)
#define lduw_kernel(p) lduw_raw(p)
#define ldsw_kernel(p) ldsw_raw(p)
#define ldl_kernel(p) ldl_raw(p)
#define ldq_kernel(p) ldq_raw(p)
#define ldfl_kernel(p) ldfl_raw(p)
#define ldfq_kernel(p) ldfq_raw(p)
#define stb_kernel(p, v) stb_raw(p, v)
#define stw_kernel(p, v) stw_raw(p, v)
#define stl_kernel(p, v) stl_raw(p, v)
#define stq_kernel(p, v) stq_raw(p, v)
#define stfl_kernel(p, v) stfl_raw(p, v)
#define stfq_kernel(p, vt) stfq_raw(p, v)
#define cpu_ldub_data(env, addr) ldub_raw(addr)
#define cpu_lduw_data(env, addr) lduw_raw(addr)
#define cpu_ldl_data(env, addr) ldl_raw(addr)
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
#endif /* defined(CONFIG_USER_ONLY) */
/* page related stuff */
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)

400
include/exec/cpu_ldst.h Normal file
View File

@@ -0,0 +1,400 @@
/*
* Software MMU support
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Generate inline load/store functions for all MMU modes (typically
* at least _user and _kernel) as well as _data versions, for all data
* sizes.
*
* Used by target op helpers.
*
* MMU mode suffixes are defined in target cpu.h.
*/
#ifndef CPU_LDST_H
#define CPU_LDST_H
#if defined(CONFIG_USER_ONLY)
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
#define h2g_valid(x) 1
#else
#define h2g_valid(x) ({ \
unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
(__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
(!RESERVED_VA || (__guest < RESERVED_VA)); \
})
#endif
#define h2g_nocheck(x) ({ \
unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
(abi_ulong)__ret; \
})
#define h2g(x) ({ \
/* Check if given address fits target address space */ \
assert(h2g_valid(x)); \
h2g_nocheck(x); \
})
#define saddr(x) g2h(x)
#define laddr(x) g2h(x)
#else /* !CONFIG_USER_ONLY */
/* NOTE: we use double casts if pointers and target_ulong have
different sizes */
#define saddr(x) (uint8_t *)(intptr_t)(x)
#define laddr(x) (uint8_t *)(intptr_t)(x)
#endif
#define ldub_raw(p) ldub_p(laddr((p)))
#define ldsb_raw(p) ldsb_p(laddr((p)))
#define lduw_raw(p) lduw_p(laddr((p)))
#define ldsw_raw(p) ldsw_p(laddr((p)))
#define ldl_raw(p) ldl_p(laddr((p)))
#define ldq_raw(p) ldq_p(laddr((p)))
#define ldfl_raw(p) ldfl_p(laddr((p)))
#define ldfq_raw(p) ldfq_p(laddr((p)))
#define stb_raw(p, v) stb_p(saddr((p)), v)
#define stw_raw(p, v) stw_p(saddr((p)), v)
#define stl_raw(p, v) stl_p(saddr((p)), v)
#define stq_raw(p, v) stq_p(saddr((p)), v)
#define stfl_raw(p, v) stfl_p(saddr((p)), v)
#define stfq_raw(p, v) stfq_p(saddr((p)), v)
#if defined(CONFIG_USER_ONLY)
/* if user mode, no other memory access functions */
#define ldub(p) ldub_raw(p)
#define ldsb(p) ldsb_raw(p)
#define lduw(p) lduw_raw(p)
#define ldsw(p) ldsw_raw(p)
#define ldl(p) ldl_raw(p)
#define ldq(p) ldq_raw(p)
#define ldfl(p) ldfl_raw(p)
#define ldfq(p) ldfq_raw(p)
#define stb(p, v) stb_raw(p, v)
#define stw(p, v) stw_raw(p, v)
#define stl(p, v) stl_raw(p, v)
#define stq(p, v) stq_raw(p, v)
#define stfl(p, v) stfl_raw(p, v)
#define stfq(p, v) stfq_raw(p, v)
#define cpu_ldub_code(env1, p) ldub_raw(p)
#define cpu_ldsb_code(env1, p) ldsb_raw(p)
#define cpu_lduw_code(env1, p) lduw_raw(p)
#define cpu_ldsw_code(env1, p) ldsw_raw(p)
#define cpu_ldl_code(env1, p) ldl_raw(p)
#define cpu_ldq_code(env1, p) ldq_raw(p)
#define cpu_ldub_data(env, addr) ldub_raw(addr)
#define cpu_lduw_data(env, addr) lduw_raw(addr)
#define cpu_ldsw_data(env, addr) ldsw_raw(addr)
#define cpu_ldl_data(env, addr) ldl_raw(addr)
#define cpu_ldq_data(env, addr) ldq_raw(addr)
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
#define cpu_stq_data(env, addr, data) stq_raw(addr, data)
#define cpu_ldub_kernel(env, addr) ldub_raw(addr)
#define cpu_lduw_kernel(env, addr) lduw_raw(addr)
#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr)
#define cpu_ldl_kernel(env, addr) ldl_raw(addr)
#define cpu_ldq_kernel(env, addr) ldq_raw(addr)
#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data)
#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data)
#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data)
#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data)
#define ldub_kernel(p) ldub_raw(p)
#define ldsb_kernel(p) ldsb_raw(p)
#define lduw_kernel(p) lduw_raw(p)
#define ldsw_kernel(p) ldsw_raw(p)
#define ldl_kernel(p) ldl_raw(p)
#define ldq_kernel(p) ldq_raw(p)
#define ldfl_kernel(p) ldfl_raw(p)
#define ldfq_kernel(p) ldfq_raw(p)
#define stb_kernel(p, v) stb_raw(p, v)
#define stw_kernel(p, v) stw_raw(p, v)
#define stl_kernel(p, v) stl_raw(p, v)
#define stq_kernel(p, v) stq_raw(p, v)
#define stfl_kernel(p, v) stfl_raw(p, v)
#define stfq_kernel(p, vt) stfq_raw(p, v)
#define cpu_ldub_data(env, addr) ldub_raw(addr)
#define cpu_lduw_data(env, addr) lduw_raw(addr)
#define cpu_ldl_data(env, addr) ldl_raw(addr)
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
#else
/* XXX: find something cleaner.
* Furthermore, this is false for 64 bits targets
*/
#define ldul_user ldl_user
#define ldul_kernel ldl_kernel
#define ldul_hypv ldl_hypv
#define ldul_executive ldl_executive
#define ldul_supervisor ldl_supervisor
/* The memory helpers for tcg-generated code need tcg_target_long etc. */
#include "tcg.h"
uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
void helper_stb_mmu(CPUArchState *env, target_ulong addr,
uint8_t val, int mmu_idx);
void helper_stw_mmu(CPUArchState *env, target_ulong addr,
uint16_t val, int mmu_idx);
void helper_stl_mmu(CPUArchState *env, target_ulong addr,
uint32_t val, int mmu_idx);
void helper_stq_mmu(CPUArchState *env, target_ulong addr,
uint64_t val, int mmu_idx);
uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
#define CPU_MMU_INDEX 0
#define MEMSUFFIX MMU_MODE0_SUFFIX
#define DATA_SIZE 1
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 2
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 4
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 8
#include "exec/cpu_ldst_template.h"
#undef CPU_MMU_INDEX
#undef MEMSUFFIX
#define CPU_MMU_INDEX 1
#define MEMSUFFIX MMU_MODE1_SUFFIX
#define DATA_SIZE 1
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 2
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 4
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 8
#include "exec/cpu_ldst_template.h"
#undef CPU_MMU_INDEX
#undef MEMSUFFIX
#if (NB_MMU_MODES >= 3)
#define CPU_MMU_INDEX 2
#define MEMSUFFIX MMU_MODE2_SUFFIX
#define DATA_SIZE 1
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 2
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 4
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 8
#include "exec/cpu_ldst_template.h"
#undef CPU_MMU_INDEX
#undef MEMSUFFIX
#endif /* (NB_MMU_MODES >= 3) */
#if (NB_MMU_MODES >= 4)
#define CPU_MMU_INDEX 3
#define MEMSUFFIX MMU_MODE3_SUFFIX
#define DATA_SIZE 1
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 2
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 4
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 8
#include "exec/cpu_ldst_template.h"
#undef CPU_MMU_INDEX
#undef MEMSUFFIX
#endif /* (NB_MMU_MODES >= 4) */
#if (NB_MMU_MODES >= 5)
#define CPU_MMU_INDEX 4
#define MEMSUFFIX MMU_MODE4_SUFFIX
#define DATA_SIZE 1
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 2
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 4
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 8
#include "exec/cpu_ldst_template.h"
#undef CPU_MMU_INDEX
#undef MEMSUFFIX
#endif /* (NB_MMU_MODES >= 5) */
#if (NB_MMU_MODES >= 6)
#define CPU_MMU_INDEX 5
#define MEMSUFFIX MMU_MODE5_SUFFIX
#define DATA_SIZE 1
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 2
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 4
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 8
#include "exec/cpu_ldst_template.h"
#undef CPU_MMU_INDEX
#undef MEMSUFFIX
#endif /* (NB_MMU_MODES >= 6) */
#if (NB_MMU_MODES > 6)
#error "NB_MMU_MODES > 6 is not supported for now"
#endif /* (NB_MMU_MODES > 6) */
/* these access are slower, they must be as rare as possible */
#define CPU_MMU_INDEX (cpu_mmu_index(env))
#define MEMSUFFIX _data
#define DATA_SIZE 1
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 2
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 4
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 8
#include "exec/cpu_ldst_template.h"
#undef CPU_MMU_INDEX
#undef MEMSUFFIX
#define ldub(p) ldub_data(p)
#define ldsb(p) ldsb_data(p)
#define lduw(p) lduw_data(p)
#define ldsw(p) ldsw_data(p)
#define ldl(p) ldl_data(p)
#define ldq(p) ldq_data(p)
#define stb(p, v) stb_data(p, v)
#define stw(p, v) stw_data(p, v)
#define stl(p, v) stl_data(p, v)
#define stq(p, v) stq_data(p, v)
#define CPU_MMU_INDEX (cpu_mmu_index(env))
#define MEMSUFFIX _code
#define SOFTMMU_CODE_ACCESS
#define DATA_SIZE 1
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 2
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 4
#include "exec/cpu_ldst_template.h"
#define DATA_SIZE 8
#include "exec/cpu_ldst_template.h"
#undef CPU_MMU_INDEX
#undef MEMSUFFIX
#undef SOFTMMU_CODE_ACCESS
/**
* tlb_vaddr_to_host:
* @env: CPUArchState
* @addr: guest virtual address to look up
* @access_type: 0 for read, 1 for write, 2 for execute
* @mmu_idx: MMU index to use for lookup
*
* Look up the specified guest virtual index in the TCG softmmu TLB.
* If the TLB contains a host virtual address suitable for direct RAM
* access, then return it. Otherwise (TLB miss, TLB entry is for an
* I/O access, etc) return NULL.
*
* This is the equivalent of the initial fast-path code used by
* TCG backends for guest load and store accesses.
*/
static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
int access_type, int mmu_idx)
{
int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
target_ulong tlb_addr;
uintptr_t haddr;
switch (access_type) {
case 0:
tlb_addr = tlbentry->addr_read;
break;
case 1:
tlb_addr = tlbentry->addr_write;
break;
case 2:
tlb_addr = tlbentry->addr_code;
break;
default:
g_assert_not_reached();
}
if ((addr & TARGET_PAGE_MASK)
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
/* TLB entry is for a different page */
return NULL;
}
if (tlb_addr & ~TARGET_PAGE_MASK) {
/* IO access */
return NULL;
}
haddr = addr + env->tlb_table[mmu_idx][index].addend;
return (void *)haddr;
}
#endif /* defined(CONFIG_USER_ONLY) */
#endif /* CPU_LDST_H */

View File

@@ -8,7 +8,7 @@
* 32 and 64 bit cases, also generate floating point functions with
* the same size.
*
* Not used directly but included from softmmu_exec.h and exec-all.h.
* Not used directly but included from cpu_ldst.h.
*
* Copyright (c) 2003 Fabrice Bellard
*
@@ -47,35 +47,18 @@
#error unsupported data size
#endif
#if ACCESS_TYPE < (NB_MMU_MODES)
#define CPU_MMU_INDEX ACCESS_TYPE
#define MMUSUFFIX _mmu
#elif ACCESS_TYPE == (NB_MMU_MODES)
#define CPU_MMU_INDEX (cpu_mmu_index(env))
#define MMUSUFFIX _mmu
#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
#define CPU_MMU_INDEX (cpu_mmu_index(env))
#define MMUSUFFIX _cmmu
#else
#error invalid ACCESS_TYPE
#endif
#if DATA_SIZE == 8
#define RES_TYPE uint64_t
#else
#define RES_TYPE uint32_t
#endif
#if ACCESS_TYPE == (NB_MMU_MODES + 1)
#ifdef SOFTMMU_CODE_ACCESS
#define ADDR_READ addr_code
#define MMUSUFFIX _cmmu
#else
#define ADDR_READ addr_read
#define MMUSUFFIX _mmu
#endif
/* generic load/store macros */
@@ -124,7 +107,7 @@ glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
}
#endif
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
#ifndef SOFTMMU_CODE_ACCESS
/* generic store macro */
@@ -148,9 +131,7 @@ glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
}
}
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
#if DATA_SIZE == 8
static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env,
@@ -200,7 +181,7 @@ static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env,
}
#endif /* DATA_SIZE == 4 */
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
#endif /* !SOFTMMU_CODE_ACCESS */
#undef RES_TYPE
#undef DATA_TYPE
@@ -208,6 +189,5 @@ static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env,
#undef SUFFIX
#undef USUFFIX
#undef DATA_SIZE
#undef CPU_MMU_INDEX
#undef MMUSUFFIX
#undef ADDR_READ

Some files were not shown because too many files have changed in this diff Show More