Compare commits

...

286 Commits

Author SHA1 Message Date
Yang Hongyang
4d77b1f238 vnc: fix bug: vnc server can't start when 'to' is specified
commit e0d03b8ceb converted VNC startup to use SocketAddress,
the interface socket_listen don't have a port_offset param, so
we need to add the port offset (5900) to both 'port' and 'to' opts.
currently only 'port' is added by offset.
This patch add the port offset to 'to' opts.

Signed-off-by: Yang Hongyang <hongyang.yang@easystack.cn>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Message-id: 1445926252-14830-1-git-send-email-hongyang.yang@easystack.cn
Cc: Daniel P. Berrange <berrange@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-11-03 10:21:49 +01:00
Peter Lieven
de3f7de7f4 vnc: allow fall back to RAW encoding
I have observed that depending on the contents and the encoding it happens
that sending data as RAW sometimes would take less space than the encoded data.
This is especially the case for small updates or areas with high color images.
If sending RAW encoded data is beneficial allow a fall back to RAW encoding
for the framebuffer update.

Signed-off-by: Peter Lieven <pl@kamp.de>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-11-03 10:21:49 +01:00
OGAWA Hirofumi
fb71956367 ui/opengl: Reduce build required libraries for opengl
We now use epoxy to load opengl libraries. This means we don't need to
link opengl libraries directly if interfaces handled by epoxy. With
this, we just need epoxy headers and epoxy's *.so to build.

Tested with epoxy-1.3.1.

- sdl2/gtk/console egl stuff doesn't require other than epoxy
- milkymist-tmu2 glx stuff doesn't require other than epoxy

(lm32 test is limited, because can't find mmone-bios.bin, so just test
to load libGL with "./lm32-softmmu/qemu-system-lm32 -M milkymist,accel=qtest")

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

[ lm32 tested by kraxel ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-11-03 10:13:42 +01:00
OGAWA Hirofumi
e72df72a55 ui/curses: Fix pageup/pagedown on -curses
Current KEY_NPAGE/KEY_PPAGE handling is broken on -curses. Those uses
"GREY", but "KEY_MASK" masked out "GREY".

To fix, we have to use correct mask value - SCANCODE_KEYMASK.

Then, this adds support of "shift + pageup/pagedown". With this,
-curses mode can use scroll-up/down as usual like other display modes.

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-11-03 10:12:46 +01:00
OGAWA Hirofumi
e2368dc968 ui/curses: Support line graphics chars on -curses mode
This converts vga code to curses code in console_write_bh().

With this changes, we can see line graphics (for example, dialog uses)
correctly.

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-11-03 10:12:46 +01:00
OGAWA Hirofumi
615220ddaf ui/curses: Fix monitor color with -curses when 256 colors
If TERM=xterm-256color, COLOR_PAIRS==256 and monitor passes chtype
like 0x74xx. Then, the code uses uninitialized color pair. As result,
monitor uses black for both of fg and bg color, i.e. terminal is
filled by black.

To fix, this initialize above than 64 with default color (fg=white,bg=black).

FIXME: on 256 color, curses may be possible better vga color emulation.

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-11-03 10:12:45 +01:00
Peter Maydell
3d861a0109 Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2015-11-02' into staging
QAPI patches

# gpg: Signature made Mon 02 Nov 2015 09:07:23 GMT using RSA key ID EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"

* remotes/armbru/tags/pull-qapi-2015-11-02: (25 commits)
  qapi: Simplify gen_struct_field()
  qapi: Reserve 'u' member name
  qapi: Finish converting to new qapi union layout
  tpm: Convert to new qapi union layout
  memory: Convert to new qapi union layout
  input: Convert to new qapi union layout
  char: Convert to new qapi union layout
  net: Convert to new qapi union layout
  sockets: Convert to new qapi union layout
  block: Convert to new qapi union layout
  tests: Convert to new qapi union layout
  qapi-visit: Convert to new qapi union layout
  qapi: Start converting to new qapi union layout
  qapi-visit: Remove redundant functions for flat union base
  qapi: Unbox base members
  qapi: Prefer typesafe upcasts to qapi base classes
  qapi-types: Refactor base fields output
  qapi-visit: Split off visit_type_FOO_fields forward decl
  vnc: Hoist allocation of VncBasicInfo to callers
  qapi: Reserve 'q_*' and 'has_*' member names
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-11-02 11:11:39 +00:00
Eric Blake
32bc6879be qapi: Simplify gen_struct_field()
Rather than having all callers pass a name, type, and optional
flag, have them instead pass a QAPISchemaObjectTypeMember which
already has all that information.

No change to generated code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-25-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:28 +01:00
Eric Blake
5e59baf90a qapi: Reserve 'u' member name
Now that we have separated union tag values from colliding with
non-variant C names, by naming the union 'u', we should reserve
this name for our use.  Note that we want to forbid 'u' even in
a struct with no variants, because it is possible for a future
qemu release to extend QMP in a backwards-compatible manner while
converting from a struct to a flat union.  Fortunately, no
existing clients were using this member name.  If we ever find
the need for QMP to have a member 'u', we could at that time
relax things, perhaps by having c_name() munge the QMP member to
'q_u'.

Note that we cannot forbid 'u' everywhere (by adding the
rejection code to check_name()), because the existing QKeyCode
enum already uses it; therefore we only reserve it as a struct
type member name.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-24-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:28 +01:00
Eric Blake
e4ba22b319 qapi: Finish converting to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

This patch is the back end for a series that converts to a
saner qapi union layout.  Now that all clients have been
converted to use 'type' and 'obj->u.value', we can drop the
temporary parallel support for 'kind' and 'obj->value'.

Given a simple union qapi type:

{ 'union':'Foo', 'data': { 'a':'int', 'b':'bool' } }

this is the overall effect, when compared to the state before
this series of patches:

| struct Foo {
|-    FooKind kind;
|-    union { /* union tag is @kind */
|+    FooKind type;
|+    union { /* union tag is @type */
|         void *data;
|         int64_t a;
|         bool b;
|-    };
|+    } u;
| };

The testsuite still contains some examples of artificial restrictions
(see flat-union-clash-type.json, for example) that are no longer
technically necessary, now that there is no longer a collision between
enum tag values and non-variant member names; but fixing this will be
done in later patches, in part because some further changes are required
to keep QAPISchema*.check() from asserting.  Also, a later patch will
add a reservation for the member name 'u' to avoid a collision between a
user's non-variant names and our internal choice of C union name.

Note, however, that we do not rename the generated enum, which
is still 'FooKind'.  A further patch could generate implicit
enums as 'FooType', but while the generator already reserved
the '*Kind' namespace (commit 4dc2e69), there are already QMP
constructs with '*Type' naming, which means changing our
reservation namespace would have lots of churn to C code to
deal with a forced name change.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-23-git-send-email-eblake@redhat.com>
[Commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:28 +01:00
Eric Blake
ce21131a0b tpm: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for TPM-related code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-22-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:28 +01:00
Eric Blake
1fd5d4fea4 memory: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for memory-related code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-21-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:28 +01:00
Eric Blake
568c73a478 input: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for input-related code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-20-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:28 +01:00
Eric Blake
130257dc44 char: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for character-related
code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-19-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:27 +01:00
Eric Blake
8d0bcba837 net: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for net-related code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-18-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:27 +01:00
Eric Blake
2d32addae7 sockets: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for socket-related code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-17-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:27 +01:00
Eric Blake
6a8f9661dc block: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for block-related code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-16-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:27 +01:00
Eric Blake
c363acef77 tests: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for testsuite code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-15-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:27 +01:00
Eric Blake
150d0564a4 qapi-visit: Convert to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

Make the conversion to the new layout for qapi-visit.py.

Generated code changes look like:

|@@ -4912,16 +4912,16 @@ void visit_type_MemoryDeviceInfo(Visitor
|     if (!*obj) {
|         goto out_obj;
|     }
|-    visit_type_MemoryDeviceInfoKind(v, &(*obj)->kind, "type", &err);
|+    visit_type_MemoryDeviceInfoKind(v, &(*obj)->type, "type", &err);
|     if (err) {
|         goto out_obj;
|     }
|-    if (!visit_start_union(v, !!(*obj)->data, &err) || err) {
|+    if (!visit_start_union(v, !!(*obj)->u.data, &err) || err) {
|         goto out_obj;
|     }
|-    switch ((*obj)->kind) {
|+    switch ((*obj)->type) {
|     case MEMORY_DEVICE_INFO_KIND_DIMM:
|-        visit_type_PCDIMMDeviceInfo(v, &(*obj)->dimm, "data", &err);
|+        visit_type_PCDIMMDeviceInfo(v, &(*obj)->u.dimm, "data", &err);
|         break;
|     default:
|         abort();
|@@ -4930,7 +4930,7 @@ out_obj:
|     error_propagate(errp, err);
|     err = NULL;
|     if (*obj) {
|-        visit_end_union(v, !!(*obj)->data, &err);
|+        visit_end_union(v, !!(*obj)->u.data, &err);
|     }
|     error_propagate(errp, err);
|     err = NULL;

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-14-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:27 +01:00
Eric Blake
f51d8fab44 qapi: Start converting to new qapi union layout
We have two issues with our qapi union layout:
1) Even though the QMP wire format spells the tag 'type', the
C code spells it 'kind', requiring some hacks in the generator.
2) The C struct uses an anonymous union, which places all tag
values in the same namespace as all non-variant members. This
leads to spurious collisions if a tag value matches a non-variant
member's name.

This patch is the front end for a series that converts to a
saner qapi union layout.  By the end of the series, we will no
longer have the type/kind mismatch, and all tag values will be
under a named union, which requires clients to access
'obj->u.value' instead of 'obj->value'.  But since the
conversion touches a number of files, it is easiest if we
temporarily support BOTH layouts simultaneously.

Given a simple union qapi type:

{ 'union':'Foo', 'data': { 'a':'int', 'b':'bool' } }

make the following changes in generated qapi-types.h:

| struct Foo {
|-    FooKind kind;
|-    union { /* union tag is @kind */
|+    union {
|+        FooKind kind;
|+        FooKind type;
|+    };
|+    union { /* union tag is @type */
|         void *data;
|         int64_t a;
|         bool b;
|+        union { /* union tag is @type */
|+            void *data;
|+            int64_t a;
|+            bool b;
|+        } u;
|     };
| };

Flat unions do not need the anonymous union for the tag member,
as we already fixed that to use the member name instead of 'kind'
back in commit 0f61af3e.

One additional change is needed in qapi.py: check_union() now
needs to check for collisions with 'type' in addition to those
with 'kind'.

Later, when the conversions are complete, we will remove the
duplication hacks, and also drop the check_union() restrictions.

Note, however, that we do not rename the generated enum, which
is still 'FooKind'.  A further patch could generate implicit
enums as 'FooType', but while the generator already reserved
the '*Kind' namespace (commit 4dc2e69), there are already QMP
constructs with '*Type' naming, which means changing our
reservation namespace would have lots of churn to C code to
deal with a forced name change.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-13-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:27 +01:00
Eric Blake
5c5e51a05b qapi-visit: Remove redundant functions for flat union base
The code for visiting the base class of a child struct created
visit_type_Base_fields() which covers all fields of Base; while
the code for visiting the base class of a flat union created
visit_type_Union_fields() covering all fields of the base
except the discriminator.  But since the base class includes
the discriminator of a flat union, we can just visit the entire
base, without needing a separate visit of the discriminator.
Not only is consistently visiting all fields easier to
understand, it lets us share code.

The generated code in qapi-visit.c loses several now-unused
visit_type_UNION_fields(), along with changes like:

|@@ -1654,11 +1557,7 @@ void visit_type_BlockdevOptions(Visitor
|     if (!*obj) {
|         goto out_obj;
|     }
|-    visit_type_BlockdevOptions_fields(v, obj, &err);
|-    if (err) {
|-        goto out_obj;
|-    }
|-    visit_type_BlockdevDriver(v, &(*obj)->driver, "driver", &err);
|+    visit_type_BlockdevOptionsBase_fields(v, (BlockdevOptionsBase **)obj, &err);
|     if (err) {
|         goto out_obj;
|     }

and forward declarations where needed.  Note that the cast of obj
to BASE ** is necessary to call visit_type_BASE_fields() (and we
can't use our upcast wrappers, because those work on pointers while
we have a pointer-to-pointer).

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-12-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:27 +01:00
Eric Blake
ddf2190896 qapi: Unbox base members
Rather than storing a base class as a pointer to a box, just
store the fields of that base class in the same order, so that
a child struct can be directly cast to its parent.  This gives
less malloc overhead, less pointer dereferencing, and even less
generated code.  Compare to the earlier commit 1e6c1616a "qapi:
Generate a nicer struct for flat unions" (although that patch
had fewer places to change, as less of qemu was directly using
qapi structs for flat unions).  It also allows us to turn on
automatic type-safe wrappers for upcasting to the base class
of a struct.

Changes to the generated code look like this in qapi-types.h:

| struct SpiceChannel {
|-    SpiceBasicInfo *base;
|+    /* Members inherited from SpiceBasicInfo: */
|+    char *host;
|+    char *port;
|+    NetworkAddressFamily family;
|+    /* Own members: */
|     int64_t connection_id;

as well as additional upcast functions like qapi_SpiceChannel_base().
Meanwhile, changes to qapi-visit.c look like:

| static void visit_type_SpiceChannel_fields(Visitor *v, SpiceChannel **obj, Error **errp)
| {
|     Error *err = NULL;
|
|-    visit_type_implicit_SpiceBasicInfo(v, &(*obj)->base, &err);
|+    visit_type_SpiceBasicInfo_fields(v, (SpiceBasicInfo **)obj, &err);
|     if (err) {

(the cast is necessary, since our upcast wrappers only deal with a
single pointer, not pointer-to-pointer); plus the wholesale
elimination of some now-unused visit_type_implicit_FOO() functions.

Without boxing, the corner case of one empty struct having
another empty struct as its base type now requires inserting a
dummy member (previously, the 'Base *base' member sufficed).

And now that we no longer consume a 'base' member in the generated
C struct, we can delete the former negative struct-base-clash-base
test.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-11-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
30594fe1cd qapi: Prefer typesafe upcasts to qapi base classes
A previous patch (commit 1e6c1616) made it possible to
directly cast from a qapi flat union type to its base type.
However, it requires the use of a C cast, which turns off
compiler type-safety checks.  Fortunately, no such casts
exist, just yet.

Regardless, add inline type-safe wrappers named
qapi_FOO_base() for any union type FOO that has a base,
which can be used for a safer upcast, and enhance the
testsuite to cover the new functionality.

A future patch will extend the upcast support to structs,
where such conversions do exist already.

Note that C makes const-correct upcasts annoying because
it lacks overloads; these functions cast away const so that
they can accept user pointers whether const or not, and the
result in turn can be assigned to normal or const pointers.
Alternatively, this could have been done with macros, but
type-safe macros are hairy, and not worthwhile here.

This patch just adds upcasts.  None of our code needed to
downcast from a base qapi class to a child.  Also, in the
case of grandchildren (such as BlockdevOptionsQcow2), the
caller will need to call two functions to get to the inner
base (although it wouldn't be too hard to generate a
qapi_FOO_base_base() if desired).  If a user changes qapi
to alter the base class hierarchy, such as going from
'A -> C' to 'A -> B -> C', it will change the type of
'qapi_C_base()', and the compiler will point out the places
that are affected by the new base.

One alternative was proposed, but was deemed too ugly to use
in practice: the generators could output redundant
information using anonymous types:
| struct Child {
|     union {
|         struct {
|             Type1 parent_member1;
|             Type2 parent_member2;
|         };
|         Parent base;
|     };
| };
With that ugly proposal, for a given qapi type, obj->member
and obj->base.member would refer to the same storage; allowing
convenience in working with members without needing 'base.'
allowing typesafe upcast without needing a C cast by accessing
'&obj->base', and allowing downcasts from the parent back to
the child possible through container_of(obj, Child, base).

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-10-git-send-email-eblake@redhat.com>
[Commit message tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
f87ab7f9bd qapi-types: Refactor base fields output
Move code from gen_union() into gen_struct_fields() in order for
a later patch to share code when enumerating inherited fields
for struct types.

No change to generated code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-9-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
d02cf37766 qapi-visit: Split off visit_type_FOO_fields forward decl
We generate a static visit_type_FOO_fields() for every type
FOO.  However, sometimes we need a forward declaration. Split
the code to generate the forward declaration out of
gen_visit_implicit_struct() into a new gen_visit_fields_decl(),
and also prepare for a forward declaration to be emitted
during gen_visit_struct(), so that a future patch can switch
from using visit_type_FOO_implicit() to the simpler
visit_type_FOO_fields() as part of unboxing the base class
of a struct.

No change to generated code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-8-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
98481bfcd6 vnc: Hoist allocation of VncBasicInfo to callers
A future qapi patch will rework generated structs with a base
class to be unboxed.  In preparation for that, change the code
that allocates then populates an info struct to instead merely
populate the fields of an info field passed in as a parameter
(renaming vnc_basic_info_get* to vnc_init_basic_info*). Add
rudimentary Error handling at the lowest levels for cases
where the old code returned NULL; but rather than plumb Error
all the way through the stack, the callers drop the error and
return NULL as before.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-7-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
9fb081e0b9 qapi: Reserve 'q_*' and 'has_*' member names
c_name() produces names starting with 'q_' when protecting a
dictionary member name that would fail to directly compile, but
in doing so can cause clashes with any member name already
beginning with 'q-' or 'q_'.  Likewise, we create a C name 'has_'
for any optional member that can clash with any member name
beginning with 'has-' or 'has_'.

Technically, rather than blindly reserving the namespace,
we could try to complain about user names only when an actual
collision occurs, or even teach c_name() how to munge names
to avoid collisions.  But it is not trivial, especially when
collisions can occur across multiple types (such as via
inheritance or flat unions).  Besides, no existing .json
files are trying to use these names.  So it's easier to just
outright forbid the potential for collision.  We can always
relax things in the future if a real need arises for QMP to
express member names that have been forbidden here.

'has_' only has to be reserved for struct/union member names,
while 'q_' is reserved everywhere (matching the fact that
only members can be optional, while we use c_name() for munging
both members and entities).  Note that we could relax 'q_'
restrictions on entities independently from member names; for
example, c_name('qmp_' + 'unix') would result in a different
function name than our current 'qmp_' + c_name('unix').

Update and add tests to cover the new error messages.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-6-git-send-email-eblake@redhat.com>
[Consistently pass protect=False to c_name(); commit message tweaked
slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
255960dd37 qapi: Reserve '*List' type names for list types
Type names ending in 'List' can clash with qapi list types in
generated C.  We don't currently use such names. It is easier to
outlaw them now than to worry about how to resolve such a clash
in the future. For precedence, see commit 4dc2e69, which did the
same for names ending in 'Kind' versus implicit enum types for
qapi unions.

Update the testsuite to match.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-5-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
f9e6102b48 qapi: More robust conditions for when labels are needed
We were using regular expressions to see if ret included
any earlier text that emitted a 'goto out;' line, to decide
whether we needed to output an 'out:' label.  But this is
fragile, if the ret text can possibly combine more than one
generated function body, where the first function used a
goto but the second does not.  Change the code to just check
for the known conditions which cause an error check to be
needed.  Besides, it's slightly more efficient to use plain
checks than regular expression searching.

No change to generated code.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-4-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
8712fa5333 qapi: More idiomatic string operations
Rather than slicing the end of a string, we can use python's
endswith().  And rather than creating a set of characters,
we can search for a character within a string.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-3-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:26 +01:00
Eric Blake
1976708321 tests/qapi-schema: Test for reserved names, empty struct
Add some testsuite coverage to ensure future patches are on
the right track:

Our current C representation of qapi arrays is done by appending
'List' to the element name; but we are not preventing the
creation of an object type with the same name.  Add
reserved-type-list.json to test this.  Then rename
enum-union-clash.json to reserved-type-kind.json to cover the
reservation that we DO detect, and shorten it to match the fact
that the name is reserved even if there is no clash.

We are failing to detect a collision between a dictionary member
and the implicit 'has_*' flag for another optional member. The
easiest fix would be for a future patch to reserve the entire
"has[-_]" namespace for member names (the collision is also
possible for branch names within flat unions, but only as long as
branch names can collide with (non-variant) members; however,
since future patches are about to remove that, it is not worth
testing here). Add reserved-member-has.json to test this.

A similar collision exists between a dictionary member where
c_name() munges what might otherwise be a reserved name to start
with 'q_', and another member explicitly starts with "q[-_]".
Again, the easiest solution for a future patch will be reserving
the entire namespace, but here for commands as well as members.
Add reserved-member-q.json and reserved-command-q.json to test
this; separate tests since arguably our munging of command 'unix'
to 'qmp_q_unix()' could be done without a q_, which is different
than the munging of a member 'unix' to 'foo.q_unix'.

Finally, our testsuite does not have any compilation coverage
of struct inheritance with empty qapi structs.  Update
qapi-schema-test.json to test this.

Note that there is currently no technical reason to forbid type
name patterns from member names, or member name patterns from
types, since the two are not in the same namespace in C and
won't collide; but it's not worth adding positive tests of these
corner cases at this time, especially while there is other churn
pending in patches that rearrange which collisions actually
happen.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1445898903-12082-2-git-send-email-eblake@redhat.com>
[Commit message tweaked slightly]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:25 +01:00
Daniel P. Berrange
2ea1793bd9 qapi-schema: mark InetSocketAddress as mandatory again
Revert the qapi-schema.json change done in:

  commit 0983f5e6af
  Author: Daniel P. Berrange <berrange@redhat.com>
  Date:   Tue Sep 1 14:46:50 2015 +0100

    sockets: allow port to be NULL when listening on IP address

Switching "port" from mandatory to optional causes the QAPI
code generator to add a 'has_port' field to the InetSocketAddress
struct. No code that created InetSocketAddress objects was updated
to set 'has_port = true', which caused the non-NULL port strings
to be silently dropped when copying InetSocketAddress objects.

Reported-by: Knut Omang <knuto@ifi.uio.no>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-Id: <1445509543-30679-1-git-send-email-berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-11-02 08:30:25 +01:00
Peter Maydell
24f4a0f5c9 Merge remote-tracking branch 'remotes/rth/tags/pull-tile-20151030' into staging
Prefetch in y2 pipe

# gpg: Signature made Fri 30 Oct 2015 20:40:02 GMT using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"

* remotes/rth/tags/pull-tile-20151030:
  target-tilegx: Implement prefetch instructions in pipe y2

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-30 21:59:48 +00:00
Peter Maydell
3a958f559e Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
# gpg: Signature made Thu 29 Oct 2015 18:09:16 GMT 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:
  block: Consider all child nodes in bdrv_requests_pending()
  target-arm: xlnx-zynqmp: Add sdhci support.
  sdhci: Split sdhci.h for public and internal device usage
  sd.h: Move sd.h to include/hw/sd/
  virtio: sync the dataplane vring state to the virtqueue before virtio_save
  gdb command: qemu handlers
  virtio-blk: switch off scsi-passthrough by default
  ppc/spapr: add 2.4 compat props
  s390x: include HW_COMPAT_* props
  qemu-gdb: add $qemu_coroutine_sp and $qemu_coroutine_pc
  qemu-gdb: extract parts of "qemu coroutine" implementation
  qemu-gdb: allow using glibc_pointer_guard() on core dumps

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-30 19:47:47 +00:00
Peter Maydell
e79ea9e424 Merge remote-tracking branch 'remotes/lalrae/tags/mips-20151030' into staging
MIPS patches 2015-10-30

Changes:
* R6 CPU can be woken up by non-enabled interrupts
* PC fix in KVM
* Coprocessor 0 XContext calculation fix
* various MIPS R6 updates

# gpg: Signature made Fri 30 Oct 2015 14:51:56 GMT using RSA key ID 0B29DA6B
# gpg: Good signature from "Leon Alrae <leon.alrae@imgtec.com>"

* remotes/lalrae/tags/mips-20151030:
  target-mips: fix updating XContext on mmu exception
  target-mips: add SIGRIE instruction
  target-mips: Set Config5.XNP for R6 cores
  target-mips: add PC, XNP reg numbers to RDHWR
  hw/mips_malta: Fix KVM PC initialisation
  target-mips: Add enum for BREAK32
  target-mips: update writing to CP0.Status.KX/SX/UX in MIPS Release R6
  target-mips: implement the CPU wake-up on non-enabled interrupts in R6
  target-mips: move the test for enabled interrupts to a separate function

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-30 16:30:25 +00:00
Yongbok Kim
60270f85cc target-mips: fix updating XContext on mmu exception
Correct updating XContext.Region field on mmu exceptions.
If Config3.CTXTC = 0 then the R field of XContext has to be updated
with the value of bits 63..62 of the virtual address upon a TLB
exception.
Also fixed the below line which overs 80 characters.

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
Reviewed-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-30 14:36:19 +00:00
Yongbok Kim
bb238210bb target-mips: add SIGRIE instruction
Add SIGRIE (Signal Reserved Instruction Exception) for both MIPS and
microMIPS.
The instruction allows to use the 16-bit code field for software use.
This instruction is introduced by and required as of Release 6.

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-30 14:36:19 +00:00
Yongbok Kim
35ac9e342e target-mips: Set Config5.XNP for R6 cores
Set Config5.XNP for R6 cores to indicate the extended LL/SC family
of instructions NOT present.

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-30 14:36:19 +00:00
Yongbok Kim
b00c72180c target-mips: add PC, XNP reg numbers to RDHWR
Add Performance Counter (4) and XNP (5) register numbers to RDHWR.
Add check_hwrena() to simplify access control checkings.
Add RDHWR support to microMIPS R6.

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-30 14:35:52 +00:00
James Hogan
ca2f6bbbce hw/mips_malta: Fix KVM PC initialisation
Commit 71c199c81d ("mips_malta: provide ememsize env variable to
kernels") changed the meaning of loaderparams.ram_size to be the whole
of RAM rather than just the low part below where the boot code is placed
for KVM, but it didn't update the PC initialisation for KVM to use
ram_low_size. Fix that now.

Fixes: 71c199c81d ("mips_malta: provide ememsize env variable to kernels")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leon Alrae <leon.alrae@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-30 13:30:14 +00:00
Peter Maydell
fdf927621a Merge remote-tracking branch 'remotes/armbru/tags/pull-monitor-2015-10-30' into staging
QMP and QObject patches

# gpg: Signature made Fri 30 Oct 2015 08:06:26 GMT using RSA key ID EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>"

* remotes/armbru/tags/pull-monitor-2015-10-30:
  docs: Document QMP event rate limiting
  monitor: Throttle event VSERPORT_CHANGE separately by "id"
  monitor: Turn monitor_qapi_event_state[] into a hash table
  glib: add compatibility interface for g_hash_table_add()
  monitor: Split MonitorQAPIEventConf off MonitorQAPIEventState
  monitor: Switch from timer_new() to timer_new_ns()
  monitor: Simplify event throttling
  monitor: Reduce casting of QAPI event QDict
  qstring: Make conversion from QObject * accept null
  qlist: Make conversion from QObject * accept null
  qfloat qint: Make conversion from QObject * accept null
  qdict: Make conversion from QObject * accept null
  qbool: Make conversion from QObject * accept null
  qobject: Drop QObject_HEAD

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-30 09:41:15 +00:00
Markus Armbruster
7f1e7b23d5 docs: Document QMP event rate limiting
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444921716-9511-8-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-10-30 09:05:38 +01:00
Markus Armbruster
7de0be6573 monitor: Throttle event VSERPORT_CHANGE separately by "id"
VSERPORT_CHANGE is emitted when the guest opens or closes a
virtio-serial port.  The event's member "id" identifies the port.

When several events arrive quickly, throttling drops all but the last
of them.  Because of that, a QMP client must assume that *any* port
may have changed state when it receives a VSERPORT_CHANGE event and
throttling may have happened.

Make the event more useful by throttling it for each port separately.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1444921716-9511-7-git-send-email-armbru@redhat.com>
2015-10-30 09:05:38 +01:00
Markus Armbruster
a24712af54 monitor: Turn monitor_qapi_event_state[] into a hash table
In preparation of finer grained throttling.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1444921716-9511-6-git-send-email-armbru@redhat.com>
2015-10-30 09:05:38 +01:00
Markus Armbruster
8681dffa91 glib: add compatibility interface for g_hash_table_add()
The next commit will use it.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-10-30 09:01:03 +01:00
Kevin Wolf
37a639a7fb block: Consider all child nodes in bdrv_requests_pending()
The function manually recursed into bs->file and bs->backing to check
whether there were any requests pending, but it ignored other children.

There's no need to special case file and backing here, so just replace
these two explicit recursions by a loop recursing for all child nodes.

Reported-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Message-id: 1446029211-27148-1-git-send-email-kwolf@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:27 +00:00
Sai Pavan Boddu
33108e9f33 target-arm: xlnx-zynqmp: Add sdhci support.
Add two SYSBUS_SDHCI devices for xlnx-zynqmp

Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:27 +00:00
Sai Pavan Boddu
637d23beb6 sdhci: Split sdhci.h for public and internal device usage
Split sdhci.h into pubilc version (i.e include/hw/sd/sdhci.h) and
internal version (i.e hw/sd/sdhci-interna.h) based on register
declarations and object declaration.

Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:27 +00:00
Sai Pavan Boddu
e3382ef0ea sd.h: Move sd.h to include/hw/sd/
Create a sd directory under include/hw/ and move sd.h to
include/hw/sd/

Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:27 +00:00
Pavel Butsykin
10a06fd65f virtio: sync the dataplane vring state to the virtqueue before virtio_save
When creating snapshot with the dataplane enabled, the snapshot file gets
not the actual state of virtqueue, because the current state is stored in
VirtIOBlockDataPlane. Therefore, before saving snapshot need to sync
the dataplane vring state to the virtqueue. The dataplane will resume its
work at the next notify virtqueue.

When snapshot loads with loadvm we get a message:
VQ 0 size 0x80 Guest index 0x15f5 inconsistent with Host index 0x0:
    delta 0x15f5
error while loading state for instance 0x0 of device
    '0000:00:08.0/virtio-blk'
Error -1 while loading VM state

to reproduce the error I used the following hmp commands:
savevm snap1
loadvm snap1

qemu parameters:
--enable-kvm -smp 4 -m 1024 -drive file=/var/lib/libvirt/images/centos6.4.qcow2,if=none,id=drive-virtio-disk0,format=qcow2,cache=none,aio=native -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x8,drive=drive-virtio-disk0,id=virtio-disk0 -set device.virtio-disk0.x-data-plane=on

Signed-off-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
Signed-off-by: Denis V. Lunev <den@openvz.org>
Message-id: 1445859777-2982-1-git-send-email-den@openvz.org
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: "Michael S. Tsirkin" <mst@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
CC: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:27 +00:00
Dr. David Alan Gilbert
c900ef86c5 gdb command: qemu handlers
A new gdb commands are added:

  qemu handlers

     That dumps an AioContext list (by default qemu_aio_context)
     possibly including a backtrace for cases it knows about
     (with the verbose option).  Intended to help find why something
     is hanging waiting for IO.

  Use 'qemu handlers --verbose iohandler_ctx'  to find out why
your incoming migration is stuck.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: 1445951385-11924-1-git-send-email-dgilbert@redhat.com

V2:
  Merge into one command with optional handlers arg, and only do
    backtrace in verbose mode

 (gdb) qemu handlers
 ----
 {pfd = {fd = 6, events = 25, revents = 0}, io_read = 0x55869656ffd0
 <event_notifier_dummy_cb>, io_write = 0x0, deleted = 0, opaque =
 0x558698c4ce08, node = {le_next = 0x0, le_prev = 0x558698c4cdc0}}

 (gdb) qemu handlers iohandler_ctx
 ----
 {pfd = {fd = 9, events = 25, revents = 0}, io_read = 0x558696581380
 <fd_coroutine_enter>, io_write = 0x0, deleted = 0, opaque =
 0x558698dc99d0, node = {le_next = 0x558698c4cca0, le_prev =
 0x558698c4c1d0}}
 ----
 {pfd = {fd = 4, events = 25, revents = 0}, io_read = 0x55869657b330
 <sigfd_handler>, io_write = 0x0, deleted = 0, opaque = 0x4, node =
 {le_next = 0x558698c4c260, le_prev = 0x558699f72508}}
 ----
 {pfd = {fd = 5, events = 25, revents = 0}, io_read = 0x55869656ffd0
 <event_notifier_dummy_cb>, io_write = 0x0, deleted = 0, opaque =
 0x558698c4c218, node = {le_next = 0x0, le_prev = 0x558698c4ccc8}}
 ----
 (gdb) qemu handlers --verbose iohandler_ctx
 ----
 {pfd = {fd = 9, events = 25, revents = 0}, io_read = 0x558696581380
 <fd_coroutine_enter>, io_write = 0x0, deleted = 0, opaque =
 0x558698dc99d0, node = {le_next = 0x558698c4cca0, le_prev =
 0x558698c4c1d0}}
 #0  0x0000558696581820 in qemu_coroutine_switch
 (from_=from_@entry=0x558698cb3cf0, to_=to_@entry=0x7f421c37eac8,
 action=action@entry=COROUTINE_YIELD) at
 /home/dgilbert/git/qemu/coroutine-ucontext.c:177
 #1  0x0000558696580c00 in qemu_coroutine_yield () at
 /home/dgilbert/git/qemu/qemu-coroutine.c:145
 #2  0x00005586965814f5 in yield_until_fd_readable (fd=9) at
 /home/dgilbert/git/qemu/qemu-coroutine-io.c:90
 #3  0x0000558696523937 in socket_get_buffer (opaque=0x55869a3dc620,
 buf=0x558698c505a0 "", pos=<optimized out>, size=32768) at
 /home/dgilbert/git/qemu/migration/qemu-file-unix.c:101
 #4  0x0000558696521fac in qemu_fill_buffer (f=0x558698c50570) at
 /home/dgilbert/git/qemu/migration/qemu-file.c:227
 #5  0x0000558696522989 in qemu_peek_byte (f=0x558698c50570, offset=0)
     at /home/dgilbert/git/qemu/migration/qemu-file.c:507
 #6  0x0000558696522bf4 in qemu_get_be32 (f=0x558698c50570) at
 /home/dgilbert/git/qemu/migration/qemu-file.c:520
 #7  0x0000558696522bf4 in qemu_get_be32 (f=f@entry=0x558698c50570)
     at /home/dgilbert/git/qemu/migration/qemu-file.c:604
 #8  0x0000558696347e5c in qemu_loadvm_state (f=f@entry=0x558698c50570)
     at /home/dgilbert/git/qemu/migration/savevm.c:1821
 #9  0x000055869651de8c in process_incoming_migration_co
 (opaque=0x558698c50570)
     at /home/dgilbert/git/qemu/migration/migration.c:336
 #10 0x000055869658188a in coroutine_trampoline (i0=<optimized out>,
 i1=<optimized out>)
     at /home/dgilbert/git/qemu/coroutine-ucontext.c:80
 #11 0x00007f420f05df10 in __start_context () at /lib64/libc.so.6
 #12 0x00007ffc40815f50 in  ()
 #13 0x0000000000000000 in  ()

  ----
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:27 +00:00
Cornelia Huck
ed65fd1a27 virtio-blk: switch off scsi-passthrough by default
Devices that are compliant with virtio-1 do not support scsi
passthrough any more (and it has not been a recommended setup
anyway for quite some time). To avoid having to switch it off
explicitly in newer qemus that turn on virtio-1 by default, let's
switch the default to scsi=false for 2.5.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Message-id: 1444991154-79217-4-git-send-email-cornelia.huck@de.ibm.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:27 +00:00
Cornelia Huck
80fd50f96b ppc/spapr: add 2.4 compat props
HW_COMPAT_2_4 will become non-empty: prepare for it.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Message-id: 1444991154-79217-3-git-send-email-cornelia.huck@de.ibm.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:26 +00:00
Cornelia Huck
54d8ec84fa s390x: include HW_COMPAT_* props
We want to inherit generic hw compat as well.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Message-id: 1444991154-79217-2-git-send-email-cornelia.huck@de.ibm.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:26 +00:00
Paolo Bonzini
a201b0ff28 qemu-gdb: add $qemu_coroutine_sp and $qemu_coroutine_pc
These can be useful to manually get a stack trace of a coroutine inside
a core dump.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1444636974-19950-4-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:26 +00:00
Paolo Bonzini
80ab31b257 qemu-gdb: extract parts of "qemu coroutine" implementation
Provide useful Python functions to reach and decipher a jmpbuf.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1444636974-19950-3-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:26 +00:00
Paolo Bonzini
1138f24645 qemu-gdb: allow using glibc_pointer_guard() on core dumps
get_fs_base() cannot be run on a core dump, because it uses the arch_prctl
system call.  The fs base is the value that is returned by pthread_self(),
and it would be nice to just glean it from the "info threads" output:

* 1    Thread 0x7f16a3fff700 (LWP 33642) pthread_cond_wait@@GLIBC_2.3.2 ()
              ^^^^^^^^^^^^^^

but unfortunately the gdb API does not provide that.  Instead, we can
look for the "arg" argument of the start_thread function if glibc debug
information are available.  If not, fall back to the old mechanism.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Message-id: 1444636974-19950-2-git-send-email-pbonzini@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2015-10-29 17:59:26 +00:00
Yongbok Kim
dbd8af9824 target-mips: Add enum for BREAK32
Add enum for BREAK32

Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-29 16:16:44 +00:00
Leon Alrae
2dcf7908d9 target-mips: update writing to CP0.Status.KX/SX/UX in MIPS Release R6
Implement the relationship between CP0.Status.KX, SX and UX. It should not
be possible to set UX bit if SX is 0, the same applies for setting SX if
KX is 0.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-29 16:16:44 +00:00
Leon Alrae
7540a43a1d target-mips: implement the CPU wake-up on non-enabled interrupts in R6
In Release 6, the behaviour of WAIT has been modified to make it a
requirement that a processor that has disabled operation as a result of
executing a WAIT will resume operation on arrival of an interrupt even if
interrupts are not enabled.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-29 16:16:44 +00:00
Leon Alrae
71ca034a0d target-mips: move the test for enabled interrupts to a separate function
Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
2015-10-29 16:16:44 +00:00
Markus Armbruster
b9b03ab0d4 monitor: Split MonitorQAPIEventConf off MonitorQAPIEventState
In preparation of turning monitor_qapi_event_state[] into a hash table
for finer grained throttling.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1444921716-9511-5-git-send-email-armbru@redhat.com>
2015-10-29 14:34:45 +01:00
Markus Armbruster
1824c41a62 monitor: Switch from timer_new() to timer_new_ns()
We don't actually care for the scale, so we can just as well use the
simpler interface.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444921716-9511-4-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-10-29 14:34:45 +01:00
Markus Armbruster
93f8f982fe monitor: Simplify event throttling
The event throttling state machine is hard to understand.  I'm not
sure it's entirely correct.  Rewrite it in a more straightforward
manner:

State 1: No event sent recently (less than evconf->rate ns ago)

    Invariant: evstate->timer is not pending, evstate->qdict is null

    On event: send event, arm timer, goto state 2

State 2: Event sent recently, no additional event being delayed

    Invariant: evstate->timer is pending, evstate->qdict is null

    On event: store it in evstate->qdict, goto state 3

    On timer: goto state 1

State 3: Event sent recently, additional event being delayed

    Invariant: evstate->timer is pending, evstate->qdict is non-null

    On event: store it in evstate->qdict, goto state 3

    On timer: send evstate->qdict, clear evstate->qdict,
              arm timer, goto state 2

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444921716-9511-3-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-10-29 14:34:45 +01:00
Markus Armbruster
688b4b7de7 monitor: Reduce casting of QAPI event QDict
Make the variables holding the event QDict instead of QObject.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1444921716-9511-2-git-send-email-armbru@redhat.com>
2015-10-29 14:34:45 +01:00
Markus Armbruster
7f0278435d qstring: Make conversion from QObject * accept null
qobject_to_qstring() crashes on null, which is a trap for the unwary.
Return null instead, and simplify a few callers.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444918537-18107-7-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-10-29 14:34:45 +01:00
Markus Armbruster
2d6421a900 qlist: Make conversion from QObject * accept null
qobject_to_qlist() crashes on null, which is a trap for the unwary.
Return null instead.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444918537-18107-6-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-10-29 14:34:45 +01:00
Markus Armbruster
fcf73f66a6 qfloat qint: Make conversion from QObject * accept null
qobject_to_qfloat() and qobject_to_qint() crash on null, which is a
trap for the unwary.  Return null instead, and simplify a few callers.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444918537-18107-5-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-10-29 14:34:45 +01:00
Markus Armbruster
89cad9f3ec qdict: Make conversion from QObject * accept null
qobject_to_qdict() crashes on null, which is a trap for the unwary.
Return null instead, and simplify a few callers.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444918537-18107-4-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-10-29 14:34:45 +01:00
Markus Armbruster
14b6160099 qbool: Make conversion from QObject * accept null
qobject_to_qbool() crashes on null, which is a trap for the unwary.
Return null instead, and simplify a few callers.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444918537-18107-3-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-10-29 14:34:44 +01:00
Markus Armbruster
c7c462123c qobject: Drop QObject_HEAD
QObject_HEAD is a macro expanding into the common part of structs that
are sub-types of QObject.  It's always been just QObject base, and
unlikely to change.  Drop the macro, because the code is clearer with
out it.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <1444918537-18107-2-git-send-email-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Luiz Capitulino <lcapitulino@redhat.com>
2015-10-29 14:34:44 +01:00
Peter Maydell
7bc8e0c967 Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio, pc, memory: fixes+features for 2.5

New features:
    This enables hotplug for multifunction devices.
    Patches are very small, so I think it's OK to merge
    at this stage.

    There's also some new infrastructure for vhost-user testing
    not enabled yet so it's harmless to merge.

I've reverted the "gap between DIMMs" workaround, as it seems too risky, and
applied my own patch in virtio, but not in dataplane code.  This means that
dataplane is broken for some complex DIMM configurations for now.  Waiting for
Stefan to review the dataplane fix.

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

# gpg: Signature made Thu 29 Oct 2015 09:36:16 GMT using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  enable multi-function hot-add
  remove function during multi-function hot-add
  tests/vhost-user-bridge: add vhost-user bridge application
  Revert "memhp: extend address auto assignment to support gaps"
  Revert "pc: memhp: force gaps between DIMM's GPA"
  virtio: drop virtqueue_map_sg
  virtio-scsi: convert to virtqueue_map
  virtio-serial: convert to virtio_map
  virtio-blk: convert to virtqueue_map
  virtio: switch to virtio_map
  virtio: introduce virtio_map
  mmap-alloc: fix error handling
  pc: memhp: do not emit inserting event for coldplugged DIMMs
  vhost-user-test: fix up rhel6 build
  vhost-user: cleanup msg size math
  vhost-user: cleanup struct size math

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-29 09:49:52 +00:00
Cao jin
3f1e1478db enable multi-function hot-add
Enable PCIe device multi-function hot-add, just ensure function 0 is added
last, then driver will get the notification to scan the slot.

Signed-off-by: Cao jin <caoj.fnst@cn.fujitsu.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:17:53 +02:00
Cao jin
0d1c7d88ad remove function during multi-function hot-add
In case user want to cancel the hot-add operation, should roll back,
device_del the added function that still don`t work.

Signed-off-by: Cao jin <caoj.fnst@cn.fujitsu.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:17:52 +02:00
Victor Kaplansky
3595e2eb0a tests/vhost-user-bridge: add vhost-user bridge application
The test existing in QEMU for vhost-user feature is good for
testing the management protocol, but does not allow actual
traffic. This patch proposes Vhost-User Bridge application, which
can serve the QEMU community as a comprehensive test by running
real internet traffic by means of vhost-user interface.

Essentially the Vhost-User Bridge is a very basic vhost-user
backend for QEMU. It runs as a standalone user-level process.
For packet processing Vhost-User Bridge uses an additional QEMU
instance with a backend configured by "-net socket" as a shared
VLAN.  This way another QEMU virtual machine can effectively
serve as a shared bus by means of UDP communication.

For a more simple setup, the another QEMU instance running the
SLiRP backend can be the same QEMU instance running vhost-user
client.

This Vhost-User Bridge implementation is very preliminary.  It is
missing many features. I has been studying vhost-user protocol
internals, so I've written vhost-user-bridge bit by bit as I
progressed through the protocol.  Most probably its internal
architecture will change significantly.

To run Vhost-User Bridge application:

1. Build vhost-user-bridge with a regular procedure. This will
create a vhost-user-bridge executable under tests directory:

    $ configure; make tests/vhost-user-bridge

2. Ensure the machine has hugepages enabled in kernel with
command line like:

    default_hugepagesz=2M hugepagesz=2M hugepages=2048

3. Run Vhost-User Bridge with:

    $ tests/vhost-user-bridge

The above will run vhost-user server listening for connections
on UNIX domain socket /tmp/vubr.sock, and will try to connect
by UDP to VLAN bridge to localhost:5555, while listening on
localhost:4444

Run qemu with a virtio-net backed by vhost-user:

    $ qemu \
        -enable-kvm -m 512 -smp 2 \
        -object memory-backend-file,id=mem,size=512M,mem-path=/dev/hugepages,share=on \
        -numa node,memdev=mem -mem-prealloc \
        -chardev socket,id=char0,path=/tmp/vubr.sock \
        -netdev type=vhost-user,id=mynet1,chardev=char0,vhostforce \
        -device virtio-net-pci,netdev=mynet1 \
        -net none \
        -net socket,vlan=0,udp=localhost:4444,localaddr=localhost:5555 \
        -net user,vlan=0 \
        disk.img

vhost-user-bridge was tested very lightly: it's able to bringup a
linux on client VM with the virtio-net driver, and execute transmits
and receives to the internet. I tested with "wget redhat.com",
"dig redhat.com".

PS. I've consulted DPDK's code for vhost-user during Vhost-User
Bridge implementation.

Signed-off-by: Victor Kaplansky <victork@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:11:07 +02:00
Michael S. Tsirkin
d6a9b0b89d Revert "memhp: extend address auto assignment to support gaps"
This reverts commit df0acded19.

There's no point to it now that the only user has been reverted.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:11:07 +02:00
Michael S. Tsirkin
340065e5a1 Revert "pc: memhp: force gaps between DIMM's GPA"
This reverts commit aa8580cddf.

As described in
http://article.gmane.org/gmane.comp.emulators.qemu/371432
that commit causes linux guests to crash on memory hot-unplug.

The original problem it's trying to solve has now
been addressed within virtio.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:11:07 +02:00
Michael S. Tsirkin
3945ecf1ec virtio: drop virtqueue_map_sg
Deprecated in favor of virtqueue_map.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
4ada533189 virtio-scsi: convert to virtqueue_map
Note: virtqueue_map already validates input
so virtio-scsi does not have to.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
bff712dc22 virtio-serial: convert to virtio_map
This also fixes a minor bug:
-                virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
-                                 port->elem.out_num, 1);
is wrong: out_sg is not written so should not be marked dirty.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
3d8db153b4 virtio-blk: convert to virtqueue_map
Drop deprecated use of virtqueue_map_sg.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
13972ac5e2 virtio: switch to virtio_map
Drop use of the deprecated virtio_map_sg in virtio core.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
8059feee00 virtio: introduce virtio_map
virtio_map_sg currently fails if one of the entries it's mapping is
contigious in GPA but not HVA address space.  Introduce virtio_map which
handles this by splitting sg entries.

This new API generally turns out to be a good idea since it's harder to
misuse: at least in one case the existing one was used incorrectly.

This will still fail if there's no space left in the sg, but luckily max
queue size in use is currently 256, while max sg size is 1024, so we
should be OK even is all entries happen to cross a single DIMM boundary.

Won't work well with very small DIMM sizes, unfortunately:
e.g. this will fail with 4K DIMMs where a single
request might span a large number of DIMMs.

Let's hope these are uncommon - at least we are not breaking things.

Note: virtio-scsi calls virtio_map_sg on data loaded from network, and
validates input, asserting on failure.  Copy the validating code here -
it will be dropped from virtio-scsi in a follow-up patch.

Reported-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
9d4ec9370a mmap-alloc: fix error handling
Existing callers are checking for MAP_FAILED,
so we should return that on error.

Reported-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:05:24 +02:00
Igor Mammedov
4828b10bda pc: memhp: do not emit inserting event for coldplugged DIMMs
currently acpi_memory_plug_cb() sets is_inserting for
cold- and hot-plugged DIMMs as result ASL MHPD.MSCN()
method issues device check even for every coldplugged
DIMM. There isn't much harm in it but if we try to
unplug such DIMM, OSPM will issue device check
intstead of device eject event. So OSPM won't eject
memory module as expected and it will try to eject it
only when another memory device is hot-(un)plugged.

As a fix do not set 'is_inserting' event and do not
issue SCI for cold-plugged DIMMs as they are
enumerated and activated by OSPM during guest's boot.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
12ebf69083 vhost-user-test: fix up rhel6 build
Build on RHEL6 fails:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42875

Apparently unnamed unions couldn't use C99  named field initializers.
Let's just name the payload union field.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
7fc0246c07 vhost-user: cleanup msg size math
We are sending msg fields, use sizeof on these
and not on local variables which happen to
have a matching type.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:05:24 +02:00
Michael S. Tsirkin
86abad0fed vhost-user: cleanup struct size math
We are using local msg structures everywhere, use them
for sizeof as well.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-29 11:05:24 +02:00
Peter Maydell
331c5e2091 Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20151028' into staging
Breakpoint fixes

# gpg: Signature made Wed 28 Oct 2015 17:58:52 GMT using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"

* remotes/rth/tags/pull-tcg-20151028:
  target-*: Advance pc after recognizing a breakpoint

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-28 20:10:22 +00:00
Richard Henderson
522a0d4e3c target-*: Advance pc after recognizing a breakpoint
Some targets already had this within their logic, but make sure
it's present for all targets.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-10-28 10:57:16 -07:00
Peter Maydell
496fedddce Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging
target-i386: finally enable "check" mode by default

# gpg: Signature made Wed 28 Oct 2015 14:13:10 GMT using RSA key ID 984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"

* remotes/ehabkost/tags/x86-pull-request:
  target-i386: Enable "check" mode by default
  target-i386: Don't left shift negative constant

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-28 15:08:36 +00:00
Peter Maydell
739680da59 Merge remote-tracking branch 'remotes/mcayland/tags/qemu-openbios-signed' into staging
Update OpenBIOS images

# gpg: Signature made Wed 28 Oct 2015 00:02:46 GMT using RSA key ID AE0F321F
# gpg: Good signature from "Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>"

* remotes/mcayland/tags/qemu-openbios-signed:
  Update OpenBIOS images

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-28 14:02:27 +00:00
Mark Cave-Ayland
637016c260 Update OpenBIOS images
Update OpenBIOS images to SVN r1353 built from submodule.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
2015-10-28 00:01:28 +00:00
Eduardo Habkost
15e4134590 target-i386: Enable "check" mode by default
Current default behavior of QEMU is to silently disable features that
are not supported by the host when a CPU model is requested in the
command-line. This means that in addition to risking breaking guest ABI
by default, we are silent about it.

I would like to enable "enforce" by default, but this can easily break
existing production systems because of the way libvirt makes assumptions
about CPU models today (this will change in the future, once QEMU
provide a proper interface for checking if a CPU model is runnable).

But there's no reason we should be silent about it. So, change
target-i386 to enable "check" mode by default so at least we have some
warning printed to stderr (and hopefully logged somewhere) when QEMU
disables a feature that is not supported by the host system.

Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-27 16:12:15 -02:00
Eduardo Habkost
712b4243c7 target-i386: Don't left shift negative constant
Left shift of negative values is undefined behavior. Detected by clang:
  qemu/target-i386/translate.c:2423:26: runtime error:
    left shift of negative value -8

This changes the code to reverse the sign after the left shift.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-27 15:52:11 -02:00
Peter Maydell
c012e1b7ad Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20151027-1' into staging
target-arm queue:
 * more EL2 preparation: handling for stage 2 translations
 * standardize debug macros in i.MX devices
 * improve error message in a corner case for virt board
 * disable live migration of KVM GIC if the kernel can't handle it
 * add SPSR_(ABT|UND|IRQ|FIQ) registers
 * handle non-executable page-straddling Thumb instructions
 * fix a "no 64-bit EL2" assumption in arm_excp_unmasked()

# gpg: Signature made Tue 27 Oct 2015 16:03:31 GMT using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"

* remotes/pmaydell/tags/pull-target-arm-20151027-1: (27 commits)
  target-arm: Add support for S1 + S2 MMU translations
  target-arm: Route S2 MMU faults to EL2
  target-arm: Add S2 translation to 32bit S1 PTWs
  target-arm: Add S2 translation to 64bit S1 PTWs
  target-arm: Add ARMMMUFaultInfo
  target-arm: Avoid inline for get_phys_addr
  target-arm: Add support for S2 page-table protection bits
  target-arm: Add computation of starting level for S2 PTW
  target-arm: lpae: Rename granule_sz to stride
  target-arm: lpae: Replace tsz with computed inputsize
  target-arm: Add support for AArch32 S2 negative t0sz
  target-arm: lpae: Move declaration of t0sz and t1sz
  target-arm: lpae: Make t0sz and t1sz signed integers
  target-arm: Add HPFAR_EL2
  i.MX: Standardize i.MX GPT debug
  i.MX: Standardize i.MX EPIT debug
  i.MX: Standardize i.MX FEC debug
  i.MX: Standardize i.MX CCM debug
  i.MX: Standardize i.MX AVIC debug
  i.MX: Standardize i.MX I2C debug
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 16:17:55 +00:00
Edgar E. Iglesias
9b539263fa target-arm: Add support for S1 + S2 MMU translations
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-15-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:47 +00:00
Edgar E. Iglesias
d759a457a1 target-arm: Route S2 MMU faults to EL2
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-14-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:47 +00:00
Edgar E. Iglesias
a614e69854 target-arm: Add S2 translation to 32bit S1 PTWs
Add support for applying S2 translation to 32bit S1
page-table walks.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-13-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:47 +00:00
Edgar E. Iglesias
3778597762 target-arm: Add S2 translation to 64bit S1 PTWs
Add support for applying S2 translation to 64bit S1
page-table walks.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-12-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:47 +00:00
Edgar E. Iglesias
e14b5a23d8 target-arm: Add ARMMMUFaultInfo
Introduce ARMMMUFaultInfo to propagate MMU Fault information
across the MMU translation code path. This is in preparation for
adding Stage-2 translation.

No functional changes.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-11-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:47 +00:00
Edgar E. Iglesias
af51f566ec target-arm: Avoid inline for get_phys_addr
Avoid inline for get_phys_addr() to prepare for future recursive use.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-10-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:47 +00:00
Edgar E. Iglesias
6ab1a5ee1c target-arm: Add support for S2 page-table protection bits
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-9-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:47 +00:00
Edgar E. Iglesias
1853d5a9dc target-arm: Add computation of starting level for S2 PTW
The starting level for S2 pagetable walks is computed
differently from the S1 starting level. Implement the S2
variant.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-8-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:47 +00:00
Edgar E. Iglesias
973a543482 target-arm: lpae: Rename granule_sz to stride
Rename granule_sz to stride to better match the reference manuals.

No functional change.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-7-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Edgar E. Iglesias
4ca6a05175 target-arm: lpae: Replace tsz with computed inputsize
Remove the tsz variable and introduce inputsize.
This simplifies the code a little and makes it easier to
compare with the reference manuals.

No functional change.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-6-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Edgar E. Iglesias
4ee3809801 target-arm: Add support for AArch32 S2 negative t0sz
Add support for AArch32 S2 negative t0sz. In preparation for
using 40bit IPAs on AArch32.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-5-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Edgar E. Iglesias
1f4c8c18a5 target-arm: lpae: Move declaration of t0sz and t1sz
Move declaration of t0sz and t1sz to the top of the function
avoiding a mix of code and variable declarations.

No functional change.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-4-git-send-email-edgar.iglesias@gmail.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Edgar E. Iglesias
5c31a10d16 target-arm: lpae: Make t0sz and t1sz signed integers
Make t0sz and t1sz signed integers to match tsz and to make
it easier to implement support for AArch32 negative t0sz.
t1sz is changed for consistensy.

No functional change.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-3-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Edgar E. Iglesias
59e0553073 target-arm: Add HPFAR_EL2
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-id: 1445864527-14520-2-git-send-email-edgar.iglesias@gmail.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Jean-Christophe Dubois
054535262f i.MX: Standardize i.MX GPT debug
The goal is to have debug code always compiled during build.

We standardize all debug output on the following format:

[QOM_TYPE_NAME]reporting_function: debug message

We also replace IPRINTF with qemu_log_mask(). The qemu_log_mask() output
is following the same format as the above debug.

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: b7ce7e98a051479453744aded122789531d80a44.1445781957.git.jcd@tribudubois.net
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Jean-Christophe Dubois
4929f6563c i.MX: Standardize i.MX EPIT debug
The goal is to have debug code always compiled during build.

We standardize all debug output on the following format:

[QOM_TYPE_NAME]reporting_function: debug message

We also replace IPRINTF with qemu_log_mask(). The qemu_log_mask() output
is following the same format as the above debug.

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 5bbad71517ca728d8865f7b9f998baa0df022794.1445781957.git.jcd@tribudubois.net
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Jean-Christophe Dubois
b72d8d257c i.MX: Standardize i.MX FEC debug
The goal is to have debug code always compiled during build.

We standardize all debug output on the following format:

[QOM_TYPE_NAME]reporting_function: debug message

The qemu_log_mask() output is following the same format as the
above debug.

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 57e565982db94fb433c32dfa17608888464d21de.1445781957.git.jcd@tribudubois.net
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Jean-Christophe Dubois
4a6aa0af85 i.MX: Standardize i.MX CCM debug
The goal is to have debug code always compiled during build.

We standardize all debug output on the following format:

[QOM_TYPE_NAME]reporting_function: debug message

The qemu_log_mask() output is following the same format as the
above debug.

Adding some missing qemu_log_mask call for bad registers.

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 293e08f31cbb4df84d58f693243e61e770c73b3a.1445781957.git.jcd@tribudubois.net
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Jean-Christophe Dubois
f50ed7853a i.MX: Standardize i.MX AVIC debug
The goal is to have debug code always compiled during build.

We standardize all debug output on the following format:

[QOM_TYPE_NAME]reporting_function: debug message

We also replace IPRINTF with qemu_log_mask(). The qemu_log_mask() output
is following the same format as the above debug.

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 29885ffea2577eaf2288c1d17fd87ee951748b49.1445781957.git.jcd@tribudubois.net
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Jean-Christophe Dubois
3afcbb01bc i.MX: Standardize i.MX I2C debug
The goal is to have debug code always compiled during build.

We standardize all debug output on the following format:

[QOM_TYPE_NAME]reporting_function: debug message

The qemu_log_mask() output is following the same format as
the above debug.

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 328acfe6fc09a5afdbfbfd5220e0869fd5082660.1445781957.git.jcd@tribudubois.net
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Jean-Christophe Dubois
5641112574 i.MX: Standardize i.MX GPIO debug
The goal is to have debug code always compiled during build.

We standardize all debug output on the following format:

[QOM_TYPE_NAME]reporting_function: debug message

The qemu_log_mask() outputis following the same format as
the above debug.

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 4f2007adcf0f579864bb4dd8a825824e0e9098b8.1445781957.git.jcd@tribudubois.net
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 15:59:46 +00:00
Jean-Christophe Dubois
8ccce77c04 i.MX: Standardize i.MX serial debug.
The goal is to have debug code always compiled during build.

We standardize all debug output on the following format:

[QOM_TYPE_NAME]reporting_function: debug message

We also replace IPRINTF with qemu_log_mask(). The qemu_log_mask() output
is following the same format as the above debug.

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Message-id: 47b8759b251d356c633faf7ea34f897f340aea4e.1445781957.git.jcd@tribudubois.net
[PMM: Drop attempt to print the ram_addr of a memory region in
 one DPRINTF, which (a) was using the wrong format string so
 didn't build on 32-bit and (b) was incorrectly looking at a
 private field of a MemoryRegion struct]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 13:16:21 +00:00
Andrew Jones
4b280b726a hw/arm/virt: don't use a15memmap directly
We should always go through VirtBoardInfo when we need the memmap.
To avoid using a15memmap directly, in this case, we need to defer
the max-cpus check from class init time to instance init time. In
class init we now use MAX_CPUMASK_BITS for max_cpus initialization,
which is the maximum QEMU supports, and also, incidentally, the
maximum KVM/gicv3 currently supports. Also, a nice side-effect of
delaying the max-cpus check is that we now get more appropriate
error messages for gicv2 machines that try to configure more than
123 cpus. Before this patch it would complain that the requested
number of cpus was greater than 123, but for gicv2 configs, it
should complain that the number is greater than 8.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Message-id: 1445189728-860-3-git-send-email-drjones@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 12:00:50 +00:00
Pavel Fedin
24182fbc19 arm_gic_kvm: Disable live migration if not supported
Currently, if the kernel does not have live migration API, the migration
will still be attempted, but vGIC save/restore functions will just not do
anything. This will result in a broken machine state.

This patch fixes the problem by adding migration blocker if kernel API is
not supported.

Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 12:00:50 +00:00
Soren Brinkmann
b876452507 target-arm: Add support for SPSR_(ABT|UND|IRQ|FIQ)
Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 12:00:50 +00:00
Peter Maydell
541ebcd401 target-arm/translate.c: Handle non-executable page-straddling Thumb insns
When the memory we're trying to translate code from is not executable we have
to turn this into a guest fault. In order to report the correct PC for this
fault, and to make sure it is not reported until after any other possible
faults for instructions earlier in execution, we must terminate TBs at
the end of a page, in case the next instruction is in a non-executable page.
This is simple for T16, A32 and A64 instructions, which are always aligned
to their size. However T32 instructions may be 32-bits but only 16-aligned,
so they can straddle a page boundary.

Correct the condition that checks whether the next instruction will touch
the following page, to ensure that if we're 2 bytes before the boundary
and this insn is T32 then we end the TB.

Reported-by: Pavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Reviewed-by: Laurent Desnogues <laurent.desnogues@gmail.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 12:00:50 +00:00
Peter Maydell
7cd6de3bb1 target-arm: Fix "no 64-bit EL2" assumption in arm_excp_unmasked()
The code in arm_excp_unmasked() suppresses the ability of PSTATE.AIF
to mask exceptions from a lower EL targeting EL2 or EL3 if the
CPU is 64-bit. This is correct for a target of EL3, but not correct
for targeting EL2. Further, we go to some effort to calculate
scr and hcr values which are not used at all for the 64-bit CPU
case.

Rearrange the code to correctly implement the 64-bit CPU logic
and keep the hcr/scr calculations in the 32-bit CPU codepath.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1444327729-4120-1-git-send-email-peter.maydell@linaro.org
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
2015-10-27 12:00:50 +00:00
Peter Maydell
7e038b94e7 Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging
# gpg: Signature made Tue 27 Oct 2015 05:47:28 GMT using RSA key ID 398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 215D 46F4 8246 689E C77F  3562 EF04 965B 398D 6211

* remotes/jasowang/tags/net-pull-request:
  net: free the string returned by object_get_canonical_path_component
  net: make iov_to_buf take right size argument in nc_sendv_compat()
  net: Remove duplicate data from query-rx-filter on multiqueue net devices
  vmxnet3: Do not fill stats if device is inactive
  options: Add documentation for filter-dump
  net/dump: Provide the dumping facility as a net-filter
  net/dump: Separate the NetClientState from the DumpState
  net/dump: Rework net-dump init functions
  net/dump: Add support for receive_iov function
  net: cadence_gem: Set initial MAC address

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-27 10:10:46 +00:00
Yang Hongyang
a3e8a3f382 net: free the string returned by object_get_canonical_path_component
The value returned from object_get_canonical_path_component
must be freed.

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:42 +08:00
Yang Hongyang
edc981443d net: make iov_to_buf take right size argument in nc_sendv_compat()
We want "buf, sizeof(buf)" here.  sizeof(buffer) is the size of a
pointer, which is wrong.
Thanks to Paolo for pointing it out.

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:40 +08:00
Vladislav Yasevich
5320c2caf4 net: Remove duplicate data from query-rx-filter on multiqueue net devices
When responding to a query-rx-filter command on a multiqueue
netdev, qemu reports the data for each queue.  The data, however,
is not per-queue, but per device and the same data is reported
multiple times.  This causes confusion and may also cause extra
unnecessary processing when looking at the data.

Commit 638fb14169 (net: Make qmp_query_rx_filter() with name argument
more obvious) partially addresses this issue, by limiting the output
when the name is specified.  However, when the name is not specified,
the issue still persists.

Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:39 +08:00
Shmulik Ladkani
eedeeeffd4 vmxnet3: Do not fill stats if device is inactive
Guest OS may issue VMXNET3_CMD_GET_STATS even before device was
activated (for example in linux, after insmod but prior net-dev open).

Accessing shared descriptors prior device activation is illegal as the
VMXNET3State structures have not been fully initialized.

As a result, guest memory gets corrupted and may lead to guest OS
crashes.

Fix, by not filling the stats descriptors if device is inactive.

Reported-by: Leonid Shatz <leonid.shatz@ravellosystems.com>
Acked-by: Dmitry Fleytman <dmitry@daynix.com>
Signed-off-by: Dana Rubin <dana.rubin@ravellosystems.com>
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@ravellosystems.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:38 +08:00
Thomas Huth
d3e0c032f5 options: Add documentation for filter-dump
Add a short description for the filter-dump command line options.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:36 +08:00
Thomas Huth
9d3e12e881 net/dump: Provide the dumping facility as a net-filter
Use the net-filter infrastructure to provide the dumping
functions for netdev devices, too.

Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:35 +08:00
Thomas Huth
75310e3486 net/dump: Separate the NetClientState from the DumpState
With the upcoming dumping-via-netfilter patch, the DumpState
should not be related to NetClientState anymore, so move the
related information to a new struct called DumpNetClient.

Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:34 +08:00
Thomas Huth
7bc3074c27 net/dump: Rework net-dump init functions
Move the creation of the dump client from net_dump_init() into
net_init_dump(), so we can later use the former function for
dump via netfilter, too. Also rename net_dump_init() to
net_dump_state_init() to make it easier distinguishable from
net_init_dump().

Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:32 +08:00
Thomas Huth
43192fcc1a net/dump: Add support for receive_iov function
Adding a proper receive_iov function to the net dump module.
This will make it easier to support the dump filter feature for
the -netdev option in later patches.

Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:31 +08:00
Sebastian Huber
afb4c51fad net: cadence_gem: Set initial MAC address
Set initial MAC address to the one specified by the command line.

Signed-off-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
2015-10-27 10:30:30 +08:00
Peter Maydell
9666248a85 Merge remote-tracking branch 'remotes/sstabellini/tags/xen-2015-10-26' into staging
Xen 2015-10-26

# gpg: Signature made Mon 26 Oct 2015 11:32:50 GMT using RSA key ID 70E1AE90
# gpg: Good signature from "Stefano Stabellini <stefano.stabellini@eu.citrix.com>"

* remotes/sstabellini/tags/xen-2015-10-26:
  xen-platform: Replace assert() with appropriate error reporting
  xen_platform: switch to realize
  Qemu/Xen: Fix early freeing MSIX MMIO memory region

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-26 13:13:38 +00:00
Eduardo Habkost
b1ecd51bdb xen-platform: Replace assert() with appropriate error reporting
Commit dbb7405d8c made it possible to
trigger an assert using "-device xen-platform". Replace it with
appropriate error reporting.

Before:

  $ qemu-system-x86_64 -device xen-platform
  qemu-system-x86_64: hw/i386/xen/xen_platform.c:391: xen_platform_initfn: Assertion `xen_enabled()' failed.
  Aborted (core dumped)
  $

After:

  $ qemu-system-x86_64 -device xen-platform
  qemu-system-x86_64: -device xen-platform: xen-platform device requires the Xen accelerator
  $

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2015-10-26 11:32:24 +00:00
Stefano Stabellini
4098d49db5 xen_platform: switch to realize
Use realize to initialize the xen_platform device

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-26 11:32:24 +00:00
Peter Maydell
251d7e6014 Merge remote-tracking branch 'remotes/elmarco/tags/ivshmem-pull-request' into staging
ivshmem series

# gpg: Signature made Mon 26 Oct 2015 09:27:46 GMT using RSA key ID 75969CE5
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>"
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* remotes/elmarco/tags/ivshmem-pull-request: (51 commits)
  doc: document ivshmem & hugepages
  ivshmem: use little-endian int64_t for the protocol
  ivshmem: use kvm irqfd for msi notifications
  ivshmem: rename MSI eventfd_table
  ivshmem: remove EventfdEntry.vector
  ivshmem: add hostmem backend
  ivshmem: use qemu_strtosz()
  ivshmem: do not keep shm_fd open
  tests: add ivshmem qtest
  qtest: add qtest_add_abrt_handler()
  msix: implement pba write (but read-only)
  contrib: remove unnecessary strdup()
  ivshmem: add check on protocol version in QEMU
  docs: update ivshmem device spec
  ivshmem-server: fix hugetlbfs support
  ivshmem-server: use a uint16 for client ID
  ivshmem-client: check the number of vectors
  contrib: add ivshmem client and server
  util: const event_notifier_get_fd() argument
  ivshmem: reset mask on device reset
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-26 11:32:20 +00:00
Lan Tianyu
4e494de668 Qemu/Xen: Fix early freeing MSIX MMIO memory region
msix->mmio is added to XenPCIPassthroughState's object as property.
object_finalize_child_property is called for XenPCIPassthroughState's
object, which calls object_property_del_all, which is going to try to
delete msix->mmio. object_finalize_child_property() will access
msix->mmio's obj. But the whole msix struct has already been freed
by xen_pt_msix_delete. This will cause segment fault when msix->mmio
has been overwritten.

This patch is to fix the issue.

Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
2015-10-26 11:32:18 +00:00
Marc-André Lureau
7d4f4bdaf7 doc: document ivshmem & hugepages
Document and give some examples of hugepages support with ivshmem device
and server.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2015-10-26 10:19:53 +01:00
Marc-André Lureau
f7a199b2b4 ivshmem: use little-endian int64_t for the protocol
The current ivshmem protocol uses 'long' for integers. But the
sizeof(long) depends on the host and the endianess is not defined, which
may cause portability troubles.

Instead, switch to using little-endian int64_t. This breaks the
protocol, except on x64 little-endian host where this change
should be compatible.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-26 10:19:53 +01:00
Marc-André Lureau
660c97eef6 ivshmem: use kvm irqfd for msi notifications
Use irqfd for improving context switch when notifying the guest.
If the host doesn't support kvm irqfd, regular msi notifications are
still supported.

Note: the ivshmem implementation doesn't allow switching between MSI and
IO interrupts, this patch doesn't either.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
2015-10-26 10:19:53 +01:00
Marc-André Lureau
0f57350e5c ivshmem: rename MSI eventfd_table
The array is used to have vector specific data, so use a more
descriptive name.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-26 10:19:53 +01:00
Marc-André Lureau
d160f3f791 ivshmem: remove EventfdEntry.vector
No need to store an extra int for the vector number when it can be
computed easily by looking at the position in the array.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-26 10:19:53 +01:00
Marc-André Lureau
d9453c93fe ivshmem: add hostmem backend
Instead of handling allocation, teach ivshmem to use a memory backend.
This allows to use hugetlbfs backed memory now.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-26 10:19:53 +01:00
Marc-André Lureau
2c04752cc8 ivshmem: use qemu_strtosz()
Use the common qemu utility function to parse the memory size.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-26 10:19:53 +01:00
Marc-André Lureau
f689d2811a ivshmem: do not keep shm_fd open
Remove shm_fd from device state, closing it as early as possible to avoid leaks.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-26 10:19:53 +01:00
Marc-André Lureau
ddef6a0d68 tests: add ivshmem qtest
Adds 4 ivshmemtests:
- single qemu instance and basic IO
- pair of instances, check memory sharing
- pair of instances with server, and MSIX
- hot plug/unplug

A temporary shm is created as well as a directory to place server
socket, both should be clear on exit and abort.

Cc: Cam Macdonell <cam@cs.ualberta.ca>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-10-26 10:19:48 +01:00
Marc-André Lureau
063c23d909 qtest: add qtest_add_abrt_handler()
Allow a test to add abort handlers, use GHook for all handlers.

There is currently no way to remove a handler, but it could be
later added if needed.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:03:18 +02:00
Marc-André Lureau
43b11a91dd msix: implement pba write (but read-only)
qpci_msix_pending() writes on pba region, causing qemu to SEGV:

  Program received signal SIGSEGV, Segmentation fault.
  [Switching to Thread 0x7ffff7fba8c0 (LWP 25882)]
  0x0000000000000000 in ?? ()
  (gdb) bt
  #0  0x0000000000000000 in  ()
  #1  0x00005555556556c5 in memory_region_oldmmio_write_accessor (mr=0x5555579f3f80, addr=0, value=0x7fffffffbf68, size=4, shift=0, mask=4294967295, attrs=...) at /home/elmarco/src/qemu/memory.c:434
  #2  0x00005555556558e1 in access_with_adjusted_size (addr=0, value=0x7fffffffbf68, size=4, access_size_min=1, access_size_max=4, access=0x55555565563e <memory_region_oldmmio_write_accessor>, mr=0x5555579f3f80, attrs=...) at /home/elmarco/src/qemu/memory.c:506
  #3  0x00005555556581eb in memory_region_dispatch_write (mr=0x5555579f3f80, addr=0, data=0, size=4, attrs=...) at /home/elmarco/src/qemu/memory.c:1176
  #4  0x000055555560b6f9 in address_space_rw (as=0x555555eff4e0 <address_space_memory>, addr=3759147008, attrs=..., buf=0x7fffffffc1b0 "", len=4, is_write=true) at /home/elmarco/src/qemu/exec.c:2439
  #5  0x000055555560baa2 in cpu_physical_memory_rw (addr=3759147008, buf=0x7fffffffc1b0 "", len=4, is_write=1) at /home/elmarco/src/qemu/exec.c:2534
  #6  0x000055555564c005 in cpu_physical_memory_write (addr=3759147008, buf=0x7fffffffc1b0, len=4) at /home/elmarco/src/qemu/include/exec/cpu-common.h:80
  #7  0x000055555564cd9c in qtest_process_command (chr=0x55555642b890, words=0x5555578de4b0) at /home/elmarco/src/qemu/qtest.c:378
  #8  0x000055555564db77 in qtest_process_inbuf (chr=0x55555642b890, inbuf=0x55555641b340) at /home/elmarco/src/qemu/qtest.c:569
  #9  0x000055555564dc07 in qtest_read (opaque=0x55555642b890, buf=0x7fffffffc2e0 "writel 0xe0100800 0x0\n", size=22) at /home/elmarco/src/qemu/qtest.c:581
  #10 0x000055555574ce3e in qemu_chr_be_write (s=0x55555642b890, buf=0x7fffffffc2e0 "writel 0xe0100800 0x0\n", len=22) at qemu-char.c:306
  #11 0x0000555555751263 in tcp_chr_read (chan=0x55555642bcf0, cond=G_IO_IN, opaque=0x55555642b890) at qemu-char.c:2876
  #12 0x00007ffff64c9a8a in g_main_context_dispatch (context=0x55555641c400) at gmain.c:3122

(without this patch, this can be reproduced with the ivshmem qtest)

Implement an empty mmio write to avoid the crash.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
2015-10-24 18:03:18 +02:00
Marc-André Lureau
45b00c44ce contrib: remove unnecessary strdup()
getopt() optarg points to argv memory, no need to dup those values,
fixes small leaks detected by clang-analyzer.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2015-10-24 18:03:18 +02:00
David Marchand
5105b1d8c2 ivshmem: add check on protocol version in QEMU
Send a protocol version as the first message from server, clients must
close communication if they don't support this protocol version.  Older
QEMUs should be fine with this change in the protocol since they
overrides their own vm_id on reception of an id associated to no
eventfd.

Signed-off-by: David Marchand <david.marchand@6wind.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
[use fifo_update_and_get()]
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:03:18 +02:00
David Marchand
8c4ef202b9 docs: update ivshmem device spec
Add some notes on the parts needed to use ivshmem devices: more specifically,
explain the purpose of an ivshmem server and the basic concept to use the
ivshmem devices in guests.
Move some parts of the documentation and re-organise it.

Signed-off-by: David Marchand <david.marchand@6wind.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2015-10-24 18:03:17 +02:00
Marc-André Lureau
1e21feb628 ivshmem-server: fix hugetlbfs support
As pointed out on the ML by Andrew Jones, glibc no longer permits
creating POSIX shm on hugetlbfs directly. When given a hugetlbfs path,
create a shareable file there.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2015-10-24 18:03:16 +02:00
Marc-André Lureau
022cffe313 ivshmem-server: use a uint16 for client ID
In practice, the number of VM is limited to MAXUINT16 in ivshmem, so use
the same limit on the server (removes a theorical infinite loop)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:03:16 +02:00
Marc-André Lureau
95204aa951 ivshmem-client: check the number of vectors
Check the number of vectors received from the server, to avoid
out of bound array access.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:03:16 +02:00
David Marchand
a75eb03b9f contrib: add ivshmem client and server
When using ivshmem devices, notifications between guests can be sent as
interrupts using a ivshmem-server (typical use described in documentation).
The client is provided as a debug tool.

Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
Signed-off-by: David Marchand <david.marchand@6wind.com>
[fix a valgrind warning, option and server_close() segvs, extra server
headers includes, getopt() return type, out-of-tree build, use qemu
event_notifier instead of eventfd, fix x86/osx warnings - Marc-André]
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2015-10-24 18:03:16 +02:00
Marc-André Lureau
12f0b68c82 util: const event_notifier_get_fd() argument
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
972ad21553 ivshmem: reset mask on device reset
The interrupt mask is a state value, it should be reset, like the
interrupt status.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
1ee57de444 ivshmem: error on too many eventfd received
The number of eventfd that can be handled per peer is limited by the
number of vectors. Return an error when receiving too many of them.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
f456179fae ivshmem: replace 'guest' for 'peer' appropriately
The terms 'guest' and 'peer' are used sometime interchangeably which may
be confusing. Instead, use 'peer' for the remote instances of ivshmem
clients, and 'guest' for the local VM.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
f64a078d45 ivshmem: fix pci_ivshmem_exit()
Free all objects owned by the device, making sure the device is free,
fixing hot-unplug.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
d383537d01 ivshmem: add device description
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
945001a1af ivshmem: check shm isn't already initialized
The server should not change the shm, and this isn't handled by qemu and
we should should verify this in qemu.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
86d471bfa4 ivshmem: shmfd can be 0
0 is a valid fd value, so change conditions and set -1 value early

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
1f8552df2c ivshmem: migrate with VMStateDescription
load_state_old() is used to keep compatibility with version 0.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
e309366337 ivshmem: use common is_power_of_2()
The common version correctly checks for 0 value case.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
6f8a16d55d ivshmem: use common return
Both if branches return, move this out to common end.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
9a2f0e64ae ivshmem: simplify a bit the code
Use some more explicit variables to simplify the code.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
ffa99afd6e ivshmem: print error on invalid peer id
The server shouldn't send invalid peer id, so print an error if it's the
case.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
36617792b4 ivshmem: improve error handling
The test whether the chardev is an AF_UNIX socket rejects
"-chardev socket,id=chr0,path=/tmp/foo,server,nowait -device
ivshmem,chardev=chr0", but fails to explain why.

Use an explicit error on why a chardev may be rejected.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
f59bb37898 ivshmem: improve debug messages
Some misc improvements to ivshmem debug.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:49 +02:00
Marc-André Lureau
95c8425cc3 ivshmem: remove max_peer field
max_peer isn't really useful, it tracks the maximum received VM id, but
that quickly matches nb_peers, the size of the peers array. Since VM
come and go, there might be sparse peers so it doesn't help much in
general to have this value around.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
95e7c8a0f6 ivshmem: initialize max_peer to -1
There is no peer when device is initialized, do not let doorbell for
inexisting peer 0.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
d8a5da075a ivshmem: remove useless ivshmem_update_irq() val argument
val isn't used in ivshmem_update_irq() function.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
81e507f0bc ivshmem: allocate eventfds in resize_peers()
It simplifies a bit the code to allocate the array when setting the
number of peers instead of lazily when receiving the first vector.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
1300b2733a ivshmem: simplify around increase_dynamic_storage()
Set the number of peers and array allocation in a single place. Rename
to better reflect the function content.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
61ea2d8648 ivshmem: limit maximum number of peers to G_MAXUINT16
Limit the maximum number of peers to MAXUINT16. This is more realistic
and better matches the limit of the doorbell register.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
03977ad552 ivshmem: remove last exit(1)
Failing to create a chardev shouldn't be fatal.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
d58d7e848e ivshmem: more qdev conversion
Use the latest qemu device modeling API, in particular, convert to
realize to fix the error handling; right now a botched device_add
ivhsmem command kills the VM.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
49b2951f84 ivshmem: remove useless doorbell field
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
9113e3f394 ivshmem: remove superflous ivshmem_attr field
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
dee2151e72 ivshmem: remove unnecessary dup()
qemu_chr_fe_get_msgfd() transfers ownership, there is no need to dup the
fd.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
0f14fd71c1 ivshmem: factor out the incoming fifo handling
Make a new function fifo_update_and_get() that can be reused by other
functions (in next commits).

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
951dada665 ivshmem: fix number of bytes to push to fifo
If the fifo has 0 bytes, and the read is of size 1, the call to
fifo8_push_all() will copy off boundary data.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
b8ab854b27 ivhsmem: read do not accept more than sizeof(long)
ivshmem_read() only reads sizeof(long) from the input buffer.  Accepting
more could lead to fifo8 abort() on 32bit systems if fifo is not empty.

A following patch will change the protocol to 64-bit little-endian
instead.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
c246a62f26 msix: add VMSTATE_MSIX_TEST
ivshmem is going to use MSIX state conditionally.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
1ad78ea51a char: add qemu_chr_free()
If a chardev is allowed to be created outside of QMP, then it must be
also possible to free it. This is useful for ivshmem that creates
chardev anonymously and must be able to free them.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
2015-10-24 18:02:48 +02:00
Andreas Färber
bbfc2efefe tests: Add ivshmem qtest
Note that it launches two instances, as sharing memory is the purpose of
ivshmem.

Cc: Cam Macdonell <cam@cs.ualberta.ca>
Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
[ Remove Nahanni codename, add test to pci set - Marc-André ]
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2015-10-24 18:02:48 +02:00
Marc-André Lureau
dd054be35f config: enable ivshmem on POSIX
ivshmem doesn't actually require kvm, so enable it when POSIX is
enabled. (it is required however when ioeventfd is enabled)

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2015-10-24 18:02:47 +02:00
Peter Maydell
af25e7277d Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches

# gpg: Signature made Fri 23 Oct 2015 17:59:56 BST using RSA key ID C88F2FD6
# gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>"

* remotes/kevin/tags/for-upstream: (37 commits)
  tests: Add test case for aio_disable_external
  block: Add "drained begin/end" for internal snapshot
  block: Add "drained begin/end" for transactional blockdev-backup
  block: Add "drained begin/end" for transactional backup
  block: Add "drained begin/end" for transactional external snapshot
  block: Introduce "drained begin/end" API
  aio: introduce aio_{disable,enable}_external
  dataplane: Mark host notifiers' client type as "external"
  nbd: Mark fd handlers client type as "external"
  aio: Add "is_external" flag for event handlers
  throttle: Remove throttle_group_lock/unlock()
  blockdev: Allow more options for BB-less BDS tree
  blockdev: Pull out blockdev option extraction
  blockdev: Do not create BDS for empty drive
  block: Prepare for NULL BDS
  block: Add blk_insert_bs()
  block: Prepare remaining BB functions for NULL BDS
  block: Fail requests to empty BlockBackend
  block: Make some BB functions fall back to BBRS
  block: Add BlockBackendRootState
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-23 18:14:42 +01:00
Fam Zheng
c07bc2c165 tests: Add test case for aio_disable_external
Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:24 +02:00
Fam Zheng
507306cc8e block: Add "drained begin/end" for internal snapshot
This ensures the atomicity of the transaction by avoiding processing of
external requests such as those from ioeventfd.

state->bs is assigned right after bdrv_drained_begin. Because it was
used as the flag for deletion or not in abort, now we need a separate
flag - InternalSnapshotState.created.

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:24 +02:00
Fam Zheng
ff52bf36a3 block: Add "drained begin/end" for transactional blockdev-backup
Similar to the previous patch, make sure that external events are not
dispatched during transaction operations.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:24 +02:00
Fam Zheng
1fdd4b7be3 block: Add "drained begin/end" for transactional backup
This ensures the atomicity of the transaction by avoiding processing of
external requests such as those from ioeventfd.

Move the assignment to state->bs up right after bdrv_drained_begin, so
that we can use it in the clean callback. The abort callback will still
check bs->job and state->job, so it's OK.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:24 +02:00
Fam Zheng
da763e8301 block: Add "drained begin/end" for transactional external snapshot
This ensures the atomicity of the transaction by avoiding processing of
external requests such as those from ioeventfd.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:24 +02:00
Fam Zheng
51288d7917 block: Introduce "drained begin/end" API
The semantics is that after bdrv_drained_begin(bs), bs will not get new external
requests until the matching bdrv_drained_end(bs).

Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:24 +02:00
Fam Zheng
c1e1e5fa8f aio: introduce aio_{disable,enable}_external
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:24 +02:00
Fam Zheng
3a1e8074d7 dataplane: Mark host notifiers' client type as "external"
They will be excluded by type in the nested event loops in block layer,
so that unwanted events won't be processed there.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:24 +02:00
Fam Zheng
172cc129a5 nbd: Mark fd handlers client type as "external"
So we could distinguish it from internal used fds, thus avoid handling
unwanted events in nested aio polls.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Fam Zheng
dca21ef23b aio: Add "is_external" flag for event handlers
All callers pass in false, and the real external ones will switch to
true in coming patches.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Alberto Garcia
d87d01e16a throttle: Remove throttle_group_lock/unlock()
The group throttling code was always meant to handle its locking
internally. However, bdrv_swap() was touching the ThrottleGroup
structure directly and therefore needed an API for that.

Now that bdrv_swap() no longer exists there's no need for the
throttle_group_lock() API anymore.

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
bd745e238b blockdev: Allow more options for BB-less BDS tree
Most of the options which blockdev_init() parses for both the
BlockBackend and the root BDS are valid for just the root BDS as well
(e.g. read-only). This patch allows specifying these options even if not
creating a BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
fbf8175eac blockdev: Pull out blockdev option extraction
Extract some of the blockdev option extraction code from blockdev_init()
into its own function. This simplifies blockdev_init() and will allow
reusing the code in a different function added in a follow-up patch.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
5ec18f8c83 blockdev: Do not create BDS for empty drive
Do not use "rudimentary" BDSs for empty drives any longer (for
freshly created drives).

After a follow-up patch, empty drives will generally use a NULL BDS, not
only the freshly created drives.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
5433c24f0f block: Prepare for NULL BDS
blk_bs() will not necessarily return a non-NULL value any more (unless
blk_is_available() is true or it can be assumed to otherwise, e.g.
because it is called immediately after a successful blk_new_with_bs() or
blk_new_open()).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
0c3c36d651 block: Add blk_insert_bs()
This function associates the given BlockDriverState with the given
BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
a46fc9c950 block: Prepare remaining BB functions for NULL BDS
There are several BlockBackend functions which, in theory, cannot fail.
This patch makes them cope with the BlockDriverState pointer being NULL
by making them fall back to some default action like ignoring the value
in setters and returning the default in getters.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
c09ba36c9a block: Fail requests to empty BlockBackend
If there is no BlockDriverState in a BlockBackend or if the tray of the
guest device is open, fail all requests (where that is possible) with
-ENOMEDIUM.

The reason the status of the guest device is taken into account is
because once the guest device's tray is opened, any request on the same
BlockBackend as the guest uses should fail. If the BDS tree is supposed
to be usable even after ejecting it from the guest, a different
BlockBackend must be used.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
061959e8da block: Make some BB functions fall back to BBRS
If there is no BDS tree attached to a BlockBackend, functions that can
do so should fall back to the BlockBackendRootState structure.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
281d22d86c block: Add BlockBackendRootState
This structure will store some of the state of the root BDS if the BDS
tree is removed, so that state can be restored once a new BDS tree is
inserted.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
973f2ddf7b block/throttle-groups: Make incref/decref public
Throttle groups are not necessarily referenced by BDSs alone; a later
patch will essentially allow BBs to reference them, too. Make the
ref/unref functions public so that reference can be properly accounted
for.

Their interface is slightly adjusted in that they return and take a
ThrottleState pointer, respectively, instead of a ThrottleGroup pointer.
Functionally, they are equivalent, but since ThrottleGroup is not meant
to be used outside of block/throttle-groups.c, ThrottleState is easier
to handle.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
373340b26c block: Move I/O status and error actions into BB
These options are only relevant for the user of a whole BDS tree (like a
guest device or a block job) and should thus be moved into the
BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
7f0e9da6f1 block: Move BlockAcctStats into BlockBackend
As the comment above bdrv_get_stats() says, BlockAcctStats is something
which belongs to the device instead of each BlockDriverState. This patch
therefore moves it into the BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
53d8f9d8fb block: Remove wr_highest_sector from BlockAcctStats
BlockAcctStats contains statistics about the data transferred from and
to the device; wr_highest_sector does not fit in with the rest.

Furthermore, those statistics are supposed to be specific for a certain
device and not necessarily for a BDS (see the comment above
bdrv_get_stats()); on the other hand, wr_highest_sector may be a rather
important information to know for each BDS. When BlockAcctStats is
finally removed from the BDS, we will want to keep wr_highest_sector in
the BDS.

Finally, wr_highest_sector is renamed to wr_highest_offset and given the
appropriate meaning. Externally, it is represented as an offset so there
is no point in doing something different internally. Its definition is
changed to match that in qapi/block-core.json which is "the offset after
the greatest byte written to". Doing so should not cause any harm since
if external programs tried to calculate the volume usage by
(wr_highest_offset + 512) / volume_size, after this patch they will just
assume the volume to be full slightly earlier than before.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
68e9ec017b block: Move guest_block_size into BlockBackend
guest_block_size is a guest device property so it should be moved into
the interface between block layer and guest devices, which is the
BlockBackend.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
4981bdec0d block: Fix BB AIOCB AioContext without BDS
Fix the BlockBackend's AIOCB AioContext for aborting AIO in case there
is no BDS. If there is no implementation of AIOCBInfo::get_aio_context()
the AioContext is derived from the BDS the AIOCB belongs to. If that BDS
is NULL (because it has been removed from the BB) this will not work.

This patch makes blk_get_aio_context() fall back to the main loop
context if the BDS pointer is NULL and implements
AIOCBInfo::get_aio_context() (blk_aiocb_get_aio_context()) which invokes
blk_get_aio_context().

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
7d3467d903 hw/usb-storage: Check whether BB is inserted
Only call bdrv_add_key() on the BlockDriverState if it is not NULL.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
2e1280e8ff hw/block/fdc: Implement tray status
The tray of an FDD is open iff there is no medium inserted (there are
only two states for an FDD: "medium inserted" or "no medium inserted").

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
b4d02820d9 block: Invoke change media CB before NULLing drv
In order to handle host device passthrough, some guest device models
may call blk_is_inserted() to check whether the medium is inserted on
the host, when checking the guest tray status.

This tray status is inquired by blk_dev_change_media_cb(); because
bdrv_is_inserted() (invoked by blk_is_inserted()) always returns false
for BDS with drv set to NULL, blk_dev_change_media_cb() should therefore
be called before drv is set to NULL.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
1354c47378 block/raw_bsd: Drop raw_is_inserted()
With the new automatically-recursive implementation of
bdrv_is_inserted() checking by default whether all the children of a BDS
are inserted, we can drop raw's own implementation.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:23 +02:00
Max Reitz
28d7a78996 block: Make bdrv_is_inserted() recursive
If bdrv_is_inserted() is called on the top level BDS, it should make
sure all nodes in the BDS tree are actually inserted.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:22 +02:00
Max Reitz
db0284f86a block: Add blk_is_available()
blk_is_available() returns true iff the BDS is inserted (which means
blk_bs() is not NULL and bdrv_is_inserted() returns true) and if the
tray of the guest device is closed.

blk_is_inserted() is changed to return true only if blk_bs() is not
NULL.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:22 +02:00
Max Reitz
e031f75048 block: Make bdrv_is_inserted() return a bool
Make bdrv_is_inserted(), blk_is_inserted(), and the callback
BlockDriver.bdrv_is_inserted() return a bool.

Suggested-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:22 +02:00
Max Reitz
8e9e653038 iotests: Only create BB if necessary
Tests 071 and 081 test giving references in blockdev-add. It is not
necessary to create a BlockBackend here, so omit it.

While at it, fix up some blockdev-add invocations in the vicinity
(s/raw/$IMGFMT/ in 081, drop the format BDS for blkverify's raw child in
071).

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:22 +02:00
Max Reitz
be4b67bc7d blockdev: Allow creation of BDS trees without BB
If the "id" field is missing from the options given to blockdev-add,
just omit the BlockBackend and create the BlockDriverState tree alone.

However, if "id" is missing, "node-name" must be specified; otherwise,
the BDS tree would no longer be accessible.

Many BDS options which are not parsed by bdrv_open() (like caching)
cannot be specified for these BB-less BDS trees yet. A future patch will
remove this limitation.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:22 +02:00
Max Reitz
d44f928a54 block: Set BDRV_O_INCOMING in bdrv_fill_options()
This flag should not be set for the root BDS only, but for any BDS that
is being created while incoming migration is pending, so setting it is
moved from blockdev_init() to bdrv_fill_options().

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:22 +02:00
Max Reitz
f709623b3d block: Remove host floppy support
It has been deprecated as of 2.3, so we can now remove it.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2015-10-23 18:18:22 +02:00
Peter Maydell
bc79082e4c Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging
X86 queue, 2015-10-23

# gpg: Signature made Fri 23 Oct 2015 16:30:58 BST using RSA key ID 984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"

* remotes/ehabkost/tags/x86-pull-request:
  vl: trivial: minor tweaks to a max-cpu error msg
  target-i386: Use 1UL for bit shift
  target-i386: Add DE to TCG_FEATURES
  target-i386: Ensure always-1 bits on DR6 can't be cleared
  target-i386: Check CR4[DE] for processing DR4/DR5
  target-i386: Handle I/O breakpoints
  target-i386: Optimize setting dr[0-3]
  target-i386: Move hw_*breakpoint_* functions
  target-i386: Ensure bit 10 on DR7 is never cleared
  target-i386: Re-introduce optimal breakpoint removal
  target-i386: Introduce cpu_x86_update_dr7
  target-i386: Disable cache info passthrough by default
  target-i386: allow any alignment for SMBASE

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-23 16:35:43 +01:00
Andrew Jones
31bfa2a400 vl: trivial: minor tweaks to a max-cpu error msg
Signed-off-by: Andrew Jones <drjones@redhat.com>
2015-10-23 13:11:52 -02:00
Eduardo Habkost
72370dc114 target-i386: Use 1UL for bit shift
Fix undefined behavior detected by clang runtime check:

  qemu/target-i386/cpu.c:1494:15: runtime error:
    left shift of 1 by 31 places cannot be represented in type 'int'

While doing that, add extra parenthesis for clarity.

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 13:07:27 -02:00
Eduardo Habkost
b6c5a6f021 target-i386: Add DE to TCG_FEATURES
Now DE is supported by TCG so it can be enabled in CPUID bits.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Eduardo Habkost
462f8ed1f1 target-i386: Ensure always-1 bits on DR6 can't be cleared
Bits 4-11 and 16-31 on DR6 are documented as always 1, so ensure they
can't be cleared by software.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Richard Henderson
d005233923 target-i386: Check CR4[DE] for processing DR4/DR5
Introduce helper_get_dr so that we don't have to put CR4[DE]
into the scarce HFLAGS resource.  At the same time, rename
helper_movl_drN_T0 to helper_set_dr and set the helper flags.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Eduardo Habkost
5223a9423c target-i386: Handle I/O breakpoints
Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Richard Henderson
7525b55051 target-i386: Optimize setting dr[0-3]
If the debug register is not enabled, we need
do nothing besides update the register.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Richard Henderson
696ad9e4b2 target-i386: Move hw_*breakpoint_* functions
They're only used from bpt_helper.c now.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Eduardo Habkost
9055330ffb target-i386: Ensure bit 10 on DR7 is never cleared
Bit 10 of DR7 is documented as always set to 1, so ensure that's
always the case.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Richard Henderson
36eb6e0967 target-i386: Re-introduce optimal breakpoint removal
Before the last patch, we had an efficient loop that disabled
local breakpoints on task switch.  Re-add that, but in a more
general way that handles changes to the global enable bits too.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Richard Henderson
93d00d0fbe target-i386: Introduce cpu_x86_update_dr7
This moves the last of the iteration over breakpoints into
the bpt_helper.c file.  This also allows us to make several
breakpoint functions static.

Signed-off-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Eduardo Habkost
e265e3e480 target-i386: Disable cache info passthrough by default
The host cache information may not make sense for the guest if the VM
CPU topology doesn't match the host CPU topology. To make sure we won't
expose broken cache information to the guest, disable cache info
passthrough by default, and add a new "host-cache-info" property that
can be used to enable the old behavior for users that really need it.

Cc: Benoît Canet <benoit@irqsave.net>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:27 -02:00
Paolo Bonzini
dd75d4fcb4 target-i386: allow any alignment for SMBASE
Processors up to the Pentium (says Bochs---I do not have old enough
manuals) require a 32KiB alignment for the SMBASE, but newer processors
do not need that, and Tiano Core will use non-aligned SMBASE values.

Reported-by: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2015-10-23 12:59:26 -02:00
Peter Maydell
1e700f4c6c Merge remote-tracking branch 'remotes/mdroth/tags/qga-pull-2015-10-23-tag' into staging
qemu-ga patch queue

* unbreak qga-test unit test on travis-ci systems by not assuming a
  disk-based filesystem must be present

# gpg: Signature made Fri 23 Oct 2015 15:01:47 BST using RSA key ID F108B584
# gpg: Good signature from "Michael Roth <flukshun@gmail.com>"
# gpg:                 aka "Michael Roth <mdroth@utexas.edu>"
# gpg:                 aka "Michael Roth <mdroth@linux.vnet.ibm.com>"

* remotes/mdroth/tags/qga-pull-2015-10-23-tag:
  tests: test-qga, loosen assumptions about host filesystems

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-23 15:55:50 +01:00
Michael Roth
b3e9e584fc tests: test-qga, loosen assumptions about host filesystems
QGA skips pseudo-filesystems when querying filesystems via
guest-get-fsinfo. On some hosts, such as travis-ci which uses
containers with simfs filesystems, QGA might not report *any*
filesystems. Our test case assumes there would be at least one,
leading to false error messages in these situations.

Instead, sanity-check values iff we get at least one filesystem.

Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
Cc: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
2015-10-23 08:57:45 -05:00
Peter Maydell
147482ae35 Merge remote-tracking branch 'remotes/dgibson/tags/ppc-next-20151023' into staging
ppc patch queue - 2015-10-23

sPAPR highlights:
  * Allow VFIO devices on the spapr-pci-host-bridge
  * Allow virtio VGA
  * Safer handling of HTAB allocation
  * ibm,pa-features device tree property

non-sPAPR highlights:
  * Categorization of many ppc specific devices in help output
  * Tweaks to MMU type constants

# gpg: Signature made Fri 23 Oct 2015 07:27:56 BST using RSA key ID 20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-next-20151023: (21 commits)
  prep: do not use CPU_LOG_IOPORT, convert to tracepoints
  openpic: add to misc category
  macio-nvram: add to misc category
  macio: add to bridge category
  uninorth: add to bridge category
  macio-ide: add to storage category
  cuda: add to bridge category
  grackle: add to bridge category
  escc: add to input category
  cmd646: add to storage category
  adb: add to input category
  ppc/spapr: Add "ibm,pa-features" property to the device-tree
  ppc: Add mmu_model defines for arch 2.03 and 2.07
  hw/scsi/spapr_vscsi: Remove superfluous memset
  spapr_pci: Allow VFIO devices to work on the normal PCI host bridge
  spapr_iommu: Provide a function to switch a TCE table to allowing VFIO
  spapr_iommu: Rename vfio_accel parameter
  spapr_pci: Allow PCI host bridge DMA window to be configured
  spapr: Add "slb-size" property to CPU device tree nodes
  spapr: Abort when HTAB of requested size isn't allocated
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-23 13:09:09 +01:00
Peter Maydell
431429a5b8 Merge remote-tracking branch 'remotes/berrange/tags/qcrypto-fixes-pull-20151022-2' into staging
Merge qcrypto-fixes 2015/10/22

# gpg: Signature made Thu 22 Oct 2015 19:03:45 BST using RSA key ID 15104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>"

* remotes/berrange/tags/qcrypto-fixes-pull-20151022-2:
  configure: avoid polluting global CFLAGS with tasn1 flags
  crypto: add sanity checking of plaintext/ciphertext length
  crypto: don't let builtin aes crash if no IV is provided
  crypto: allow use of nettle/gcrypt to be selected explicitly

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-23 12:09:02 +01:00
Peter Maydell
dfbe0642ef Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
vhost: build fix

Fix build breakages when using older gcc.

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

# gpg: Signature made Thu 22 Oct 2015 20:36:07 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  vhost-user: fix up rhel6 build

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-23 10:24:08 +01:00
Paolo Bonzini
659f7f6556 prep: do not use CPU_LOG_IOPORT, convert to tracepoints
These messages are disabled by default; a perfect usecase for tracepoints.
Convert them over.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:38:28 +11:00
Laurent Vivier
29f8dd66e8 openpic: add to misc category
openpic is a programmable interrupt controller, so
add it to the misc category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:18 +11:00
Laurent Vivier
175fe9e7c8 macio-nvram: add to misc category
The macio nvram is a non volatile RAM, so add it
the misc category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:18 +11:00
Laurent Vivier
f9f2a9f26f macio: add to bridge category
macio is a bridge between the PCI bus and the Mac nvram,
IDE controller and PIC, so add it to the bridge category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:18 +11:00
Laurent Vivier
1d16f86a43 uninorth: add to bridge category
Uninorth is the mac99 PCI host controller, so add
it to the bridge category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:18 +11:00
Laurent Vivier
3469d9bce8 macio-ide: add to storage category
macio-ide is an IDE controller, so add it
to the storage category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:18 +11:00
Laurent Vivier
599d7326c3 cuda: add to bridge category
Cuda is a bridge between PowerMac system bus and the ADB controller,
real-time clock, pram and the power management unit.

So add it to the bridge category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:18 +11:00
Laurent Vivier
e16244355f grackle: add to bridge category
Grackle is the PCI host controller of oldworld powermac,
so add it to the bridge category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:18 +11:00
Laurent Vivier
f8d4c07c78 escc: add to input category
ESCC is a serial port controller, so add it
to the input category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:17 +11:00
Laurent Vivier
74623e7369 cmd646: add to storage category
cmd646 is an IDE controller, so add it to the
storage category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:17 +11:00
Laurent Vivier
32f3a8992e adb: add to input category
The Apple Desktop Bus is used to connect a keyboard and a mouse,
so add it to the input category.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:35:17 +11:00
Benjamin Herrenschmidt
90da0d5a70 ppc/spapr: Add "ibm,pa-features" property to the device-tree
LoPAPR defines a "ibm,pa-features" per-CPU device tree property which
describes extended features of the Processor Architecture.

This adds the property to the device tree. At the moment this is the
copy of what pHyp advertises except "I=1 (cache inhibited) Large Pages"
which is enabled for TCG and disabled when running under HV KVM host
with 4K system page size.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[aik: rebased, changed commit log, moved ci_large_pages initialization,
renamed pa_features arrays]
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:22:40 +11:00
Benjamin Herrenschmidt
aa4bb58752 ppc: Add mmu_model defines for arch 2.03 and 2.07
This removes unused POWERPC_MMU_2_06a/POWERPC_MMU_2_06d.

This replaces POWERPC_MMU_64B with POWERPC_MMU_2_03 for POWER5+ to be
more explicit about the version of the PowerISA supported.

This defines POWERPC_MMU_2_07 and uses it for the POWER8 CPU family.
This will not have an immediate effect now but it will in the following
patch.

This should cause no behavioural change.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
[aik: rebased, changed commit log]
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 12:22:40 +11:00
Thomas Huth
a23dec105c hw/scsi/spapr_vscsi: Remove superfluous memset
g_malloc0 already clears the memory, so no need for
the additional memset here.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Alexander Graf <agraf@suse.de>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 10:38:11 +11:00
David Gibson
185181f883 spapr_pci: Allow VFIO devices to work on the normal PCI host bridge
The core VFIO infrastructure more or less allows VFIO devices to work
on any normal guest PCI host bridge (PHB) without extra logic.
However, the "spapr-pci-host-bridge" device (as opposed to the special
"spapr-pci-vfio-host-bridge" device) breaks this by using a partially
KVM accelerated implementation of the guest kernel IOMMU which won't
work with VFIO devices, without additional kernel support.

This patch allows VFIO devices to work on the spapr-pci-host-bridge,
by having it switch off KVM TCE acceleration when a VFIO device is
added to the PHB (either on startup, or by hotplug).

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
2015-10-23 10:38:10 +11:00
David Gibson
c10325d6f9 spapr_iommu: Provide a function to switch a TCE table to allowing VFIO
Because of the way non-VFIO guest IOMMU operations are KVM accelerated, not
all TCE tables (guest IOMMU contexts) can support VFIO devices.  Currently,
this is decided at creation time.

To support hotplug of VFIO devices, we need to allow a TCE table which
previously didn't allow VFIO devices to be switched so that it can.  This
patch adds an spapr_tce_set_need_vfio() function to do this, by
reallocating the table in userspace if necessary.

Currently this doesn't allow the KVM acceleration to be re-enabled if all
the VFIO devices are removed.  That's an optimization for another time.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
2015-10-23 10:38:10 +11:00
David Gibson
6a81dd172c spapr_iommu: Rename vfio_accel parameter
The vfio_accel parameter used when creating a new TCE table (guest IOMMU
context) has a confusing name.  What it really means is whether we need the
TCE table created to be able to support VFIO devices.

VFIO is relevant, because when available we use in-kernel acceleration of
the TCE table, but that may not work with VFIO devices because updates to
the table are handled in kernel, bypass qemu and so don't hit qemu's
infrastructure for keeping the VFIO host IOMMU state in sync with the guest
IOMMU state.

Rename the parameter to "need_vfio" throughout.  This is a cosmetic change,
with no impact on the logic.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
2015-10-23 10:38:10 +11:00
David Gibson
f93caaac36 spapr_pci: Allow PCI host bridge DMA window to be configured
At present the PCI host bridge (PHB) for the pseries machine type has a
fixed DMA window from 0..1GB (in PCI address space) which is mapped to real
memory via the PAPR paravirtualized IOMMU.

For better support of VFIO devices, we're going to want to allow for
different configurations of the DMA window.

Eventually we'll want to allow the guest itself to reconfigure the window
via the PAPR dynamic DMA window interface, but as a preliminary this patch
allows the user to reconfigure the window with new properties on the PHB
device.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
2015-10-23 10:38:10 +11:00
Thomas Huth
fd5da5c472 spapr: Add "slb-size" property to CPU device tree nodes
According to a commit message in the Linux kernel (see here
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=b60c31d85a2a
for example), the name of the property that carries the information
about the number of SLB entries should be called "slb-size", and
not "ibm,slb-size". The Linux kernel can deal with both names, but
to be on the safe side we should support the official name, too.

[Now that LoPAPR is public, the relevant requirement can be found in
section C.6.1.8 --dwg]

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 10:38:10 +11:00
Bharata B Rao
7735fedaf4 spapr: Abort when HTAB of requested size isn't allocated
Terminate the guest when HTAB of requested size isn't allocated by
the host.

When memory hotplug is attempted on a guest that has booted with
less than requested HTAB size, the guest kernel will not be able
to gracefully fail the hotplug request. This patch will ensure that
we never end up in a situation where memory hotplug fails due to
less than requested HTAB size.

Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 10:38:10 +11:00
Bharata B Rao
b817772a25 spapr: Allocate HTAB from machine init
Allocate HTAB from ppc_spapr_init() so that we can abort the guest
if requested HTAB size is't allocated by the host. However retain the
htab reset call in spapr_reset_htab() so that HTAB gets reset (and
not allocated) during machine reset.

Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2015-10-23 10:38:10 +11:00
Michael S. Tsirkin
7f4a930e64 vhost-user: fix up rhel6 build
Build on RHEL6 fails:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42875

Apparently unnamed unions couldn't use C99  named field initializers.
Let's just name the payload union field.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2015-10-22 22:34:59 +03:00
Daniel P. Berrange
9024603776 configure: avoid polluting global CFLAGS with tasn1 flags
The previous commit

  commit 9a2fd4347c
  Author: Daniel P. Berrange <berrange@redhat.com>
  Date:   Mon Apr 13 14:01:39 2015 +0100

    crypto: add sanity checking of TLS x509 credentials

defined new variables $TEST_LIBS and $TEST_CFLAGS and
used them in tests/Makefile to augment $LIBS and $CFLAGS.

Unfortunately this overlooks the fact that tests/Makefile
is not executed via recursive-make, it is just pulled into
the top level Makefile via an include statement. So rather
than just augmenting the compiler/linker flags for tests
it polluted the global flags.

This is thought to be behind a reported failure when
building the pixman module as a sub-module, since global
$CFLAGS are passed down to configure in pixman.

This change removes the $TEST_LIBS and $TEST_CFLAGS
replacing them with $TASN1_LIBS and $TASN1_CFLAGS,
setting only against specific objects/executables
that need them.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2015-10-22 19:03:08 +01:00
Daniel P. Berrange
3a661f1eab crypto: add sanity checking of plaintext/ciphertext length
When encrypting/decrypting data, the plaintext/ciphertext
buffers are required to be a multiple of the cipher block
size. If this is not done, nettle will abort and gcrypt
will report an error. To get consistent behaviour add
explicit checks upfront for the buffer sizes.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2015-10-22 19:03:08 +01:00
Daniel P. Berrange
eb2a770b17 crypto: don't let builtin aes crash if no IV is provided
If no IV is provided, then use a default IV of all-zeros
instead of crashing. This gives parity with gcrypt and
nettle backends.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2015-10-22 19:03:08 +01:00
Daniel P. Berrange
91bfcdb01d crypto: allow use of nettle/gcrypt to be selected explicitly
Currently the choice of whether to use nettle or gcrypt is
made based on what gnutls is linked to. There are times
when it is desirable to be able to force build against a
specific library. For example, if testing changes to QEMU's
crypto code all 3 possible backends need to be checked
regardless of what the local gnutls uses.

It is also desirable to be able to enable nettle/gcrypt
for cipher/hash algorithms, without enabling gnutls
for TLS support.

This gives two new configure flags, which allow the
following possibilities

Automatically determine nettle vs gcrypt from what
gnutls links to (recommended to minimize number of
crypto libraries linked to)

 ./configure

Automatically determine nettle vs gcrypt based on
which is installed

 ./configure --disable-gnutls

Force use of nettle

 ./configure --enable-nettle

Force use of gcrypt

 ./configure --enable-gcrypt

Force use of built-in AES & crippled-DES

 ./configure --disable-nettle --disable-gcrypt

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2015-10-22 19:03:07 +01:00
Chen Gang
2a080ce266 target-tilegx: Implement prefetch instructions in pipe y2
Originally, tilegx qemu only implement prefetch instructions in pipe x1,
did not implement them in pipe y2.

Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-10-22 07:51:49 -10:00
Peter Maydell
6a6739de51 Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20151021' into staging
Collected tcg backend patches

# gpg: Signature made Wed 21 Oct 2015 22:34:28 BST using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"

* remotes/rth/tags/pull-tcg-20151021:
  cpu-exec: Add "nochain" debug flag
  tcg/mips: Support r6 SEL{NE, EQ}Z instead of MOVN/MOVZ
  tcg/mips: Support r6 multiply/divide encodings
  tcg/mips: Support r6 JR encoding
  tcg/mips: Add use_mips32r6_instructions definition
  disas/mips: Add R6 jr/jr.hb to disassembler
  tcg-opc.h: Simplify insn_start def
  tcg/ppc: Prefer mask over andi.
  tcg/ppc: Revise goto_tb implementation
  tcg/ppc: Adjust exit_tb for change in prologue placement

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-22 18:01:53 +01:00
Peter Maydell
b803894e2c Merge remote-tracking branch 'remotes/afaerber/tags/qom-cpu-for-peter' into staging
QOM CPUState and X86CPU

* Adoption of CPUClass::disas_set_info() hook

# gpg: Signature made Thu 22 Oct 2015 17:11:24 BST using RSA key ID 3E7E013F
# gpg: Good signature from "Andreas Färber <afaerber@suse.de>"
# gpg:                 aka "Andreas Färber <afaerber@suse.com>"

* remotes/afaerber/tags/qom-cpu-for-peter:
  disas: QOMify alpha specific disas setup
  disas: QOMify mips specific disas setup
  disas: QOMify sh4 specific disas setup
  disas: QOMify lm32 specific disas setup
  disas: QOMify sparc specific disas setup
  disas: QOMify m68k specific disas setup
  disas: QOMify moxie specific disas setup
  disas: QOMify s390x specific disas setup

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2015-10-22 17:33:54 +01:00
Richard Henderson
89a82cd4b6 cpu-exec: Add "nochain" debug flag
Respect it to avoid linking TBs together.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-10-19 11:04:39 -10:00
James Hogan
137d63902f tcg/mips: Support r6 SEL{NE, EQ}Z instead of MOVN/MOVZ
Extend MIPS movcond implementation to support the SELNEZ/SELEQZ
instructions introduced in MIPS r6 (where MOVN/MOVZ have been removed).

Whereas the "MOVN/MOVZ rd, rs, rt" instructions have the following
semantics:
 rd = [!]rt ? rs : rd

The "SELNEZ/SELEQZ rd, rs, rt" instructions are slightly different:
 rd = [!]rt ? rs : 0

First we ensure that if one of the movcond input values is zero that it
comes last (we can swap the input arguments if we invert the condition).
This is so that it can exactly match one of the SELNEZ/SELEQZ
instructions and avoid the need to emit the other one.

Otherwise we emit the opposite instruction first into a temporary
register, and OR that into the result:
 SELNEZ/SELEQZ  TMP1, v2, c1
 SELEQZ/SELNEZ  ret, v1, c1
 OR             ret, ret, TMP1

Which does the following:
 ret = cond ? v1 : v2

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
Message-Id: <1443788657-14537-7-git-send-email-james.hogan@imgtec.com>
2015-10-19 11:04:39 -10:00
James Hogan
bc6d0c22b0 tcg/mips: Support r6 multiply/divide encodings
MIPSr6 adds several new integer multiply, divide, and modulo
instructions, and removes several pre-r6 encodings, along with the HI/LO
registers which were the implicit operands of some of those
instructions. Update TCG to use the new instructions when built for r6.

The new instructions actually map much more directly to the TCG ops, as
they only provide a single 32-bit half of the result and in a normal
general purpose register instead of HI or LO.

The mulu2_i32 and muls2_i32 operations are no longer appropriate for r6,
so they are removed from the TCG opcode table. This is because they
would need to emit two separate host instructions anyway (for the high
and low half of the result), which TCG can arrange automatically for us
in the absense of mulu2_i32/muls2_i32 by splitting it into mul_i32 and
mul*h_i32 TCG ops.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
Message-Id: <1443788657-14537-6-git-send-email-james.hogan@imgtec.com>
2015-10-19 11:04:39 -10:00
James Hogan
6e0d096989 tcg/mips: Support r6 JR encoding
MIPSr6 encodes JR as JALR with zero as the link register, and the pre-r6
JR encoding is removed. Update TCG to use the new encoding when built
for r6.

We still use the old encoding for pre-r6, so as not to confuse return
prediction stack hardware which may detect only particular encodings of
the return instruction.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
Message-Id: <1443788657-14537-5-git-send-email-james.hogan@imgtec.com>
2015-10-19 11:04:38 -10:00
James Hogan
ce14bd4d46 tcg/mips: Add use_mips32r6_instructions definition
Add definition use_mips32r6_instructions to the MIPS TCG backend which
is constant 1 when built for MIPS release 6. This will be used to decide
between pre-R6 and R6 instruction encodings.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
Message-Id: <1443788657-14537-4-git-send-email-james.hogan@imgtec.com>
2015-10-19 11:04:38 -10:00
James Hogan
d76f365350 disas/mips: Add R6 jr/jr.hb to disassembler
MIPS r6 encodes jr as jalr zero, and jr.hb as jalr.hb zero, so add these
encodings to the MIPS disassembly table.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Leon Alrae <leon.alrae@imgtec.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
Message-Id: <1443788657-14537-3-git-send-email-james.hogan@imgtec.com>
2015-10-19 11:04:38 -10:00
James Hogan
c0e40dbdcc tcg-opc.h: Simplify insn_start def
We already have a TLADDR_ARGS definition, so rearrange the order
slightly and use it in the definition of insn_start, instead of
having an #ifdef.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
Message-Id: <1443788657-14537-2-git-send-email-james.hogan@imgtec.com>
2015-10-19 11:04:38 -10:00
Richard Henderson
1e1df962e3 tcg/ppc: Prefer mask over andi.
Prefer the instruction that isn't required to modify cr0.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-10-19 11:04:38 -10:00
Richard Henderson
5bfd75a35c tcg/ppc: Revise goto_tb implementation
Restrict the size of code_gen_buffer to 2GB on ppc64, which
lets us assert that everything is reachable with addis+addi
from tb_ret_addr.  This lets us use a max of 4 insns for goto_tb
instead of 7.

Emit the indirect branch portion of goto_tb up front, which
means we only have to update two insns to update any link.
With a 64-bit store, we can update the link atomically, which
may be required in future.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-10-19 11:04:37 -10:00
Richard Henderson
70f897bdc4 tcg/ppc: Adjust exit_tb for change in prologue placement
Changing the prologue to the beginning of the code_gen_buffer
changes the direction of the "return" branch.  Need to change
the logic to match.

Signed-off-by: Richard Henderson <rth@twiddle.net>
2015-10-19 11:04:37 -10:00
307 changed files with 8937 additions and 2940 deletions

View File

@@ -151,6 +151,8 @@ dummy := $(call unnest-vars,, \
stub-obj-y \
util-obj-y \
qga-obj-y \
ivshmem-client-obj-y \
ivshmem-server-obj-y \
qga-vss-dll-obj-y \
block-obj-y \
block-obj-m \
@@ -323,6 +325,11 @@ ifneq ($(EXESUF),)
qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI)
endif
ivshmem-client$(EXESUF): $(ivshmem-client-obj-y)
$(call LINK, $^)
ivshmem-server$(EXESUF): $(ivshmem-server-obj-y) libqemuutil.a libqemustub.a
$(call LINK, $^)
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h

View File

@@ -104,3 +104,8 @@ target-obj-y += trace/
# by libqemuutil.a. These should be moved to a separate .json schema.
qga-obj-y = qga/
qga-vss-dll-obj-y = qga/
######################################################################
# contrib
ivshmem-client-obj-y = contrib/ivshmem-client/
ivshmem-server-obj-y = contrib/ivshmem-server/

View File

@@ -25,6 +25,7 @@ struct AioHandler
IOHandler *io_write;
int deleted;
void *opaque;
bool is_external;
QLIST_ENTRY(AioHandler) node;
};
@@ -43,6 +44,7 @@ static AioHandler *find_aio_handler(AioContext *ctx, int fd)
void aio_set_fd_handler(AioContext *ctx,
int fd,
bool is_external,
IOHandler *io_read,
IOHandler *io_write,
void *opaque)
@@ -82,6 +84,7 @@ void aio_set_fd_handler(AioContext *ctx,
node->io_read = io_read;
node->io_write = io_write;
node->opaque = opaque;
node->is_external = is_external;
node->pfd.events = (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR : 0);
node->pfd.events |= (io_write ? G_IO_OUT | G_IO_ERR : 0);
@@ -92,10 +95,11 @@ void aio_set_fd_handler(AioContext *ctx,
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *notifier,
bool is_external,
EventNotifierHandler *io_read)
{
aio_set_fd_handler(ctx, event_notifier_get_fd(notifier),
(IOHandler *)io_read, NULL, notifier);
is_external, (IOHandler *)io_read, NULL, notifier);
}
bool aio_prepare(AioContext *ctx)
@@ -257,7 +261,8 @@ bool aio_poll(AioContext *ctx, bool blocking)
/* fill pollfds */
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (!node->deleted && node->pfd.events) {
if (!node->deleted && node->pfd.events
&& aio_node_check(ctx, node->is_external)) {
add_pollfd(node);
}
}

View File

@@ -28,11 +28,13 @@ struct AioHandler {
GPollFD pfd;
int deleted;
void *opaque;
bool is_external;
QLIST_ENTRY(AioHandler) node;
};
void aio_set_fd_handler(AioContext *ctx,
int fd,
bool is_external,
IOHandler *io_read,
IOHandler *io_write,
void *opaque)
@@ -86,6 +88,7 @@ void aio_set_fd_handler(AioContext *ctx,
node->opaque = opaque;
node->io_read = io_read;
node->io_write = io_write;
node->is_external = is_external;
event = event_notifier_get_handle(&ctx->notifier);
WSAEventSelect(node->pfd.fd, event,
@@ -98,6 +101,7 @@ void aio_set_fd_handler(AioContext *ctx,
void aio_set_event_notifier(AioContext *ctx,
EventNotifier *e,
bool is_external,
EventNotifierHandler *io_notify)
{
AioHandler *node;
@@ -133,6 +137,7 @@ void aio_set_event_notifier(AioContext *ctx,
node->e = e;
node->pfd.fd = (uintptr_t)event_notifier_get_handle(e);
node->pfd.events = G_IO_IN;
node->is_external = is_external;
QLIST_INSERT_HEAD(&ctx->aio_handlers, node, node);
g_source_add_poll(&ctx->source, &node->pfd);
@@ -304,7 +309,8 @@ bool aio_poll(AioContext *ctx, bool blocking)
/* fill fd sets */
count = 0;
QLIST_FOREACH(node, &ctx->aio_handlers, node) {
if (!node->deleted && node->io_notify) {
if (!node->deleted && node->io_notify
&& aio_node_check(ctx, node->is_external)) {
events[count++] = event_notifier_get_handle(node->e);
}
}

View File

@@ -247,7 +247,7 @@ aio_ctx_finalize(GSource *source)
}
qemu_mutex_unlock(&ctx->bh_lock);
aio_set_event_notifier(ctx, &ctx->notifier, NULL);
aio_set_event_notifier(ctx, &ctx->notifier, false, NULL);
event_notifier_cleanup(&ctx->notifier);
rfifolock_destroy(&ctx->lock);
qemu_mutex_destroy(&ctx->bh_lock);
@@ -329,6 +329,7 @@ AioContext *aio_context_new(Error **errp)
}
g_source_set_can_recurse(&ctx->source, true);
aio_set_event_notifier(ctx, &ctx->notifier,
false,
(EventNotifierHandler *)
event_notifier_dummy_cb);
ctx->thread_pool = NULL;

180
block.c
View File

@@ -257,7 +257,6 @@ BlockDriverState *bdrv_new(void)
for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
QLIST_INIT(&bs->op_blockers[i]);
}
bdrv_iostatus_disable(bs);
notifier_list_init(&bs->close_notifiers);
notifier_with_return_list_init(&bs->before_write_notifiers);
qemu_co_queue_init(&bs->throttled_reqs[0]);
@@ -857,7 +856,6 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
goto fail_opts;
}
bs->guest_block_size = 512;
bs->request_alignment = 512;
bs->zero_beyond_eof = true;
open_flags = bdrv_open_flags(bs, flags);
@@ -1081,6 +1079,10 @@ static int bdrv_fill_options(QDict **options, const char **pfilename,
}
}
if (runstate_check(RUN_STATE_INMIGRATE)) {
*flags |= BDRV_O_INCOMING;
}
return 0;
}
@@ -1908,6 +1910,10 @@ void bdrv_close(BlockDriverState *bs)
bdrv_drain(bs); /* in case flush left pending I/O */
notifier_list_notify(&bs->close_notifiers, bs);
if (bs->blk) {
blk_dev_change_media_cb(bs->blk, false);
}
if (bs->drv) {
BdrvChild *child, *next;
@@ -1946,10 +1952,6 @@ void bdrv_close(BlockDriverState *bs)
bs->full_open_options = NULL;
}
if (bs->blk) {
blk_dev_change_media_cb(bs->blk, false);
}
QLIST_FOREACH_SAFE(ban, &bs->aio_notifiers, list, ban_next) {
g_free(ban);
}
@@ -1998,19 +2000,10 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
/* move some fields that need to stay attached to the device */
/* dev info */
bs_dest->guest_block_size = bs_src->guest_block_size;
bs_dest->copy_on_read = bs_src->copy_on_read;
bs_dest->enable_write_cache = bs_src->enable_write_cache;
/* r/w error */
bs_dest->on_read_error = bs_src->on_read_error;
bs_dest->on_write_error = bs_src->on_write_error;
/* i/o status */
bs_dest->iostatus_enabled = bs_src->iostatus_enabled;
bs_dest->iostatus = bs_src->iostatus;
/* dirty bitmap */
bs_dest->dirty_bitmaps = bs_src->dirty_bitmaps;
}
@@ -2497,82 +2490,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
}
void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
BlockdevOnError on_write_error)
{
bs->on_read_error = on_read_error;
bs->on_write_error = on_write_error;
}
BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read)
{
return is_read ? bs->on_read_error : bs->on_write_error;
}
BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int error)
{
BlockdevOnError on_err = is_read ? bs->on_read_error : bs->on_write_error;
switch (on_err) {
case BLOCKDEV_ON_ERROR_ENOSPC:
return (error == ENOSPC) ?
BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
case BLOCKDEV_ON_ERROR_STOP:
return BLOCK_ERROR_ACTION_STOP;
case BLOCKDEV_ON_ERROR_REPORT:
return BLOCK_ERROR_ACTION_REPORT;
case BLOCKDEV_ON_ERROR_IGNORE:
return BLOCK_ERROR_ACTION_IGNORE;
default:
abort();
}
}
static void send_qmp_error_event(BlockDriverState *bs,
BlockErrorAction action,
bool is_read, int error)
{
IoOperationType optype;
optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
qapi_event_send_block_io_error(bdrv_get_device_name(bs), optype, action,
bdrv_iostatus_is_enabled(bs),
error == ENOSPC, strerror(error),
&error_abort);
}
/* This is done by device models because, while the block layer knows
* about the error, it does not know whether an operation comes from
* the device or the block layer (from a job, for example).
*/
void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
bool is_read, int error)
{
assert(error >= 0);
if (action == BLOCK_ERROR_ACTION_STOP) {
/* First set the iostatus, so that "info block" returns an iostatus
* that matches the events raised so far (an additional error iostatus
* is fine, but not a lost one).
*/
bdrv_iostatus_set_err(bs, error);
/* Then raise the request to stop the VM and the event.
* qemu_system_vmstop_request_prepare has two effects. First,
* it ensures that the STOP event always comes after the
* BLOCK_IO_ERROR event. Second, it ensures that even if management
* can observe the STOP event and do a "cont" before the STOP
* event is issued, the VM will not stop. In this case, vm_start()
* also ensures that the STOP/RESUME pair of events is emitted.
*/
qemu_system_vmstop_request_prepare();
send_qmp_error_event(bs, action, is_read, error);
qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
} else {
send_qmp_error_event(bs, action, is_read, error);
}
}
int bdrv_is_read_only(BlockDriverState *bs)
{
return bs->read_only;
@@ -2766,6 +2683,11 @@ BlockDriverState *bdrv_lookup_bs(const char *device,
blk = blk_by_name(device);
if (blk) {
if (!blk_bs(blk)) {
error_setg(errp, "Device '%s' has no medium", device);
return NULL;
}
return blk_bs(blk);
}
}
@@ -3136,15 +3058,23 @@ void bdrv_invalidate_cache_all(Error **errp)
/**
* Return TRUE if the media is present
*/
int bdrv_is_inserted(BlockDriverState *bs)
bool bdrv_is_inserted(BlockDriverState *bs)
{
BlockDriver *drv = bs->drv;
BdrvChild *child;
if (!drv)
return 0;
if (!drv->bdrv_is_inserted)
return 1;
return drv->bdrv_is_inserted(bs);
if (!drv) {
return false;
}
if (drv->bdrv_is_inserted) {
return drv->bdrv_is_inserted(bs);
}
QLIST_FOREACH(child, &bs->children, next) {
if (!bdrv_is_inserted(child->bs)) {
return false;
}
}
return true;
}
/**
@@ -3195,11 +3125,6 @@ void bdrv_lock_medium(BlockDriverState *bs, bool locked)
}
}
void bdrv_set_guest_block_size(BlockDriverState *bs, int align)
{
bs->guest_block_size = align;
}
BdrvDirtyBitmap *bdrv_find_dirty_bitmap(BlockDriverState *bs, const char *name)
{
BdrvDirtyBitmap *bm;
@@ -3597,46 +3522,6 @@ bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
return true;
}
void bdrv_iostatus_enable(BlockDriverState *bs)
{
bs->iostatus_enabled = true;
bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
}
/* The I/O status is only enabled if the drive explicitly
* enables it _and_ the VM is configured to stop on errors */
bool bdrv_iostatus_is_enabled(const BlockDriverState *bs)
{
return (bs->iostatus_enabled &&
(bs->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
bs->on_write_error == BLOCKDEV_ON_ERROR_STOP ||
bs->on_read_error == BLOCKDEV_ON_ERROR_STOP));
}
void bdrv_iostatus_disable(BlockDriverState *bs)
{
bs->iostatus_enabled = false;
}
void bdrv_iostatus_reset(BlockDriverState *bs)
{
if (bdrv_iostatus_is_enabled(bs)) {
bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
if (bs->job) {
block_job_iostatus_reset(bs->job);
}
}
}
void bdrv_iostatus_set_err(BlockDriverState *bs, int error)
{
assert(bdrv_iostatus_is_enabled(bs));
if (bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
BLOCK_DEVICE_IO_STATUS_FAILED;
}
}
void bdrv_img_create(const char *filename, const char *fmt,
const char *base_filename, const char *base_fmt,
char *options, uint64_t img_size, int flags,
@@ -4148,14 +4033,3 @@ void bdrv_refresh_filename(BlockDriverState *bs)
QDECREF(json);
}
}
/* This accessor function purpose is to allow the device models to access the
* BlockAcctStats structure embedded inside a BlockDriverState without being
* aware of the BlockDriverState structure layout.
* It will go away when the BlockAcctStats structure will be moved inside
* the device models.
*/
BlockAcctStats *bdrv_get_stats(BlockDriverState *bs)
{
return &bs->stats;
}

View File

@@ -47,14 +47,6 @@ void block_acct_done(BlockAcctStats *stats, BlockAcctCookie *cookie)
}
void block_acct_highest_sector(BlockAcctStats *stats, int64_t sector_num,
unsigned int nb_sectors)
{
if (stats->wr_highest_sector < sector_num + nb_sectors - 1) {
stats->wr_highest_sector = sector_num + nb_sectors - 1;
}
}
void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type,
int num_requests)
{

View File

@@ -21,6 +21,7 @@
#include "block/blockjob.h"
#include "qapi/qmp/qerror.h"
#include "qemu/ratelimit.h"
#include "sysemu/block-backend.h"
#define BACKUP_CLUSTER_BITS 16
#define BACKUP_CLUSTER_SIZE (1 << BACKUP_CLUSTER_BITS)
@@ -215,7 +216,9 @@ static void backup_iostatus_reset(BlockJob *job)
{
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
bdrv_iostatus_reset(s->target);
if (s->target->blk) {
blk_iostatus_reset(s->target->blk);
}
}
static const BlockJobDriver backup_job_driver = {
@@ -360,8 +363,10 @@ static void coroutine_fn backup_run(void *opaque)
job->bitmap = hbitmap_alloc(end, 0);
bdrv_set_enable_write_cache(target, true);
bdrv_set_on_error(target, on_target_error, on_target_error);
bdrv_iostatus_enable(target);
if (target->blk) {
blk_set_on_error(target->blk, on_target_error, on_target_error);
blk_iostatus_enable(target->blk);
}
bdrv_add_before_write_notifier(bs, &before_write);
@@ -451,7 +456,9 @@ static void coroutine_fn backup_run(void *opaque)
}
hbitmap_free(job->bitmap);
bdrv_iostatus_disable(target);
if (target->blk) {
blk_iostatus_disable(target->blk);
}
bdrv_op_unblock_all(target, job->common.blocker);
data = g_malloc(sizeof(*data));
@@ -480,7 +487,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||
on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
!bdrv_iostatus_is_enabled(bs)) {
(!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
error_setg(errp, QERR_INVALID_PARAMETER, "on-source-error");
return;
}

View File

@@ -12,12 +12,17 @@
#include "sysemu/block-backend.h"
#include "block/block_int.h"
#include "block/blockjob.h"
#include "block/throttle-groups.h"
#include "sysemu/blockdev.h"
#include "sysemu/sysemu.h"
#include "qapi-event.h"
/* Number of coroutines to reserve per attached device model */
#define COROUTINE_POOL_RESERVATION 64
static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb);
struct BlockBackend {
char *name;
int refcnt;
@@ -29,15 +34,31 @@ struct BlockBackend {
/* TODO change to DeviceState when all users are qdevified */
const BlockDevOps *dev_ops;
void *dev_opaque;
/* the block size for which the guest device expects atomicity */
int guest_block_size;
/* If the BDS tree is removed, some of its options are stored here (which
* can be used to restore those options in the new BDS on insert) */
BlockBackendRootState root_state;
/* I/O stats (display with "info blockstats"). */
BlockAcctStats stats;
BlockdevOnError on_read_error, on_write_error;
bool iostatus_enabled;
BlockDeviceIoStatus iostatus;
};
typedef struct BlockBackendAIOCB {
BlockAIOCB common;
QEMUBH *bh;
BlockBackend *blk;
int ret;
} BlockBackendAIOCB;
static const AIOCBInfo block_backend_aiocb_info = {
.get_aio_context = blk_aiocb_get_aio_context,
.aiocb_size = sizeof(BlockBackendAIOCB),
};
@@ -145,6 +166,10 @@ static void blk_delete(BlockBackend *blk)
bdrv_unref(blk->bs);
blk->bs = NULL;
}
if (blk->root_state.throttle_state) {
g_free(blk->root_state.throttle_group);
throttle_group_unref(blk->root_state.throttle_state);
}
/* Avoid double-remove after blk_hide_on_behalf_of_hmp_drive_del() */
if (blk->name[0]) {
QTAILQ_REMOVE(&blk_backends, blk, link);
@@ -308,6 +333,17 @@ void blk_hide_on_behalf_of_hmp_drive_del(BlockBackend *blk)
}
}
/*
* Associates a new BlockDriverState with @blk.
*/
void blk_insert_bs(BlockBackend *blk, BlockDriverState *bs)
{
assert(!blk->bs && !bs->blk);
bdrv_ref(bs);
blk->bs = bs;
bs->blk = blk;
}
/*
* Attach device model @dev to @blk.
* Return 0 on success, -EBUSY when a device model is attached already.
@@ -320,7 +356,7 @@ int blk_attach_dev(BlockBackend *blk, void *dev)
}
blk_ref(blk);
blk->dev = dev;
bdrv_iostatus_reset(blk->bs);
blk_iostatus_reset(blk);
return 0;
}
@@ -347,7 +383,7 @@ void blk_detach_dev(BlockBackend *blk, void *dev)
blk->dev = NULL;
blk->dev_ops = NULL;
blk->dev_opaque = NULL;
bdrv_set_guest_block_size(blk->bs, 512);
blk->guest_block_size = 512;
blk_unref(blk);
}
@@ -452,7 +488,47 @@ void blk_dev_resize_cb(BlockBackend *blk)
void blk_iostatus_enable(BlockBackend *blk)
{
bdrv_iostatus_enable(blk->bs);
blk->iostatus_enabled = true;
blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
}
/* The I/O status is only enabled if the drive explicitly
* enables it _and_ the VM is configured to stop on errors */
bool blk_iostatus_is_enabled(const BlockBackend *blk)
{
return (blk->iostatus_enabled &&
(blk->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
blk->on_write_error == BLOCKDEV_ON_ERROR_STOP ||
blk->on_read_error == BLOCKDEV_ON_ERROR_STOP));
}
BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
{
return blk->iostatus;
}
void blk_iostatus_disable(BlockBackend *blk)
{
blk->iostatus_enabled = false;
}
void blk_iostatus_reset(BlockBackend *blk)
{
if (blk_iostatus_is_enabled(blk)) {
blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
if (blk->bs && blk->bs->job) {
block_job_iostatus_reset(blk->bs->job);
}
}
}
void blk_iostatus_set_err(BlockBackend *blk, int error)
{
assert(blk_iostatus_is_enabled(blk));
if (blk->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
blk->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
BLOCK_DEVICE_IO_STATUS_FAILED;
}
}
static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
@@ -464,7 +540,7 @@ static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
return -EIO;
}
if (!blk_is_inserted(blk)) {
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
@@ -558,6 +634,7 @@ static BlockAIOCB *abort_aio_request(BlockBackend *blk, BlockCompletionFunc *cb,
QEMUBH *bh;
acb = blk_aio_get(&block_backend_aiocb_info, blk, cb, opaque);
acb->blk = blk;
acb->ret = ret;
bh = aio_bh_new(blk_get_aio_context(blk), error_callback_bh, acb);
@@ -602,16 +679,28 @@ int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int count)
int64_t blk_getlength(BlockBackend *blk)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_getlength(blk->bs);
}
void blk_get_geometry(BlockBackend *blk, uint64_t *nb_sectors_ptr)
{
bdrv_get_geometry(blk->bs, nb_sectors_ptr);
if (!blk->bs) {
*nb_sectors_ptr = 0;
} else {
bdrv_get_geometry(blk->bs, nb_sectors_ptr);
}
}
int64_t blk_nb_sectors(BlockBackend *blk)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_nb_sectors(blk->bs);
}
@@ -642,6 +731,10 @@ BlockAIOCB *blk_aio_writev(BlockBackend *blk, int64_t sector_num,
BlockAIOCB *blk_aio_flush(BlockBackend *blk,
BlockCompletionFunc *cb, void *opaque)
{
if (!blk_is_available(blk)) {
return abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
}
return bdrv_aio_flush(blk->bs, cb, opaque);
}
@@ -683,12 +776,20 @@ int blk_aio_multiwrite(BlockBackend *blk, BlockRequest *reqs, int num_reqs)
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_ioctl(blk->bs, req, buf);
}
BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
BlockCompletionFunc *cb, void *opaque)
{
if (!blk_is_available(blk)) {
return abort_aio_request(blk, cb, opaque, -ENOMEDIUM);
}
return bdrv_aio_ioctl(blk->bs, req, buf, cb, opaque);
}
@@ -704,11 +805,19 @@ int blk_co_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
int blk_co_flush(BlockBackend *blk)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_co_flush(blk->bs);
}
int blk_flush(BlockBackend *blk)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_flush(blk->bs);
}
@@ -719,7 +828,9 @@ int blk_flush_all(void)
void blk_drain(BlockBackend *blk)
{
bdrv_drain(blk->bs);
if (blk->bs) {
bdrv_drain(blk->bs);
}
}
void blk_drain_all(void)
@@ -727,76 +838,178 @@ void blk_drain_all(void)
bdrv_drain_all();
}
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
BlockdevOnError on_write_error)
{
blk->on_read_error = on_read_error;
blk->on_write_error = on_write_error;
}
BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
{
return bdrv_get_on_error(blk->bs, is_read);
return is_read ? blk->on_read_error : blk->on_write_error;
}
BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
int error)
{
return bdrv_get_error_action(blk->bs, is_read, error);
BlockdevOnError on_err = blk_get_on_error(blk, is_read);
switch (on_err) {
case BLOCKDEV_ON_ERROR_ENOSPC:
return (error == ENOSPC) ?
BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
case BLOCKDEV_ON_ERROR_STOP:
return BLOCK_ERROR_ACTION_STOP;
case BLOCKDEV_ON_ERROR_REPORT:
return BLOCK_ERROR_ACTION_REPORT;
case BLOCKDEV_ON_ERROR_IGNORE:
return BLOCK_ERROR_ACTION_IGNORE;
default:
abort();
}
}
static void send_qmp_error_event(BlockBackend *blk,
BlockErrorAction action,
bool is_read, int error)
{
IoOperationType optype;
optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
qapi_event_send_block_io_error(blk_name(blk), optype, action,
blk_iostatus_is_enabled(blk),
error == ENOSPC, strerror(error),
&error_abort);
}
/* This is done by device models because, while the block layer knows
* about the error, it does not know whether an operation comes from
* the device or the block layer (from a job, for example).
*/
void blk_error_action(BlockBackend *blk, BlockErrorAction action,
bool is_read, int error)
{
bdrv_error_action(blk->bs, action, is_read, error);
assert(error >= 0);
if (action == BLOCK_ERROR_ACTION_STOP) {
/* First set the iostatus, so that "info block" returns an iostatus
* that matches the events raised so far (an additional error iostatus
* is fine, but not a lost one).
*/
blk_iostatus_set_err(blk, error);
/* Then raise the request to stop the VM and the event.
* qemu_system_vmstop_request_prepare has two effects. First,
* it ensures that the STOP event always comes after the
* BLOCK_IO_ERROR event. Second, it ensures that even if management
* can observe the STOP event and do a "cont" before the STOP
* event is issued, the VM will not stop. In this case, vm_start()
* also ensures that the STOP/RESUME pair of events is emitted.
*/
qemu_system_vmstop_request_prepare();
send_qmp_error_event(blk, action, is_read, error);
qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
} else {
send_qmp_error_event(blk, action, is_read, error);
}
}
int blk_is_read_only(BlockBackend *blk)
{
return bdrv_is_read_only(blk->bs);
if (blk->bs) {
return bdrv_is_read_only(blk->bs);
} else {
return blk->root_state.read_only;
}
}
int blk_is_sg(BlockBackend *blk)
{
if (!blk->bs) {
return 0;
}
return bdrv_is_sg(blk->bs);
}
int blk_enable_write_cache(BlockBackend *blk)
{
return bdrv_enable_write_cache(blk->bs);
if (blk->bs) {
return bdrv_enable_write_cache(blk->bs);
} else {
return !!(blk->root_state.open_flags & BDRV_O_CACHE_WB);
}
}
void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
{
bdrv_set_enable_write_cache(blk->bs, wce);
if (blk->bs) {
bdrv_set_enable_write_cache(blk->bs, wce);
} else {
if (wce) {
blk->root_state.open_flags |= BDRV_O_CACHE_WB;
} else {
blk->root_state.open_flags &= ~BDRV_O_CACHE_WB;
}
}
}
void blk_invalidate_cache(BlockBackend *blk, Error **errp)
{
if (!blk->bs) {
error_setg(errp, "Device '%s' has no medium", blk->name);
return;
}
bdrv_invalidate_cache(blk->bs, errp);
}
int blk_is_inserted(BlockBackend *blk)
bool blk_is_inserted(BlockBackend *blk)
{
return bdrv_is_inserted(blk->bs);
return blk->bs && bdrv_is_inserted(blk->bs);
}
bool blk_is_available(BlockBackend *blk)
{
return blk_is_inserted(blk) && !blk_dev_is_tray_open(blk);
}
void blk_lock_medium(BlockBackend *blk, bool locked)
{
bdrv_lock_medium(blk->bs, locked);
if (blk->bs) {
bdrv_lock_medium(blk->bs, locked);
}
}
void blk_eject(BlockBackend *blk, bool eject_flag)
{
bdrv_eject(blk->bs, eject_flag);
if (blk->bs) {
bdrv_eject(blk->bs, eject_flag);
}
}
int blk_get_flags(BlockBackend *blk)
{
return bdrv_get_flags(blk->bs);
if (blk->bs) {
return bdrv_get_flags(blk->bs);
} else {
return blk->root_state.open_flags;
}
}
int blk_get_max_transfer_length(BlockBackend *blk)
{
return blk->bs->bl.max_transfer_length;
if (blk->bs) {
return blk->bs->bl.max_transfer_length;
} else {
return 0;
}
}
void blk_set_guest_block_size(BlockBackend *blk, int align)
{
bdrv_set_guest_block_size(blk->bs, align);
blk->guest_block_size = align;
}
void *blk_blockalign(BlockBackend *blk, size_t size)
@@ -806,40 +1019,64 @@ void *blk_blockalign(BlockBackend *blk, size_t size)
bool blk_op_is_blocked(BlockBackend *blk, BlockOpType op, Error **errp)
{
if (!blk->bs) {
return false;
}
return bdrv_op_is_blocked(blk->bs, op, errp);
}
void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason)
{
bdrv_op_unblock(blk->bs, op, reason);
if (blk->bs) {
bdrv_op_unblock(blk->bs, op, reason);
}
}
void blk_op_block_all(BlockBackend *blk, Error *reason)
{
bdrv_op_block_all(blk->bs, reason);
if (blk->bs) {
bdrv_op_block_all(blk->bs, reason);
}
}
void blk_op_unblock_all(BlockBackend *blk, Error *reason)
{
bdrv_op_unblock_all(blk->bs, reason);
if (blk->bs) {
bdrv_op_unblock_all(blk->bs, reason);
}
}
AioContext *blk_get_aio_context(BlockBackend *blk)
{
return bdrv_get_aio_context(blk->bs);
if (blk->bs) {
return bdrv_get_aio_context(blk->bs);
} else {
return qemu_get_aio_context();
}
}
static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
{
BlockBackendAIOCB *blk_acb = DO_UPCAST(BlockBackendAIOCB, common, acb);
return blk_get_aio_context(blk_acb->blk);
}
void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
{
bdrv_set_aio_context(blk->bs, new_context);
if (blk->bs) {
bdrv_set_aio_context(blk->bs, new_context);
}
}
void blk_add_aio_context_notifier(BlockBackend *blk,
void (*attached_aio_context)(AioContext *new_context, void *opaque),
void (*detach_aio_context)(void *opaque), void *opaque)
{
bdrv_add_aio_context_notifier(blk->bs, attached_aio_context,
detach_aio_context, opaque);
if (blk->bs) {
bdrv_add_aio_context_notifier(blk->bs, attached_aio_context,
detach_aio_context, opaque);
}
}
void blk_remove_aio_context_notifier(BlockBackend *blk,
@@ -848,28 +1085,36 @@ void blk_remove_aio_context_notifier(BlockBackend *blk,
void (*detach_aio_context)(void *),
void *opaque)
{
bdrv_remove_aio_context_notifier(blk->bs, attached_aio_context,
detach_aio_context, opaque);
if (blk->bs) {
bdrv_remove_aio_context_notifier(blk->bs, attached_aio_context,
detach_aio_context, opaque);
}
}
void blk_add_close_notifier(BlockBackend *blk, Notifier *notify)
{
bdrv_add_close_notifier(blk->bs, notify);
if (blk->bs) {
bdrv_add_close_notifier(blk->bs, notify);
}
}
void blk_io_plug(BlockBackend *blk)
{
bdrv_io_plug(blk->bs);
if (blk->bs) {
bdrv_io_plug(blk->bs);
}
}
void blk_io_unplug(BlockBackend *blk)
{
bdrv_io_unplug(blk->bs);
if (blk->bs) {
bdrv_io_unplug(blk->bs);
}
}
BlockAcctStats *blk_get_stats(BlockBackend *blk)
{
return bdrv_get_stats(blk->bs);
return &blk->stats;
}
void *blk_aio_get(const AIOCBInfo *aiocb_info, BlockBackend *blk,
@@ -902,6 +1147,10 @@ int blk_write_compressed(BlockBackend *blk, int64_t sector_num,
int blk_truncate(BlockBackend *blk, int64_t offset)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_truncate(blk->bs, offset);
}
@@ -918,20 +1167,67 @@ int blk_discard(BlockBackend *blk, int64_t sector_num, int nb_sectors)
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
int64_t pos, int size)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_save_vmstate(blk->bs, buf, pos, size);
}
int blk_load_vmstate(BlockBackend *blk, uint8_t *buf, int64_t pos, int size)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_load_vmstate(blk->bs, buf, pos, size);
}
int blk_probe_blocksizes(BlockBackend *blk, BlockSizes *bsz)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_probe_blocksizes(blk->bs, bsz);
}
int blk_probe_geometry(BlockBackend *blk, HDGeometry *geo)
{
if (!blk_is_available(blk)) {
return -ENOMEDIUM;
}
return bdrv_probe_geometry(blk->bs, geo);
}
/*
* Updates the BlockBackendRootState object with data from the currently
* attached BlockDriverState.
*/
void blk_update_root_state(BlockBackend *blk)
{
assert(blk->bs);
blk->root_state.open_flags = blk->bs->open_flags;
blk->root_state.read_only = blk->bs->read_only;
blk->root_state.detect_zeroes = blk->bs->detect_zeroes;
if (blk->root_state.throttle_group) {
g_free(blk->root_state.throttle_group);
throttle_group_unref(blk->root_state.throttle_state);
}
if (blk->bs->throttle_state) {
const char *name = throttle_group_get_name(blk->bs);
blk->root_state.throttle_group = g_strdup(name);
blk->root_state.throttle_state = throttle_group_incref(name);
} else {
blk->root_state.throttle_group = NULL;
blk->root_state.throttle_state = NULL;
}
}
BlockBackendRootState *blk_get_root_state(BlockBackend *blk)
{
return &blk->root_state;
}

View File

@@ -17,6 +17,7 @@
#include "block/blockjob.h"
#include "qapi/qmp/qerror.h"
#include "qemu/ratelimit.h"
#include "sysemu/block-backend.h"
enum {
/*
@@ -213,7 +214,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
!bdrv_iostatus_is_enabled(bs)) {
(!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
error_setg(errp, "Invalid parameter combination");
return;
}

View File

@@ -154,18 +154,20 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,
DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd);
switch (action) {
case CURL_POLL_IN:
aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
NULL, state);
aio_set_fd_handler(s->aio_context, fd, false,
curl_multi_read, NULL, state);
break;
case CURL_POLL_OUT:
aio_set_fd_handler(s->aio_context, fd, NULL, curl_multi_do, state);
aio_set_fd_handler(s->aio_context, fd, false,
NULL, curl_multi_do, state);
break;
case CURL_POLL_INOUT:
aio_set_fd_handler(s->aio_context, fd, curl_multi_read,
curl_multi_do, state);
aio_set_fd_handler(s->aio_context, fd, false,
curl_multi_read, curl_multi_do, state);
break;
case CURL_POLL_REMOVE:
aio_set_fd_handler(s->aio_context, fd, NULL, NULL, NULL);
aio_set_fd_handler(s->aio_context, fd, false,
NULL, NULL, NULL);
break;
}

View File

@@ -23,6 +23,7 @@
*/
#include "trace.h"
#include "sysemu/block-backend.h"
#include "block/blockjob.h"
#include "block/block_int.h"
#include "block/throttle-groups.h"
@@ -215,6 +216,8 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs)
/* Check if any requests are in-flight (including throttled requests) */
bool bdrv_requests_pending(BlockDriverState *bs)
{
BdrvChild *child;
if (!QLIST_EMPTY(&bs->tracked_requests)) {
return true;
}
@@ -224,12 +227,13 @@ bool bdrv_requests_pending(BlockDriverState *bs)
if (!qemu_co_queue_empty(&bs->throttled_reqs[1])) {
return true;
}
if (bs->file && bdrv_requests_pending(bs->file->bs)) {
return true;
}
if (bs->backing && bdrv_requests_pending(bs->backing->bs)) {
return true;
QLIST_FOREACH(child, &bs->children, next) {
if (bdrv_requests_pending(child->bs)) {
return true;
}
}
return false;
}
@@ -1151,7 +1155,9 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
bdrv_set_dirty(bs, sector_num, nb_sectors);
block_acct_highest_sector(&bs->stats, sector_num, nb_sectors);
if (bs->wr_highest_offset < offset + bytes) {
bs->wr_highest_offset = offset + bytes;
}
if (ret >= 0) {
bs->total_sectors = MAX(bs->total_sectors, sector_num + nb_sectors);
@@ -1903,7 +1909,10 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
}
}
block_acct_merge_done(&bs->stats, BLOCK_ACCT_WRITE, num_reqs - outidx - 1);
if (bs->blk) {
block_acct_merge_done(blk_get_stats(bs->blk), BLOCK_ACCT_WRITE,
num_reqs - outidx - 1);
}
return outidx + 1;
}
@@ -2618,3 +2627,20 @@ void bdrv_flush_io_queue(BlockDriverState *bs)
}
bdrv_start_throttled_reqs(bs);
}
void bdrv_drained_begin(BlockDriverState *bs)
{
if (!bs->quiesce_counter++) {
aio_disable_external(bdrv_get_aio_context(bs));
}
bdrv_drain(bs);
}
void bdrv_drained_end(BlockDriverState *bs)
{
assert(bs->quiesce_counter > 0);
if (--bs->quiesce_counter > 0) {
return;
}
aio_enable_external(bdrv_get_aio_context(bs));
}

View File

@@ -291,8 +291,8 @@ iscsi_set_events(IscsiLun *iscsilun)
int ev = iscsi_which_events(iscsi);
if (ev != iscsilun->events) {
aio_set_fd_handler(iscsilun->aio_context,
iscsi_get_fd(iscsi),
aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsi),
false,
(ev & POLLIN) ? iscsi_process_read : NULL,
(ev & POLLOUT) ? iscsi_process_write : NULL,
iscsilun);
@@ -1280,9 +1280,8 @@ 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);
aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsilun->iscsi),
false, NULL, NULL, NULL);
iscsilun->events = 0;
if (iscsilun->nop_timer) {

View File

@@ -287,7 +287,7 @@ 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);
aio_set_event_notifier(old_context, &s->e, false, NULL);
qemu_bh_delete(s->completion_bh);
}
@@ -296,7 +296,8 @@ void laio_attach_aio_context(void *s_, AioContext *new_context)
struct qemu_laio_state *s = s_;
s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s);
aio_set_event_notifier(new_context, &s->e, qemu_laio_completion_cb);
aio_set_event_notifier(new_context, &s->e, false,
qemu_laio_completion_cb);
}
void *laio_init(void)

View File

@@ -14,6 +14,7 @@
#include "trace.h"
#include "block/blockjob.h"
#include "block/block_int.h"
#include "sysemu/block-backend.h"
#include "qapi/qmp/qerror.h"
#include "qemu/ratelimit.h"
#include "qemu/bitmap.h"
@@ -599,7 +600,9 @@ immediate_exit:
g_free(s->cow_bitmap);
g_free(s->in_flight_bitmap);
bdrv_release_dirty_bitmap(bs, s->dirty_bitmap);
bdrv_iostatus_disable(s->target);
if (s->target->blk) {
blk_iostatus_disable(s->target->blk);
}
data = g_malloc(sizeof(*data));
data->ret = ret;
@@ -621,7 +624,9 @@ static void mirror_iostatus_reset(BlockJob *job)
{
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
bdrv_iostatus_reset(s->target);
if (s->target->blk) {
blk_iostatus_reset(s->target->blk);
}
}
static void mirror_complete(BlockJob *job, Error **errp)
@@ -704,7 +709,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||
on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
!bdrv_iostatus_is_enabled(bs)) {
(!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
error_setg(errp, QERR_INVALID_PARAMETER, "on-source-error");
return;
}
@@ -740,8 +745,10 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
return;
}
bdrv_set_enable_write_cache(s->target, true);
bdrv_set_on_error(s->target, on_target_error, on_target_error);
bdrv_iostatus_enable(s->target);
if (s->target->blk) {
blk_set_on_error(s->target->blk, on_target_error, on_target_error);
blk_iostatus_enable(s->target->blk);
}
s->common.co = qemu_coroutine_create(mirror_run);
trace_mirror_start(bs, s, s->common.co, opaque);
qemu_coroutine_enter(s->common.co, s);

View File

@@ -124,7 +124,7 @@ static int nbd_co_send_request(BlockDriverState *bs,
s->send_coroutine = qemu_coroutine_self();
aio_context = bdrv_get_aio_context(bs);
aio_set_fd_handler(aio_context, s->sock,
aio_set_fd_handler(aio_context, s->sock, false,
nbd_reply_ready, nbd_restart_write, bs);
if (qiov) {
if (!s->is_unix) {
@@ -144,7 +144,8 @@ static int nbd_co_send_request(BlockDriverState *bs,
} else {
rc = nbd_send_request(s->sock, request);
}
aio_set_fd_handler(aio_context, s->sock, nbd_reply_ready, NULL, bs);
aio_set_fd_handler(aio_context, s->sock, false,
nbd_reply_ready, NULL, bs);
s->send_coroutine = NULL;
qemu_co_mutex_unlock(&s->send_mutex);
return rc;
@@ -348,14 +349,15 @@ int nbd_client_co_discard(BlockDriverState *bs, int64_t sector_num,
void nbd_client_detach_aio_context(BlockDriverState *bs)
{
aio_set_fd_handler(bdrv_get_aio_context(bs),
nbd_get_client_session(bs)->sock, NULL, NULL, NULL);
nbd_get_client_session(bs)->sock,
false, NULL, NULL, NULL);
}
void nbd_client_attach_aio_context(BlockDriverState *bs,
AioContext *new_context)
{
aio_set_fd_handler(new_context, nbd_get_client_session(bs)->sock,
nbd_reply_ready, NULL, bs);
false, nbd_reply_ready, NULL, bs);
}
void nbd_client_close(BlockDriverState *bs)

View File

@@ -206,24 +206,24 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, char **export,
saddr = g_new0(SocketAddress, 1);
if (qdict_haskey(options, "path")) {
saddr->kind = SOCKET_ADDRESS_KIND_UNIX;
saddr->q_unix = g_new0(UnixSocketAddress, 1);
saddr->q_unix->path = g_strdup(qdict_get_str(options, "path"));
saddr->type = SOCKET_ADDRESS_KIND_UNIX;
saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
saddr->u.q_unix->path = g_strdup(qdict_get_str(options, "path"));
qdict_del(options, "path");
} else {
saddr->kind = SOCKET_ADDRESS_KIND_INET;
saddr->inet = g_new0(InetSocketAddress, 1);
saddr->inet->host = g_strdup(qdict_get_str(options, "host"));
saddr->type = SOCKET_ADDRESS_KIND_INET;
saddr->u.inet = g_new0(InetSocketAddress, 1);
saddr->u.inet->host = g_strdup(qdict_get_str(options, "host"));
if (!qdict_get_try_str(options, "port")) {
saddr->inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
saddr->u.inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
} else {
saddr->inet->port = g_strdup(qdict_get_str(options, "port"));
saddr->u.inet->port = g_strdup(qdict_get_str(options, "port"));
}
qdict_del(options, "host");
qdict_del(options, "port");
}
s->client.is_unix = saddr->kind == SOCKET_ADDRESS_KIND_UNIX;
s->client.is_unix = saddr->type == SOCKET_ADDRESS_KIND_UNIX;
*export = g_strdup(qdict_get_try_str(options, "export"));
if (*export) {

View File

@@ -63,11 +63,10 @@ static void nfs_set_events(NFSClient *client)
{
int ev = nfs_which_events(client->context);
if (ev != client->events) {
aio_set_fd_handler(client->aio_context,
nfs_get_fd(client->context),
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
false,
(ev & POLLIN) ? nfs_process_read : NULL,
(ev & POLLOUT) ? nfs_process_write : NULL,
client);
(ev & POLLOUT) ? nfs_process_write : NULL, client);
}
client->events = ev;
@@ -242,9 +241,8 @@ 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);
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
false, NULL, NULL, NULL);
client->events = 0;
}
@@ -263,9 +261,8 @@ static void nfs_client_close(NFSClient *client)
if (client->fh) {
nfs_close(client->context, client->fh);
}
aio_set_fd_handler(client->aio_context,
nfs_get_fd(client->context),
NULL, NULL, NULL);
aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context),
false, NULL, NULL, NULL);
nfs_destroy_context(client->context);
}
memset(client, 0, sizeof(NFSClient));

View File

@@ -301,17 +301,17 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
info->tray_open = blk_dev_is_tray_open(blk);
}
if (bdrv_iostatus_is_enabled(bs)) {
if (blk_iostatus_is_enabled(blk)) {
info->has_io_status = true;
info->io_status = bs->iostatus;
info->io_status = blk_iostatus(blk);
}
if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
if (bs && !QLIST_EMPTY(&bs->dirty_bitmaps)) {
info->has_dirty_bitmaps = true;
info->dirty_bitmaps = bdrv_query_dirty_bitmaps(bs);
}
if (bs->drv) {
if (bs && bs->drv) {
info->has_inserted = true;
info->inserted = bdrv_block_device_info(bs, errp);
if (info->inserted == NULL) {
@@ -344,18 +344,22 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs,
}
s->stats = g_malloc0(sizeof(*s->stats));
s->stats->rd_bytes = bs->stats.nr_bytes[BLOCK_ACCT_READ];
s->stats->wr_bytes = bs->stats.nr_bytes[BLOCK_ACCT_WRITE];
s->stats->rd_operations = bs->stats.nr_ops[BLOCK_ACCT_READ];
s->stats->wr_operations = bs->stats.nr_ops[BLOCK_ACCT_WRITE];
s->stats->rd_merged = bs->stats.merged[BLOCK_ACCT_READ];
s->stats->wr_merged = bs->stats.merged[BLOCK_ACCT_WRITE];
s->stats->wr_highest_offset =
bs->stats.wr_highest_sector * BDRV_SECTOR_SIZE;
s->stats->flush_operations = bs->stats.nr_ops[BLOCK_ACCT_FLUSH];
s->stats->wr_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_WRITE];
s->stats->rd_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_READ];
s->stats->flush_total_time_ns = bs->stats.total_time_ns[BLOCK_ACCT_FLUSH];
if (bs->blk) {
BlockAcctStats *stats = blk_get_stats(bs->blk);
s->stats->rd_bytes = stats->nr_bytes[BLOCK_ACCT_READ];
s->stats->wr_bytes = stats->nr_bytes[BLOCK_ACCT_WRITE];
s->stats->rd_operations = stats->nr_ops[BLOCK_ACCT_READ];
s->stats->wr_operations = stats->nr_ops[BLOCK_ACCT_WRITE];
s->stats->rd_merged = stats->merged[BLOCK_ACCT_READ];
s->stats->wr_merged = stats->merged[BLOCK_ACCT_WRITE];
s->stats->flush_operations = stats->nr_ops[BLOCK_ACCT_FLUSH];
s->stats->wr_total_time_ns = stats->total_time_ns[BLOCK_ACCT_WRITE];
s->stats->rd_total_time_ns = stats->total_time_ns[BLOCK_ACCT_READ];
s->stats->flush_total_time_ns = stats->total_time_ns[BLOCK_ACCT_FLUSH];
}
s->stats->wr_highest_offset = bs->wr_highest_offset;
if (bs->file) {
s->has_parent = true;

View File

@@ -2738,18 +2738,16 @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs)
ImageInfoSpecific *spec_info = g_new(ImageInfoSpecific, 1);
*spec_info = (ImageInfoSpecific){
.kind = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
{
.qcow2 = g_new(ImageInfoSpecificQCow2, 1),
},
.type = IMAGE_INFO_SPECIFIC_KIND_QCOW2,
.u.qcow2 = g_new(ImageInfoSpecificQCow2, 1),
};
if (s->qcow_version == 2) {
*spec_info->qcow2 = (ImageInfoSpecificQCow2){
*spec_info->u.qcow2 = (ImageInfoSpecificQCow2){
.compat = g_strdup("0.10"),
.refcount_bits = s->refcount_bits,
};
} else if (s->qcow_version == 3) {
*spec_info->qcow2 = (ImageInfoSpecificQCow2){
*spec_info->u.qcow2 = (ImageInfoSpecificQCow2){
.compat = g_strdup("1.1"),
.lazy_refcounts = s->compatible_features &
QCOW2_COMPAT_LAZY_REFCOUNTS,

View File

@@ -127,11 +127,6 @@ do { \
#define FTYPE_FILE 0
#define FTYPE_CD 1
#define FTYPE_FD 2
/* if the FD is not accessed during that time (in ns), we try to
reopen it to see if the disk has been changed */
#define FD_OPEN_TIMEOUT (1000000000)
#define MAX_BLOCKSIZE 4096
@@ -141,13 +136,6 @@ typedef struct BDRVRawState {
int open_flags;
size_t buf_align;
#if defined(__linux__)
/* linux floppy specific */
int64_t fd_open_time;
int64_t fd_error_time;
int fd_got_error;
int fd_media_changed;
#endif
#ifdef CONFIG_LINUX_AIO
int use_aio;
void *aio_ctx;
@@ -635,7 +623,7 @@ static int raw_reopen_prepare(BDRVReopenState *state,
}
#endif
if (s->type == FTYPE_FD || s->type == FTYPE_CD) {
if (s->type == FTYPE_CD) {
raw_s->open_flags |= O_NONBLOCK;
}
@@ -2187,47 +2175,6 @@ static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
}
#if defined(__linux__)
/* Note: we do not have a reliable method to detect if the floppy is
present. The current method is to try to open the floppy at every
I/O and to keep it opened during a few hundreds of ms. */
static int fd_open(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
int last_media_present;
if (s->type != FTYPE_FD)
return 0;
last_media_present = (s->fd >= 0);
if (s->fd >= 0 &&
(qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
qemu_close(s->fd);
s->fd = -1;
DPRINTF("Floppy closed\n");
}
if (s->fd < 0) {
if (s->fd_got_error &&
(qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
DPRINTF("No floppy (open delayed)\n");
return -EIO;
}
s->fd = qemu_open(bs->filename, s->open_flags & ~O_NONBLOCK);
if (s->fd < 0) {
s->fd_error_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
s->fd_got_error = 1;
if (last_media_present)
s->fd_media_changed = 1;
DPRINTF("No floppy\n");
return -EIO;
}
DPRINTF("Floppy opened\n");
}
if (!last_media_present)
s->fd_media_changed = 1;
s->fd_open_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
s->fd_got_error = 0;
return 0;
}
static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
{
BDRVRawState *s = bs->opaque;
@@ -2256,8 +2203,8 @@ static BlockAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
}
#endif /* linux */
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int fd_open(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
@@ -2267,14 +2214,6 @@ static int fd_open(BlockDriverState *bs)
return 0;
return -EIO;
}
#else /* !linux && !FreeBSD */
static int fd_open(BlockDriverState *bs)
{
return 0;
}
#endif /* !linux && !FreeBSD */
static coroutine_fn BlockAIOCB *hdev_aio_discard(BlockDriverState *bs,
int64_t sector_num, int nb_sectors,
@@ -2318,14 +2257,13 @@ static int hdev_create(const char *filename, QemuOpts *opts,
int64_t total_size = 0;
bool has_prefix;
/* This function is used by all three protocol block drivers and therefore
* any of these three prefixes may be given.
/* This function is used by both protocol block drivers and therefore either
* of these prefixes may be given.
* The return value has to be stored somewhere, otherwise this is an error
* due to -Werror=unused-value. */
has_prefix =
strstart(filename, "host_device:", &filename) ||
strstart(filename, "host_cdrom:" , &filename) ||
strstart(filename, "host_floppy:", &filename);
strstart(filename, "host_cdrom:" , &filename);
(void)has_prefix;
@@ -2405,155 +2343,6 @@ static BlockDriver bdrv_host_device = {
#endif
};
#ifdef __linux__
static void floppy_parse_filename(const char *filename, QDict *options,
Error **errp)
{
/* The prefix is optional, just as for "file". */
strstart(filename, "host_floppy:", &filename);
qdict_put_obj(options, "filename", QOBJECT(qstring_from_str(filename)));
}
static int floppy_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVRawState *s = bs->opaque;
Error *local_err = NULL;
int ret;
s->type = FTYPE_FD;
/* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
ret = raw_open_common(bs, options, flags, O_NONBLOCK, &local_err);
if (ret) {
if (local_err) {
error_propagate(errp, local_err);
}
return ret;
}
/* close fd so that we can reopen it as needed */
qemu_close(s->fd);
s->fd = -1;
s->fd_media_changed = 1;
error_report("Host floppy pass-through is deprecated");
error_printf("Support for it will be removed in a future release.\n");
return 0;
}
static int floppy_probe_device(const char *filename)
{
int fd, ret;
int prio = 0;
struct floppy_struct fdparam;
struct stat st;
if (strstart(filename, "/dev/fd", NULL) &&
!strstart(filename, "/dev/fdset/", NULL) &&
!strstart(filename, "/dev/fd/", NULL)) {
prio = 50;
}
fd = qemu_open(filename, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
goto out;
}
ret = fstat(fd, &st);
if (ret == -1 || !S_ISBLK(st.st_mode)) {
goto outc;
}
/* Attempt to detect via a floppy specific ioctl */
ret = ioctl(fd, FDGETPRM, &fdparam);
if (ret >= 0)
prio = 100;
outc:
qemu_close(fd);
out:
return prio;
}
static int floppy_is_inserted(BlockDriverState *bs)
{
return fd_open(bs) >= 0;
}
static int floppy_media_changed(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
int ret;
/*
* XXX: we do not have a true media changed indication.
* It does not work if the floppy is changed without trying to read it.
*/
fd_open(bs);
ret = s->fd_media_changed;
s->fd_media_changed = 0;
DPRINTF("Floppy changed=%d\n", ret);
return ret;
}
static void floppy_eject(BlockDriverState *bs, bool eject_flag)
{
BDRVRawState *s = bs->opaque;
int fd;
if (s->fd >= 0) {
qemu_close(s->fd);
s->fd = -1;
}
fd = qemu_open(bs->filename, s->open_flags | O_NONBLOCK);
if (fd >= 0) {
if (ioctl(fd, FDEJECT, 0) < 0)
perror("FDEJECT");
qemu_close(fd);
}
}
static BlockDriver bdrv_host_floppy = {
.format_name = "host_floppy",
.protocol_name = "host_floppy",
.instance_size = sizeof(BDRVRawState),
.bdrv_needs_filename = true,
.bdrv_probe_device = floppy_probe_device,
.bdrv_parse_filename = floppy_parse_filename,
.bdrv_file_open = floppy_open,
.bdrv_close = raw_close,
.bdrv_reopen_prepare = raw_reopen_prepare,
.bdrv_reopen_commit = raw_reopen_commit,
.bdrv_reopen_abort = raw_reopen_abort,
.bdrv_create = hdev_create,
.create_opts = &raw_create_opts,
.bdrv_aio_readv = raw_aio_readv,
.bdrv_aio_writev = raw_aio_writev,
.bdrv_aio_flush = raw_aio_flush,
.bdrv_refresh_limits = raw_refresh_limits,
.bdrv_io_plug = raw_aio_plug,
.bdrv_io_unplug = raw_aio_unplug,
.bdrv_flush_io_queue = raw_aio_flush_io_queue,
.bdrv_truncate = raw_truncate,
.bdrv_getlength = raw_getlength,
.has_variable_length = true,
.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,
.bdrv_eject = floppy_eject,
};
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static void cdrom_parse_filename(const char *filename, QDict *options,
Error **errp)
@@ -2609,15 +2398,13 @@ out:
return prio;
}
static int cdrom_is_inserted(BlockDriverState *bs)
static bool cdrom_is_inserted(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
int ret;
ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
if (ret == CDS_DISC_OK)
return 1;
return 0;
return ret == CDS_DISC_OK;
}
static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
@@ -2743,7 +2530,7 @@ static int cdrom_reopen(BlockDriverState *bs)
return 0;
}
static int cdrom_is_inserted(BlockDriverState *bs)
static bool cdrom_is_inserted(BlockDriverState *bs)
{
return raw_getlength(bs) > 0;
}
@@ -2831,7 +2618,6 @@ static void bdrv_file_init(void)
bdrv_register(&bdrv_file);
bdrv_register(&bdrv_host_device);
#ifdef __linux__
bdrv_register(&bdrv_host_floppy);
bdrv_register(&bdrv_host_cdrom);
#endif
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)

View File

@@ -154,11 +154,6 @@ static int raw_truncate(BlockDriverState *bs, int64_t offset)
return bdrv_truncate(bs->file->bs, offset);
}
static int raw_is_inserted(BlockDriverState *bs)
{
return bdrv_is_inserted(bs->file->bs);
}
static int raw_media_changed(BlockDriverState *bs)
{
return bdrv_media_changed(bs->file->bs);
@@ -264,7 +259,6 @@ BlockDriver bdrv_raw = {
.bdrv_refresh_limits = &raw_refresh_limits,
.bdrv_probe_blocksizes = &raw_probe_blocksizes,
.bdrv_probe_geometry = &raw_probe_geometry,
.bdrv_is_inserted = &raw_is_inserted,
.bdrv_media_changed = &raw_media_changed,
.bdrv_eject = &raw_eject,
.bdrv_lock_medium = &raw_lock_medium,

View File

@@ -651,14 +651,16 @@ static coroutine_fn void do_co_req(void *opaque)
unsigned int *rlen = srco->rlen;
co = qemu_coroutine_self();
aio_set_fd_handler(srco->aio_context, sockfd, NULL, restart_co_req, co);
aio_set_fd_handler(srco->aio_context, sockfd, false,
NULL, restart_co_req, co);
ret = send_co_req(sockfd, hdr, data, wlen);
if (ret < 0) {
goto out;
}
aio_set_fd_handler(srco->aio_context, sockfd, restart_co_req, NULL, co);
aio_set_fd_handler(srco->aio_context, sockfd, false,
restart_co_req, NULL, co);
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
if (ret != sizeof(*hdr)) {
@@ -683,7 +685,8 @@ 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. */
aio_set_fd_handler(srco->aio_context, sockfd, NULL, NULL, NULL);
aio_set_fd_handler(srco->aio_context, sockfd, false,
NULL, NULL, NULL);
srco->ret = ret;
srco->finished = true;
@@ -735,7 +738,8 @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
BDRVSheepdogState *s = opaque;
AIOReq *aio_req, *next;
aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
aio_set_fd_handler(s->aio_context, s->fd, false, NULL,
NULL, NULL);
close(s->fd);
s->fd = -1;
@@ -938,7 +942,8 @@ static int get_sheep_fd(BDRVSheepdogState *s, Error **errp)
return fd;
}
aio_set_fd_handler(s->aio_context, fd, co_read_response, NULL, s);
aio_set_fd_handler(s->aio_context, fd, false,
co_read_response, NULL, s);
return fd;
}
@@ -1199,7 +1204,7 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
qemu_co_mutex_lock(&s->lock);
s->co_send = qemu_coroutine_self();
aio_set_fd_handler(s->aio_context, s->fd,
aio_set_fd_handler(s->aio_context, s->fd, false,
co_read_response, co_write_request, s);
socket_set_cork(s->fd, 1);
@@ -1218,7 +1223,8 @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
}
out:
socket_set_cork(s->fd, 0);
aio_set_fd_handler(s->aio_context, s->fd, co_read_response, NULL, s);
aio_set_fd_handler(s->aio_context, s->fd, false,
co_read_response, NULL, s);
s->co_send = NULL;
qemu_co_mutex_unlock(&s->lock);
}
@@ -1368,7 +1374,8 @@ static void sd_detach_aio_context(BlockDriverState *bs)
{
BDRVSheepdogState *s = bs->opaque;
aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
aio_set_fd_handler(s->aio_context, s->fd, false, NULL,
NULL, NULL);
}
static void sd_attach_aio_context(BlockDriverState *bs,
@@ -1377,7 +1384,8 @@ static void sd_attach_aio_context(BlockDriverState *bs,
BDRVSheepdogState *s = bs->opaque;
s->aio_context = new_context;
aio_set_fd_handler(new_context, s->fd, co_read_response, NULL, s);
aio_set_fd_handler(new_context, s->fd, false,
co_read_response, NULL, s);
}
/* TODO Convert to fine grained options */
@@ -1490,7 +1498,8 @@ static int sd_open(BlockDriverState *bs, QDict *options, int flags,
g_free(buf);
return 0;
out:
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd,
false, NULL, NULL, NULL);
if (s->fd >= 0) {
closesocket(s->fd);
}
@@ -1528,7 +1537,8 @@ static void sd_reopen_commit(BDRVReopenState *state)
BDRVSheepdogState *s = state->bs->opaque;
if (s->fd) {
aio_set_fd_handler(s->aio_context, s->fd, NULL, NULL, NULL);
aio_set_fd_handler(s->aio_context, s->fd, false,
NULL, NULL, NULL);
closesocket(s->fd);
}
@@ -1551,7 +1561,8 @@ static void sd_reopen_abort(BDRVReopenState *state)
}
if (re_s->fd) {
aio_set_fd_handler(s->aio_context, re_s->fd, NULL, NULL, NULL);
aio_set_fd_handler(s->aio_context, re_s->fd, false,
NULL, NULL, NULL);
closesocket(re_s->fd);
}
@@ -1935,7 +1946,8 @@ static void sd_close(BlockDriverState *bs)
error_report("%s, %s", sd_strerror(rsp->result), s->name);
}
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd, NULL, NULL, NULL);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->fd,
false, NULL, NULL, NULL);
closesocket(s->fd);
g_free(s->host_spec);
}

View File

@@ -800,14 +800,15 @@ static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs)
rd_handler, wr_handler);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
rd_handler, wr_handler, co);
false, rd_handler, wr_handler, co);
}
static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
BlockDriverState *bs)
{
DPRINTF("s->sock=%d", s->sock);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, NULL, NULL, NULL);
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
false, NULL, NULL, NULL);
}
/* A non-blocking call returned EAGAIN, so yield, ensuring the

View File

@@ -16,6 +16,7 @@
#include "block/blockjob.h"
#include "qapi/qmp/qerror.h"
#include "qemu/ratelimit.h"
#include "sysemu/block-backend.h"
enum {
/*
@@ -222,7 +223,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
!bdrv_iostatus_is_enabled(bs)) {
(!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
error_setg(errp, QERR_INVALID_PARAMETER, "on-error");
return;
}

View File

@@ -33,8 +33,7 @@
* its own locking.
*
* This locking is however handled internally in this file, so it's
* mostly transparent to outside users (but see the documentation in
* throttle_groups_lock()).
* transparent to outside users.
*
* The whole ThrottleGroup structure is private and invisible to
* outside users, that only use it through its ThrottleState.
@@ -76,9 +75,9 @@ static QTAILQ_HEAD(, ThrottleGroup) throttle_groups =
* created.
*
* @name: the name of the ThrottleGroup
* @ret: the ThrottleGroup
* @ret: the ThrottleState member of the ThrottleGroup
*/
static ThrottleGroup *throttle_group_incref(const char *name)
ThrottleState *throttle_group_incref(const char *name)
{
ThrottleGroup *tg = NULL;
ThrottleGroup *iter;
@@ -108,7 +107,7 @@ static ThrottleGroup *throttle_group_incref(const char *name)
qemu_mutex_unlock(&throttle_groups_lock);
return tg;
return &tg->ts;
}
/* Decrease the reference count of a ThrottleGroup.
@@ -116,10 +115,12 @@ static ThrottleGroup *throttle_group_incref(const char *name)
* When the reference count reaches zero the ThrottleGroup is
* destroyed.
*
* @tg: The ThrottleGroup to unref
* @ts: The ThrottleGroup to unref, given by its ThrottleState member
*/
static void throttle_group_unref(ThrottleGroup *tg)
void throttle_group_unref(ThrottleState *ts)
{
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
qemu_mutex_lock(&throttle_groups_lock);
if (--tg->refcount == 0) {
QTAILQ_REMOVE(&throttle_groups, tg, list);
@@ -401,7 +402,8 @@ static void write_timer_cb(void *opaque)
void throttle_group_register_bs(BlockDriverState *bs, const char *groupname)
{
int i;
ThrottleGroup *tg = throttle_group_incref(groupname);
ThrottleState *ts = throttle_group_incref(groupname);
ThrottleGroup *tg = container_of(ts, ThrottleGroup, ts);
int clock_type = QEMU_CLOCK_REALTIME;
if (qtest_enabled()) {
@@ -409,7 +411,7 @@ void throttle_group_register_bs(BlockDriverState *bs, const char *groupname)
clock_type = QEMU_CLOCK_VIRTUAL;
}
bs->throttle_state = &tg->ts;
bs->throttle_state = ts;
qemu_mutex_lock(&tg->lock);
/* If the ThrottleGroup is new set this BlockDriverState as the token */
@@ -461,38 +463,10 @@ void throttle_group_unregister_bs(BlockDriverState *bs)
throttle_timers_destroy(&bs->throttle_timers);
qemu_mutex_unlock(&tg->lock);
throttle_group_unref(tg);
throttle_group_unref(&tg->ts);
bs->throttle_state = NULL;
}
/* Acquire the lock of this throttling group.
*
* You won't normally need to use this. None of the functions from the
* ThrottleGroup API require you to acquire the lock since all of them
* deal with it internally.
*
* This should only be used in exceptional cases when you want to
* access the protected fields of a BlockDriverState directly
* (e.g. bdrv_swap()).
*
* @bs: a BlockDriverState that is member of the group
*/
void throttle_group_lock(BlockDriverState *bs)
{
ThrottleGroup *tg = container_of(bs->throttle_state, ThrottleGroup, ts);
qemu_mutex_lock(&tg->lock);
}
/* Release the lock of this throttling group.
*
* See the comments in throttle_group_lock().
*/
void throttle_group_unlock(BlockDriverState *bs)
{
ThrottleGroup *tg = container_of(bs->throttle_state, ThrottleGroup, ts);
qemu_mutex_unlock(&tg->lock);
}
static void throttle_groups_init(void)
{
qemu_mutex_init(&throttle_groups_lock);

View File

@@ -2161,19 +2161,19 @@ static ImageInfoSpecific *vmdk_get_specific_info(BlockDriverState *bs)
ImageInfoList **next;
*spec_info = (ImageInfoSpecific){
.kind = IMAGE_INFO_SPECIFIC_KIND_VMDK,
.type = IMAGE_INFO_SPECIFIC_KIND_VMDK,
{
.vmdk = g_new0(ImageInfoSpecificVmdk, 1),
},
};
*spec_info->vmdk = (ImageInfoSpecificVmdk) {
*spec_info->u.vmdk = (ImageInfoSpecificVmdk) {
.create_type = g_strdup(s->create_type),
.cid = s->cid,
.parent_cid = s->parent_cid,
};
next = &spec_info->vmdk->extents;
next = &spec_info->u.vmdk->extents;
for (i = 0; i < s->num_extents; i++) {
*next = g_new0(ImageInfoList, 1);
(*next)->value = vmdk_get_extent_info(&s->extents[i]);

View File

@@ -174,7 +174,7 @@ 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_set_event_notifier(old_context, &aio->e, false, NULL);
aio->is_aio_context_attached = false;
}
@@ -182,7 +182,8 @@ 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);
aio_set_event_notifier(new_context, &aio->e, false,
win32_aio_completion_cb);
}
QEMUWin32AIOState *win32_aio_init(void)

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@
#include "block/block.h"
#include "block/blockjob.h"
#include "block/block_int.h"
#include "sysemu/block-backend.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qjson.h"
#include "qemu/coroutine.h"
@@ -354,8 +355,8 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
job->user_paused = true;
block_job_pause(job);
block_job_iostatus_set_err(job, error);
if (bs != job->bs) {
bdrv_iostatus_set_err(bs, error);
if (bs->blk && bs != job->bs) {
blk_iostatus_set_err(bs->blk, error);
}
}
return action;

132
configure vendored
View File

@@ -331,6 +331,8 @@ gtkabi=""
gtk_gl="no"
gnutls=""
gnutls_hash=""
nettle=""
gcrypt=""
vte=""
virglrenderer=""
tpm="yes"
@@ -417,9 +419,6 @@ if test "$debug_info" = "yes"; then
LDFLAGS="-g $LDFLAGS"
fi
test_cflags=""
test_libs=""
# make source path absolute
source_path=`cd "$source_path"; pwd`
@@ -1114,6 +1113,14 @@ for opt do
;;
--enable-gnutls) gnutls="yes"
;;
--disable-nettle) nettle="no"
;;
--enable-nettle) nettle="yes"
;;
--disable-gcrypt) gcrypt="no"
;;
--enable-gcrypt) gcrypt="yes"
;;
--enable-rdma) rdma="yes"
;;
--disable-rdma) rdma="no"
@@ -1324,6 +1331,8 @@ disabled with --disable-FEATURE, default is enabled if available:
sparse sparse checker
gnutls GNUTLS cryptography support
nettle nettle cryptography support
gcrypt libgcrypt cryptography support
sdl SDL UI
--with-sdlabi select preferred SDL ABI 1.2 or 2.0
gtk gtk UI
@@ -2254,20 +2263,76 @@ else
gnutls_hash="no"
fi
if test "$gnutls_gcrypt" != "no"; then
if has "libgcrypt-config"; then
# If user didn't give a --disable/enable-gcrypt flag,
# then mark as disabled if user requested nettle
# explicitly, or if gnutls links to nettle
if test -z "$gcrypt"
then
if test "$nettle" = "yes" || test "$gnutls_nettle" = "yes"
then
gcrypt="no"
fi
fi
# If user didn't give a --disable/enable-nettle flag,
# then mark as disabled if user requested gcrypt
# explicitly, or if gnutls links to gcrypt
if test -z "$nettle"
then
if test "$gcrypt" = "yes" || test "$gnutls_gcrypt" = "yes"
then
nettle="no"
fi
fi
has_libgcrypt_config() {
if ! has "libgcrypt-config"
then
return 1
fi
if test -n "$cross_prefix"
then
host=`libgcrypt-config --host`
if test "$host-" != $cross_prefix
then
return 1
fi
fi
return 0
}
if test "$gcrypt" != "no"; then
if has_libgcrypt_config; then
gcrypt_cflags=`libgcrypt-config --cflags`
gcrypt_libs=`libgcrypt-config --libs`
# Debian has remove -lgpg-error from libgcrypt-config
# as it "spreads unnecessary dependencies" which in
# turn breaks static builds...
if test "$static" = "yes"
then
gcrypt_libs="$gcrypt_libs -lgpg-error"
fi
libs_softmmu="$gcrypt_libs $libs_softmmu"
libs_tools="$gcrypt_libs $libs_tools"
QEMU_CFLAGS="$QEMU_CFLAGS $gcrypt_cflags"
gcrypt="yes"
if test -z "$nettle"; then
nettle="no"
fi
else
feature_not_found "gcrypt" "Install gcrypt devel"
if test "$gcrypt" = "yes"; then
feature_not_found "gcrypt" "Install gcrypt devel"
else
gcrypt="no"
fi
fi
fi
if test "$gnutls_nettle" != "no"; then
if test "$nettle" != "no"; then
if $pkg_config --exists "nettle"; then
nettle_cflags=`$pkg_config --cflags nettle`
nettle_libs=`$pkg_config --libs nettle`
@@ -2275,20 +2340,30 @@ if test "$gnutls_nettle" != "no"; then
libs_softmmu="$nettle_libs $libs_softmmu"
libs_tools="$nettle_libs $libs_tools"
QEMU_CFLAGS="$QEMU_CFLAGS $nettle_cflags"
nettle="yes"
else
feature_not_found "nettle" "Install nettle devel"
if test "$nettle" = "yes"; then
feature_not_found "nettle" "Install nettle devel"
else
nettle="no"
fi
fi
fi
if test "$gcrypt" = "yes" && test "$nettle" = "yes"
then
error_exit "Only one of gcrypt & nettle can be enabled"
fi
##########################################
# libtasn1 - only for the TLS creds/session test suite
tasn1=yes
tasn1_cflags=""
tasn1_libs=""
if $pkg_config --exists "libtasn1"; then
tasn1_cflags=`$pkg_config --cflags libtasn1`
tasn1_libs=`$pkg_config --libs libtasn1`
test_cflags="$test_cflags $tasn1_cflags"
test_libs="$test_libs $tasn1_libs"
else
tasn1=no
fi
@@ -3211,25 +3286,11 @@ fi
libs_softmmu="$libs_softmmu $fdt_libs"
##########################################
# opengl probe (for sdl2, milkymist-tmu2)
# GLX probe, used by milkymist-tmu2
# this is temporary, code will be switched to egl mid-term.
cat > $TMPC << EOF
#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
int main(void) { glBegin(0); glXQueryVersion(0,0,0); return 0; }
EOF
if compile_prog "" "-lGL -lX11" ; then
have_glx=yes
else
have_glx=no
fi
# opengl probe (for sdl2, gtk, milkymist-tmu2)
if test "$opengl" != "no" ; then
opengl_pkgs="gl glesv2 epoxy egl"
if $pkg_config $opengl_pkgs x11 && test "$have_glx" = "yes"; then
opengl_pkgs="epoxy"
if $pkg_config $opengl_pkgs x11; then
opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags"
opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs"
opengl=yes
@@ -4433,6 +4494,7 @@ if test "$want_tools" = "yes" ; then
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
tools="qemu-nbd\$(EXESUF) $tools"
tools="ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools"
fi
fi
if test "$softmmu" = yes ; then
@@ -4621,8 +4683,8 @@ echo "GTK support $gtk"
echo "GTK GL support $gtk_gl"
echo "GNUTLS support $gnutls"
echo "GNUTLS hash $gnutls_hash"
echo "GNUTLS gcrypt $gnutls_gcrypt"
echo "GNUTLS nettle $gnutls_nettle ${gnutls_nettle+($nettle_version)}"
echo "libgcrypt $gcrypt"
echo "nettle $nettle ${nettle+($nettle_version)}"
echo "libtasn1 $tasn1"
echo "VTE support $vte"
echo "curses support $curses"
@@ -4991,11 +5053,11 @@ fi
if test "$gnutls_hash" = "yes" ; then
echo "CONFIG_GNUTLS_HASH=y" >> $config_host_mak
fi
if test "$gnutls_gcrypt" = "yes" ; then
echo "CONFIG_GNUTLS_GCRYPT=y" >> $config_host_mak
if test "$gcrypt" = "yes" ; then
echo "CONFIG_GCRYPT=y" >> $config_host_mak
fi
if test "$gnutls_nettle" = "yes" ; then
echo "CONFIG_GNUTLS_NETTLE=y" >> $config_host_mak
if test "$nettle" = "yes" ; then
echo "CONFIG_NETTLE=y" >> $config_host_mak
echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak
fi
if test "$tasn1" = "yes" ; then
@@ -5330,8 +5392,8 @@ echo "EXESUF=$EXESUF" >> $config_host_mak
echo "DSOSUF=$DSOSUF" >> $config_host_mak
echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak
echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
echo "TEST_LIBS=$test_libs" >> $config_host_mak
echo "TEST_CFLAGS=$test_cflags" >> $config_host_mak
echo "TASN1_LIBS=$tasn1_libs" >> $config_host_mak
echo "TASN1_CFLAGS=$tasn1_cflags" >> $config_host_mak
echo "POD2MAN=$POD2MAN" >> $config_host_mak
echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak
if test "$gcov" = "yes" ; then

View File

@@ -0,0 +1 @@
ivshmem-client-obj-y = ivshmem-client.o main.o

View File

@@ -0,0 +1,446 @@
/*
* Copyright 6WIND S.A., 2014
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "qemu-common.h"
#include "qemu/queue.h"
#include "ivshmem-client.h"
/* log a message on stdout if verbose=1 */
#define IVSHMEM_CLIENT_DEBUG(client, fmt, ...) do { \
if ((client)->verbose) { \
printf(fmt, ## __VA_ARGS__); \
} \
} while (0)
/* read message from the unix socket */
static int
ivshmem_client_read_one_msg(IvshmemClient *client, int64_t *index, int *fd)
{
int ret;
struct msghdr msg;
struct iovec iov[1];
union {
struct cmsghdr cmsg;
char control[CMSG_SPACE(sizeof(int))];
} msg_control;
struct cmsghdr *cmsg;
iov[0].iov_base = index;
iov[0].iov_len = sizeof(*index);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = &msg_control;
msg.msg_controllen = sizeof(msg_control);
ret = recvmsg(client->sock_fd, &msg, 0);
if (ret < sizeof(*index)) {
IVSHMEM_CLIENT_DEBUG(client, "cannot read message: %s\n",
strerror(errno));
return -1;
}
if (ret == 0) {
IVSHMEM_CLIENT_DEBUG(client, "lost connection to server\n");
return -1;
}
*index = GINT64_FROM_LE(*index);
*fd = -1;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) {
continue;
}
memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
}
return 0;
}
/* free a peer when the server advertises a disconnection or when the
* client is freed */
static void
ivshmem_client_free_peer(IvshmemClient *client, IvshmemClientPeer *peer)
{
unsigned vector;
QTAILQ_REMOVE(&client->peer_list, peer, next);
for (vector = 0; vector < peer->vectors_count; vector++) {
close(peer->vectors[vector]);
}
g_free(peer);
}
/* handle message coming from server (new peer, new vectors) */
static int
ivshmem_client_handle_server_msg(IvshmemClient *client)
{
IvshmemClientPeer *peer;
int64_t peer_id;
int ret, fd;
ret = ivshmem_client_read_one_msg(client, &peer_id, &fd);
if (ret < 0) {
return -1;
}
/* can return a peer or the local client */
peer = ivshmem_client_search_peer(client, peer_id);
/* delete peer */
if (fd == -1) {
if (peer == NULL || peer == &client->local) {
IVSHMEM_CLIENT_DEBUG(client, "receive delete for invalid "
"peer %" PRId64 "\n", peer_id);
return -1;
}
IVSHMEM_CLIENT_DEBUG(client, "delete peer id = %" PRId64 "\n", peer_id);
ivshmem_client_free_peer(client, peer);
return 0;
}
/* new peer */
if (peer == NULL) {
peer = g_malloc0(sizeof(*peer));
peer->id = peer_id;
peer->vectors_count = 0;
QTAILQ_INSERT_TAIL(&client->peer_list, peer, next);
IVSHMEM_CLIENT_DEBUG(client, "new peer id = %" PRId64 "\n", peer_id);
}
/* new vector */
IVSHMEM_CLIENT_DEBUG(client, " new vector %d (fd=%d) for peer id %"
PRId64 "\n", peer->vectors_count, fd, peer->id);
if (peer->vectors_count >= G_N_ELEMENTS(peer->vectors)) {
IVSHMEM_CLIENT_DEBUG(client, "Too many vectors received, failing");
return -1;
}
peer->vectors[peer->vectors_count] = fd;
peer->vectors_count++;
return 0;
}
/* init a new ivshmem client */
int
ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
IvshmemClientNotifCb notif_cb, void *notif_arg,
bool verbose)
{
int ret;
unsigned i;
memset(client, 0, sizeof(*client));
ret = snprintf(client->unix_sock_path, sizeof(client->unix_sock_path),
"%s", unix_sock_path);
if (ret < 0 || ret >= sizeof(client->unix_sock_path)) {
IVSHMEM_CLIENT_DEBUG(client, "could not copy unix socket path\n");
return -1;
}
for (i = 0; i < IVSHMEM_CLIENT_MAX_VECTORS; i++) {
client->local.vectors[i] = -1;
}
QTAILQ_INIT(&client->peer_list);
client->local.id = -1;
client->notif_cb = notif_cb;
client->notif_arg = notif_arg;
client->verbose = verbose;
client->shm_fd = -1;
client->sock_fd = -1;
return 0;
}
/* create and connect to the unix socket */
int
ivshmem_client_connect(IvshmemClient *client)
{
struct sockaddr_un sun;
int fd, ret;
int64_t tmp;
IVSHMEM_CLIENT_DEBUG(client, "connect to client %s\n",
client->unix_sock_path);
client->sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (client->sock_fd < 0) {
IVSHMEM_CLIENT_DEBUG(client, "cannot create socket: %s\n",
strerror(errno));
return -1;
}
sun.sun_family = AF_UNIX;
ret = snprintf(sun.sun_path, sizeof(sun.sun_path), "%s",
client->unix_sock_path);
if (ret < 0 || ret >= sizeof(sun.sun_path)) {
IVSHMEM_CLIENT_DEBUG(client, "could not copy unix socket path\n");
goto err_close;
}
if (connect(client->sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
IVSHMEM_CLIENT_DEBUG(client, "cannot connect to %s: %s\n", sun.sun_path,
strerror(errno));
goto err_close;
}
/* first, we expect a protocol version */
if (ivshmem_client_read_one_msg(client, &tmp, &fd) < 0 ||
(tmp != IVSHMEM_PROTOCOL_VERSION) || fd != -1) {
IVSHMEM_CLIENT_DEBUG(client, "cannot read from server\n");
goto err_close;
}
/* then, we expect our index + a fd == -1 */
if (ivshmem_client_read_one_msg(client, &client->local.id, &fd) < 0 ||
client->local.id < 0 || fd != -1) {
IVSHMEM_CLIENT_DEBUG(client, "cannot read from server (2)\n");
goto err_close;
}
IVSHMEM_CLIENT_DEBUG(client, "our_id=%" PRId64 "\n", client->local.id);
/* now, we expect shared mem fd + a -1 index, note that shm fd
* is not used */
if (ivshmem_client_read_one_msg(client, &tmp, &fd) < 0 ||
tmp != -1 || fd < 0) {
if (fd >= 0) {
close(fd);
}
IVSHMEM_CLIENT_DEBUG(client, "cannot read from server (3)\n");
goto err_close;
}
client->shm_fd = fd;
IVSHMEM_CLIENT_DEBUG(client, "shm_fd=%d\n", fd);
return 0;
err_close:
close(client->sock_fd);
client->sock_fd = -1;
return -1;
}
/* close connection to the server, and free all peer structures */
void
ivshmem_client_close(IvshmemClient *client)
{
IvshmemClientPeer *peer;
unsigned i;
IVSHMEM_CLIENT_DEBUG(client, "close client\n");
while ((peer = QTAILQ_FIRST(&client->peer_list)) != NULL) {
ivshmem_client_free_peer(client, peer);
}
close(client->shm_fd);
client->shm_fd = -1;
close(client->sock_fd);
client->sock_fd = -1;
client->local.id = -1;
for (i = 0; i < IVSHMEM_CLIENT_MAX_VECTORS; i++) {
close(client->local.vectors[i]);
client->local.vectors[i] = -1;
}
client->local.vectors_count = 0;
}
/* get the fd_set according to the unix socket and peer list */
void
ivshmem_client_get_fds(const IvshmemClient *client, fd_set *fds, int *maxfd)
{
int fd;
unsigned vector;
FD_SET(client->sock_fd, fds);
if (client->sock_fd >= *maxfd) {
*maxfd = client->sock_fd + 1;
}
for (vector = 0; vector < client->local.vectors_count; vector++) {
fd = client->local.vectors[vector];
FD_SET(fd, fds);
if (fd >= *maxfd) {
*maxfd = fd + 1;
}
}
}
/* handle events from eventfd: just print a message on notification */
static int
ivshmem_client_handle_event(IvshmemClient *client, const fd_set *cur, int maxfd)
{
IvshmemClientPeer *peer;
uint64_t kick;
unsigned i;
int ret;
peer = &client->local;
for (i = 0; i < peer->vectors_count; i++) {
if (peer->vectors[i] >= maxfd || !FD_ISSET(peer->vectors[i], cur)) {
continue;
}
ret = read(peer->vectors[i], &kick, sizeof(kick));
if (ret < 0) {
return ret;
}
if (ret != sizeof(kick)) {
IVSHMEM_CLIENT_DEBUG(client, "invalid read size = %d\n", ret);
errno = EINVAL;
return -1;
}
IVSHMEM_CLIENT_DEBUG(client, "received event on fd %d vector %d: %"
PRIu64 "\n", peer->vectors[i], i, kick);
if (client->notif_cb != NULL) {
client->notif_cb(client, peer, i, client->notif_arg);
}
}
return 0;
}
/* read and handle new messages on the given fd_set */
int
ivshmem_client_handle_fds(IvshmemClient *client, fd_set *fds, int maxfd)
{
if (client->sock_fd < maxfd && FD_ISSET(client->sock_fd, fds) &&
ivshmem_client_handle_server_msg(client) < 0 && errno != EINTR) {
IVSHMEM_CLIENT_DEBUG(client, "ivshmem_client_handle_server_msg() "
"failed\n");
return -1;
} else if (ivshmem_client_handle_event(client, fds, maxfd) < 0 &&
errno != EINTR) {
IVSHMEM_CLIENT_DEBUG(client, "ivshmem_client_handle_event() failed\n");
return -1;
}
return 0;
}
/* send a notification on a vector of a peer */
int
ivshmem_client_notify(const IvshmemClient *client,
const IvshmemClientPeer *peer, unsigned vector)
{
uint64_t kick;
int fd;
if (vector >= peer->vectors_count) {
IVSHMEM_CLIENT_DEBUG(client, "invalid vector %u on peer %" PRId64 "\n",
vector, peer->id);
return -1;
}
fd = peer->vectors[vector];
IVSHMEM_CLIENT_DEBUG(client, "notify peer %" PRId64
" on vector %d, fd %d\n", peer->id, vector, fd);
kick = 1;
if (write(fd, &kick, sizeof(kick)) != sizeof(kick)) {
fprintf(stderr, "could not write to %d: %s\n", peer->vectors[vector],
strerror(errno));
return -1;
}
return 0;
}
/* send a notification to all vectors of a peer */
int
ivshmem_client_notify_all_vects(const IvshmemClient *client,
const IvshmemClientPeer *peer)
{
unsigned vector;
int ret = 0;
for (vector = 0; vector < peer->vectors_count; vector++) {
if (ivshmem_client_notify(client, peer, vector) < 0) {
ret = -1;
}
}
return ret;
}
/* send a notification to all peers */
int
ivshmem_client_notify_broadcast(const IvshmemClient *client)
{
IvshmemClientPeer *peer;
int ret = 0;
QTAILQ_FOREACH(peer, &client->peer_list, next) {
if (ivshmem_client_notify_all_vects(client, peer) < 0) {
ret = -1;
}
}
return ret;
}
/* lookup peer from its id */
IvshmemClientPeer *
ivshmem_client_search_peer(IvshmemClient *client, int64_t peer_id)
{
IvshmemClientPeer *peer;
if (peer_id == client->local.id) {
return &client->local;
}
QTAILQ_FOREACH(peer, &client->peer_list, next) {
if (peer->id == peer_id) {
return peer;
}
}
return NULL;
}
/* dump our info, the list of peers their vectors on stdout */
void
ivshmem_client_dump(const IvshmemClient *client)
{
const IvshmemClientPeer *peer;
unsigned vector;
/* dump local infos */
peer = &client->local;
printf("our_id = %" PRId64 "\n", peer->id);
for (vector = 0; vector < peer->vectors_count; vector++) {
printf(" vector %d is enabled (fd=%d)\n", vector,
peer->vectors[vector]);
}
/* dump peers */
QTAILQ_FOREACH(peer, &client->peer_list, next) {
printf("peer_id = %" PRId64 "\n", peer->id);
for (vector = 0; vector < peer->vectors_count; vector++) {
printf(" vector %d is enabled (fd=%d)\n", vector,
peer->vectors[vector]);
}
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright 6WIND S.A., 2014
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#ifndef _IVSHMEM_CLIENT_H_
#define _IVSHMEM_CLIENT_H_
/**
* This file provides helper to implement an ivshmem client. It is used
* on the host to ask QEMU to send an interrupt to an ivshmem PCI device in a
* guest. QEMU also implements an ivshmem client similar to this one, they both
* connect to an ivshmem server.
*
* A standalone ivshmem client based on this file is provided for debug/test
* purposes.
*/
#include <limits.h>
#include <sys/select.h>
#include "qemu/queue.h"
#include "hw/misc/ivshmem.h"
/**
* Maximum number of notification vectors supported by the client
*/
#define IVSHMEM_CLIENT_MAX_VECTORS 64
/**
* Structure storing a peer
*
* Each time a client connects to an ivshmem server, it is advertised to
* all connected clients through the unix socket. When our ivshmem
* client receives a notification, it creates a IvshmemClientPeer
* structure to store the infos of this peer.
*
* This structure is also used to store the information of our own
* client in (IvshmemClient)->local.
*/
typedef struct IvshmemClientPeer {
QTAILQ_ENTRY(IvshmemClientPeer) next; /**< next in list*/
int64_t id; /**< the id of the peer */
int vectors[IVSHMEM_CLIENT_MAX_VECTORS]; /**< one fd per vector */
unsigned vectors_count; /**< number of vectors */
} IvshmemClientPeer;
QTAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer);
typedef struct IvshmemClientPeerList IvshmemClientPeerList;
typedef struct IvshmemClient IvshmemClient;
/**
* Typedef of callback function used when our IvshmemClient receives a
* notification from a peer.
*/
typedef void (*IvshmemClientNotifCb)(
const IvshmemClient *client,
const IvshmemClientPeer *peer,
unsigned vect, void *arg);
/**
* Structure describing an ivshmem client
*
* This structure stores all information related to our client: the name
* of the server unix socket, the list of peers advertised by the
* server, our own client information, and a pointer the notification
* callback function used when we receive a notification from a peer.
*/
struct IvshmemClient {
char unix_sock_path[PATH_MAX]; /**< path to unix sock */
int sock_fd; /**< unix sock filedesc */
int shm_fd; /**< shm file descriptor */
IvshmemClientPeerList peer_list; /**< list of peers */
IvshmemClientPeer local; /**< our own infos */
IvshmemClientNotifCb notif_cb; /**< notification callback */
void *notif_arg; /**< notification argument */
bool verbose; /**< true to enable debug */
};
/**
* Initialize an ivshmem client
*
* @client: A pointer to an uninitialized IvshmemClient structure
* @unix_sock_path: The pointer to the unix socket file name
* @notif_cb: If not NULL, the pointer to the function to be called when
* our IvshmemClient receives a notification from a peer
* @notif_arg: Opaque pointer given as-is to the notification callback
* function
* @verbose: True to enable debug
*
* Returns: 0 on success, or a negative value on error
*/
int ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path,
IvshmemClientNotifCb notif_cb, void *notif_arg,
bool verbose);
/**
* Connect to the server
*
* Connect to the server unix socket, and read the first initial
* messages sent by the server, giving the ID of the client and the file
* descriptor of the shared memory.
*
* @client: The ivshmem client
*
* Returns: 0 on success, or a negative value on error
*/
int ivshmem_client_connect(IvshmemClient *client);
/**
* Close connection to the server and free all peer structures
*
* @client: The ivshmem client
*/
void ivshmem_client_close(IvshmemClient *client);
/**
* Fill a fd_set with file descriptors to be monitored
*
* This function will fill a fd_set with all file descriptors
* that must be polled (unix server socket and peers eventfd). The
* function will not initialize the fd_set, it is up to the caller
* to do this.
*
* @client: The ivshmem client
* @fds: The fd_set to be updated
* @maxfd: Must be set to the max file descriptor + 1 in fd_set. This value is
* updated if this function adds a greater fd in fd_set.
*/
void ivshmem_client_get_fds(const IvshmemClient *client, fd_set *fds,
int *maxfd);
/**
* Read and handle new messages
*
* Given a fd_set filled by select(), handle incoming messages from
* server or peers.
*
* @client: The ivshmem client
* @fds: The fd_set containing the file descriptors to be checked. Note
* that file descriptors that are not related to our client are
* ignored.
* @maxfd: The maximum fd in fd_set, plus one.
*
* Returns: 0 on success, or a negative value on error
*/
int ivshmem_client_handle_fds(IvshmemClient *client, fd_set *fds, int maxfd);
/**
* Send a notification to a vector of a peer
*
* @client: The ivshmem client
* @peer: The peer to be notified
* @vector: The number of the vector
*
* Returns: 0 on success, or a negative value on error
*/
int ivshmem_client_notify(const IvshmemClient *client,
const IvshmemClientPeer *peer, unsigned vector);
/**
* Send a notification to all vectors of a peer
*
* @client: The ivshmem client
* @peer: The peer to be notified
*
* Returns: 0 on success, or a negative value on error (at least one
* notification failed)
*/
int ivshmem_client_notify_all_vects(const IvshmemClient *client,
const IvshmemClientPeer *peer);
/**
* Broadcat a notification to all vectors of all peers
*
* @client: The ivshmem client
*
* Returns: 0 on success, or a negative value on error (at least one
* notification failed)
*/
int ivshmem_client_notify_broadcast(const IvshmemClient *client);
/**
* Search a peer from its identifier
*
* Return the peer structure from its peer_id. If the given peer_id is
* the local id, the function returns the local peer structure.
*
* @client: The ivshmem client
* @peer_id: The identifier of the peer structure
*
* Returns: The peer structure, or NULL if not found
*/
IvshmemClientPeer *
ivshmem_client_search_peer(IvshmemClient *client, int64_t peer_id);
/**
* Dump information of this ivshmem client on stdout
*
* Dump the id and the vectors of the given ivshmem client and the list
* of its peers and their vectors on stdout.
*
* @client: The ivshmem client
*/
void ivshmem_client_dump(const IvshmemClient *client);
#endif /* _IVSHMEM_CLIENT_H_ */

View File

@@ -0,0 +1,240 @@
/*
* Copyright 6WIND S.A., 2014
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#include "qemu-common.h"
#include "ivshmem-client.h"
#define IVSHMEM_CLIENT_DEFAULT_VERBOSE 0
#define IVSHMEM_CLIENT_DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
typedef struct IvshmemClientArgs {
bool verbose;
const char *unix_sock_path;
} IvshmemClientArgs;
/* show ivshmem_client_usage and exit with given error code */
static void
ivshmem_client_usage(const char *name, int code)
{
fprintf(stderr, "%s [opts]\n", name);
fprintf(stderr, " -h: show this help\n");
fprintf(stderr, " -v: verbose mode\n");
fprintf(stderr, " -S <unix_sock_path>: path to the unix socket\n"
" to connect to.\n"
" default=%s\n", IVSHMEM_CLIENT_DEFAULT_UNIX_SOCK_PATH);
exit(code);
}
/* parse the program arguments, exit on error */
static void
ivshmem_client_parse_args(IvshmemClientArgs *args, int argc, char *argv[])
{
int c;
while ((c = getopt(argc, argv,
"h" /* help */
"v" /* verbose */
"S:" /* unix_sock_path */
)) != -1) {
switch (c) {
case 'h': /* help */
ivshmem_client_usage(argv[0], 0);
break;
case 'v': /* verbose */
args->verbose = 1;
break;
case 'S': /* unix_sock_path */
args->unix_sock_path = optarg;
break;
default:
ivshmem_client_usage(argv[0], 1);
break;
}
}
}
/* show command line help */
static void
ivshmem_client_cmdline_help(void)
{
printf("dump: dump peers (including us)\n"
"int <peer> <vector>: notify one vector on a peer\n"
"int <peer> all: notify all vectors of a peer\n"
"int all: notify all vectors of all peers (excepting us)\n");
}
/* read stdin and handle commands */
static int
ivshmem_client_handle_stdin_command(IvshmemClient *client)
{
IvshmemClientPeer *peer;
char buf[128];
char *s, *token;
int ret;
int peer_id, vector;
memset(buf, 0, sizeof(buf));
ret = read(0, buf, sizeof(buf) - 1);
if (ret < 0) {
return -1;
}
s = buf;
while ((token = strsep(&s, "\n\r;")) != NULL) {
if (!strcmp(token, "")) {
continue;
}
if (!strcmp(token, "?")) {
ivshmem_client_cmdline_help();
}
if (!strcmp(token, "help")) {
ivshmem_client_cmdline_help();
} else if (!strcmp(token, "dump")) {
ivshmem_client_dump(client);
} else if (!strcmp(token, "int all")) {
ivshmem_client_notify_broadcast(client);
} else if (sscanf(token, "int %d %d", &peer_id, &vector) == 2) {
peer = ivshmem_client_search_peer(client, peer_id);
if (peer == NULL) {
printf("cannot find peer_id = %d\n", peer_id);
continue;
}
ivshmem_client_notify(client, peer, vector);
} else if (sscanf(token, "int %d all", &peer_id) == 1) {
peer = ivshmem_client_search_peer(client, peer_id);
if (peer == NULL) {
printf("cannot find peer_id = %d\n", peer_id);
continue;
}
ivshmem_client_notify_all_vects(client, peer);
} else {
printf("invalid command, type help\n");
}
}
printf("cmd> ");
fflush(stdout);
return 0;
}
/* listen on stdin (command line), on unix socket (notifications of new
* and dead peers), and on eventfd (IRQ request) */
static int
ivshmem_client_poll_events(IvshmemClient *client)
{
fd_set fds;
int ret, maxfd;
while (1) {
FD_ZERO(&fds);
FD_SET(0, &fds); /* add stdin in fd_set */
maxfd = 1;
ivshmem_client_get_fds(client, &fds, &maxfd);
ret = select(maxfd, &fds, NULL, NULL, NULL);
if (ret < 0) {
if (errno == EINTR) {
continue;
}
fprintf(stderr, "select error: %s\n", strerror(errno));
break;
}
if (ret == 0) {
continue;
}
if (FD_ISSET(0, &fds) &&
ivshmem_client_handle_stdin_command(client) < 0 && errno != EINTR) {
fprintf(stderr, "ivshmem_client_handle_stdin_command() failed\n");
break;
}
if (ivshmem_client_handle_fds(client, &fds, maxfd) < 0) {
fprintf(stderr, "ivshmem_client_handle_fds() failed\n");
break;
}
}
return ret;
}
/* callback when we receive a notification (just display it) */
static void
ivshmem_client_notification_cb(const IvshmemClient *client,
const IvshmemClientPeer *peer,
unsigned vect, void *arg)
{
(void)client;
(void)arg;
printf("receive notification from peer_id=%" PRId64 " vector=%u\n",
peer->id, vect);
}
int
main(int argc, char *argv[])
{
struct sigaction sa;
IvshmemClient client;
IvshmemClientArgs args = {
.verbose = IVSHMEM_CLIENT_DEFAULT_VERBOSE,
.unix_sock_path = IVSHMEM_CLIENT_DEFAULT_UNIX_SOCK_PATH,
};
/* parse arguments, will exit on error */
ivshmem_client_parse_args(&args, argc, argv);
/* Ignore SIGPIPE, see this link for more info:
* http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
if (sigemptyset(&sa.sa_mask) == -1 ||
sigaction(SIGPIPE, &sa, 0) == -1) {
perror("failed to ignore SIGPIPE; sigaction");
return 1;
}
ivshmem_client_cmdline_help();
printf("cmd> ");
fflush(stdout);
if (ivshmem_client_init(&client, args.unix_sock_path,
ivshmem_client_notification_cb, NULL,
args.verbose) < 0) {
fprintf(stderr, "cannot init client\n");
return 1;
}
while (1) {
if (ivshmem_client_connect(&client) < 0) {
fprintf(stderr, "cannot connect to server, retry in 1 second\n");
sleep(1);
continue;
}
fprintf(stdout, "listen on server socket %d\n", client.sock_fd);
if (ivshmem_client_poll_events(&client) == 0) {
continue;
}
/* disconnected from server, reset all peers */
fprintf(stdout, "disconnected from server\n");
ivshmem_client_close(&client);
}
return 0;
}

View File

@@ -0,0 +1 @@
ivshmem-server-obj-y = ivshmem-server.o main.o

View File

@@ -0,0 +1,491 @@
/*
* Copyright 6WIND S.A., 2014
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#include "qemu-common.h"
#include "qemu/sockets.h"
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#ifdef CONFIG_LINUX
#include <sys/vfs.h>
#endif
#include "ivshmem-server.h"
/* log a message on stdout if verbose=1 */
#define IVSHMEM_SERVER_DEBUG(server, fmt, ...) do { \
if ((server)->verbose) { \
printf(fmt, ## __VA_ARGS__); \
} \
} while (0)
/** maximum size of a huge page, used by ivshmem_server_ftruncate() */
#define IVSHMEM_SERVER_MAX_HUGEPAGE_SIZE (1024 * 1024 * 1024)
/** default listen backlog (number of sockets not accepted) */
#define IVSHMEM_SERVER_LISTEN_BACKLOG 10
/* send message to a client unix socket */
static int
ivshmem_server_send_one_msg(int sock_fd, int64_t peer_id, int fd)
{
int ret;
struct msghdr msg;
struct iovec iov[1];
union {
struct cmsghdr cmsg;
char control[CMSG_SPACE(sizeof(int))];
} msg_control;
struct cmsghdr *cmsg;
peer_id = GINT64_TO_LE(peer_id);
iov[0].iov_base = &peer_id;
iov[0].iov_len = sizeof(peer_id);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = iov;
msg.msg_iovlen = 1;
/* if fd is specified, add it in a cmsg */
if (fd >= 0) {
memset(&msg_control, 0, sizeof(msg_control));
msg.msg_control = &msg_control;
msg.msg_controllen = sizeof(msg_control);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
}
ret = sendmsg(sock_fd, &msg, 0);
if (ret <= 0) {
return -1;
}
return 0;
}
/* free a peer when the server advertises a disconnection or when the
* server is freed */
static void
ivshmem_server_free_peer(IvshmemServer *server, IvshmemServerPeer *peer)
{
unsigned vector;
IvshmemServerPeer *other_peer;
IVSHMEM_SERVER_DEBUG(server, "free peer %" PRId64 "\n", peer->id);
close(peer->sock_fd);
QTAILQ_REMOVE(&server->peer_list, peer, next);
/* advertise the deletion to other peers */
QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
ivshmem_server_send_one_msg(other_peer->sock_fd, peer->id, -1);
}
for (vector = 0; vector < peer->vectors_count; vector++) {
event_notifier_cleanup(&peer->vectors[vector]);
}
g_free(peer);
}
/* send the peer id and the shm_fd just after a new client connection */
static int
ivshmem_server_send_initial_info(IvshmemServer *server, IvshmemServerPeer *peer)
{
int ret;
/* send our protocol version first */
ret = ivshmem_server_send_one_msg(peer->sock_fd, IVSHMEM_PROTOCOL_VERSION,
-1);
if (ret < 0) {
IVSHMEM_SERVER_DEBUG(server, "cannot send version: %s\n",
strerror(errno));
return -1;
}
/* send the peer id to the client */
ret = ivshmem_server_send_one_msg(peer->sock_fd, peer->id, -1);
if (ret < 0) {
IVSHMEM_SERVER_DEBUG(server, "cannot send peer id: %s\n",
strerror(errno));
return -1;
}
/* send the shm_fd */
ret = ivshmem_server_send_one_msg(peer->sock_fd, -1, server->shm_fd);
if (ret < 0) {
IVSHMEM_SERVER_DEBUG(server, "cannot send shm fd: %s\n",
strerror(errno));
return -1;
}
return 0;
}
/* handle message on listening unix socket (new client connection) */
static int
ivshmem_server_handle_new_conn(IvshmemServer *server)
{
IvshmemServerPeer *peer, *other_peer;
struct sockaddr_un unaddr;
socklen_t unaddr_len;
int newfd;
unsigned i;
/* accept the incoming connection */
unaddr_len = sizeof(unaddr);
newfd = qemu_accept(server->sock_fd,
(struct sockaddr *)&unaddr, &unaddr_len);
if (newfd < 0) {
IVSHMEM_SERVER_DEBUG(server, "cannot accept() %s\n", strerror(errno));
return -1;
}
qemu_set_nonblock(newfd);
IVSHMEM_SERVER_DEBUG(server, "accept()=%d\n", newfd);
/* allocate new structure for this peer */
peer = g_malloc0(sizeof(*peer));
peer->sock_fd = newfd;
/* get an unused peer id */
/* XXX: this could use id allocation such as Linux IDA, or simply
* a free-list */
for (i = 0; i < G_MAXUINT16; i++) {
if (ivshmem_server_search_peer(server, server->cur_id) == NULL) {
break;
}
server->cur_id++;
}
if (i == G_MAXUINT16) {
IVSHMEM_SERVER_DEBUG(server, "cannot allocate new client id\n");
goto fail;
}
peer->id = server->cur_id++;
/* create eventfd, one per vector */
peer->vectors_count = server->n_vectors;
for (i = 0; i < peer->vectors_count; i++) {
if (event_notifier_init(&peer->vectors[i], FALSE) < 0) {
IVSHMEM_SERVER_DEBUG(server, "cannot create eventfd\n");
goto fail;
}
}
/* send peer id and shm fd */
if (ivshmem_server_send_initial_info(server, peer) < 0) {
IVSHMEM_SERVER_DEBUG(server, "cannot send initial info\n");
goto fail;
}
/* advertise the new peer to others */
QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
for (i = 0; i < peer->vectors_count; i++) {
ivshmem_server_send_one_msg(other_peer->sock_fd, peer->id,
peer->vectors[i].wfd);
}
}
/* advertise the other peers to the new one */
QTAILQ_FOREACH(other_peer, &server->peer_list, next) {
for (i = 0; i < peer->vectors_count; i++) {
ivshmem_server_send_one_msg(peer->sock_fd, other_peer->id,
other_peer->vectors[i].wfd);
}
}
/* advertise the new peer to itself */
for (i = 0; i < peer->vectors_count; i++) {
ivshmem_server_send_one_msg(peer->sock_fd, peer->id,
event_notifier_get_fd(&peer->vectors[i]));
}
QTAILQ_INSERT_TAIL(&server->peer_list, peer, next);
IVSHMEM_SERVER_DEBUG(server, "new peer id = %" PRId64 "\n",
peer->id);
return 0;
fail:
while (i--) {
event_notifier_cleanup(&peer->vectors[i]);
}
close(newfd);
g_free(peer);
return -1;
}
/* Try to ftruncate a file to next power of 2 of shmsize.
* If it fails; all power of 2 above shmsize are tested until
* we reach the maximum huge page size. This is useful
* if the shm file is in a hugetlbfs that cannot be truncated to the
* shm_size value. */
static int
ivshmem_server_ftruncate(int fd, unsigned shmsize)
{
int ret;
struct stat mapstat;
/* align shmsize to next power of 2 */
shmsize = pow2ceil(shmsize);
if (fstat(fd, &mapstat) != -1 && mapstat.st_size == shmsize) {
return 0;
}
while (shmsize <= IVSHMEM_SERVER_MAX_HUGEPAGE_SIZE) {
ret = ftruncate(fd, shmsize);
if (ret == 0) {
return ret;
}
shmsize *= 2;
}
return -1;
}
/* Init a new ivshmem server */
int
ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
const char *shm_path, size_t shm_size, unsigned n_vectors,
bool verbose)
{
int ret;
memset(server, 0, sizeof(*server));
server->verbose = verbose;
ret = snprintf(server->unix_sock_path, sizeof(server->unix_sock_path),
"%s", unix_sock_path);
if (ret < 0 || ret >= sizeof(server->unix_sock_path)) {
IVSHMEM_SERVER_DEBUG(server, "could not copy unix socket path\n");
return -1;
}
ret = snprintf(server->shm_path, sizeof(server->shm_path),
"%s", shm_path);
if (ret < 0 || ret >= sizeof(server->shm_path)) {
IVSHMEM_SERVER_DEBUG(server, "could not copy shm path\n");
return -1;
}
server->shm_size = shm_size;
server->n_vectors = n_vectors;
QTAILQ_INIT(&server->peer_list);
return 0;
}
#ifdef CONFIG_LINUX
#define HUGETLBFS_MAGIC 0x958458f6
static long gethugepagesize(const char *path)
{
struct statfs fs;
int ret;
do {
ret = statfs(path, &fs);
} while (ret != 0 && errno == EINTR);
if (ret != 0) {
return -1;
}
if (fs.f_type != HUGETLBFS_MAGIC) {
return -1;
}
return fs.f_bsize;
}
#endif
/* open shm, create and bind to the unix socket */
int
ivshmem_server_start(IvshmemServer *server)
{
struct sockaddr_un sun;
int shm_fd, sock_fd, ret;
/* open shm file */
#ifdef CONFIG_LINUX
long hpagesize;
hpagesize = gethugepagesize(server->shm_path);
if (hpagesize < 0 && errno != ENOENT) {
IVSHMEM_SERVER_DEBUG(server, "cannot stat shm file %s: %s\n",
server->shm_path, strerror(errno));
}
if (hpagesize > 0) {
gchar *filename = g_strdup_printf("%s/ivshmem.XXXXXX", server->shm_path);
IVSHMEM_SERVER_DEBUG(server, "Using hugepages: %s\n", server->shm_path);
shm_fd = mkstemp(filename);
unlink(filename);
g_free(filename);
} else
#endif
{
IVSHMEM_SERVER_DEBUG(server, "Using POSIX shared memory: %s\n",
server->shm_path);
shm_fd = shm_open(server->shm_path, O_CREAT|O_RDWR, S_IRWXU);
}
if (shm_fd < 0) {
fprintf(stderr, "cannot open shm file %s: %s\n", server->shm_path,
strerror(errno));
return -1;
}
if (ivshmem_server_ftruncate(shm_fd, server->shm_size) < 0) {
fprintf(stderr, "ftruncate(%s) failed: %s\n", server->shm_path,
strerror(errno));
goto err_close_shm;
}
IVSHMEM_SERVER_DEBUG(server, "create & bind socket %s\n",
server->unix_sock_path);
/* create the unix listening socket */
sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock_fd < 0) {
IVSHMEM_SERVER_DEBUG(server, "cannot create socket: %s\n",
strerror(errno));
goto err_close_shm;
}
sun.sun_family = AF_UNIX;
ret = snprintf(sun.sun_path, sizeof(sun.sun_path), "%s",
server->unix_sock_path);
if (ret < 0 || ret >= sizeof(sun.sun_path)) {
IVSHMEM_SERVER_DEBUG(server, "could not copy unix socket path\n");
goto err_close_sock;
}
if (bind(sock_fd, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
IVSHMEM_SERVER_DEBUG(server, "cannot connect to %s: %s\n", sun.sun_path,
strerror(errno));
goto err_close_sock;
}
if (listen(sock_fd, IVSHMEM_SERVER_LISTEN_BACKLOG) < 0) {
IVSHMEM_SERVER_DEBUG(server, "listen() failed: %s\n", strerror(errno));
goto err_close_sock;
}
server->sock_fd = sock_fd;
server->shm_fd = shm_fd;
return 0;
err_close_sock:
close(sock_fd);
err_close_shm:
close(shm_fd);
return -1;
}
/* close connections to clients, the unix socket and the shm fd */
void
ivshmem_server_close(IvshmemServer *server)
{
IvshmemServerPeer *peer, *npeer;
IVSHMEM_SERVER_DEBUG(server, "close server\n");
QTAILQ_FOREACH_SAFE(peer, &server->peer_list, next, npeer) {
ivshmem_server_free_peer(server, peer);
}
unlink(server->unix_sock_path);
close(server->sock_fd);
close(server->shm_fd);
server->sock_fd = -1;
server->shm_fd = -1;
}
/* get the fd_set according to the unix socket and the peer list */
void
ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd)
{
IvshmemServerPeer *peer;
if (server->sock_fd == -1) {
return;
}
FD_SET(server->sock_fd, fds);
if (server->sock_fd >= *maxfd) {
*maxfd = server->sock_fd + 1;
}
QTAILQ_FOREACH(peer, &server->peer_list, next) {
FD_SET(peer->sock_fd, fds);
if (peer->sock_fd >= *maxfd) {
*maxfd = peer->sock_fd + 1;
}
}
}
/* process incoming messages on the sockets in fd_set */
int
ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd)
{
IvshmemServerPeer *peer, *peer_next;
if (server->sock_fd < maxfd && FD_ISSET(server->sock_fd, fds) &&
ivshmem_server_handle_new_conn(server) < 0 && errno != EINTR) {
IVSHMEM_SERVER_DEBUG(server, "ivshmem_server_handle_new_conn() "
"failed\n");
return -1;
}
QTAILQ_FOREACH_SAFE(peer, &server->peer_list, next, peer_next) {
/* any message from a peer socket result in a close() */
IVSHMEM_SERVER_DEBUG(server, "peer->sock_fd=%d\n", peer->sock_fd);
if (peer->sock_fd < maxfd && FD_ISSET(peer->sock_fd, fds)) {
ivshmem_server_free_peer(server, peer);
}
}
return 0;
}
/* lookup peer from its id */
IvshmemServerPeer *
ivshmem_server_search_peer(IvshmemServer *server, int64_t peer_id)
{
IvshmemServerPeer *peer;
QTAILQ_FOREACH(peer, &server->peer_list, next) {
if (peer->id == peer_id) {
return peer;
}
}
return NULL;
}
/* dump our info, the list of peers their vectors on stdout */
void
ivshmem_server_dump(const IvshmemServer *server)
{
const IvshmemServerPeer *peer;
unsigned vector;
/* dump peers */
QTAILQ_FOREACH(peer, &server->peer_list, next) {
printf("peer_id = %" PRId64 "\n", peer->id);
for (vector = 0; vector < peer->vectors_count; vector++) {
printf(" vector %d is enabled (fd=%d)\n", vector,
event_notifier_get_fd(&peer->vectors[vector]));
}
}
}

View File

@@ -0,0 +1,167 @@
/*
* Copyright 6WIND S.A., 2014
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#ifndef _IVSHMEM_SERVER_H_
#define _IVSHMEM_SERVER_H_
/**
* The ivshmem server is a daemon that creates a unix socket in listen
* mode. The ivshmem clients (qemu or ivshmem-client) connect to this
* unix socket. For each client, the server will create some eventfd
* (see EVENTFD(2)), one per vector. These fd are transmitted to all
* clients using the SCM_RIGHTS cmsg message. Therefore, each client is
* able to send a notification to another client without beeing
* "profixied" by the server.
*
* We use this mechanism to send interruptions between guests.
* qemu is able to transform an event on a eventfd into a PCI MSI-x
* interruption in the guest.
*
* The ivshmem server is also able to share the file descriptor
* associated to the ivshmem shared memory.
*/
#include <limits.h>
#include <sys/select.h>
#include <stdint.h>
#include <stdbool.h>
#include "qemu/event_notifier.h"
#include "qemu/queue.h"
#include "hw/misc/ivshmem.h"
/**
* Maximum number of notification vectors supported by the server
*/
#define IVSHMEM_SERVER_MAX_VECTORS 64
/**
* Structure storing a peer
*
* Each time a client connects to an ivshmem server, a new
* IvshmemServerPeer structure is created. This peer and all its
* vectors are advertised to all connected clients through the connected
* unix sockets.
*/
typedef struct IvshmemServerPeer {
QTAILQ_ENTRY(IvshmemServerPeer) next; /**< next in list*/
int sock_fd; /**< connected unix sock */
int64_t id; /**< the id of the peer */
EventNotifier vectors[IVSHMEM_SERVER_MAX_VECTORS]; /**< one per vector */
unsigned vectors_count; /**< number of vectors */
} IvshmemServerPeer;
QTAILQ_HEAD(IvshmemServerPeerList, IvshmemServerPeer);
typedef struct IvshmemServerPeerList IvshmemServerPeerList;
/**
* Structure describing an ivshmem server
*
* This structure stores all information related to our server: the name
* of the server unix socket and the list of connected peers.
*/
typedef struct IvshmemServer {
char unix_sock_path[PATH_MAX]; /**< path to unix socket */
int sock_fd; /**< unix sock file descriptor */
char shm_path[PATH_MAX]; /**< path to shm */
size_t shm_size; /**< size of shm */
int shm_fd; /**< shm file descriptor */
unsigned n_vectors; /**< number of vectors */
uint16_t cur_id; /**< id to be given to next client */
bool verbose; /**< true in verbose mode */
IvshmemServerPeerList peer_list; /**< list of peers */
} IvshmemServer;
/**
* Initialize an ivshmem server
*
* @server: A pointer to an uninitialized IvshmemServer structure
* @unix_sock_path: The pointer to the unix socket file name
* @shm_path: Path to the shared memory. The path corresponds to a POSIX
* shm name or a hugetlbfs mount point.
* @shm_size: Size of shared memory
* @n_vectors: Number of interrupt vectors per client
* @verbose: True to enable verbose mode
*
* Returns: 0 on success, or a negative value on error
*/
int
ivshmem_server_init(IvshmemServer *server, const char *unix_sock_path,
const char *shm_path, size_t shm_size, unsigned n_vectors,
bool verbose);
/**
* Open the shm, then create and bind to the unix socket
*
* @server: The pointer to the initialized IvshmemServer structure
*
* Returns: 0 on success, or a negative value on error
*/
int ivshmem_server_start(IvshmemServer *server);
/**
* Close the server
*
* Close connections to all clients, close the unix socket and the
* shared memory file descriptor. The structure remains initialized, so
* it is possible to call ivshmem_server_start() again after a call to
* ivshmem_server_close().
*
* @server: The ivshmem server
*/
void ivshmem_server_close(IvshmemServer *server);
/**
* Fill a fd_set with file descriptors to be monitored
*
* This function will fill a fd_set with all file descriptors that must
* be polled (unix server socket and peers unix socket). The function
* will not initialize the fd_set, it is up to the caller to do it.
*
* @server: The ivshmem server
* @fds: The fd_set to be updated
* @maxfd: Must be set to the max file descriptor + 1 in fd_set. This value is
* updated if this function adds a greater fd in fd_set.
*/
void
ivshmem_server_get_fds(const IvshmemServer *server, fd_set *fds, int *maxfd);
/**
* Read and handle new messages
*
* Given a fd_set (for instance filled by a call to select()), handle
* incoming messages from peers.
*
* @server: The ivshmem server
* @fds: The fd_set containing the file descriptors to be checked. Note that
* file descriptors that are not related to our server are ignored.
* @maxfd: The maximum fd in fd_set, plus one.
*
* Returns: 0 on success, or a negative value on error
*/
int ivshmem_server_handle_fds(IvshmemServer *server, fd_set *fds, int maxfd);
/**
* Search a peer from its identifier
*
* @server: The ivshmem server
* @peer_id: The identifier of the peer structure
*
* Returns: The peer structure, or NULL if not found
*/
IvshmemServerPeer *
ivshmem_server_search_peer(IvshmemServer *server, int64_t peer_id);
/**
* Dump information of this ivshmem server and its peers on stdout
*
* @server: The ivshmem server
*/
void ivshmem_server_dump(const IvshmemServer *server);
#endif /* _IVSHMEM_SERVER_H_ */

View File

@@ -0,0 +1,263 @@
/*
* Copyright 6WIND S.A., 2014
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#include "qemu-common.h"
#include "ivshmem-server.h"
#define IVSHMEM_SERVER_DEFAULT_VERBOSE 0
#define IVSHMEM_SERVER_DEFAULT_FOREGROUND 0
#define IVSHMEM_SERVER_DEFAULT_PID_FILE "/var/run/ivshmem-server.pid"
#define IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH "/tmp/ivshmem_socket"
#define IVSHMEM_SERVER_DEFAULT_SHM_PATH "ivshmem"
#define IVSHMEM_SERVER_DEFAULT_SHM_SIZE (4*1024*1024)
#define IVSHMEM_SERVER_DEFAULT_N_VECTORS 1
/* used to quit on signal SIGTERM */
static int ivshmem_server_quit;
/* arguments given by the user */
typedef struct IvshmemServerArgs {
bool verbose;
bool foreground;
const char *pid_file;
const char *unix_socket_path;
const char *shm_path;
uint64_t shm_size;
unsigned n_vectors;
} IvshmemServerArgs;
/* show ivshmem_server_usage and exit with given error code */
static void
ivshmem_server_usage(const char *name, int code)
{
fprintf(stderr, "%s [opts]\n", name);
fprintf(stderr, " -h: show this help\n");
fprintf(stderr, " -v: verbose mode\n");
fprintf(stderr, " -F: foreground mode (default is to daemonize)\n");
fprintf(stderr, " -p <pid_file>: path to the PID file (used in daemon\n"
" mode only).\n"
" Default=%s\n", IVSHMEM_SERVER_DEFAULT_SHM_PATH);
fprintf(stderr, " -S <unix_socket_path>: path to the unix socket\n"
" to listen to.\n"
" Default=%s\n", IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH);
fprintf(stderr, " -m <shm_path>: path to the shared memory.\n"
" The path corresponds to a POSIX shm name or a\n"
" hugetlbfs mount point.\n"
" default=%s\n", IVSHMEM_SERVER_DEFAULT_SHM_PATH);
fprintf(stderr, " -l <size>: size of shared memory in bytes. The suffix\n"
" K, M and G can be used (ex: 1K means 1024).\n"
" default=%u\n", IVSHMEM_SERVER_DEFAULT_SHM_SIZE);
fprintf(stderr, " -n <n_vects>: number of vectors.\n"
" default=%u\n", IVSHMEM_SERVER_DEFAULT_N_VECTORS);
exit(code);
}
/* parse the program arguments, exit on error */
static void
ivshmem_server_parse_args(IvshmemServerArgs *args, int argc, char *argv[])
{
int c;
unsigned long long v;
Error *errp = NULL;
while ((c = getopt(argc, argv,
"h" /* help */
"v" /* verbose */
"F" /* foreground */
"p:" /* pid_file */
"S:" /* unix_socket_path */
"m:" /* shm_path */
"l:" /* shm_size */
"n:" /* n_vectors */
)) != -1) {
switch (c) {
case 'h': /* help */
ivshmem_server_usage(argv[0], 0);
break;
case 'v': /* verbose */
args->verbose = 1;
break;
case 'F': /* foreground */
args->foreground = 1;
break;
case 'p': /* pid_file */
args->pid_file = optarg;
break;
case 'S': /* unix_socket_path */
args->unix_socket_path = optarg;
break;
case 'm': /* shm_path */
args->shm_path = optarg;
break;
case 'l': /* shm_size */
parse_option_size("shm_size", optarg, &args->shm_size, &errp);
if (errp) {
fprintf(stderr, "cannot parse shm size: %s\n",
error_get_pretty(errp));
error_free(errp);
ivshmem_server_usage(argv[0], 1);
}
break;
case 'n': /* n_vectors */
if (parse_uint_full(optarg, &v, 0) < 0) {
fprintf(stderr, "cannot parse n_vectors\n");
ivshmem_server_usage(argv[0], 1);
}
args->n_vectors = v;
break;
default:
ivshmem_server_usage(argv[0], 1);
break;
}
}
if (args->n_vectors > IVSHMEM_SERVER_MAX_VECTORS) {
fprintf(stderr, "too many requested vectors (max is %d)\n",
IVSHMEM_SERVER_MAX_VECTORS);
ivshmem_server_usage(argv[0], 1);
}
if (args->verbose == 1 && args->foreground == 0) {
fprintf(stderr, "cannot use verbose in daemon mode\n");
ivshmem_server_usage(argv[0], 1);
}
}
/* wait for events on listening server unix socket and connected client
* sockets */
static int
ivshmem_server_poll_events(IvshmemServer *server)
{
fd_set fds;
int ret = 0, maxfd;
while (!ivshmem_server_quit) {
FD_ZERO(&fds);
maxfd = 0;
ivshmem_server_get_fds(server, &fds, &maxfd);
ret = select(maxfd, &fds, NULL, NULL, NULL);
if (ret < 0) {
if (errno == EINTR) {
continue;
}
fprintf(stderr, "select error: %s\n", strerror(errno));
break;
}
if (ret == 0) {
continue;
}
if (ivshmem_server_handle_fds(server, &fds, maxfd) < 0) {
fprintf(stderr, "ivshmem_server_handle_fds() failed\n");
break;
}
}
return ret;
}
static void
ivshmem_server_quit_cb(int signum)
{
ivshmem_server_quit = 1;
}
int
main(int argc, char *argv[])
{
IvshmemServer server;
struct sigaction sa, sa_quit;
IvshmemServerArgs args = {
.verbose = IVSHMEM_SERVER_DEFAULT_VERBOSE,
.foreground = IVSHMEM_SERVER_DEFAULT_FOREGROUND,
.pid_file = IVSHMEM_SERVER_DEFAULT_PID_FILE,
.unix_socket_path = IVSHMEM_SERVER_DEFAULT_UNIX_SOCK_PATH,
.shm_path = IVSHMEM_SERVER_DEFAULT_SHM_PATH,
.shm_size = IVSHMEM_SERVER_DEFAULT_SHM_SIZE,
.n_vectors = IVSHMEM_SERVER_DEFAULT_N_VECTORS,
};
int ret = 1;
/* parse arguments, will exit on error */
ivshmem_server_parse_args(&args, argc, argv);
/* Ignore SIGPIPE, see this link for more info:
* http://www.mail-archive.com/libevent-users@monkey.org/msg01606.html */
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
if (sigemptyset(&sa.sa_mask) == -1 ||
sigaction(SIGPIPE, &sa, 0) == -1) {
perror("failed to ignore SIGPIPE; sigaction");
goto err;
}
sa_quit.sa_handler = ivshmem_server_quit_cb;
sa_quit.sa_flags = 0;
if (sigemptyset(&sa_quit.sa_mask) == -1 ||
sigaction(SIGTERM, &sa_quit, 0) == -1) {
perror("failed to add SIGTERM handler; sigaction");
goto err;
}
/* init the ivshms structure */
if (ivshmem_server_init(&server, args.unix_socket_path, args.shm_path,
args.shm_size, args.n_vectors, args.verbose) < 0) {
fprintf(stderr, "cannot init server\n");
goto err;
}
/* start the ivshmem server (open shm & unix socket) */
if (ivshmem_server_start(&server) < 0) {
fprintf(stderr, "cannot bind\n");
goto err;
}
/* daemonize if asked to */
if (!args.foreground) {
FILE *fp;
if (qemu_daemon(1, 1) < 0) {
fprintf(stderr, "cannot daemonize: %s\n", strerror(errno));
goto err_close;
}
/* write pid file */
fp = fopen(args.pid_file, "w");
if (fp == NULL) {
fprintf(stderr, "cannot write pid file: %s\n", strerror(errno));
goto err_close;
}
fprintf(fp, "%d\n", (int) getpid());
fclose(fp);
}
ivshmem_server_poll_events(&server);
fprintf(stdout, "server disconnected\n");
ret = 0;
err_close:
ivshmem_server_close(&server);
err:
return ret;
}

View File

@@ -477,7 +477,8 @@ int cpu_exec(CPUState *cpu)
/* see if we can patch the calling TB. When the TB
spans two pages, we cannot safely do a direct
jump. */
if (next_tb != 0 && tb->page_addr[1] == -1) {
if (next_tb != 0 && tb->page_addr[1] == -1
&& !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
next_tb & TB_EXIT_MASK, tb);
}

View File

@@ -25,8 +25,7 @@ typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
struct QCryptoCipherBuiltinAES {
AES_KEY encrypt_key;
AES_KEY decrypt_key;
uint8_t *iv;
size_t niv;
uint8_t iv[AES_BLOCK_SIZE];
};
typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
struct QCryptoCipherBuiltinDESRFB {
@@ -40,6 +39,7 @@ struct QCryptoCipherBuiltin {
QCryptoCipherBuiltinAES aes;
QCryptoCipherBuiltinDESRFB desrfb;
} state;
size_t blocksize;
void (*free)(QCryptoCipher *cipher);
int (*setiv)(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
@@ -61,7 +61,6 @@ static void qcrypto_cipher_free_aes(QCryptoCipher *cipher)
{
QCryptoCipherBuiltin *ctxt = cipher->opaque;
g_free(ctxt->state.aes.iv);
g_free(ctxt);
cipher->opaque = NULL;
}
@@ -145,15 +144,13 @@ static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
Error **errp)
{
QCryptoCipherBuiltin *ctxt = cipher->opaque;
if (niv != 16) {
error_setg(errp, "IV must be 16 bytes not %zu", niv);
if (niv != AES_BLOCK_SIZE) {
error_setg(errp, "IV must be %d bytes not %zu",
AES_BLOCK_SIZE, niv);
return -1;
}
g_free(ctxt->state.aes.iv);
ctxt->state.aes.iv = g_new0(uint8_t, niv);
memcpy(ctxt->state.aes.iv, iv, niv);
ctxt->state.aes.niv = niv;
memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE);
return 0;
}
@@ -185,6 +182,7 @@ static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
goto error;
}
ctxt->blocksize = AES_BLOCK_SIZE;
ctxt->free = qcrypto_cipher_free_aes;
ctxt->setiv = qcrypto_cipher_setiv_aes;
ctxt->encrypt = qcrypto_cipher_encrypt_aes;
@@ -286,6 +284,7 @@ static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher,
memcpy(ctxt->state.desrfb.key, key, nkey);
ctxt->state.desrfb.nkey = nkey;
ctxt->blocksize = 8;
ctxt->free = qcrypto_cipher_free_des_rfb;
ctxt->setiv = qcrypto_cipher_setiv_des_rfb;
ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
@@ -374,6 +373,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
{
QCryptoCipherBuiltin *ctxt = cipher->opaque;
if (len % ctxt->blocksize) {
error_setg(errp, "Length %zu must be a multiple of block size %zu",
len, ctxt->blocksize);
return -1;
}
return ctxt->encrypt(cipher, in, out, len, errp);
}
@@ -386,6 +391,12 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
{
QCryptoCipherBuiltin *ctxt = cipher->opaque;
if (len % ctxt->blocksize) {
error_setg(errp, "Length %zu must be a multiple of block size %zu",
len, ctxt->blocksize);
return -1;
}
return ctxt->decrypt(cipher, in, out, len, errp);
}

View File

@@ -34,6 +34,11 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
}
}
typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt;
struct QCryptoCipherGcrypt {
gcry_cipher_hd_t handle;
size_t blocksize;
};
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
@@ -41,7 +46,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
Error **errp)
{
QCryptoCipher *cipher;
gcry_cipher_hd_t handle;
QCryptoCipherGcrypt *ctx;
gcry_error_t err;
int gcryalg, gcrymode;
@@ -87,7 +92,9 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
cipher->alg = alg;
cipher->mode = mode;
err = gcry_cipher_open(&handle, gcryalg, gcrymode, 0);
ctx = g_new0(QCryptoCipherGcrypt, 1);
err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
if (err != 0) {
error_setg(errp, "Cannot initialize cipher: %s",
gcry_strerror(err));
@@ -100,10 +107,12 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
* bizarre RFB variant of DES :-)
*/
uint8_t *rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
err = gcry_cipher_setkey(handle, rfbkey, nkey);
err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey);
g_free(rfbkey);
ctx->blocksize = 8;
} else {
err = gcry_cipher_setkey(handle, key, nkey);
err = gcry_cipher_setkey(ctx->handle, key, nkey);
ctx->blocksize = 16;
}
if (err != 0) {
error_setg(errp, "Cannot set key: %s",
@@ -111,11 +120,12 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
goto error;
}
cipher->opaque = handle;
cipher->opaque = ctx;
return cipher;
error:
gcry_cipher_close(handle);
gcry_cipher_close(ctx->handle);
g_free(ctx);
g_free(cipher);
return NULL;
}
@@ -123,12 +133,13 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
void qcrypto_cipher_free(QCryptoCipher *cipher)
{
gcry_cipher_hd_t handle;
QCryptoCipherGcrypt *ctx;
if (!cipher) {
return;
}
handle = cipher->opaque;
gcry_cipher_close(handle);
ctx = cipher->opaque;
gcry_cipher_close(ctx->handle);
g_free(ctx);
g_free(cipher);
}
@@ -139,10 +150,16 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
size_t len,
Error **errp)
{
gcry_cipher_hd_t handle = cipher->opaque;
QCryptoCipherGcrypt *ctx = cipher->opaque;
gcry_error_t err;
err = gcry_cipher_encrypt(handle,
if (len % ctx->blocksize) {
error_setg(errp, "Length %zu must be a multiple of block size %zu",
len, ctx->blocksize);
return -1;
}
err = gcry_cipher_encrypt(ctx->handle,
out, len,
in, len);
if (err != 0) {
@@ -161,10 +178,16 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
size_t len,
Error **errp)
{
gcry_cipher_hd_t handle = cipher->opaque;
QCryptoCipherGcrypt *ctx = cipher->opaque;
gcry_error_t err;
err = gcry_cipher_decrypt(handle,
if (len % ctx->blocksize) {
error_setg(errp, "Length %zu must be a multiple of block size %zu",
len, ctx->blocksize);
return -1;
}
err = gcry_cipher_decrypt(ctx->handle,
out, len,
in, len);
if (err != 0) {
@@ -180,11 +203,17 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp)
{
gcry_cipher_hd_t handle = cipher->opaque;
QCryptoCipherGcrypt *ctx = cipher->opaque;
gcry_error_t err;
gcry_cipher_reset(handle);
err = gcry_cipher_setiv(handle, iv, niv);
if (niv != ctx->blocksize) {
error_setg(errp, "Expected IV size %zu not %zu",
ctx->blocksize, niv);
return -1;
}
gcry_cipher_reset(ctx->handle);
err = gcry_cipher_setiv(ctx->handle, iv, niv);
if (err != 0) {
error_setg(errp, "Cannot set IV: %s",
gcry_strerror(err));

View File

@@ -69,7 +69,7 @@ struct QCryptoCipherNettle {
nettle_cipher_func *alg_encrypt;
nettle_cipher_func *alg_decrypt;
uint8_t *iv;
size_t niv;
size_t blocksize;
};
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
@@ -125,7 +125,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
ctx->alg_encrypt = des_encrypt_wrapper;
ctx->alg_decrypt = des_decrypt_wrapper;
ctx->niv = DES_BLOCK_SIZE;
ctx->blocksize = DES_BLOCK_SIZE;
break;
case QCRYPTO_CIPHER_ALG_AES_128:
@@ -140,14 +140,14 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
ctx->alg_encrypt = aes_encrypt_wrapper;
ctx->alg_decrypt = aes_decrypt_wrapper;
ctx->niv = AES_BLOCK_SIZE;
ctx->blocksize = AES_BLOCK_SIZE;
break;
default:
error_setg(errp, "Unsupported cipher algorithm %d", alg);
goto error;
}
ctx->iv = g_new0(uint8_t, ctx->niv);
ctx->iv = g_new0(uint8_t, ctx->blocksize);
cipher->opaque = ctx;
return cipher;
@@ -184,6 +184,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
{
QCryptoCipherNettle *ctx = cipher->opaque;
if (len % ctx->blocksize) {
error_setg(errp, "Length %zu must be a multiple of block size %zu",
len, ctx->blocksize);
return -1;
}
switch (cipher->mode) {
case QCRYPTO_CIPHER_MODE_ECB:
ctx->alg_encrypt(ctx->ctx_encrypt, len, out, in);
@@ -191,7 +197,7 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
case QCRYPTO_CIPHER_MODE_CBC:
cbc_encrypt(ctx->ctx_encrypt, ctx->alg_encrypt,
ctx->niv, ctx->iv,
ctx->blocksize, ctx->iv,
len, out, in);
break;
default:
@@ -211,6 +217,12 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
{
QCryptoCipherNettle *ctx = cipher->opaque;
if (len % ctx->blocksize) {
error_setg(errp, "Length %zu must be a multiple of block size %zu",
len, ctx->blocksize);
return -1;
}
switch (cipher->mode) {
case QCRYPTO_CIPHER_MODE_ECB:
ctx->alg_decrypt(ctx->ctx_decrypt ? ctx->ctx_decrypt : ctx->ctx_encrypt,
@@ -219,7 +231,7 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
case QCRYPTO_CIPHER_MODE_CBC:
cbc_decrypt(ctx->ctx_decrypt ? ctx->ctx_decrypt : ctx->ctx_encrypt,
ctx->alg_decrypt, ctx->niv, ctx->iv,
ctx->alg_decrypt, ctx->blocksize, ctx->iv,
len, out, in);
break;
default:
@@ -235,9 +247,9 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
Error **errp)
{
QCryptoCipherNettle *ctx = cipher->opaque;
if (niv != ctx->niv) {
if (niv != ctx->blocksize) {
error_setg(errp, "Expected IV size %zu not %zu",
ctx->niv, niv);
ctx->blocksize, niv);
return -1;
}
memcpy(ctx->iv, iv, niv);

View File

@@ -47,7 +47,7 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
return true;
}
#if defined(CONFIG_GNUTLS_GCRYPT) || defined(CONFIG_GNUTLS_NETTLE)
#if defined(CONFIG_GCRYPT) || defined(CONFIG_NETTLE)
static uint8_t *
qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
size_t nkey)
@@ -63,11 +63,11 @@ qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
}
return ret;
}
#endif /* CONFIG_GNUTLS_GCRYPT || CONFIG_GNUTLS_NETTLE */
#endif /* CONFIG_GCRYPT || CONFIG_NETTLE */
#ifdef CONFIG_GNUTLS_GCRYPT
#ifdef CONFIG_GCRYPT
#include "crypto/cipher-gcrypt.c"
#elif defined CONFIG_GNUTLS_NETTLE
#elif defined CONFIG_NETTLE
#include "crypto/cipher-nettle.c"
#else
#include "crypto/cipher-builtin.c"

View File

@@ -24,8 +24,9 @@
#ifdef CONFIG_GNUTLS
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#endif
#ifdef CONFIG_GNUTLS_GCRYPT
#ifdef CONFIG_GCRYPT
#include <gcrypt.h>
#endif
@@ -37,6 +38,7 @@
* - When GNUTLS >= 2.12, we must not initialize gcrypt threading
* because GNUTLS will do that itself
* - When GNUTLS < 2.12 we must always initialize gcrypt threading
* - When GNUTLS is disabled we must always initialize gcrypt threading
*
* But....
*
@@ -47,12 +49,15 @@
*
* - gcrypt < 1.6.0
* AND
* - gnutls < 2.12
* - gnutls < 2.12
* OR
* - gnutls is disabled
*
*/
#if (defined(CONFIG_GNUTLS_GCRYPT) && \
(!defined(GNUTLS_VERSION_NUMBER) || \
#if (defined(CONFIG_GCRYPT) && \
(!defined(CONFIG_GNUTLS) || \
!defined(GNUTLS_VERSION_NUMBER) || \
(GNUTLS_VERSION_NUMBER < 0x020c00)) && \
(!defined(GCRYPT_VERSION_NUMBER) || \
(GCRYPT_VERSION_NUMBER < 0x010600)))
@@ -113,6 +118,7 @@ static struct gcry_thread_cbs qcrypto_gcrypt_thread_impl = {
int qcrypto_init(Error **errp)
{
#ifdef CONFIG_GNUTLS
int ret;
ret = gnutls_global_init();
if (ret < 0) {
@@ -125,8 +131,9 @@ int qcrypto_init(Error **errp)
gnutls_global_set_log_level(10);
gnutls_global_set_log_function(qcrypto_gnutls_log);
#endif
#endif
#ifdef CONFIG_GNUTLS_GCRYPT
#ifdef CONFIG_GCRYPT
if (!gcry_check_version(GCRYPT_VERSION)) {
error_setg(errp, "Unable to initialize gcrypt");
return -1;
@@ -139,12 +146,3 @@ int qcrypto_init(Error **errp)
return 0;
}
#else /* ! CONFIG_GNUTLS */
int qcrypto_init(Error **errp G_GNUC_UNUSED)
{
return 0;
}
#endif /* ! CONFIG_GNUTLS */

View File

@@ -35,5 +35,5 @@ CONFIG_SDHCI=y
CONFIG_EDU=y
CONFIG_VGA=y
CONFIG_VGA_PCI=y
CONFIG_IVSHMEM=$(CONFIG_KVM)
CONFIG_IVSHMEM=$(CONFIG_POSIX)
CONFIG_ROCKER=y

View File

@@ -2420,9 +2420,11 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"hibernate","", 0x42000023, 0xffffffff, 0, 0, V1 },
{"ins", "t,r,+A,+B", 0x7c000004, 0xfc00003f, WR_t|RD_s, 0, I33 },
{"jr", "s", 0x00000008, 0xfc1fffff, UBD|RD_s, 0, I1 },
{"jr", "s", 0x00000009, 0xfc1fffff, UBD|RD_s, 0, I32R6 }, /* jalr */
/* jr.hb is officially MIPS{32,64}R2, but it works on R1 as jr with
the same hazard barrier effect. */
{"jr.hb", "s", 0x00000408, 0xfc1fffff, UBD|RD_s, 0, I32 },
{"jr.hb", "s", 0x00000409, 0xfc1fffff, UBD|RD_s, 0, I32R6 }, /* jalr.hb */
{"j", "s", 0x00000008, 0xfc1fffff, UBD|RD_s, 0, I1 }, /* jr */
/* SVR4 PIC code requires special handling for j, so it must be a
macro. */

View File

@@ -106,12 +106,15 @@ Types, commands, and events share a common namespace. Therefore,
generally speaking, type definitions should always use CamelCase for
user-defined type names, while built-in types are lowercase. Type
definitions should not end in 'Kind', as this namespace is used for
creating implicit C enums for visiting union types. Command names,
creating implicit C enums for visiting union types, or in 'List', as
this namespace is used for creating array types. Command names,
and field names within a type, should be all lower case with words
separated by a hyphen. However, some existing older commands and
complex types use underscore; when extending such expressions,
consistency is preferred over blindly avoiding underscore. Event
names should be ALL_CAPS with words separated by underscore.
names should be ALL_CAPS with words separated by underscore. Field
names cannot start with 'has-' or 'has_', as this is reserved for
tracking optional fields.
Any name (command, event, type, field, or enum value) beginning with
"x-" is marked experimental, and may be withdrawn or changed
@@ -122,9 +125,10 @@ vendor), even if the rest of the name uses dash (example:
__com.redhat_drive-mirror). Other than downstream extensions (with
leading underscore and the use of dots), all names should begin with a
letter, and contain only ASCII letters, digits, dash, and underscore.
It is okay to reuse names that match C keywords; the generator will
rename a field named "default" in the QAPI to "q_default" in the
generated C code.
Names beginning with 'q_' are reserved for the generator: QMP names
that resemble C keywords or other problematic strings will be munged
in C to use this prefix. For example, a field named "default" in
qapi becomes "q_default" in the generated C code.
In the rest of this document, usage lines are given for each
expression type, with literal strings written in lower case and

View File

@@ -28,6 +28,8 @@ Example:
"data": { "actual": 944766976 },
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
Note: this event is rate-limited.
BLOCK_IMAGE_CORRUPTED
---------------------
@@ -296,6 +298,8 @@ Example:
"data": { "reference": "usr1", "sector-num": 345435, "sectors-count": 5 },
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
Note: this event is rate-limited.
QUORUM_REPORT_BAD
-----------------
@@ -318,6 +322,8 @@ Example:
"data": { "node-name": "1.raw", "sector-num": 345435, "sectors-count": 5 },
"timestamp": { "seconds": 1344522075, "microseconds": 745528 } }
Note: this event is rate-limited.
RESET
-----
@@ -358,6 +364,8 @@ Example:
"data": { "offset": 78 },
"timestamp": { "seconds": 1267020223, "microseconds": 435656 } }
Note: this event is rate-limited.
SHUTDOWN
--------
@@ -632,6 +640,8 @@ Example:
"data": { "id": "channel0", "open": true },
"timestamp": { "seconds": 1401385907, "microseconds": 422329 } }
Note: this event is rate-limited separately for each "id".
WAKEUP
------
@@ -662,3 +672,5 @@ Example:
Note: If action is "reset", "shutdown", or "pause" the WATCHDOG event is
followed respectively by the RESET, SHUTDOWN, or STOP events.
Note: this event is rate-limited.

View File

@@ -175,6 +175,11 @@ The format of asynchronous events is:
For a listing of supported asynchronous events, please, refer to the
qmp-events.txt file.
Some events are rate-limited to at most one per second. If additional
"similar" events arrive within one second, all but the last one are
dropped, and the last one is delayed. "Similar" normally means same
event type. See qmp-events.txt for details.
2.5 QGA Synchronization
-----------------------

View File

@@ -2,30 +2,106 @@
Device Specification for Inter-VM shared memory device
------------------------------------------------------
The Inter-VM shared memory device is designed to share a region of memory to
userspace in multiple virtual guests. The memory region does not belong to any
guest, but is a POSIX memory object on the host. Optionally, the device may
support sending interrupts to other guests sharing the same memory region.
The Inter-VM shared memory device is designed to share a memory region (created
on the host via the POSIX shared memory API) between multiple QEMU processes
running different guests. In order for all guests to be able to pick up the
shared memory area, it is modeled by QEMU as a PCI device exposing said memory
to the guest as a PCI BAR.
The memory region does not belong to any guest, but is a POSIX memory object on
the host. The host can access this shared memory if needed.
The device also provides an optional communication mechanism between guests
sharing the same memory object. More details about that in the section 'Guest to
guest communication' section.
The Inter-VM PCI device
-----------------------
*BARs*
From the VM point of view, the ivshmem PCI device supports three BARs.
The device supports three BARs. BAR0 is a 1 Kbyte MMIO region to support
registers. BAR1 is used for MSI-X when it is enabled in the device. BAR2 is
used to map the shared memory object from the host. The size of BAR2 is
specified when the guest is started and must be a power of 2 in size.
- BAR0 is a 1 Kbyte MMIO region to support registers and interrupts when MSI is
not used.
- BAR1 is used for MSI-X when it is enabled in the device.
- BAR2 is used to access the shared memory object.
*Registers*
It is your choice how to use the device but you must choose between two
behaviors :
The device currently supports 4 registers of 32-bits each. Registers
are used for synchronization between guests sharing the same memory object when
interrupts are supported (this requires using the shared memory server).
- basically, if you only need the shared memory part, you will map BAR2.
This way, you have access to the shared memory in guest and can use it as you
see fit (memnic, for example, uses it in userland
http://dpdk.org/browse/memnic).
The server assigns each VM an ID number and sends this ID number to the QEMU
process when the guest starts.
- BAR0 and BAR1 are used to implement an optional communication mechanism
through interrupts in the guests. If you need an event mechanism between the
guests accessing the shared memory, you will most likely want to write a
kernel driver that will handle interrupts. See details in the section 'Guest
to guest communication' section.
The behavior is chosen when starting your QEMU processes:
- no communication mechanism needed, the first QEMU to start creates the shared
memory on the host, subsequent QEMU processes will use it.
- communication mechanism needed, an ivshmem server must be started before any
QEMU processes, then each QEMU process connects to the server unix socket.
For more details on the QEMU ivshmem parameters, see qemu-doc documentation.
Guest to guest communication
----------------------------
This section details the communication mechanism between the guests accessing
the ivhsmem shared memory.
*ivshmem server*
This server code is available in qemu.git/contrib/ivshmem-server.
The server must be started on the host before any guest.
It creates a shared memory object then waits for clients to connect on a unix
socket. All the messages are little-endian int64_t integer.
For each client (QEMU process) that connects to the server:
- the server sends a protocol version, if client does not support it, the client
closes the communication,
- the server assigns an ID for this client and sends this ID to him as the first
message,
- the server sends a fd to the shared memory object to this client,
- the server creates a new set of host eventfds associated to the new client and
sends this set to all already connected clients,
- finally, the server sends all the eventfds sets for all clients to the new
client.
The server signals all clients when one of them disconnects.
The client IDs are limited to 16 bits because of the current implementation (see
Doorbell register in 'PCI device registers' subsection). Hence only 65536
clients are supported.
All the file descriptors (fd to the shared memory, eventfds for each client)
are passed to clients using SCM_RIGHTS over the server unix socket.
Apart from the current ivshmem implementation in QEMU, an ivshmem client has
been provided in qemu.git/contrib/ivshmem-client for debug.
*QEMU as an ivshmem client*
At initialisation, when creating the ivshmem device, QEMU first receives a
protocol version and closes communication with server if it does not match.
Then, QEMU gets its ID from the server then makes it available through BAR0
IVPosition register for the VM to use (see 'PCI device registers' subsection).
QEMU then uses the fd to the shared memory to map it to BAR2.
eventfds for all other clients received from the server are stored to implement
BAR0 Doorbell register (see 'PCI device registers' subsection).
Finally, eventfds assigned to this QEMU process are used to send interrupts in
this VM.
*PCI device registers*
From the VM point of view, the ivshmem PCI device supports 4 registers of
32-bits each.
enum ivshmem_registers {
IntrMask = 0,
@@ -49,8 +125,8 @@ bit to 0 and unmasked by setting the first bit to 1.
IVPosition Register: The IVPosition register is read-only and reports the
guest's ID number. The guest IDs are non-negative integers. When using the
server, since the server is a separate process, the VM ID will only be set when
the device is ready (shared memory is received from the server and accessible via
the device). If the device is not ready, the IVPosition will return -1.
the device is ready (shared memory is received from the server and accessible
via the device). If the device is not ready, the IVPosition will return -1.
Applications should ensure that they have a valid VM ID before accessing the
shared memory.
@@ -59,8 +135,8 @@ Doorbell register. The doorbell register is 32-bits, logically divided into
two 16-bit fields. The high 16-bits are the guest ID to interrupt and the low
16-bits are the interrupt vector to trigger. The semantics of the value
written to the doorbell depends on whether the device is using MSI or a regular
pin-based interrupt. In short, MSI uses vectors while regular interrupts set the
status register.
pin-based interrupt. In short, MSI uses vectors while regular interrupts set
the status register.
Regular Interrupts
@@ -71,7 +147,7 @@ interrupt in the destination guest.
Message Signalled Interrupts
A ivshmem device may support multiple MSI vectors. If so, the lower 16-bits
An ivshmem device may support multiple MSI vectors. If so, the lower 16-bits
written to the Doorbell register must be between 0 and the maximum number of
vectors the guest supports. The lower 16 bits written to the doorbell is the
MSI vector that will be raised in the destination guest. The number of MSI
@@ -83,14 +159,3 @@ interrupt itself should be communicated via the shared memory region. Devices
supporting multiple MSI vectors can use different vectors to indicate different
events have occurred. The semantics of interrupt vectors are left to the
user's discretion.
Usage in the Guest
------------------
The shared memory device is intended to be used with the provided UIO driver.
Very little configuration is needed. The guest should map BAR0 to access the
registers (an array of 32-bit ints allows simple writing) and map BAR2 to
access the shared memory region itself. The size of the shared memory region
is specified when the guest (or shared memory server) is started. A guest may
map the whole shared memory region or only part of it.

26
hmp.c
View File

@@ -569,8 +569,8 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict)
for (client = info->clients; client; client = client->next) {
monitor_printf(mon, "Client:\n");
monitor_printf(mon, " address: %s:%s\n",
client->value->base->host,
client->value->base->service);
client->value->host,
client->value->service);
monitor_printf(mon, " x509_dname: %s\n",
client->value->x509_dname ?
client->value->x509_dname : "none");
@@ -638,7 +638,7 @@ void hmp_info_spice(Monitor *mon, const QDict *qdict)
for (chan = info->channels; chan; chan = chan->next) {
monitor_printf(mon, "Channel:\n");
monitor_printf(mon, " address: %s:%s%s\n",
chan->value->base->host, chan->value->base->port,
chan->value->host, chan->value->port,
chan->value->tls ? " [tls]" : "");
monitor_printf(mon, " session: %" PRId64 "\n",
chan->value->connection_id);
@@ -841,11 +841,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
c, TpmModel_lookup[ti->model]);
monitor_printf(mon, " \\ %s: type=%s",
ti->id, TpmTypeOptionsKind_lookup[ti->options->kind]);
ti->id, TpmTypeOptionsKind_lookup[ti->options->type]);
switch (ti->options->kind) {
switch (ti->options->type) {
case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
tpo = ti->options->passthrough;
tpo = ti->options->u.passthrough;
monitor_printf(mon, "%s%s%s%s",
tpo->has_path ? ",path=" : "",
tpo->has_path ? tpo->path : "",
@@ -1735,15 +1735,15 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict)
if (*endp != '\0') {
goto err_out;
}
keylist->value->kind = KEY_VALUE_KIND_NUMBER;
keylist->value->number = value;
keylist->value->type = KEY_VALUE_KIND_NUMBER;
keylist->value->u.number = value;
} else {
int idx = index_from_key(keyname_buf);
if (idx == Q_KEY_CODE_MAX) {
goto err_out;
}
keylist->value->kind = KEY_VALUE_KIND_QCODE;
keylist->value->qcode = idx;
keylist->value->type = KEY_VALUE_KIND_QCODE;
keylist->value->u.qcode = idx;
}
if (!separator) {
@@ -1958,12 +1958,12 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
value = info->value;
if (value) {
switch (value->kind) {
switch (value->type) {
case MEMORY_DEVICE_INFO_KIND_DIMM:
di = value->dimm;
di = value->u.dimm;
monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
MemoryDeviceInfoKind_lookup[value->kind],
MemoryDeviceInfoKind_lookup[value->type],
di->id ? di->id : "");
monitor_printf(mon, " addr: 0x%" PRIx64 "\n", di->addr);
monitor_printf(mon, " slot: %" PRId64 "\n", di->slot);

View File

@@ -238,10 +238,12 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
mdev->dimm = dev;
mdev->is_enabled = true;
mdev->is_inserting = true;
if (dev->hotplugged) {
mdev->is_inserting = true;
/* do ACPI magic */
acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
/* do ACPI magic */
acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
}
return;
}

View File

@@ -923,7 +923,7 @@ static void machvirt_init(MachineState *machine)
qemu_irq pic[NUM_IRQS];
MemoryRegion *sysmem = get_system_memory();
int gic_version = vms->gic_version;
int n;
int n, max_cpus;
MemoryRegion *ram = g_new(MemoryRegion, 1);
const char *cpu_model = machine->cpu_model;
VirtBoardInfo *vbi;
@@ -957,6 +957,22 @@ static void machvirt_init(MachineState *machine)
exit(1);
}
/* The maximum number of CPUs depends on the GIC version, or on how
* many redistributors we can fit into the memory map.
*/
if (gic_version == 3) {
max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000;
} else {
max_cpus = GIC_NCPU;
}
if (smp_cpus > max_cpus) {
error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "
"supported by machine 'mach-virt' (%d)",
smp_cpus, max_cpus);
exit(1);
}
vbi->smp_cpus = smp_cpus;
if (machine->ram_size > vbi->memmap[VIRT_MEM].size) {
@@ -1155,10 +1171,11 @@ static void virt_class_init(ObjectClass *oc, void *data)
mc->desc = "ARM Virtual Machine",
mc->init = machvirt_init;
/* Our maximum number of CPUs depends on how many redistributors
* we can fit into memory map
/* Start max_cpus at the maximum QEMU supports. We'll further restrict
* it later in machvirt_init, where we have more information about the
* configuration of the particular instance.
*/
mc->max_cpus = a15memmap[VIRT_GIC_REDIST].size / 0x20000;
mc->max_cpus = MAX_CPUMASK_BITS;
mc->has_dynamic_sysbus = true;
mc->block_default_type = IF_VIRTIO;
mc->no_cdrom = 1;

View File

@@ -48,6 +48,14 @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
21, 22,
};
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
0xFF160000, 0xFF170000,
};
static const int sdhci_intr[XLNX_ZYNQMP_NUM_SDHCI] = {
48, 49,
};
typedef struct XlnxZynqMPGICRegion {
int region_index;
uint32_t address;
@@ -97,6 +105,13 @@ static void xlnx_zynqmp_init(Object *obj)
object_initialize(&s->sata, sizeof(s->sata), TYPE_SYSBUS_AHCI);
qdev_set_parent_bus(DEVICE(&s->sata), sysbus_get_default());
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
object_initialize(&s->sdhci[i], sizeof(s->sdhci[i]),
TYPE_SYSBUS_SDHCI);
qdev_set_parent_bus(DEVICE(&s->sdhci[i]),
sysbus_get_default());
}
}
static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -258,6 +273,19 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, SATA_ADDR);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]);
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
object_property_set_bool(OBJECT(&s->sdhci[i]), true,
"realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
sdhci_addr[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[i]), 0,
gic_spi[sdhci_intr[i]]);
}
}
static Property xlnx_zynqmp_props[] = {

View File

@@ -283,7 +283,8 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
/* 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->host_notifier, true,
handle_notify);
aio_context_release(s->ctx);
return;
@@ -319,7 +320,7 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
aio_context_acquire(s->ctx);
/* Stop notifications for new requests from guest */
aio_set_event_notifier(s->ctx, &s->host_notifier, NULL);
aio_set_event_notifier(s->ctx, &s->host_notifier, true, NULL);
/* Drain and switch bs back to the QEMU main loop */
blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context());

View File

@@ -192,6 +192,8 @@ typedef struct FDrive {
uint8_t ro; /* Is read-only */
uint8_t media_changed; /* Is media changed */
uint8_t media_rate; /* Data rate of medium */
bool media_inserted; /* Is there a medium in the tray */
} FDrive;
static void fd_init(FDrive *drv)
@@ -261,7 +263,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
#endif
drv->head = head;
if (drv->track != track) {
if (drv->blk != NULL && blk_is_inserted(drv->blk)) {
if (drv->media_inserted) {
drv->media_changed = 0;
}
ret = 1;
@@ -270,7 +272,7 @@ static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
drv->sect = sect;
}
if (drv->blk == NULL || !blk_is_inserted(drv->blk)) {
if (!drv->media_inserted) {
ret = 2;
}
@@ -296,7 +298,7 @@ static void fd_revalidate(FDrive *drv)
ro = blk_is_read_only(drv->blk);
pick_geometry(drv->blk, &nb_heads, &max_track,
&last_sect, drv->drive, &drive, &rate);
if (!blk_is_inserted(drv->blk)) {
if (!drv->media_inserted) {
FLOPPY_DPRINTF("No disk in drive\n");
} else {
FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
@@ -692,7 +694,7 @@ static bool fdrive_media_changed_needed(void *opaque)
{
FDrive *drive = opaque;
return (drive->blk != NULL && drive->media_changed != 1);
return (drive->media_inserted && drive->media_changed != 1);
}
static const VMStateDescription vmstate_fdrive_media_changed = {
@@ -2184,12 +2186,21 @@ static void fdctrl_change_cb(void *opaque, bool load)
{
FDrive *drive = opaque;
drive->media_inserted = load && drive->blk && blk_is_inserted(drive->blk);
drive->media_changed = 1;
fd_revalidate(drive);
}
static bool fdctrl_is_tray_open(void *opaque)
{
FDrive *drive = opaque;
return !drive->media_inserted;
}
static const BlockDevOps fdctrl_block_ops = {
.change_media_cb = fdctrl_change_cb,
.is_tray_open = fdctrl_is_tray_open,
};
/* Init functions */
@@ -2217,6 +2228,7 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl, Error **errp)
fdctrl_change_cb(drive, 0);
if (drive->blk) {
blk_set_dev_ops(drive->blk, &fdctrl_block_ops, drive);
drive->media_inserted = blk_is_inserted(drive->blk);
}
}
}

View File

@@ -798,6 +798,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
static void virtio_blk_save(QEMUFile *f, void *opaque)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);
VirtIOBlock *s = VIRTIO_BLK(vdev);
if (s->dataplane) {
virtio_blk_data_plane_stop(s->dataplane);
}
virtio_save(vdev, f);
}
@@ -839,10 +844,7 @@ static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,
req->next = s->rq;
s->rq = req;
virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr,
req->elem.in_num, 1);
virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr,
req->elem.out_num, 0);
virtqueue_map(&req->elem);
}
return 0;
@@ -975,7 +977,7 @@ static Property virtio_blk_properties[] = {
DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial),
DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true),
#ifdef __linux__
DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, true),
DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, false),
#endif
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
true),

View File

@@ -931,9 +931,11 @@ static int blk_connect(struct XenDevice *xendev)
blk_attach_dev_nofail(blkdev->blk, blkdev);
blkdev->file_size = blk_getlength(blkdev->blk);
if (blkdev->file_size < 0) {
BlockDriverState *bs = blk_bs(blkdev->blk);
const char *drv_name = bs ? bdrv_get_format_name(bs) : NULL;
xen_be_printf(&blkdev->xendev, 1, "blk_getlength: %d (%s) | drv %s\n",
(int)blkdev->file_size, strerror(-blkdev->file_size),
bdrv_get_format_name(blk_bs(blkdev->blk)) ?: "-");
drv_name ?: "-");
blkdev->file_size = 0;
}

View File

@@ -842,13 +842,13 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
ChannelState *s = (ChannelState *)dev;
int qcode, keycode;
assert(evt->kind == INPUT_EVENT_KIND_KEY);
qcode = qemu_input_key_value_to_qcode(evt->key->key);
assert(evt->type == INPUT_EVENT_KIND_KEY);
qcode = qemu_input_key_value_to_qcode(evt->u.key->key);
trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
evt->key->down);
evt->u.key->down);
if (qcode == Q_KEY_CODE_CAPS_LOCK) {
if (evt->key->down) {
if (evt->u.key->down) {
s->caps_lock_mode ^= 1;
if (s->caps_lock_mode == 2) {
return; /* Drop second press */
@@ -862,7 +862,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
}
if (qcode == Q_KEY_CODE_NUM_LOCK) {
if (evt->key->down) {
if (evt->u.key->down) {
s->num_lock_mode ^= 1;
if (s->num_lock_mode == 2) {
return; /* Drop second press */
@@ -876,7 +876,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
}
keycode = qcode_to_keycode[qcode];
if (!evt->key->down) {
if (!evt->u.key->down) {
keycode |= 0x80;
}
trace_escc_sunkbd_event_out(keycode);
@@ -1035,6 +1035,7 @@ static void escc_class_init(ObjectClass *klass, void *data)
dc->reset = escc_reset;
dc->vmsd = &vmstate_escc;
dc->props = escc_properties;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
static const TypeInfo escc_info = {

View File

@@ -22,25 +22,17 @@
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
//#define DEBUG_SERIAL 1
#ifdef DEBUG_SERIAL
#define DPRINTF(fmt, args...) \
do { printf("%s: " fmt , TYPE_IMX_SERIAL, ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while (0)
#ifndef DEBUG_IMX_UART
#define DEBUG_IMX_UART 0
#endif
/*
* Define to 1 for messages about attempts to
* access unimplemented registers or similar.
*/
//#define DEBUG_IMPLEMENTATION 1
#ifdef DEBUG_IMPLEMENTATION
# define IPRINTF(fmt, args...) \
do { fprintf(stderr, "%s: " fmt, TYPE_IMX_SERIAL, ##args); } while (0)
#else
# define IPRINTF(fmt, args...) do {} while (0)
#endif
#define DPRINTF(fmt, args...) \
do { \
if (DEBUG_IMX_UART) { \
fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SERIAL, \
__func__, ##args); \
} \
} while (0)
static const VMStateDescription vmstate_imx_serial = {
.name = TYPE_IMX_SERIAL,
@@ -115,7 +107,8 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
IMXSerialState *s = (IMXSerialState *)opaque;
uint32_t c;
DPRINTF("read(offset=%x)\n", offset >> 2);
DPRINTF("read(offset=0x%" HWADDR_PRIx ")\n", offset);
switch (offset >> 2) {
case 0x0: /* URXD */
c = s->readbuff;
@@ -167,7 +160,8 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
return 0x0; /* TODO */
default:
IPRINTF("%s: bad offset: 0x%x\n", __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
return 0;
}
}
@@ -178,9 +172,8 @@ static void imx_serial_write(void *opaque, hwaddr offset,
IMXSerialState *s = (IMXSerialState *)opaque;
unsigned char ch;
DPRINTF("write(offset=%x, value = %x) to %s\n",
offset >> 2,
(unsigned int)value, s->chr ? s->chr->label : "NODEV");
DPRINTF("write(offset=0x%" HWADDR_PRIx ", value = 0x%x) to %s\n",
offset, (unsigned int)value, s->chr ? s->chr->label : "NODEV");
switch (offset >> 2) {
case 0x10: /* UTXD */
@@ -198,7 +191,9 @@ static void imx_serial_write(void *opaque, hwaddr offset,
case 0x20: /* UCR1 */
s->ucr1 = value & 0xffff;
DPRINTF("write(ucr1=%x)\n", (unsigned int)value);
imx_update(s);
break;
@@ -266,12 +261,14 @@ static void imx_serial_write(void *opaque, hwaddr offset,
case 0x2d: /* UTS1 */
case 0x23: /* UCR4 */
IPRINTF("Unimplemented Register %x written to\n", offset >> 2);
qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
/* TODO */
break;
default:
IPRINTF("%s: Bad offset 0x%x\n", __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
}
}
@@ -284,7 +281,9 @@ static int imx_can_receive(void *opaque)
static void imx_put_data(void *opaque, uint32_t value)
{
IMXSerialState *s = (IMXSerialState *)opaque;
DPRINTF("received char\n");
s->usr1 |= USR1_RRDY;
s->usr2 |= USR2_RDR;
s->uts1 &= ~UTS1_RXEMPTY;
@@ -319,8 +318,7 @@ static void imx_serial_realize(DeviceState *dev, Error **errp)
qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
imx_event, s);
} else {
DPRINTF("No char dev for uart at 0x%lx\n",
(unsigned long)s->iomem.ram_addr);
DPRINTF("No char dev for uart\n");
}
}

View File

@@ -705,10 +705,7 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id,
qemu_get_buffer(f, (unsigned char *)&port->elem,
sizeof(port->elem));
virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
port->elem.in_num, 1);
virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
port->elem.out_num, 1);
virtqueue_map(&port->elem);
/*
* Port was throttled on source machine. Let's

View File

@@ -30,8 +30,8 @@
#include "qemu/error-report.h"
#include <X11/Xlib.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <epoxy/gl.h>
#include <epoxy/glx.h>
enum {
R_CTL = 0,

View File

@@ -29,11 +29,12 @@ typedef enum IMXGPIOLevel {
} IMXGPIOLevel;
#define DPRINTF(fmt, args...) \
do { \
if (DEBUG_IMX_GPIO) { \
fprintf(stderr, "%s: " fmt , __func__, ##args); \
} \
} while (0)
do { \
if (DEBUG_IMX_GPIO) { \
fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_GPIO, \
__func__, ##args); \
} \
} while (0)
static const char *imx_gpio_reg_name(uint32_t reg)
{
@@ -176,19 +177,19 @@ static uint64_t imx_gpio_read(void *opaque, hwaddr offset, unsigned size)
if (s->has_edge_sel) {
reg_value = s->edge_sel;
} else {
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: EDGE_SEL register not "
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not "
"present on this version of GPIO device\n",
TYPE_IMX_GPIO, __func__);
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad register at offset %d\n",
TYPE_IMX_GPIO, __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset);
break;
}
DPRINTF("(%s) = 0x%"PRIx32"\n", imx_gpio_reg_name(offset), reg_value);
DPRINTF("(%s) = 0x%" PRIx32 "\n", imx_gpio_reg_name(offset), reg_value);
return reg_value;
}
@@ -198,7 +199,7 @@ static void imx_gpio_write(void *opaque, hwaddr offset, uint64_t value,
{
IMXGPIOState *s = IMX_GPIO(opaque);
DPRINTF("(%s, value = 0x%"PRIx32")\n", imx_gpio_reg_name(offset),
DPRINTF("(%s, value = 0x%" PRIx32 ")\n", imx_gpio_reg_name(offset),
(uint32_t)value);
switch (offset) {
@@ -238,15 +239,15 @@ static void imx_gpio_write(void *opaque, hwaddr offset, uint64_t value,
s->edge_sel = value;
imx_gpio_set_all_int_lines(s);
} else {
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: EDGE_SEL register not "
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not "
"present on this version of GPIO device\n",
TYPE_IMX_GPIO, __func__);
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad register at offset %d\n",
TYPE_IMX_GPIO, __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset);
break;
}

View File

@@ -21,13 +21,17 @@
#include "hw/i2c/imx_i2c.h"
#include "hw/i2c/i2c.h"
#ifndef IMX_I2C_DEBUG
#define IMX_I2C_DEBUG 0
#ifndef DEBUG_IMX_I2C
#define DEBUG_IMX_I2C 0
#endif
#if IMX_I2C_DEBUG
#define DPRINT(fmt, args...) \
do { fprintf(stderr, "%s: "fmt, __func__, ## args); } while (0)
#define DPRINTF(fmt, args...) \
do { \
if (DEBUG_IMX_I2C) { \
fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_I2C, \
__func__, ##args); \
} \
} while (0)
static const char *imx_i2c_get_regname(unsigned offset)
{
@@ -46,9 +50,6 @@ static const char *imx_i2c_get_regname(unsigned offset)
return "[?]";
}
}
#else
#define DPRINT(fmt, args...) do { } while (0)
#endif
static inline bool imx_i2c_is_enabled(IMXI2CState *s)
{
@@ -121,11 +122,11 @@ static uint64_t imx_i2c_read(void *opaque, hwaddr offset,
if (s->address == ADDR_RESET) {
/* something is wrong as the address is not set */
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Trying to read "
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read "
"without specifying the slave address\n",
TYPE_IMX_I2C, __func__);
} else if (s->i2cr & I2CR_MTX) {
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Trying to read "
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read "
"but MTX is set\n", TYPE_IMX_I2C, __func__);
} else {
/* get the next byte */
@@ -134,7 +135,7 @@ static uint64_t imx_i2c_read(void *opaque, hwaddr offset,
if (ret >= 0) {
imx_i2c_raise_interrupt(s);
} else {
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: read failed "
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: read failed "
"for device 0x%02x\n", TYPE_IMX_I2C,
__func__, s->address);
ret = 0xff;
@@ -143,19 +144,19 @@ static uint64_t imx_i2c_read(void *opaque, hwaddr offset,
s->i2dr_read = ret;
} else {
qemu_log_mask(LOG_UNIMP, "%s[%s]: slave mode not implemented\n",
qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
TYPE_IMX_I2C, __func__);
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_I2C, __func__, s->address);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_I2C, __func__, offset);
value = 0;
break;
}
DPRINT("read %s [0x%02x] -> 0x%02x\n", imx_i2c_get_regname(offset),
(unsigned int)offset, value);
DPRINTF("read %s [0x%" HWADDR_PRIx "] -> 0x%02x\n",
imx_i2c_get_regname(offset), offset, value);
return (uint64_t)value;
}
@@ -165,8 +166,8 @@ static void imx_i2c_write(void *opaque, hwaddr offset,
{
IMXI2CState *s = IMX_I2C(opaque);
DPRINT("write %s [0x%02x] <- 0x%02x\n", imx_i2c_get_regname(offset),
(unsigned int)offset, (int)value);
DPRINTF("write %s [0x%" HWADDR_PRIx "] <- 0x%02x\n",
imx_i2c_get_regname(offset), offset, (int)value);
value &= 0xff;
@@ -264,13 +265,13 @@ static void imx_i2c_write(void *opaque, hwaddr offset,
}
}
} else {
qemu_log_mask(LOG_UNIMP, "%s[%s]: slave mode not implemented\n",
qemu_log_mask(LOG_UNIMP, "[%s]%s: slave mode not implemented\n",
TYPE_IMX_I2C, __func__);
}
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_I2C, __func__, s->address);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_I2C, __func__, offset);
break;
}
}

View File

@@ -1616,7 +1616,6 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
HotplugHandlerClass *hhc;
Error *local_err = NULL;
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MemoryRegion *mr = ddc->get_memory_region(dimm);
@@ -1632,8 +1631,7 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
goto out;
}
pc_dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align,
pcmc->inter_dimm_gap, &local_err);
pc_dimm_memory_plug(dev, &pcms->hotplug_memory, mr, align, &local_err);
if (local_err) {
goto out;
}
@@ -1953,7 +1951,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
PCMachineClass *pcmc = PC_MACHINE_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
pcmc->inter_dimm_gap = true;
pcmc->get_hotplug_handler = mc->get_hotplug_handler;
mc->get_hotplug_handler = pc_get_hotpug_handler;
mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id;

View File

@@ -487,7 +487,6 @@ static void pc_i440fx_2_4_machine_options(MachineClass *m)
m->alias = NULL;
m->is_default = 0;
pcmc->broken_reserved_end = true;
pcmc->inter_dimm_gap = false;
SET_MACHINE_COMPAT(m, PC_COMPAT_2_4);
}

View File

@@ -385,7 +385,6 @@ static void pc_q35_2_4_machine_options(MachineClass *m)
pc_q35_2_5_machine_options(m);
m->alias = NULL;
pcmc->broken_reserved_end = true;
pcmc->inter_dimm_gap = false;
SET_MACHINE_COMPAT(m, PC_COMPAT_2_4);
}

View File

@@ -33,6 +33,7 @@
#include "trace.h"
#include "exec/address-spaces.h"
#include "sysemu/block-backend.h"
#include "qemu/error-report.h"
#include <xenguest.h>
@@ -382,13 +383,16 @@ static const VMStateDescription vmstate_xen_platform = {
}
};
static int xen_platform_initfn(PCIDevice *dev)
static void xen_platform_realize(PCIDevice *dev, Error **errp)
{
PCIXenPlatformState *d = XEN_PLATFORM(dev);
uint8_t *pci_conf;
/* Device will crash on reset if xen is not initialized */
assert(xen_enabled());
if (!xen_enabled()) {
error_setg(errp, "xen-platform device requires the Xen accelerator");
return;
}
pci_conf = dev->config;
@@ -407,8 +411,6 @@ static int xen_platform_initfn(PCIDevice *dev)
&d->mmio_bar);
platform_fixed_ioport_init(d);
return 0;
}
static void platform_reset(DeviceState *dev)
@@ -423,7 +425,7 @@ static void xen_platform_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->init = xen_platform_initfn;
k->realize = xen_platform_realize;
k->vendor_id = PCI_VENDOR_ID_XEN;
k->device_id = PCI_DEVICE_ID_XEN_PLATFORM;
k->class_id = PCI_CLASS_OTHERS << 8 | 0x80;

View File

@@ -417,6 +417,7 @@ static void cmd646_ide_class_init(ObjectClass *klass, void *data)
k->config_read = cmd646_pci_config_read;
k->config_write = cmd646_pci_config_write;
dc->props = cmd646_ide_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo cmd646_ide_info = {

View File

@@ -590,6 +590,7 @@ static void macio_ide_class_init(ObjectClass *oc, void *data)
dc->realize = macio_ide_realizefn;
dc->reset = macio_ide_reset;
dc->vmsd = &vmstate_pmac;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo macio_ide_type_info = {

View File

@@ -362,6 +362,7 @@ static void adb_kbd_class_init(ObjectClass *oc, void *data)
akc->parent_realize = dc->realize;
dc->realize = adb_kbd_realizefn;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
adc->devreq = adb_kbd_request;
dc->reset = adb_kbd_reset;
@@ -566,6 +567,7 @@ static void adb_mouse_class_init(ObjectClass *oc, void *data)
amc->parent_realize = dc->realize;
dc->realize = adb_mouse_realizefn;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
adc->devreq = adb_mouse_request;
dc->reset = adb_mouse_reset;

View File

@@ -119,33 +119,33 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
assert(hs->n < QUEUE_LENGTH);
e = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK];
switch (evt->kind) {
switch (evt->type) {
case INPUT_EVENT_KIND_REL:
if (evt->rel->axis == INPUT_AXIS_X) {
e->xdx += evt->rel->value;
} else if (evt->rel->axis == INPUT_AXIS_Y) {
e->ydy += evt->rel->value;
if (evt->u.rel->axis == INPUT_AXIS_X) {
e->xdx += evt->u.rel->value;
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
e->ydy += evt->u.rel->value;
}
break;
case INPUT_EVENT_KIND_ABS:
if (evt->rel->axis == INPUT_AXIS_X) {
e->xdx = evt->rel->value;
} else if (evt->rel->axis == INPUT_AXIS_Y) {
e->ydy = evt->rel->value;
if (evt->u.rel->axis == INPUT_AXIS_X) {
e->xdx = evt->u.rel->value;
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
e->ydy = evt->u.rel->value;
}
break;
case INPUT_EVENT_KIND_BTN:
if (evt->btn->down) {
e->buttons_state |= bmap[evt->btn->button];
if (evt->btn->button == INPUT_BUTTON_WHEEL_UP) {
if (evt->u.btn->down) {
e->buttons_state |= bmap[evt->u.btn->button];
if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
e->dz--;
} else if (evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) {
} else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
e->dz++;
}
} else {
e->buttons_state &= ~bmap[evt->btn->button];
e->buttons_state &= ~bmap[evt->u.btn->button];
}
break;
@@ -223,8 +223,8 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
int scancodes[3], i, count;
int slot;
count = qemu_input_key_value_to_scancode(evt->key->key,
evt->key->down,
count = qemu_input_key_value_to_scancode(evt->u.key->key,
evt->u.key->down,
scancodes);
if (hs->n + count > QUEUE_LENGTH) {
fprintf(stderr, "usb-kbd: warning: key event queue full\n");

View File

@@ -183,8 +183,8 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
int scancodes[3], i, count;
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
count = qemu_input_key_value_to_scancode(evt->key->key,
evt->key->down,
count = qemu_input_key_value_to_scancode(evt->u.key->key,
evt->u.key->down,
scancodes);
for (i = 0; i < count; i++) {
ps2_put_keycode(s, scancodes[i]);
@@ -393,25 +393,25 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
return;
switch (evt->kind) {
switch (evt->type) {
case INPUT_EVENT_KIND_REL:
if (evt->rel->axis == INPUT_AXIS_X) {
s->mouse_dx += evt->rel->value;
} else if (evt->rel->axis == INPUT_AXIS_Y) {
s->mouse_dy -= evt->rel->value;
if (evt->u.rel->axis == INPUT_AXIS_X) {
s->mouse_dx += evt->u.rel->value;
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
s->mouse_dy -= evt->u.rel->value;
}
break;
case INPUT_EVENT_KIND_BTN:
if (evt->btn->down) {
s->mouse_buttons |= bmap[evt->btn->button];
if (evt->btn->button == INPUT_BUTTON_WHEEL_UP) {
if (evt->u.btn->down) {
s->mouse_buttons |= bmap[evt->u.btn->button];
if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
s->mouse_dz--;
} else if (evt->btn->button == INPUT_BUTTON_WHEEL_DOWN) {
} else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
s->mouse_dz++;
}
} else {
s->mouse_buttons &= ~bmap[evt->btn->button];
s->mouse_buttons &= ~bmap[evt->u.btn->button];
}
break;

View File

@@ -191,44 +191,45 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
virtio_input_event event;
int qcode;
switch (evt->kind) {
switch (evt->type) {
case INPUT_EVENT_KIND_KEY:
qcode = qemu_input_key_value_to_qcode(evt->key->key);
qcode = qemu_input_key_value_to_qcode(evt->u.key->key);
if (qcode && keymap_qcode[qcode]) {
event.type = cpu_to_le16(EV_KEY);
event.code = cpu_to_le16(keymap_qcode[qcode]);
event.value = cpu_to_le32(evt->key->down ? 1 : 0);
event.value = cpu_to_le32(evt->u.key->down ? 1 : 0);
virtio_input_send(vinput, &event);
} else {
if (evt->key->down) {
if (evt->u.key->down) {
fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
qcode, QKeyCode_lookup[qcode]);
}
}
break;
case INPUT_EVENT_KIND_BTN:
if (keymap_button[evt->btn->button]) {
if (keymap_button[evt->u.btn->button]) {
event.type = cpu_to_le16(EV_KEY);
event.code = cpu_to_le16(keymap_button[evt->btn->button]);
event.value = cpu_to_le32(evt->btn->down ? 1 : 0);
event.code = cpu_to_le16(keymap_button[evt->u.btn->button]);
event.value = cpu_to_le32(evt->u.btn->down ? 1 : 0);
virtio_input_send(vinput, &event);
} else {
if (evt->btn->down) {
if (evt->u.btn->down) {
fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
evt->btn->button, InputButton_lookup[evt->btn->button]);
evt->u.btn->button,
InputButton_lookup[evt->u.btn->button]);
}
}
break;
case INPUT_EVENT_KIND_REL:
event.type = cpu_to_le16(EV_REL);
event.code = cpu_to_le16(axismap_rel[evt->rel->axis]);
event.value = cpu_to_le32(evt->rel->value);
event.code = cpu_to_le16(axismap_rel[evt->u.rel->axis]);
event.value = cpu_to_le32(evt->u.rel->value);
virtio_input_send(vinput, &event);
break;
case INPUT_EVENT_KIND_ABS:
event.type = cpu_to_le16(EV_ABS);
event.code = cpu_to_le16(axismap_abs[evt->abs->axis]);
event.value = cpu_to_le32(evt->abs->value);
event.code = cpu_to_le16(axismap_abs[evt->u.abs->axis]);
event.value = cpu_to_le32(evt->u.abs->value);
virtio_input_send(vinput, &event);
break;
default:

View File

@@ -20,6 +20,7 @@
*/
#include "hw/sysbus.h"
#include "migration/migration.h"
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "gic_internal.h"
@@ -307,11 +308,6 @@ static void kvm_arm_gic_put(GICState *s)
int num_cpu;
int num_irq;
if (!kvm_arm_gic_can_save_restore(s)) {
DPRINTF("Cannot put kernel gic state, no kernel interface");
return;
}
/* Note: We do the restore in a slightly different order than the save
* (where the order doesn't matter and is simply ordered according to the
* register offset values */
@@ -411,11 +407,6 @@ static void kvm_arm_gic_get(GICState *s)
int i;
int cpu;
if (!kvm_arm_gic_can_save_restore(s)) {
DPRINTF("Cannot get kernel gic state, no kernel interface");
return;
}
/*****************************************************************
* Distributor State
*/
@@ -503,7 +494,10 @@ static void kvm_arm_gic_reset(DeviceState *dev)
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
kgc->parent_reset(dev);
kvm_arm_gic_put(s);
if (kvm_arm_gic_can_save_restore(s)) {
kvm_arm_gic_put(s);
}
}
static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
@@ -573,6 +567,12 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
KVM_DEV_ARM_VGIC_GRP_ADDR,
KVM_VGIC_V2_ADDR_TYPE_CPU,
s->dev_fd);
if (!kvm_arm_gic_can_save_restore(s)) {
error_setg(&s->migration_blocker, "This operating system kernel does "
"not support vGICv2 migration");
migrate_add_blocker(s->migration_blocker);
}
}
static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)

View File

@@ -17,27 +17,17 @@
#include "hw/intc/imx_avic.h"
#define DEBUG_INT 1
#undef DEBUG_INT /* comment out for debugging */
#ifndef DEBUG_IMX_AVIC
#define DEBUG_IMX_AVIC 0
#endif
#ifdef DEBUG_INT
#define DPRINTF(fmt, args...) \
do { printf("%s: " fmt , TYPE_IMX_AVIC, ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while (0)
#endif
/*
* Define to 1 for messages about attempts to
* access unimplemented registers or similar.
*/
#define DEBUG_IMPLEMENTATION 1
#if DEBUG_IMPLEMENTATION
# define IPRINTF(fmt, args...) \
do { fprintf(stderr, "%s: " fmt, TYPE_IMX_AVIC, ##args); } while (0)
#else
# define IPRINTF(fmt, args...) do {} while (0)
#endif
do { \
if (DEBUG_IMX_AVIC) { \
fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_AVIC, \
__func__, ##args); \
} \
} while (0)
static const VMStateDescription vmstate_imx_avic = {
.name = TYPE_IMX_AVIC,
@@ -115,8 +105,8 @@ static uint64_t imx_avic_read(void *opaque,
{
IMXAVICState *s = (IMXAVICState *)opaque;
DPRINTF("read(offset = 0x%" HWADDR_PRIx ")\n", offset);
DPRINTF("read(offset = 0x%x)\n", offset >> 2);
switch (offset >> 2) {
case 0: /* INTCNTL */
return s->intcntl;
@@ -213,7 +203,8 @@ static uint64_t imx_avic_read(void *opaque,
return 0x4;
default:
IPRINTF("%s: Bad offset 0x%x\n", __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_AVIC, __func__, offset);
return 0;
}
}
@@ -225,13 +216,13 @@ static void imx_avic_write(void *opaque, hwaddr offset,
/* Vector Registers not yet supported */
if (offset >= 0x100 && offset <= 0x2fc) {
IPRINTF("%s to vector register %d ignored\n", __func__,
(unsigned int)((offset - 0x100) >> 2));
qemu_log_mask(LOG_UNIMP, "[%s]%s: vector %d ignored\n",
TYPE_IMX_AVIC, __func__, (int)((offset - 0x100) >> 2));
return;
}
DPRINTF("%s(0x%x) = %x\n", __func__,
(unsigned int)offset>>2, (unsigned int)val);
DPRINTF("(0x%" HWADDR_PRIx ") = 0x%x\n", offset, (unsigned int)val);
switch (offset >> 2) {
case 0: /* Interrupt Control Register, INTCNTL */
s->intcntl = val & (ABFEN | NIDIS | FIDIS | NIAD | FIAD | NM);
@@ -305,7 +296,8 @@ static void imx_avic_write(void *opaque, hwaddr offset,
return;
default:
IPRINTF("%s: Bad offset %x\n", __func__, (int)offset);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_AVIC, __func__, offset);
}
imx_avic_update(s);
}

View File

@@ -1643,6 +1643,7 @@ static void openpic_class_init(ObjectClass *oc, void *data)
dc->props = openpic_properties;
dc->reset = openpic_reset;
dc->vmsd = &vmstate_openpic;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo openpic_info = {

View File

@@ -275,6 +275,7 @@ static void kvm_openpic_class_init(ObjectClass *oc, void *data)
dc->realize = kvm_openpic_realize;
dc->props = kvm_openpic_properties;
dc->reset = kvm_openpic_reset;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo kvm_openpic_info = {

View File

@@ -88,7 +88,8 @@ static inline DeviceState *milkymist_pfpu_create(hwaddr base,
#ifdef CONFIG_OPENGL
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <epoxy/gl.h>
#include <epoxy/glx.h>
static const int glx_fbconfig_attr[] = {
GLX_GREEN_SIZE, 5,
GLX_GREEN_SIZE, 6,

View File

@@ -33,8 +33,7 @@ typedef struct pc_dimms_capacity {
} pc_dimms_capacity;
void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
MemoryRegion *mr, uint64_t align, bool gap,
Error **errp)
MemoryRegion *mr, uint64_t align, Error **errp)
{
int slot;
MachineState *machine = MACHINE(qdev_get_machine());
@@ -50,7 +49,7 @@ void pc_dimm_memory_plug(DeviceState *dev, MemoryHotplugState *hpms,
addr = pc_dimm_get_free_addr(hpms->base,
memory_region_size(&hpms->mr),
!addr ? NULL : &addr, align, gap,
!addr ? NULL : &addr, align,
memory_region_size(mr), &local_err);
if (local_err) {
goto out;
@@ -180,7 +179,7 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque)
NULL);
di->memdev = object_get_canonical_path(OBJECT(dimm->hostmem));
info->dimm = di;
info->u.dimm = di;
elem->value = info;
elem->next = NULL;
**prev = elem;
@@ -204,9 +203,9 @@ ram_addr_t get_current_ram_size(void)
MemoryDeviceInfo *value = info->value;
if (value) {
switch (value->kind) {
switch (value->type) {
case MEMORY_DEVICE_INFO_KIND_DIMM:
size += value->dimm->size;
size += value->u.dimm->size;
break;
default:
break;
@@ -295,8 +294,8 @@ static int pc_dimm_built_list(Object *obj, void *opaque)
uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
uint64_t address_space_size,
uint64_t *hint, uint64_t align, bool gap,
uint64_t size, Error **errp)
uint64_t *hint, uint64_t align, uint64_t size,
Error **errp)
{
GSList *list = NULL, *item;
uint64_t new_addr, ret = 0;
@@ -341,15 +340,13 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
goto out;
}
if (ranges_overlap(dimm->addr, dimm_size, new_addr,
size + (gap ? 1 : 0))) {
if (ranges_overlap(dimm->addr, dimm_size, new_addr, size)) {
if (hint) {
DeviceState *d = DEVICE(dimm);
error_setg(errp, "address range conflicts with '%s'", d->id);
goto out;
}
new_addr = QEMU_ALIGN_UP(dimm->addr + dimm_size + (gap ? 1 : 0),
align);
new_addr = QEMU_ALIGN_UP(dimm->addr + dimm_size, align);
}
}
ret = new_addr;

View File

@@ -901,7 +901,7 @@ static void main_cpu_reset(void *opaque)
if (kvm_enabled()) {
/* Start running from the bootloader we wrote to end of RAM */
env->active_tc.PC = 0x40000000 + loaderparams.ram_size;
env->active_tc.PC = 0x40000000 + loaderparams.ram_low_size;
}
}

View File

@@ -16,14 +16,18 @@
#define CKIH_FREQ 26000000 /* 26MHz crystal input */
#define CKIL_FREQ 32768 /* nominal 32khz clock */
//#define DEBUG_CCM 1
#ifdef DEBUG_CCM
#define DPRINTF(fmt, args...) \
do { printf("%s: " fmt , TYPE_IMX_CCM, ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while (0)
#ifndef DEBUG_IMX_CCM
#define DEBUG_IMX_CCM 0
#endif
#define DPRINTF(fmt, args...) \
do { \
if (DEBUG_IMX_CCM) { \
fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_CCM, \
__func__, ##args); \
} \
} while (0)
static int imx_ccm_post_load(void *opaque, int version_id);
static const VMStateDescription vmstate_imx_ccm = {
@@ -109,7 +113,7 @@ static void update_clocks(IMXCCMState *s)
s->hsp_clk_freq = s->mcu_clk_freq / (1 + EXTRACT(s->pdr0, HSP));
s->ipg_clk_freq = s->hsp_clk_freq / (1 + EXTRACT(s->pdr0, IPG));
DPRINTF("%s: mcu %uMHz, HSP %uMHz, IPG %uHz\n", __func__,
DPRINTF("mcu %uMHz, HSP %uMHz, IPG %uHz\n",
s->mcu_clk_freq / 1000000,
s->hsp_clk_freq / 1000000,
s->ipg_clk_freq);
@@ -135,7 +139,8 @@ static uint64_t imx_ccm_read(void *opaque, hwaddr offset,
{
IMXCCMState *s = (IMXCCMState *)opaque;
DPRINTF("%s(offset=%x)", __func__, offset >> 2);
DPRINTF("(offset=0x%" HWADDR_PRIx ")\n", offset);
switch (offset >> 2) {
case 0: /* CCMR */
DPRINTF(" ccmr = 0x%x\n", s->ccmr);
@@ -166,9 +171,11 @@ static uint64_t imx_ccm_read(void *opaque, hwaddr offset,
case 23:
DPRINTF(" pcmr0 = 0x%x\n", s->pmcr0);
return s->pmcr0;
default:
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset);
return 0;
}
DPRINTF(" return 0\n");
return 0;
}
static void imx_ccm_write(void *opaque, hwaddr offset,
@@ -176,8 +183,9 @@ static void imx_ccm_write(void *opaque, hwaddr offset,
{
IMXCCMState *s = (IMXCCMState *)opaque;
DPRINTF("%s(offset=%x, value = %x)\n", __func__,
offset >> 2, (unsigned int)value);
DPRINTF("(offset=0x%" HWADDR_PRIx ", value = 0x%x)\n",
offset, (unsigned int)value);
switch (offset >> 2) {
case 0:
s->ccmr = CCMR_FPMF | (value & 0x3b6fdfff);
@@ -205,6 +213,8 @@ static void imx_ccm_write(void *opaque, hwaddr offset,
return;
default:
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset);
return;
}
update_clocks(s);

File diff suppressed because it is too large Load Diff

View File

@@ -738,6 +738,7 @@ static void cuda_class_init(ObjectClass *oc, void *data)
dc->reset = cuda_reset;
dc->vmsd = &vmstate_cuda;
dc->props = cuda_properties;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo cuda_type_info = {

View File

@@ -393,6 +393,7 @@ static void macio_class_init(ObjectClass *klass, void *data)
k->vendor_id = PCI_VENDOR_ID_APPLE;
k->class_id = PCI_CLASS_OTHERS << 8;
dc->props = macio_properties;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo macio_oldworld_type_info = {

View File

@@ -964,6 +964,7 @@ static void gem_reset(DeviceState *d)
{
int i;
CadenceGEMState *s = CADENCE_GEM(d);
const uint8_t *a;
DB_PRINT("\n");
@@ -982,6 +983,11 @@ static void gem_reset(DeviceState *d)
s->regs[GEM_DESCONF5] = 0x002f2145;
s->regs[GEM_DESCONF6] = 0x00000200;
/* Set MAC address */
a = &s->conf.macaddr.a[0];
s->regs[GEM_SPADDR1LO] = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24);
s->regs[GEM_SPADDR1HI] = a[4] | (a[5] << 8);
for (i = 0; i < 4; i++) {
s->sar_active[i] = false;
}

View File

@@ -27,31 +27,29 @@
/* For crc32 */
#include <zlib.h>
#ifndef IMX_FEC_DEBUG
#define IMX_FEC_DEBUG 0
#ifndef DEBUG_IMX_FEC
#define DEBUG_IMX_FEC 0
#endif
#ifndef IMX_PHY_DEBUG
#define IMX_PHY_DEBUG 0
#endif
#if IMX_FEC_DEBUG
#define FEC_PRINTF(fmt, ...) \
do { fprintf(stderr, "%s[%s]: " fmt , TYPE_IMX_FEC, __func__, \
## __VA_ARGS__); \
#define FEC_PRINTF(fmt, args...) \
do { \
if (DEBUG_IMX_FEC) { \
fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_FEC, \
__func__, ##args); \
} \
} while (0)
#else
#define FEC_PRINTF(fmt, ...) do {} while (0)
#ifndef DEBUG_IMX_PHY
#define DEBUG_IMX_PHY 0
#endif
#if IMX_PHY_DEBUG
#define PHY_PRINTF(fmt, ...) \
do { fprintf(stderr, "%s.phy[%s]: " fmt , TYPE_IMX_FEC, __func__, \
## __VA_ARGS__); \
#define PHY_PRINTF(fmt, args...) \
do { \
if (DEBUG_IMX_PHY) { \
fprintf(stderr, "[%s.phy]%s: " fmt , TYPE_IMX_FEC, \
__func__, ##args); \
} \
} while (0)
#else
#define PHY_PRINTF(fmt, ...) do {} while (0)
#endif
static const VMStateDescription vmstate_imx_fec = {
.name = TYPE_IMX_FEC,
@@ -182,12 +180,12 @@ static uint32_t do_phy_read(IMXFECState *s, int reg)
case 18:
case 27:
case 31:
qemu_log_mask(LOG_UNIMP, "%s.phy[%s]: reg %d not implemented\n",
qemu_log_mask(LOG_UNIMP, "[%s.phy]%s: reg %d not implemented\n",
TYPE_IMX_FEC, __func__, reg);
val = 0;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
TYPE_IMX_FEC, __func__, reg);
val = 0;
break;
@@ -230,11 +228,11 @@ static void do_phy_write(IMXFECState *s, int reg, uint32_t val)
case 18:
case 27:
case 31:
qemu_log_mask(LOG_UNIMP, "%s.phy[%s]: reg %d not implemented\n",
qemu_log_mask(LOG_UNIMP, "[%s.phy)%s: reg %d not implemented\n",
TYPE_IMX_FEC, __func__, reg);
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s.phy[%s]: Bad address at offset %d\n",
qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad address at offset %d\n",
TYPE_IMX_FEC, __func__, reg);
break;
}
@@ -357,7 +355,7 @@ static uint64_t imx_fec_read(void *opaque, hwaddr addr, unsigned size)
{
IMXFECState *s = IMX_FEC(opaque);
FEC_PRINTF("reading from @ 0x%03x\n", (int)addr);
FEC_PRINTF("reading from @ 0x%" HWADDR_PRIx "\n", addr);
switch (addr & 0x3ff) {
case 0x004:
@@ -417,8 +415,8 @@ static uint64_t imx_fec_read(void *opaque, hwaddr addr, unsigned size)
case 0x308:
return s->miigsk_enr;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_FEC, __func__, (int)addr);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_FEC, __func__, addr);
return 0;
}
}
@@ -428,7 +426,7 @@ static void imx_fec_write(void *opaque, hwaddr addr,
{
IMXFECState *s = IMX_FEC(opaque);
FEC_PRINTF("writing 0x%08x @ 0x%03x\n", (int)value, (int)addr);
FEC_PRINTF("writing 0x%08x @ 0x%" HWADDR_PRIx "\n", (int)value, addr);
switch (addr & 0x3ff) {
case 0x004: /* EIR */
@@ -530,8 +528,8 @@ static void imx_fec_write(void *opaque, hwaddr addr,
s->miigsk_enr = (value & 0x2) ? 0x6 : 0;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
TYPE_IMX_FEC, __func__, (int)addr);
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
HWADDR_PRIx "\n", TYPE_IMX_FEC, __func__, addr);
break;
}
@@ -561,7 +559,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
FEC_PRINTF("len %d\n", (int)size);
if (!s->rx_enabled) {
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Unexpected packet\n",
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n",
TYPE_IMX_FEC, __func__);
return 0;
}
@@ -592,14 +590,16 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
* save the remainder for when more RX buffers are
* available, or flag an error.
*/
qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Lost end of frame\n",
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Lost end of frame\n",
TYPE_IMX_FEC, __func__);
break;
}
buf_len = (size <= s->emrbr) ? size : s->emrbr;
bd.length = buf_len;
size -= buf_len;
FEC_PRINTF("rx_bd %x length %d\n", addr, bd.length);
FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length);
/* The last 4 bytes are the CRC. */
if (size < 4) {
buf_len += size - 4;

View File

@@ -1289,6 +1289,10 @@ static uint32_t vmxnet3_get_interrupt_config(VMXNET3State *s)
static void vmxnet3_fill_stats(VMXNET3State *s)
{
int i;
if (!s->device_active)
return;
for (i = 0; i < s->txq_num; i++) {
cpu_physical_memory_write(s->txq_descr[i].tx_stats_pa,
&s->txq_descr[i].txq_stats,

View File

@@ -123,6 +123,7 @@ static void macio_nvram_class_init(ObjectClass *oc, void *data)
dc->reset = macio_nvram_reset;
dc->vmsd = &vmstate_macio_nvram;
dc->props = macio_nvram_properties;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
}
static const TypeInfo macio_nvram_type_info = {

View File

@@ -146,8 +146,10 @@ static const TypeInfo grackle_pci_info = {
static void pci_grackle_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
k->init = pci_grackle_init_device;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo grackle_pci_host_info = {

View File

@@ -446,8 +446,10 @@ static const TypeInfo unin_internal_pci_host_info = {
static void pci_unin_main_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
sbc->init = pci_unin_main_init_device;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo pci_unin_main_info = {
@@ -460,8 +462,10 @@ static const TypeInfo pci_unin_main_info = {
static void pci_u3_agp_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
sbc->init = pci_u3_agp_init_device;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo pci_u3_agp_info = {
@@ -474,8 +478,10 @@ static const TypeInfo pci_u3_agp_info = {
static void pci_unin_agp_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
sbc->init = pci_unin_agp_init_device;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo pci_unin_agp_info = {
@@ -488,8 +494,10 @@ static const TypeInfo pci_unin_agp_info = {
static void pci_unin_internal_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
sbc->init = pci_unin_internal_init_device;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}
static const TypeInfo pci_unin_internal_info = {

View File

@@ -200,8 +200,14 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
return pci_get_long(dev->msix_pba + addr);
}
static void msix_pba_mmio_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
}
static const MemoryRegionOps msix_pba_mmio_ops = {
.read = msix_pba_mmio_read,
.write = msix_pba_mmio_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,

View File

@@ -847,6 +847,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
PCIConfigWriteFunc *config_write = pc->config_write;
Error *local_err = NULL;
AddressSpace *dma_as;
DeviceState *dev = DEVICE(pci_dev);
pci_dev->bus = bus;
if (devfn < 0) {
for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices);
@@ -864,9 +867,17 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
PCI_SLOT(devfn), PCI_FUNC(devfn), name,
bus->devices[devfn]->name);
return NULL;
} else if (dev->hotplugged &&
pci_get_function_0(pci_dev)) {
error_setg(errp, "PCI: slot %d function 0 already ocuppied by %s,"
" new func %s cannot be exposed to guest.",
PCI_SLOT(devfn),
bus->devices[PCI_DEVFN(PCI_SLOT(devfn), 0)]->name,
name);
return NULL;
}
pci_dev->bus = bus;
pci_dev->devfn = devfn;
dma_as = pci_device_iommu_address_space(pci_dev);
@@ -2454,6 +2465,33 @@ void pci_bus_get_w64_range(PCIBus *bus, Range *range)
pci_for_each_device_under_bus(bus, pci_dev_get_w64, range);
}
static bool pcie_has_upstream_port(PCIDevice *dev)
{
PCIDevice *parent_dev = pci_bridge_get_device(dev->bus);
/* Device associated with an upstream port.
* As there are several types of these, it's easier to check the
* parent device: upstream ports are always connected to
* root or downstream ports.
*/
return parent_dev &&
pci_is_express(parent_dev) &&
parent_dev->exp.exp_cap &&
(pcie_cap_get_type(parent_dev) == PCI_EXP_TYPE_ROOT_PORT ||
pcie_cap_get_type(parent_dev) == PCI_EXP_TYPE_DOWNSTREAM);
}
PCIDevice *pci_get_function_0(PCIDevice *pci_dev)
{
if(pcie_has_upstream_port(pci_dev)) {
/* With an upstream PCIe port, we only support 1 device at slot 0 */
return pci_dev->bus->devices[0];
} else {
/* Other bus types might support multiple devices at slots 0-31 */
return pci_dev->bus->devices[PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 0)];
}
}
static const TypeInfo pci_device_type_info = {
.name = TYPE_PCI_DEVICE,
.parent = TYPE_DEVICE,

View File

@@ -20,6 +20,7 @@
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/pci/pci_bus.h"
#include "trace.h"
/* debug PCI */
@@ -52,6 +53,13 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t limit, uint32_t val, uint32_t len)
{
assert(len <= 4);
/* non-zero functions are only exposed when function 0 is present,
* allowing direct removal of unexposed functions.
*/
if (pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) {
return;
}
trace_pci_cfg_write(pci_dev->name, PCI_SLOT(pci_dev->devfn),
PCI_FUNC(pci_dev->devfn), addr, val);
pci_dev->config_write(pci_dev, addr, val, MIN(len, limit - addr));
@@ -63,6 +71,13 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t ret;
assert(len <= 4);
/* non-zero functions are only exposed when function 0 is present,
* allowing direct removal of unexposed functions.
*/
if (pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) {
return ~0x0;
}
ret = pci_dev->config_read(pci_dev, addr, MIN(len, limit - addr));
trace_pci_cfg_read(pci_dev->name, PCI_SLOT(pci_dev->devfn),
PCI_FUNC(pci_dev->devfn), addr, ret);

View File

@@ -249,25 +249,43 @@ void pcie_cap_slot_hotplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
return;
}
/* TODO: multifunction hot-plug.
* Right now, only a device of function = 0 is allowed to be
* hot plugged/unplugged.
/* To enable multifunction hot-plug, we just ensure the function
* 0 added last. When function 0 is added, we set the sltsta and
* inform OS via event notification.
*/
assert(PCI_FUNC(pci_dev->devfn) == 0);
if (pci_get_function_0(pci_dev)) {
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_PDS);
pcie_cap_slot_event(PCI_DEVICE(hotplug_dev),
PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
}
}
pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
PCI_EXP_SLTSTA_PDS);
pcie_cap_slot_event(PCI_DEVICE(hotplug_dev),
PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
{
object_unparent(OBJECT(dev));
}
void pcie_cap_slot_hot_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
uint8_t *exp_cap;
PCIDevice *pci_dev = PCI_DEVICE(dev);
PCIBus *bus = pci_dev->bus;
pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);
/* In case user cancel the operation of multi-function hot-add,
* remove the function that is unexposed to guest individually,
* without interaction with guest.
*/
if (pci_dev->devfn &&
!bus->devices[0]) {
pcie_unplug_device(bus, pci_dev, NULL);
return;
}
pcie_cap_slot_push_attention_button(PCI_DEVICE(hotplug_dev));
}
@@ -378,11 +396,6 @@ void pcie_cap_slot_reset(PCIDevice *dev)
hotplug_event_update_event_status(dev);
}
static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
{
object_unparent(OBJECT(dev));
}
void pcie_cap_slot_write_config(PCIDevice *dev,
uint32_t addr, uint32_t val, int len)
{

View File

@@ -42,11 +42,9 @@
#include "sysemu/arch_init.h"
#include "sysemu/qtest.h"
#include "exec/address-spaces.h"
#include "trace.h"
#include "elf.h"
//#define HARD_DEBUG_PPC_IO
//#define DEBUG_PPC_IO
/* SMP is not enabled, for now */
#define MAX_CPUS 1
@@ -57,26 +55,6 @@
#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
#define DEBUG_PPC_IO
#endif
#if defined (HARD_DEBUG_PPC_IO)
#define PPC_IO_DPRINTF(fmt, ...) \
do { \
if (qemu_loglevel_mask(CPU_LOG_IOPORT)) { \
qemu_log("%s: " fmt, __func__ , ## __VA_ARGS__); \
} else { \
printf("%s : " fmt, __func__ , ## __VA_ARGS__); \
} \
} while (0)
#elif defined (DEBUG_PPC_IO)
#define PPC_IO_DPRINTF(fmt, ...) \
qemu_log_mask(CPU_LOG_IOPORT, fmt, ## __VA_ARGS__)
#else
#define PPC_IO_DPRINTF(fmt, ...) do { } while (0)
#endif
/* Constants for devices init */
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
@@ -199,8 +177,7 @@ static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
{
sysctrl_t *sysctrl = opaque;
PPC_IO_DPRINTF("0x%08" PRIx32 " => 0x%02" PRIx32 "\n",
addr - PPC_IO_BASE, val);
trace_prep_io_800_writeb(addr - PPC_IO_BASE, val);
switch (addr) {
case 0x0092:
/* Special port 92 */
@@ -327,8 +304,7 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
printf("ERROR: unaffected IO port: %04" PRIx32 " read\n", addr);
break;
}
PPC_IO_DPRINTF("0x%08" PRIx32 " <= 0x%02" PRIx32 "\n",
addr - PPC_IO_BASE, retval);
trace_prep_io_800_readb(addr - PPC_IO_BASE, retval);
return retval;
}

View File

@@ -597,6 +597,24 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
uint32_t vcpus_per_socket = smp_threads * smp_cores;
uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
/* Note: we keep CI large pages off for now because a 64K capable guest
* provisioned with large pages might otherwise try to map a qemu
* framebuffer (or other kind of memory mapped PCI BAR) using 64K pages
* even if that qemu runs on a 4k host.
*
* We can later add this bit back when we are confident this is not
* an issue (!HV KVM or 64K host)
*/
uint8_t pa_features_206[] = { 6, 0,
0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
uint8_t pa_features_207[] = { 24, 0,
0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
uint8_t *pa_features;
size_t pa_size;
_FDT((fdt_setprop_cell(fdt, offset, "reg", index)));
_FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
@@ -625,6 +643,7 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
_FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
_FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
_FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr)));
_FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr)));
_FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
_FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
@@ -662,6 +681,19 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
page_sizes_prop, page_sizes_prop_size)));
}
/* Do the ibm,pa-features property, adjust it for ci-large-pages */
if (env->mmu_model == POWERPC_MMU_2_06) {
pa_features = pa_features_206;
pa_size = sizeof(pa_features_206);
} else /* env->mmu_model == POWERPC_MMU_2_07 */ {
pa_features = pa_features_207;
pa_size = sizeof(pa_features_207);
}
if (env->ci_large_pages) {
pa_features[3] |= 0x20;
}
_FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
_FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id",
cs->cpu_index / vcpus_per_socket)));
@@ -979,7 +1011,7 @@ static void emulate_spapr_hypercall(PowerPCCPU *cpu)
#define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY))
#define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY))
static void spapr_reset_htab(sPAPRMachineState *spapr)
static void spapr_alloc_htab(sPAPRMachineState *spapr)
{
long shift;
int index;
@@ -992,20 +1024,47 @@ static void spapr_reset_htab(sPAPRMachineState *spapr)
if (shift > 0) {
/* Kernel handles htab, we don't need to allocate one */
if (shift != spapr->htab_shift) {
error_setg(&error_abort, "Failed to allocate HTAB of requested size, try with smaller maxmem");
}
spapr->htab_shift = shift;
kvmppc_kern_htab = true;
} else {
/* Allocate htab */
spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
/* And clear it */
memset(spapr->htab, 0, HTAB_SIZE(spapr));
for (index = 0; index < HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; index++) {
DIRTY_HPTE(HPTE(spapr->htab, index));
}
}
}
/*
* Clear HTAB entries during reset.
*
* If host kernel has allocated HTAB, KVM_PPC_ALLOCATE_HTAB ioctl is
* used to clear HTAB. Otherwise QEMU-allocated HTAB is cleared manually.
*/
static void spapr_reset_htab(sPAPRMachineState *spapr)
{
long shift;
int index;
shift = kvmppc_reset_htab(spapr->htab_shift);
if (shift > 0) {
if (shift != spapr->htab_shift) {
error_setg(&error_abort, "Requested HTAB allocation failed during reset");
}
/* Tell readers to update their file descriptor */
if (spapr->htab_fd >= 0) {
spapr->htab_fd_stale = true;
}
} else {
if (!spapr->htab) {
/* Allocate an htab if we don't yet have one */
spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr));
}
/* And clear it */
memset(spapr->htab, 0, HTAB_SIZE(spapr));
for (index = 0; index < HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; index++) {
@@ -1710,6 +1769,7 @@ static void ppc_spapr_init(MachineState *machine)
}
spapr->htab_shift++;
}
spapr_alloc_htab(spapr);
/* Set up Interrupt Controller before we create the VCPUs */
spapr->icp = xics_system_init(machine,
@@ -2097,7 +2157,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
goto out;
}
pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, false, &local_err);
pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err);
if (local_err) {
goto out;
}
@@ -2225,7 +2285,11 @@ static const TypeInfo spapr_machine_info = {
},
};
#define SPAPR_COMPAT_2_4 \
HW_COMPAT_2_4
#define SPAPR_COMPAT_2_3 \
SPAPR_COMPAT_2_4 \
HW_COMPAT_2_3 \
{\
.driver = "spapr-pci-host-bridge",\
@@ -2339,11 +2403,16 @@ static const TypeInfo spapr_machine_2_3_info = {
static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data)
{
static GlobalProperty compat_props[] = {
SPAPR_COMPAT_2_4
{ /* end of list */ }
};
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4";
mc->alias = "pseries";
mc->is_default = 0;
mc->compat_props = compat_props;
}
static const TypeInfo spapr_machine_2_4_info = {

View File

@@ -146,7 +146,7 @@ static int spapr_tce_table_realize(DeviceState *dev)
tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
window_size,
&tcet->fd,
tcet->vfio_accel);
tcet->need_vfio);
}
if (!tcet->table) {
@@ -168,11 +168,43 @@ static int spapr_tce_table_realize(DeviceState *dev)
return 0;
}
void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio)
{
size_t table_size = tcet->nb_table * sizeof(uint64_t);
void *newtable;
if (need_vfio == tcet->need_vfio) {
/* Nothing to do */
return;
}
if (!need_vfio) {
/* FIXME: We don't support transition back to KVM accelerated
* TCEs yet */
return;
}
tcet->need_vfio = true;
if (tcet->fd < 0) {
/* Table is already in userspace, nothing to be do */
return;
}
newtable = g_malloc(table_size);
memcpy(newtable, tcet->table, table_size);
kvmppc_remove_spapr_tce(tcet->table, tcet->fd, tcet->nb_table);
tcet->fd = -1;
tcet->table = newtable;
}
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
uint64_t bus_offset,
uint32_t page_shift,
uint32_t nb_table,
bool vfio_accel)
bool need_vfio)
{
sPAPRTCETable *tcet;
char tmp[64];
@@ -192,7 +224,7 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
tcet->bus_offset = bus_offset;
tcet->page_shift = page_shift;
tcet->nb_table = nb_table;
tcet->vfio_accel = vfio_accel;
tcet->need_vfio = need_vfio;
snprintf(tmp, sizeof(tmp), "tce-table-%x", liobn);
object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet), NULL);

View File

@@ -1083,6 +1083,12 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
void *fdt = NULL;
int fdt_start_offset = 0, fdt_size;
if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
sPAPRTCETable *tcet = spapr_tce_find_by_liobn(phb->dma_liobn);
spapr_tce_set_need_vfio(tcet, true);
}
if (dev->hotplugged) {
fdt = create_device_tree(&fdt_size);
fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0);
@@ -1387,7 +1393,7 @@ static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp)
sPAPRTCETable *tcet;
uint32_t nb_table;
nb_table = SPAPR_PCI_DMA32_SIZE >> SPAPR_TCE_PAGE_SHIFT;
nb_table = sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT;
tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
0, SPAPR_TCE_PAGE_SHIFT, nb_table, false);
if (!tcet) {
@@ -1397,7 +1403,7 @@ static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp)
}
/* Register default 32bit DMA window */
memory_region_add_subregion(&sphb->iommu_root, 0,
memory_region_add_subregion(&sphb->iommu_root, sphb->dma_win_addr,
spapr_tce_get_iommu(tcet));
}
@@ -1430,6 +1436,9 @@ static Property spapr_phb_properties[] = {
SPAPR_PCI_IO_WIN_SIZE),
DEFINE_PROP_BOOL("dynamic-reconfiguration", sPAPRPHBState, dr_enabled,
true),
/* Default DMA window is 0..1GB */
DEFINE_PROP_UINT64("dma_win_addr", sPAPRPHBState, dma_win_addr, 0),
DEFINE_PROP_UINT64("dma_win_size", sPAPRPHBState, dma_win_size, 0x40000000),
DEFINE_PROP_END_OF_LIST(),
};

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