[PULL 19/25] tests/qapi-schema: Drop simple union __org.qemu_x-Union1

2021-09-24 Thread Markus Armbruster
Replace simple union __org.qemu_x-Union1 with flat union
__org.qemu_x-Union2, except drop it from __org.qemu_x-command, because
there it's only used to pull it into QMP.  Now drop the unused
-Union1, and rename -Union2 to -Union.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-20-arm...@redhat.com>
---
 tests/unit/test-qmp-cmds.c  | 16 +---
 tests/qapi-schema/qapi-schema-test.json |  8 +++-
 tests/qapi-schema/qapi-schema-test.out  | 18 +-
 3 files changed, 13 insertions(+), 29 deletions(-)

diff --git a/tests/unit/test-qmp-cmds.c b/tests/unit/test-qmp-cmds.c
index 83c9ef5b7c..faa858624a 100644
--- a/tests/unit/test-qmp-cmds.c
+++ b/tests/unit/test-qmp-cmds.c
@@ -127,22 +127,16 @@ void qmp_boxed_empty(Empty1 *arg, Error **errp)
 {
 }
 
-__org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
-  __org_qemu_x_StructList *b,
-  __org_qemu_x_Union2 *c,
-  __org_qemu_x_Alt *d,
-  Error **errp)
+void qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
+  __org_qemu_x_StructList *b,
+  __org_qemu_x_Union *c,
+  __org_qemu_x_Alt *d,
+  Error **errp)
 {
-__org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
-
-ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
-ret->u.__org_qemu_x_branch.data = strdup("blah1");
-
 /* Also test that 'wchar-t' was munged to 'q_wchar_t' */
 if (b && b->value && !b->value->has_q_wchar_t) {
 b->value->q_wchar_t = 1;
 }
-return ret;
 }
 
 
diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index ef17ab1aae..20f4cc0cfa 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -202,11 +202,10 @@
   'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
 { 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
   'data': { '__org.qemu_x-member2': 'str', '*wchar-t': 'int' } }
-{ 'union': '__org.qemu_x-Union1', 'data': { '__org.qemu_x-branch': 'str' } }
 { 'alternate': '__org.qemu_x-Alt1', 'data': { '__org.qemu_x-branch': 'str' } }
 { 'struct': '__org.qemu_x-Struct2',
-  'data': { 'array': ['__org.qemu_x-Union1'] } }
-{ 'union': '__org.qemu_x-Union2', 'base': '__org.qemu_x-Base',
+  'data': { 'array': ['__org.qemu_x-Union'] } }
+{ 'union': '__org.qemu_x-Union', 'base': '__org.qemu_x-Base',
   'discriminator': '__org.qemu_x-member1',
   'data': { '__org.qemu_x-value': '__org.qemu_x-Struct2' } }
 { 'alternate': '__org.qemu_x-Alt',
@@ -214,8 +213,7 @@
 { 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
 { 'command': '__org.qemu_x-command',
   'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
-'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' },
-  'returns': '__org.qemu_x-Union1' }
+'c': '__org.qemu_x-Union', 'd': '__org.qemu_x-Alt' } }
 
 # test 'if' condition handling
 
diff --git a/tests/qapi-schema/qapi-schema-test.out 
b/tests/qapi-schema/qapi-schema-test.out
index 07e4161331..9337adc9ea 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -215,21 +215,13 @@ object __org.qemu_x-Struct
 base __org.qemu_x-Base
 member __org.qemu_x-member2: str optional=False
 member wchar-t: int optional=True
-object q_obj_str-wrapper
-member data: str optional=False
-enum __org.qemu_x-Union1Kind
-member __org.qemu_x-branch
-object __org.qemu_x-Union1
-member type: __org.qemu_x-Union1Kind optional=False
-tag type
-case __org.qemu_x-branch: q_obj_str-wrapper
 alternate __org.qemu_x-Alt1
 tag type
 case __org.qemu_x-branch: str
-array __org.qemu_x-Union1List __org.qemu_x-Union1
+array __org.qemu_x-UnionList __org.qemu_x-Union
 object __org.qemu_x-Struct2
-member array: __org.qemu_x-Union1List optional=False
-object __org.qemu_x-Union2
+member array: __org.qemu_x-UnionList optional=False
+object __org.qemu_x-Union
 base __org.qemu_x-Base
 tag __org.qemu_x-member1
 case __org.qemu_x-value: __org.qemu_x-Struct2
@@ -243,9 +235,9 @@ array __org.qemu_x-StructList __org.qemu_x-Struct
 object q_obj___org.qemu_x-command-arg
 member a: __org.qemu_x-EnumList optional=False
 member b: __org.qemu_x-StructList optional=False
-member c: __org.qemu_x-Union2 optional=False
+member c: __org.qemu_x-Union optional=False
 member d: __org.qemu_x-Alt optional=False
-command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> 
__org.qemu_x-Union1
+command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> None
 gen=True success_response=True boxed=False oob=False preconfig=False
 object TestIfStruct
 member foo

[PULL 22/25] tests/qapi-schema: Rename flat-union-* test cases to union-*

2021-09-24 Thread Markus Armbruster
Signed-off-by: Markus Armbruster 
Message-Id: <20210917143134.412106-23-arm...@redhat.com>
Reviewed-by: Eric Blake  union-array-branch.json} |  0
 ...rray-branch.out => union-array-branch.out} |  0
 tests/qapi-schema/union-bad-base.err  |  2 ++
 ...nion-bad-base.json => union-bad-base.json} |  0
 ...-union-bad-base.out => union-bad-base.out} |  0
 tests/qapi-schema/union-bad-discriminator.err |  2 ++
 ...ator.json => union-bad-discriminator.json} |  0
 ...inator.out => union-bad-discriminator.out} |  0
 tests/qapi-schema/union-base-any.err  |  2 ++
 ...nion-base-any.json => union-base-any.json} |  0
 ...-union-base-any.out => union-base-any.out} |  0
 tests/qapi-schema/union-base-union.err|  2 ++
 ...-base-union.json => union-base-union.json} |  0
 ...on-base-union.out => union-base-union.out} |  0
 tests/qapi-schema/union-clash-member.err  |  2 ++
 ...sh-member.json => union-clash-member.json} |  0
 ...lash-member.out => union-clash-member.out} |  0
 .../union-discriminator-bad-name.err  |  2 ++
 ...json => union-discriminator-bad-name.json} |  0
 ...e.out => union-discriminator-bad-name.out} |  0
 tests/qapi-schema/union-empty.err |  2 ++
 ...flat-union-empty.json => union-empty.json} |  0
 .../{flat-union-empty.out => union-empty.out} |  0
 .../qapi-schema/union-inline-invalid-dict.err |  2 ++
 ...ct.json => union-inline-invalid-dict.json} |  0
 ...dict.out => union-inline-invalid-dict.out} |  0
 tests/qapi-schema/union-int-branch.err|  2 ++
 ...-int-branch.json => union-int-branch.json} |  0
 ...on-int-branch.out => union-int-branch.out} |  0
 .../qapi-schema/union-invalid-branch-key.err  |  2 ++
 ...key.json => union-invalid-branch-key.json} |  0
 ...h-key.out => union-invalid-branch-key.out} |  0
 .../union-invalid-discriminator.err   |  2 ++
 json => union-invalid-discriminator.json} |  0
 ...or.out => union-invalid-discriminator.out} |  0
 .../union-invalid-if-discriminator.err|  2 ++
 ...on => union-invalid-if-discriminator.json} |  0
 ...out => union-invalid-if-discriminator.out} |  0
 tests/qapi-schema/union-no-base.err   |  2 ++
 ...-union-no-base.json => union-no-base.json} |  0
 ...at-union-no-base.out => union-no-base.out} |  0
 .../union-optional-discriminator.err  |  2 ++
 ...json => union-optional-discriminator.json} |  0
 ...r.out => union-optional-discriminator.out} |  0
 .../union-string-discriminator.err|  2 ++
 ...r.json => union-string-discriminator.json} |  0
 ...tor.out => union-string-discriminator.out} |  0
 65 files changed, 48 insertions(+), 48 deletions(-)
 delete mode 100644 tests/qapi-schema/flat-union-array-branch.err
 delete mode 100644 tests/qapi-schema/flat-union-bad-base.err
 delete mode 100644 tests/qapi-schema/flat-union-bad-discriminator.err
 delete mode 100644 tests/qapi-schema/flat-union-base-any.err
 delete mode 100644 tests/qapi-schema/flat-union-base-union.err
 delete mode 100644 tests/qapi-schema/flat-union-clash-member.err
 delete mode 100644 tests/qapi-schema/flat-union-discriminator-bad-name.err
 delete mode 100644 tests/qapi-schema/flat-union-empty.err
 delete mode 100644 tests/qapi-schema/flat-union-inline-invalid-dict.err
 delete mode 100644 tests/qapi-schema/flat-union-int-branch.err
 delete mode 100644 tests/qapi-schema/flat-union-invalid-branch-key.err
 delete mode 100644 tests/qapi-schema/flat-union-invalid-discriminator.err
 delete mode 100644 tests/qapi-schema/flat-union-invalid-if-discriminator.err
 delete mode 100644 tests/qapi-schema/flat-union-no-base.err
 delete mode 100644 tests/qapi-schema/flat-union-optional-discriminator.err
 delete mode 100644 tests/qapi-schema/flat-union-string-discriminator.err
 create mode 100644 tests/qapi-schema/union-array-branch.err
 rename tests/qapi-schema/{flat-union-array-branch.json => 
union-array-branch.json} (100%)
 rename tests/qapi-schema/{flat-union-array-branch.out => 
union-array-branch.out} (100%)
 create mode 100644 tests/qapi-schema/union-bad-base.err
 rename tests/qapi-schema/{flat-union-bad-base.json => union-bad-base.json} 
(100%)
 rename tests/qapi-schema/{flat-union-bad-base.out => union-bad-base.out} (100%)
 create mode 100644 tests/qapi-schema/union-bad-discriminator.err
 rename tests/qapi-schema/{flat-union-bad-discriminator.json => 
union-bad-discriminator.json} (100%)
 rename tests/qapi-schema/{flat-union-bad-discriminator.out => 
union-bad-discriminator.out} (100%)
 create mode 100644 tests/qapi-schema/union-base-any.err
 rename tests/qapi-schema/{flat-union-base-any.json => union-base-any.json} 
(100%)
 rename tests/qapi-schema/{flat-union-base-any.out => union-base-any.out} (100%)
 create mode 100644 tests/qapi-schema/union-base-union.err
 rename tests/qapi-schema/{flat-union-base-union.json => union-base-union.json} 
(100%)
 rename tests/qapi-schema/{flat-union-base-union.out => union-base-union.out} 
(100%)
 create mode 100644 tests/qapi-schema/union-clash-member.err
 rename tests/q

[PULL 18/25] test-clone-visitor: Wean off __org.qemu_x-Union1

2021-09-24 Thread Markus Armbruster
test_clone_complex3() uses simple union __org.qemu_x-Union1 to cover
arrays.  Use UserDefOneList instead.  Unions are still covered by
test_clone_complex1().

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-19-arm...@redhat.com>
---
 tests/unit/test-clone-visitor.c | 70 ++---
 1 file changed, 38 insertions(+), 32 deletions(-)

diff --git a/tests/unit/test-clone-visitor.c b/tests/unit/test-clone-visitor.c
index 8357a90e60..4048018607 100644
--- a/tests/unit/test-clone-visitor.c
+++ b/tests/unit/test-clone-visitor.c
@@ -153,42 +153,48 @@ static void test_clone_complex2(void)
 
 static void test_clone_complex3(void)
 {
-__org_qemu_x_Struct2 *src, *dst;
-__org_qemu_x_Union1List *tmp;
+UserDefOneList *src, *dst, *tail;
+UserDefOne *elt;
 
-src = g_new0(__org_qemu_x_Struct2, 1);
-tmp = src->array = g_new0(__org_qemu_x_Union1List, 1);
-tmp->value = g_new0(__org_qemu_x_Union1, 1);
-tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
-tmp->value->u.__org_qemu_x_branch.data = g_strdup("one");
-tmp = tmp->next = g_new0(__org_qemu_x_Union1List, 1);
-tmp->value = g_new0(__org_qemu_x_Union1, 1);
-tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
-tmp->value->u.__org_qemu_x_branch.data = g_strdup("two");
-tmp = tmp->next = g_new0(__org_qemu_x_Union1List, 1);
-tmp->value = g_new0(__org_qemu_x_Union1, 1);
-tmp->value->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
-tmp->value->u.__org_qemu_x_branch.data = g_strdup("three");
+src = NULL;
+elt = g_new0(UserDefOne, 1);
+elt->integer = 3;
+elt->string = g_strdup("three");
+elt->has_enum1 = true;
+elt->enum1 = ENUM_ONE_VALUE3;
+QAPI_LIST_PREPEND(src, elt);
+elt = g_new0(UserDefOne, 1);
+elt->integer = 2;
+elt->string = g_strdup("two");
+QAPI_LIST_PREPEND(src, elt);
+elt = g_new0(UserDefOne, 1);
+elt->integer = 1;
+elt->string = g_strdup("one");
+QAPI_LIST_PREPEND(src, elt);
+
+dst = QAPI_CLONE(UserDefOneList, src);
 
-dst = QAPI_CLONE(__org_qemu_x_Struct2, src);
 g_assert(dst);
-tmp = dst->array;
-g_assert(tmp);
-g_assert(tmp->value);
-g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "one");
-tmp = tmp->next;
-g_assert(tmp);
-g_assert(tmp->value);
-g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "two");
-tmp = tmp->next;
-g_assert(tmp);
-g_assert(tmp->value);
-g_assert_cmpstr(tmp->value->u.__org_qemu_x_branch.data, ==, "three");
-tmp = tmp->next;
-g_assert(!tmp);
+tail = dst;
+elt = tail->value;
+g_assert_cmpint(elt->integer, ==, 1);
+g_assert_cmpstr(elt->string, ==, "one");
+g_assert(!elt->has_enum1);
+tail = tail->next;
+elt = tail->value;
+g_assert_cmpint(elt->integer, ==, 2);
+g_assert_cmpstr(elt->string, ==, "two");
+g_assert(!elt->has_enum1);
+tail = tail->next;
+elt = tail->value;
+g_assert_cmpint(elt->integer, ==, 3);
+g_assert_cmpstr(elt->string, ==, "three");
+g_assert(elt->has_enum1);
+g_assert_cmpint(elt->enum1, ==, ENUM_ONE_VALUE3);
+g_assert(!tail->next);
 
-qapi_free___org_qemu_x_Struct2(src);
-qapi_free___org_qemu_x_Struct2(dst);
+qapi_free_UserDefOneList(src);
+qapi_free_UserDefOneList(dst);
 }
 
 int main(int argc, char **argv)
-- 
2.31.1




[PULL 01/25] qapi: Tidy up unusual line breaks

2021-09-24 Thread Markus Armbruster
Break lines between members instead of within members.

Signed-off-by: Markus Armbruster 
Reviewed-by: Marc-André Lureau 
Message-Id: <20210917143134.412106-2-arm...@redhat.com>
---
 docs/devel/qapi-code-gen.rst| 12 +--
 tests/qapi-schema/doc-good.json |  4 ++--
 tests/qapi-schema/enum-if-invalid.json  |  4 ++--
 tests/qapi-schema/qapi-schema-test.json | 28 -
 4 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index ced7a5ffe1..b154eae82e 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -859,9 +859,9 @@ longhand form of MEMBER.
 Example: a struct type with unconditional member 'foo' and conditional
 member 'bar' ::
 
- { 'struct': 'IfStruct', 'data':
-   { 'foo': 'int',
- 'bar': { 'type': 'int', 'if': 'IFCOND'} } }
+ { 'struct': 'IfStruct',
+   'data': { 'foo': 'int',
+ 'bar': { 'type': 'int', 'if': 'IFCOND'} } }
 
 A union's discriminator may not be conditional.
 
@@ -871,9 +871,9 @@ the longhand form of ENUM-VALUE_.
 Example: an enum type with unconditional value 'foo' and conditional
 value 'bar' ::
 
- { 'enum': 'IfEnum', 'data':
-   [ 'foo',
- { 'name' : 'bar', 'if': 'IFCOND' } ] }
+ { 'enum': 'IfEnum',
+   'data': [ 'foo',
+ { 'name' : 'bar', 'if': 'IFCOND' } ] }
 
 Likewise, features can be conditional.  This requires the longhand
 form of FEATURE_.
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index e0027e4cf6..cbf5c56c4b 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -60,8 +60,8 @@
 #
 # @two is undocumented
 ##
-{ 'enum': 'Enum', 'data':
-  [ { 'name': 'one', 'if': 'IFONE' }, 'two' ],
+{ 'enum': 'Enum',
+  'data': [ { 'name': 'one', 'if': 'IFONE' }, 'two' ],
   'features': [ 'enum-feat' ],
   'if': 'IFCOND' }
 
diff --git a/tests/qapi-schema/enum-if-invalid.json 
b/tests/qapi-schema/enum-if-invalid.json
index 60bd0ef1d7..6bd20041f3 100644
--- a/tests/qapi-schema/enum-if-invalid.json
+++ b/tests/qapi-schema/enum-if-invalid.json
@@ -1,3 +1,3 @@
 # check invalid 'if' type
-{ 'enum': 'TestIfEnum', 'data':
-  [ 'foo', { 'name' : 'bar', 'if': { 'val': 'foo' } } ] }
+{ 'enum': 'TestIfEnum',
+  'data': [ 'foo', { 'name' : 'bar', 'if': { 'val': 'foo' } } ] }
diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index b6c36a9eee..3c43e14e22 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -220,27 +220,27 @@
 
 # test 'if' condition handling
 
-{ 'struct': 'TestIfStruct', 'data':
-  { 'foo': 'int',
-'bar': { 'type': 'int', 'if': 'TEST_IF_STRUCT_BAR'} },
+{ 'struct': 'TestIfStruct',
+  'data': { 'foo': 'int',
+'bar': { 'type': 'int', 'if': 'TEST_IF_STRUCT_BAR'} },
   'if': 'TEST_IF_STRUCT' }
 
-{ 'enum': 'TestIfEnum', 'data':
-  [ 'foo', { 'name' : 'bar', 'if': 'TEST_IF_ENUM_BAR' } ],
+{ 'enum': 'TestIfEnum',
+  'data': [ 'foo', { 'name' : 'bar', 'if': 'TEST_IF_ENUM_BAR' } ],
   'if': 'TEST_IF_ENUM' }
 
-{ 'union': 'TestIfUnion', 'data':
-  { 'foo': 'TestStruct',
-'bar': { 'type': 'str', 'if': 'TEST_IF_UNION_BAR'} },
+{ 'union': 'TestIfUnion',
+  'data': { 'foo': 'TestStruct',
+'bar': { 'type': 'str', 'if': 'TEST_IF_UNION_BAR'} },
   'if': { 'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT'] } }
 
 { 'command': 'test-if-union-cmd',
   'data': { 'union-cmd-arg': 'TestIfUnion' },
   'if': { 'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT'] } }
 
-{ 'alternate': 'TestIfAlternate', 'data':
-  { 'foo': 'int',
-'bar': { 'type': 'TestStruct', 'if': 'TEST_IF_ALT_BAR'} },
+{ 'alternate': 'TestIfAlternate',
+  'data': { 'foo': 'int',
+'bar': { 'type': 'TestStruct', 'if': 'TEST_IF_ALT_BAR'} },
   'if': { 'all': ['TEST_IF_ALT', 'TEST_IF_STRUCT'] } }
 
 { 'command': 'test-if-alternate-cmd',
@@ -256,9 +256,9 @@
 
 { 'command': 'test-cmd-return-def-three', 'returns': 'UserDefThree' }
 
-{ 'event': 'TEST_IF_EVENT', 'data':
-  { 'foo': 'TestIfStruct',
-'bar': { 'type': ['TestIfEnum'], 'if': 'TEST_IF_EVT_BAR' } },
+{ 'event': 'TEST_IF_EVENT',
+  'data': { 'foo': 'TestIfStruct',
+'bar': { 'type': ['TestIfEnum'], 'if': 'TEST_IF_EVT_BAR' } },
   'if': { 'all': ['TEST_IF_EVT', 'TEST_IF_STRUCT'] } }
 
 { 'event': 'TEST_IF_EVENT2', 'data': {},
-- 
2.31.1




[PULL 07/25] qapi: Convert simple union ChardevBackend to flat one

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, convert simple union ChardevBackend to
an equivalent flat one.  Adds some boilerplate to the schema, which is
a bit ugly, but a lot easier to maintain than the simple union
feature.

Cc: "Marc-André Lureau" 
Cc: Paolo Bonzini 
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-8-arm...@redhat.com>
---
 qapi/char.json | 187 +++--
 1 file changed, 165 insertions(+), 22 deletions(-)

diff --git a/qapi/char.json b/qapi/char.json
index 9b18ee3305..cc1e455c87 100644
--- a/qapi/char.json
+++ b/qapi/char.json
@@ -407,39 +407,182 @@
   'base': 'ChardevCommon',
   'if': 'CONFIG_SPICE_PROTOCOL' }
 
+##
+# @ChardevBackendKind:
+#
+# @pipe: Since 1.5
+# @udp: Since 1.5
+# @mux: Since 1.5
+# @msmouse: Since 1.5
+# @wctablet: Since 2.9
+# @braille: Since 1.5
+# @testdev: Since 2.2
+# @stdio: Since 1.5
+# @console: Since 1.5
+# @spicevmc: Since 1.5
+# @spiceport: Since 1.5
+# @qemu-vdagent: Since 6.1
+# @vc: v1.5
+# @ringbuf: Since 1.6
+# @memory: Since 1.5
+#
+# Since: 1.4
+##
+{ 'enum': 'ChardevBackendKind',
+  'data': [ 'file',
+'serial',
+'parallel',
+'pipe',
+'socket',
+'udp',
+'pty',
+'null',
+'mux',
+'msmouse',
+'wctablet',
+'braille',
+'testdev',
+'stdio',
+'console',
+{ 'name': 'spicevmc', 'if': 'CONFIG_SPICE' },
+{ 'name': 'spiceport', 'if': 'CONFIG_SPICE' },
+{ 'name': 'qemu-vdagent', 'if': 'CONFIG_SPICE_PROTOCOL' },
+'vc',
+'ringbuf',
+# next one is just for compatibility
+'memory' ] }
+
+##
+# @ChardevFileWrapper:
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevFileWrapper',
+  'data': { 'data': 'ChardevFile' } }
+
+##
+# @ChardevHostdevWrapper:
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevHostdevWrapper',
+  'data': { 'data': 'ChardevHostdev' } }
+
+##
+# @ChardevSocketWrapper:
+#
+# Since: 1.4
+##
+{ 'struct': 'ChardevSocketWrapper',
+  'data': { 'data': 'ChardevSocket' } }
+
+##
+# @ChardevUdpWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevUdpWrapper',
+  'data': { 'data': 'ChardevUdp' } }
+
+##
+# @ChardevCommonWrapper:
+#
+# Since: 2.6
+##
+{ 'struct': 'ChardevCommonWrapper',
+  'data': { 'data': 'ChardevCommon' } }
+
+##
+# @ChardevMuxWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevMuxWrapper',
+  'data': { 'data': 'ChardevMux' } }
+
+##
+# @ChardevStdioWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevStdioWrapper',
+  'data': { 'data': 'ChardevStdio' } }
+
+##
+# @ChardevSpiceChannelWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevSpiceChannelWrapper',
+  'data': { 'data': 'ChardevSpiceChannel' } }
+
+##
+# @ChardevSpicePortWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevSpicePortWrapper',
+  'data': { 'data': 'ChardevSpicePort' } }
+
+##
+# @ChardevQemuVDAgentWrapper:
+#
+# Since: 6.1
+##
+{ 'struct': 'ChardevQemuVDAgentWrapper',
+  'data': { 'data': 'ChardevQemuVDAgent' } }
+
+##
+# @ChardevVCWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevVCWrapper',
+  'data': { 'data': 'ChardevVC' } }
+
+##
+# @ChardevRingbufWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'ChardevRingbufWrapper',
+  'data': { 'data': 'ChardevRingbuf' } }
+
 ##
 # @ChardevBackend:
 #
 # Configuration info for the new chardev backend.
 #
-# Since: 1.4 (testdev since 2.2, wctablet since 2.9, vdagent since 6.1)
+# Since: 1.4
 ##
 { 'union': 'ChardevBackend',
-  'data': { 'file': 'ChardevFile',
-'serial': 'ChardevHostdev',
-'parallel': 'ChardevHostdev',
-'pipe': 'ChardevHostdev',
-'socket': 'ChardevSocket',
-'udp': 'ChardevUdp',
-'pty': 'ChardevCommon',
-'null': 'ChardevCommon',
-'mux': 'ChardevMux',
-'msmouse': 'ChardevCommon',
-'wctablet': 'ChardevCommon',
-'braille': 'ChardevCommon',
-'testdev': 'ChardevCommon',
-'stdio': 'ChardevStdio',
-'console': 'ChardevCommon',
-'spicevmc': { 'type': 'ChardevSpiceChannel',
+  'base': { 'type': 'ChardevBackendKind' },
+  'discriminator': 'type',
+  'data': { 'file': 'ChardevFileWrapper',
+'serial': 'ChardevHostdevWrapper',
+'parallel': 'ChardevHostdevWrapper',
+'pipe': 'ChardevHostdevWrapper',
+'socket': 'ChardevSocketWrapper',
+'udp': 'ChardevUdpWrapper',
+'pty': 'ChardevCommonWrapper',
+'null': 'ChardevCommonWrapper',
+'mux': 'ChardevMuxWrapper',
+'msmouse': 'ChardevCommonWrapper',
+'wctablet': 'Cha

[PULL 08/25] qapi: Convert simple union SocketAddressLegacy to flat one

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, convert simple union SocketAddressLegacy
to an equivalent flat one, with existing enum SocketAddressType
replacing implicit enum type SocketAddressLegacyKind.  Adds some
boilerplate to the schema, which is a bit ugly, but a lot easier to
maintain than the simple union feature.

Cc: "Daniel P. Berrangé" 
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-9-arm...@redhat.com>
---
 qapi/sockets.json  | 46 +++---
 chardev/char-socket.c  |  6 +++---
 chardev/char-udp.c |  4 ++--
 tests/unit/test-yank.c |  6 +++---
 util/qemu-sockets.c|  8 
 5 files changed, 51 insertions(+), 19 deletions(-)

diff --git a/qapi/sockets.json b/qapi/sockets.json
index 7866dc27d6..ef4b16d6f2 100644
--- a/qapi/sockets.json
+++ b/qapi/sockets.json
@@ -110,6 +110,38 @@
 'cid': 'str',
 'port': 'str' } }
 
+##
+# @InetSocketAddressWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'InetSocketAddressWrapper',
+  'data': { 'data': 'InetSocketAddress' } }
+
+##
+# @UnixSocketAddressWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'UnixSocketAddressWrapper',
+  'data': { 'data': 'UnixSocketAddress' } }
+
+##
+# @VsockSocketAddressWrapper:
+#
+# Since: 2.8
+##
+{ 'struct': 'VsockSocketAddressWrapper',
+  'data': { 'data': 'VsockSocketAddress' } }
+
+##
+# @StringWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'StringWrapper',
+  'data': { 'data': 'String' } }
+
 ##
 # @SocketAddressLegacy:
 #
@@ -117,18 +149,18 @@
 #
 # Note: This type is deprecated in favor of SocketAddress.  The
 #   difference between SocketAddressLegacy and SocketAddress is that the
-#   latter is a flat union rather than a simple union. Flat is nicer
-#   because it avoids nesting on the wire, i.e. that form has fewer {}.
-
+#   latter is has fewer {} on the wire.
 #
 # Since: 1.3
 ##
 { 'union': 'SocketAddressLegacy',
+  'base': { 'type': 'SocketAddressType' },
+  'discriminator': 'type',
   'data': {
-'inet': 'InetSocketAddress',
-'unix': 'UnixSocketAddress',
-'vsock': 'VsockSocketAddress',
-'fd': 'String' } }
+'inet': 'InetSocketAddressWrapper',
+'unix': 'UnixSocketAddressWrapper',
+'vsock': 'VsockSocketAddressWrapper',
+'fd': 'StringWrapper' } }
 
 ##
 # @SocketAddressType:
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index c43668cc15..836cfa0bc2 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -1520,7 +1520,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, 
ChardevBackend *backend,
 addr = g_new0(SocketAddressLegacy, 1);
 if (path) {
 UnixSocketAddress *q_unix;
-addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
+addr->type = SOCKET_ADDRESS_TYPE_UNIX;
 q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
 q_unix->path = g_strdup(path);
 #ifdef CONFIG_LINUX
@@ -1530,7 +1530,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, 
ChardevBackend *backend,
 q_unix->abstract = abstract;
 #endif
 } else if (host) {
-addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
+addr->type = SOCKET_ADDRESS_TYPE_INET;
 addr->u.inet.data = g_new(InetSocketAddress, 1);
 *addr->u.inet.data = (InetSocketAddress) {
 .host = g_strdup(host),
@@ -1543,7 +1543,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, 
ChardevBackend *backend,
 .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
 };
 } else if (fd) {
-addr->type = SOCKET_ADDRESS_LEGACY_KIND_FD;
+addr->type = SOCKET_ADDRESS_TYPE_FD;
 addr->u.fd.data = g_new(String, 1);
 addr->u.fd.data->str = g_strdup(fd);
 } else {
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
index 16b5dbce58..6756e69924 100644
--- a/chardev/char-udp.c
+++ b/chardev/char-udp.c
@@ -165,7 +165,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, 
ChardevBackend *backend,
 qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));
 
 addr = g_new0(SocketAddressLegacy, 1);
-addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
+addr->type = SOCKET_ADDRESS_TYPE_INET;
 addr->u.inet.data = g_new(InetSocketAddress, 1);
 *addr->u.inet.data = (InetSocketAddress) {
 .host = g_strdup(host),
@@ -180,7 +180,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, 
ChardevBackend *backend,
 if (has_local) {
 udp->has_local = true;
 addr = g_new0(SocketAddressLegacy, 1);
-addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
+addr->type = SOCKET_ADDRESS_TYPE_INET;
 addr->u.inet.data = g_new(InetSocketAddress, 1);
 *addr->u.inet.data = (InetSocketAddress) {
 .host = g_strdup(localaddr),
diff --git a/tests/unit/test-ya

[PULL 15/25] tests/qapi-schema: Wean off UserDefListUnion

2021-09-24 Thread Markus Armbruster
Command boxed-union uses simple union UserDefListUnion to cover
unions.  Use UserDefFlatUnion instead.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-16-arm...@redhat.com>
---
 tests/unit/test-qmp-cmds.c  | 2 +-
 tests/qapi-schema/qapi-schema-test.json | 2 +-
 tests/qapi-schema/qapi-schema-test.out  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/unit/test-qmp-cmds.c b/tests/unit/test-qmp-cmds.c
index 83efa39720..83c9ef5b7c 100644
--- a/tests/unit/test-qmp-cmds.c
+++ b/tests/unit/test-qmp-cmds.c
@@ -119,7 +119,7 @@ void qmp_boxed_struct(UserDefZero *arg, Error **errp)
 {
 }
 
-void qmp_boxed_union(UserDefListUnion *arg, Error **errp)
+void qmp_boxed_union(UserDefFlatUnion *arg, Error **errp)
 {
 }
 
diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index b2d795cb19..a4b4405f94 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -175,7 +175,7 @@
   'returns': 'int' }
 { 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
 { 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
-{ 'command': 'boxed-union', 'data': 'UserDefListUnion', 'boxed': true }
+{ 'command': 'boxed-union', 'data': 'UserDefFlatUnion', 'boxed': true }
 { 'command': 'boxed-empty', 'boxed': true, 'data': 'Empty1' }
 
 # Smoke test on out-of-band and allow-preconfig-test
diff --git a/tests/qapi-schema/qapi-schema-test.out 
b/tests/qapi-schema/qapi-schema-test.out
index 7a488c1d06..f120f10616 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -232,7 +232,7 @@ command guest-sync q_obj_guest-sync-arg -> any
 gen=True success_response=True boxed=False oob=False preconfig=False
 command boxed-struct UserDefZero -> None
 gen=True success_response=True boxed=True oob=False preconfig=False
-command boxed-union UserDefListUnion -> None
+command boxed-union UserDefFlatUnion -> None
 gen=True success_response=True boxed=True oob=False preconfig=False
 command boxed-empty Empty1 -> None
 gen=True success_response=True boxed=True oob=False preconfig=False
-- 
2.31.1




[PULL 20/25] tests/qapi-schema: Purge simple unions from tests

2021-09-24 Thread Markus Armbruster
Drop tests that are specifically about simple unions:

* SugaredUnion in doc-good: flat unions are covered by @Object.

* union-branch-case and union-clash-branches: branch naming for flat
  unions is enforced for the tag enum instead, which is covered by
  enum-member-case and enum-clash-member.

* union-empty: empty flat unions are covered by flat-union-empty.

Rewrite the remainder to use flat unions: args-union, bad-base,
flat-union-base-union, union-branch-invalid-dict, union-unknown.

Except drop union-optional-branch. because converting this one is not
worth the trouble; we don't explicitly check names beginning with '*'
in other places, either.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-21-arm...@redhat.com>
---
 tests/qapi-schema/args-union.err  |  2 +-
 tests/qapi-schema/args-union.json |  8 ++-
 tests/qapi-schema/bad-base.err|  2 +-
 tests/qapi-schema/bad-base.json   |  8 ++-
 tests/qapi-schema/doc-good.json   |  9 
 tests/qapi-schema/doc-good.out| 22 ---
 tests/qapi-schema/doc-good.txt| 20 -
 tests/qapi-schema/flat-union-base-union.err   |  2 +-
 tests/qapi-schema/flat-union-base-union.json  |  3 +++
 tests/qapi-schema/meson.build |  4 
 tests/qapi-schema/union-branch-case.err   |  2 --
 tests/qapi-schema/union-branch-case.json  |  2 --
 tests/qapi-schema/union-branch-case.out   |  0
 .../qapi-schema/union-branch-invalid-dict.err |  2 +-
 .../union-branch-invalid-dict.json|  4 
 tests/qapi-schema/union-clash-branches.err|  2 --
 tests/qapi-schema/union-clash-branches.json   |  7 --
 tests/qapi-schema/union-clash-branches.out|  0
 tests/qapi-schema/union-empty.err |  2 --
 tests/qapi-schema/union-empty.json|  2 --
 tests/qapi-schema/union-empty.out |  0
 tests/qapi-schema/union-optional-branch.err   |  2 --
 tests/qapi-schema/union-optional-branch.json  |  2 --
 tests/qapi-schema/union-optional-branch.out   |  0
 tests/qapi-schema/union-unknown.err   |  2 +-
 tests/qapi-schema/union-unknown.json  |  5 -
 26 files changed, 30 insertions(+), 84 deletions(-)
 delete mode 100644 tests/qapi-schema/union-branch-case.err
 delete mode 100644 tests/qapi-schema/union-branch-case.json
 delete mode 100644 tests/qapi-schema/union-branch-case.out
 delete mode 100644 tests/qapi-schema/union-clash-branches.err
 delete mode 100644 tests/qapi-schema/union-clash-branches.json
 delete mode 100644 tests/qapi-schema/union-clash-branches.out
 delete mode 100644 tests/qapi-schema/union-empty.err
 delete mode 100644 tests/qapi-schema/union-empty.json
 delete mode 100644 tests/qapi-schema/union-empty.out
 delete mode 100644 tests/qapi-schema/union-optional-branch.err
 delete mode 100644 tests/qapi-schema/union-optional-branch.json
 delete mode 100644 tests/qapi-schema/union-optional-branch.out

diff --git a/tests/qapi-schema/args-union.err b/tests/qapi-schema/args-union.err
index 4bf4955027..4b80a99f74 100644
--- a/tests/qapi-schema/args-union.err
+++ b/tests/qapi-schema/args-union.err
@@ -1,2 +1,2 @@
 args-union.json: In command 'oops':
-args-union.json:3: command's 'data' can take union type 'Uni' only with 
'boxed': true
+args-union.json:9: command's 'data' can take union type 'Uni' only with 
'boxed': true
diff --git a/tests/qapi-schema/args-union.json 
b/tests/qapi-schema/args-union.json
index 2fcaeaae16..aabb159063 100644
--- a/tests/qapi-schema/args-union.json
+++ b/tests/qapi-schema/args-union.json
@@ -1,3 +1,9 @@
 # use of union arguments requires 'boxed':true
-{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
+{ 'enum': 'Enum', 'data': [ 'case1', 'case2' ] }
+{ 'struct': 'Case1', 'data': { 'data': 'int' } }
+{ 'struct': 'Case2', 'data': { 'data': 'str' } }
+{ 'union': 'Uni',
+  'base': { 'type': 'Enum' },
+  'discriminator': 'type',
+  'data': { 'case1': 'Case1', 'case2': 'Case2' } }
 { 'command': 'oops', 'data': 'Uni' }
diff --git a/tests/qapi-schema/bad-base.err b/tests/qapi-schema/bad-base.err
index 61a1efc2c0..1fad63e392 100644
--- a/tests/qapi-schema/bad-base.err
+++ b/tests/qapi-schema/bad-base.err
@@ -1,2 +1,2 @@
 bad-base.json: In struct 'MyType':
-bad-base.json:3: 'base' requires a struct type, union type 'Union' isn't
+bad-base.json:9: 'base' requires a struct type, union type 'Union' isn't
diff --git a/tests/qapi-schema/bad-base.json b/tests/qapi-schema/bad-base.json
index a634331cdd..8c773ff544 100644
--- a/tests/qapi-schema/bad-base.json
+++ b/tests/qapi-schema/bad-base.json
@@ -1,3 +1,9 @@
 # we reject a base that is not a struct
-{ 'union': 'Union', 'data': { 'a': 'int', 'b': 'str' } }
+{ 'enum': 'Enum', 'data': [ 'a', 'b' ] }
+{ 'struct': 'Int', 'data': { 'data': 'int' } }
+{ 'struct': 'Str', 'data': { 'data': 'str' } }
+{ 'union': 'Union',
+  'base': { 'type': 'Enum' },
+  'd

[PULL 09/25] qapi: Convert simple union ImageInfoSpecific to flat one

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, convert simple union ImageInfoSpecific
to an equivalent flat one.  Adds some boilerplate to the schema, which
is a bit ugly, but a lot easier to maintain than the simple union
feature.

Implicit enum ImageInfoSpecificKind becomes explicit.  It duplicates
part of enum BlockdevDriver.  We could reuse BlockdevDriver instead.

Cc: Kevin Wolf 
Cc: Hanna Reitz 
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Acked-by: Hanna Reitz 
Message-Id: <20210917143134.412106-10-arm...@redhat.com>
---
 qapi/block-core.json | 59 ++--
 1 file changed, 52 insertions(+), 7 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index c8ce1d9d5d..623a4f4a3f 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -139,6 +139,52 @@
   '*encryption-format': 'RbdImageEncryptionFormat'
   } }
 
+##
+# @ImageInfoSpecificKind:
+#
+# @luks: Since 2.7
+# @rbd: Since 6.1
+#
+# Since: 1.7
+##
+{ 'enum': 'ImageInfoSpecificKind',
+  'data': [ 'qcow2', 'vmdk', 'luks', 'rbd' ] }
+
+##
+# @ImageInfoSpecificQCow2Wrapper:
+#
+# Since: 1.7
+##
+{ 'struct': 'ImageInfoSpecificQCow2Wrapper',
+  'data': { 'data': 'ImageInfoSpecificQCow2' } }
+
+##
+# @ImageInfoSpecificVmdkWrapper:
+#
+# Since: 6.1
+##
+{ 'struct': 'ImageInfoSpecificVmdkWrapper',
+  'data': { 'data': 'ImageInfoSpecificVmdk' } }
+
+##
+# @ImageInfoSpecificLUKSWrapper:
+#
+# Since: 2.7
+##
+{ 'struct': 'ImageInfoSpecificLUKSWrapper',
+  'data': { 'data': 'QCryptoBlockInfoLUKS' } }
+# If we need to add block driver specific parameters for
+# LUKS in future, then we'll subclass QCryptoBlockInfoLUKS
+# to define a ImageInfoSpecificLUKS
+
+##
+# @ImageInfoSpecificRbdWrapper:
+#
+# Since: 6.1
+##
+{ 'struct': 'ImageInfoSpecificRbdWrapper',
+  'data': { 'data': 'ImageInfoSpecificRbd' } }
+
 ##
 # @ImageInfoSpecific:
 #
@@ -147,14 +193,13 @@
 # Since: 1.7
 ##
 { 'union': 'ImageInfoSpecific',
+  'base': { 'type': 'ImageInfoSpecificKind' },
+  'discriminator': 'type',
   'data': {
-  'qcow2': 'ImageInfoSpecificQCow2',
-  'vmdk': 'ImageInfoSpecificVmdk',
-  # If we need to add block driver specific parameters for
-  # LUKS in future, then we'll subclass QCryptoBlockInfoLUKS
-  # to define a ImageInfoSpecificLUKS
-  'luks': 'QCryptoBlockInfoLUKS',
-  'rbd': 'ImageInfoSpecificRbd'
+  'qcow2': 'ImageInfoSpecificQCow2Wrapper',
+  'vmdk': 'ImageInfoSpecificVmdkWrapper',
+  'luks': 'ImageInfoSpecificLUKSWrapper',
+  'rbd': 'ImageInfoSpecificRbdWrapper'
   } }
 
 ##
-- 
2.31.1




[PULL 02/25] qapi: Stop enforcing "type name should not end in 'Kind'

2021-09-24 Thread Markus Armbruster
I'm about to convert simple unions to flat unions, then drop simple
union support.  The conversion involves making the implict enum types
explicit.  To reduce churn, I'd like to name them exactly like the
implicit types they replace.  However, these names are reserved for
the generator's use.  They won't be once simple unions are gone.  Stop
enforcing this naming rule now rather than then.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-3-arm...@redhat.com>
---
 scripts/qapi/expr.py  | 6 +++---
 tests/qapi-schema/meson.build | 1 -
 tests/qapi-schema/reserved-type-kind.err  | 2 --
 tests/qapi-schema/reserved-type-kind.json | 2 --
 tests/qapi-schema/reserved-type-kind.out  | 0
 5 files changed, 3 insertions(+), 8 deletions(-)
 delete mode 100644 tests/qapi-schema/reserved-type-kind.err
 delete mode 100644 tests/qapi-schema/reserved-type-kind.json
 delete mode 100644 tests/qapi-schema/reserved-type-kind.out

diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py
index 90bde501b0..91959ee79a 100644
--- a/scripts/qapi/expr.py
+++ b/scripts/qapi/expr.py
@@ -171,7 +171,7 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, 
meta: str) -> None:
   - 'event' names adhere to `check_name_upper()`.
   - 'command' names adhere to `check_name_lower()`.
   - Else, meta is a type, and must pass `check_name_camel()`.
-These names must not end with ``Kind`` nor ``List``.
+These names must not end with ``List``.
 
 :param name: Name to check.
 :param info: QAPI schema source file information.
@@ -187,9 +187,9 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, 
meta: str) -> None:
 permit_underscore=name in info.pragma.command_name_exceptions)
 else:
 check_name_camel(name, info, meta)
-if name.endswith('Kind') or name.endswith('List'):
+if name.endswith('List'):
 raise QAPISemError(
-info, "%s name should not end in '%s'" % (meta, name[-4:]))
+info, "%s name should not end in 'List'" % meta)
 
 
 def check_keys(value: _JSONObject,
diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build
index 6b2a4ce41a..0798e94042 100644
--- a/tests/qapi-schema/meson.build
+++ b/tests/qapi-schema/meson.build
@@ -168,7 +168,6 @@ schemas = [
   'reserved-member-q.json',
   'reserved-member-u.json',
   'reserved-member-underscore.json',
-  'reserved-type-kind.json',
   'reserved-type-list.json',
   'returns-alternate.json',
   'returns-array-bad.json',
diff --git a/tests/qapi-schema/reserved-type-kind.err 
b/tests/qapi-schema/reserved-type-kind.err
deleted file mode 100644
index d8fb769f9d..00
--- a/tests/qapi-schema/reserved-type-kind.err
+++ /dev/null
@@ -1,2 +0,0 @@
-reserved-type-kind.json: In enum 'UnionKind':
-reserved-type-kind.json:2: enum name should not end in 'Kind'
diff --git a/tests/qapi-schema/reserved-type-kind.json 
b/tests/qapi-schema/reserved-type-kind.json
deleted file mode 100644
index 9ecaba12bc..00
--- a/tests/qapi-schema/reserved-type-kind.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# we reject types that would conflict with implicit union enum
-{ 'enum': 'UnionKind', 'data': [ 'oops' ] }
diff --git a/tests/qapi-schema/reserved-type-kind.out 
b/tests/qapi-schema/reserved-type-kind.out
deleted file mode 100644
index e69de29bb2..00
-- 
2.31.1




[PULL 23/25] test-clone-visitor: Correct an accidental rename

2021-09-24 Thread Markus Armbruster
Commit b359f4b203 "tests: Rename UserDefNativeListUnion to
UserDefListUnion" renamed test_clone_native_list() to
test_clone_list_union().  The function has nothing to do with unions.
Rename it to test_clone_list().

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-24-arm...@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé 
---
 tests/unit/test-clone-visitor.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/unit/test-clone-visitor.c b/tests/unit/test-clone-visitor.c
index 4048018607..5d48e125b8 100644
--- a/tests/unit/test-clone-visitor.c
+++ b/tests/unit/test-clone-visitor.c
@@ -63,7 +63,7 @@ static void test_clone_alternate(void)
 qapi_free_AltEnumBool(s_dst);
 }
 
-static void test_clone_list_union(void)
+static void test_clone_list(void)
 {
 uint8List *src = NULL, *dst;
 uint8List *tmp = NULL;
@@ -203,7 +203,7 @@ int main(int argc, char **argv)
 
 g_test_add_func("/visitor/clone/struct", test_clone_struct);
 g_test_add_func("/visitor/clone/alternate", test_clone_alternate);
-g_test_add_func("/visitor/clone/list_union", test_clone_list_union);
+g_test_add_func("/visitor/clone/list", test_clone_list);
 g_test_add_func("/visitor/clone/empty", test_clone_empty);
 g_test_add_func("/visitor/clone/complex1", test_clone_complex1);
 g_test_add_func("/visitor/clone/complex2", test_clone_complex2);
-- 
2.31.1




[PULL 24/25] tests/qapi-schema: Use Python OSError instead of outmoded IOError

2021-09-24 Thread Markus Armbruster
https://docs.python.org/3.6/library/exceptions.html has

Changed in version 3.3: EnvironmentError, IOError, WindowsError,
socket.error, select.error and mmap.error have been merged into
OSError, and the constructor may return a subclass.

and

The following exceptions are kept for compatibility with previous
versions; starting from Python 3.3, they are aliases of OSError.

exception EnvironmentError

exception IOError

exception WindowsError

Only available on Windows.

Switch to the preferred name.

Signed-off-by: Markus Armbruster 
Message-Id: <20210922125619.670673-2-arm...@redhat.com>
Reviewed-by: John Snow 
Reviewed-by: Philippe Mathieu-Daudé 
[Details added to commit message]
---
 tests/qapi-schema/test-qapi.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 73cffae2b6..2e384f5efd 100755
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -154,7 +154,7 @@ def test_and_diff(test_name, dir_name, update):
 errfp = open(os.path.join(dir_name, test_name + '.err'), mode)
 expected_out = outfp.readlines()
 expected_err = errfp.readlines()
-except IOError as err:
+except OSError as err:
 print("%s: can't open '%s': %s"
   % (sys.argv[0], err.filename, err.strerror),
   file=sys.stderr)
@@ -180,7 +180,7 @@ def test_and_diff(test_name, dir_name, update):
 errfp.truncate(0)
 errfp.seek(0)
 errfp.writelines(actual_err)
-except IOError as err:
+except OSError as err:
 print("%s: can't write '%s': %s"
   % (sys.argv[0], err.filename, err.strerror),
   file=sys.stderr)
-- 
2.31.1




[PULL 17/25] tests/qapi-schema: Rewrite simple union TestIfUnion to be flat

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, rewrite TestIfUnion to be flat.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-18-arm...@redhat.com>
---
 tests/qapi-schema/qapi-schema-test.json |  4 +++-
 tests/qapi-schema/qapi-schema-test.out  | 16 ++--
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index eae43f41c4..ef17ab1aae 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -229,8 +229,10 @@
   'if': 'TEST_IF_ENUM' }
 
 { 'union': 'TestIfUnion',
+  'base': { 'type': 'TestIfEnum' },
+  'discriminator': 'type',
   'data': { 'foo': 'TestStruct',
-'bar': { 'type': 'str', 'if': 'TEST_IF_UNION_BAR'} },
+'bar': { 'type': 'UserDefZero', 'if': 'TEST_IF_ENUM_BAR'} },
   'if': { 'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT'] } }
 
 { 'command': 'test-if-union-cmd',
diff --git a/tests/qapi-schema/qapi-schema-test.out 
b/tests/qapi-schema/qapi-schema-test.out
index e43073d795..07e4161331 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -257,19 +257,15 @@ enum TestIfEnum
 member bar
 if TEST_IF_ENUM_BAR
 if TEST_IF_ENUM
-object q_obj_TestStruct-wrapper
-member data: TestStruct optional=False
-enum TestIfUnionKind
-member foo
-member bar
-if TEST_IF_UNION_BAR
+object q_obj_TestIfUnion-base
+member type: TestIfEnum optional=False
 if {'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT']}
 object TestIfUnion
-member type: TestIfUnionKind optional=False
+base q_obj_TestIfUnion-base
 tag type
-case foo: q_obj_TestStruct-wrapper
-case bar: q_obj_str-wrapper
-if TEST_IF_UNION_BAR
+case foo: TestStruct
+case bar: UserDefZero
+if TEST_IF_ENUM_BAR
 if {'all': ['TEST_IF_UNION', 'TEST_IF_STRUCT']}
 object q_obj_test-if-union-cmd-arg
 member union-cmd-arg: TestIfUnion optional=False
-- 
2.31.1




[PULL 21/25] qapi: Drop simple unions

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

The previous commits eliminated simple union from the tree.  Now drop
them from the QAPI schema language entirely, and update mentions of
"flat union" to just "union".

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-22-arm...@redhat.com>
---
 docs/devel/qapi-code-gen.rst  | 125 --
 scripts/qapi/expr.py  |  21 +--
 scripts/qapi/schema.py| 101 +++---
 .../qapi-schema/flat-union-array-branch.json  |   2 +-
 tests/qapi-schema/flat-union-empty.json   |   2 +-
 tests/qapi-schema/flat-union-int-branch.json  |   2 +-
 tests/qapi-schema/flat-union-no-base.err  |   2 +-
 tests/qapi-schema/flat-union-no-base.json |   2 +-
 tests/qapi-schema/qapi-schema-test.json   |   2 +-
 tests/qapi-schema/reserved-member-u.json  |   2 +-
 tests/qapi-schema/union-base-empty.json   |   2 +-
 .../union-base-no-discriminator.err   |   2 +-
 .../union-base-no-discriminator.json  |   2 +-
 13 files changed, 62 insertions(+), 205 deletions(-)

diff --git a/docs/devel/qapi-code-gen.rst b/docs/devel/qapi-code-gen.rst
index b154eae82e..b2569de486 100644
--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -319,13 +319,9 @@ Union types
 Syntax::
 
 UNION = { 'union': STRING,
-  'data': BRANCHES,
-  '*if': COND,
-  '*features': FEATURES }
-  | { 'union': STRING,
-  'data': BRANCHES,
   'base': ( MEMBERS | STRING ),
   'discriminator': STRING,
+  'data': BRANCHES,
   '*if': COND,
   '*features': FEATURES }
 BRANCHES = { BRANCH, ... }
@@ -334,63 +330,30 @@ Syntax::
 
 Member 'union' names the union type.
 
-There are two flavors of union types: simple (no discriminator or
-base), and flat (both discriminator and base).
-
-Each BRANCH of the 'data' object defines a branch of the union.  A
-union must have at least one branch.
-
-The BRANCH's STRING name is the branch name.
-
-The BRANCH's value defines the branch's properties, in particular its
-type.  The form TYPE-REF_ is shorthand for :code:`{ 'type': TYPE-REF }`.
-
-A simple union type defines a mapping from automatic discriminator
-values to data types like in this example::
-
- { 'struct': 'BlockdevOptionsFile', 'data': { 'filename': 'str' } }
- { 'struct': 'BlockdevOptionsQcow2',
-   'data': { 'backing': 'str', '*lazy-refcounts': 'bool' } }
-
- { 'union': 'BlockdevOptionsSimple',
-   'data': { 'file': 'BlockdevOptionsFile',
- 'qcow2': 'BlockdevOptionsQcow2' } }
-
-In the Client JSON Protocol, a simple union is represented by an
-object that contains the 'type' member as a discriminator, and a
-'data' member that is of the specified data type corresponding to the
-discriminator value, as in these examples::
-
- { "type": "file", "data": { "filename": "/some/place/my-image" } }
- { "type": "qcow2", "data": { "backing": "/some/place/my-image",
-  "lazy-refcounts": true } }
-
-The generated C code uses a struct containing a union.  Additionally,
-an implicit C enum 'NameKind' is created, corresponding to the union
-'Name', for accessing the various branches of the union.  The value
-for each branch can be of any type.
-
-Flat unions permit arbitrary common members that occur in all variants
-of the union, not just a discriminator.  Their discriminators need not
-be named 'type'.  They also avoid nesting on the wire.
-
 The 'base' member defines the common members.  If it is a MEMBERS_
 object, it defines common members just like a struct type's 'data'
 member defines struct type members.  If it is a STRING, it names a
 struct type whose members are the common members.
 
-All flat union branches must be `Struct types`_.
+Member 'discriminator' must name a non-optional enum-typed member of
+the base struct.  That member's value selects a branch by its name.
+If no such branch exists, an empty branch is assumed.
 
-In the Client JSON Protocol, a flat union is represented by an object
-with the common members (from the base type) and the selected branch's
-members.  The two sets of member names must be disjoint.  Member
-'discriminator' must name a non-optional enum-typed member of the base
-struct.
+Each BRANCH of the 'data' object defines a branch of the union.  A
+union must have at least one branch.
 
-The following example enhances the above simple union example by
-adding an optional common member 'read-only', renaming the
-discriminator to something more applicable than the simple union's
-default of 'type', and reducing the number of ``{}`` required on the wire::
+The BRANCH's STRING name is the bran

[PULL 04/25] qapi: Convert simple union InputEvent to flat one

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, convert simple union InputEvent to an
equivalent flat one.  Adds some boilerplate to the schema, which is a
bit ugly, but a lot easier to maintain than the simple union feature.

Cc: Gerd Hoffmann 
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-5-arm...@redhat.com>
---
 qapi/ui.json | 42 ++
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/qapi/ui.json b/qapi/ui.json
index 9e04f9d65d..d7567ac866 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -960,6 +960,38 @@
   'data'  : { 'axis': 'InputAxis',
   'value'   : 'int' } }
 
+##
+# @InputEventKind:
+#
+# Since: 2.0
+##
+{ 'enum': 'InputEventKind',
+  'data': [ 'key', 'btn', 'rel', 'abs' ] }
+
+##
+# @InputKeyEventWrapper:
+#
+# Since: 2.0
+##
+{ 'struct': 'InputKeyEventWrapper',
+  'data': { 'data': 'InputKeyEvent' } }
+
+##
+# @InputBtnEventWrapper:
+#
+# Since: 2.0
+##
+{ 'struct': 'InputBtnEventWrapper',
+  'data': { 'data': 'InputBtnEvent' } }
+
+##
+# @InputMoveEventWrapper:
+#
+# Since: 2.0
+##
+{ 'struct': 'InputMoveEventWrapper',
+  'data': { 'data': 'InputMoveEvent' } }
+
 ##
 # @InputEvent:
 #
@@ -975,10 +1007,12 @@
 # Since: 2.0
 ##
 { 'union' : 'InputEvent',
-  'data'  : { 'key' : 'InputKeyEvent',
-  'btn' : 'InputBtnEvent',
-  'rel' : 'InputMoveEvent',
-  'abs' : 'InputMoveEvent' } }
+  'base': { 'type': 'InputEventKind' },
+  'discriminator': 'type',
+  'data'  : { 'key' : 'InputKeyEventWrapper',
+  'btn' : 'InputBtnEventWrapper',
+  'rel' : 'InputMoveEventWrapper',
+  'abs' : 'InputMoveEventWrapper' } }
 
 ##
 # @input-send-event:
-- 
2.31.1




[PULL 16/25] tests/qapi-schema: Simple union UserDefListUnion is now unused, drop

2021-09-24 Thread Markus Armbruster
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-17-arm...@redhat.com>
---
 tests/qapi-schema/qapi-schema-test.json | 17 ---
 tests/qapi-schema/qapi-schema-test.out  | 64 -
 2 files changed, 81 deletions(-)

diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index a4b4405f94..eae43f41c4 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -123,23 +123,6 @@
 # for testing use of 'str' within alternates
 { 'alternate': 'AltStrObj', 'data': { 's': 'str', 'o': 'TestStruct' } }
 
-# for testing lists
-{ 'union': 'UserDefListUnion',
-  'data': { 'integer': ['int'],
-'s8': ['int8'],
-'s16': ['int16'],
-'s32': ['int32'],
-'s64': ['int64'],
-'u8': ['uint8'],
-'u16': ['uint16'],
-'u32': ['uint32'],
-'u64': ['uint64'],
-'number': ['number'],
-'boolean': ['bool'],
-'string': ['str'],
-'sizes': ['size'],
-'any': ['any'],
-'user': ['Status'] } } # intentional forward ref. to sub-module
 { 'struct': 'ArrayStruct',
   'data': { 'integer': ['int'],
 's8': ['int8'],
diff --git a/tests/qapi-schema/qapi-schema-test.out 
b/tests/qapi-schema/qapi-schema-test.out
index f120f10616..e43073d795 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -125,70 +125,6 @@ alternate AltStrObj
 tag type
 case s: str
 case o: TestStruct
-object q_obj_intList-wrapper
-member data: intList optional=False
-object q_obj_int8List-wrapper
-member data: int8List optional=False
-object q_obj_int16List-wrapper
-member data: int16List optional=False
-object q_obj_int32List-wrapper
-member data: int32List optional=False
-object q_obj_int64List-wrapper
-member data: int64List optional=False
-object q_obj_uint8List-wrapper
-member data: uint8List optional=False
-object q_obj_uint16List-wrapper
-member data: uint16List optional=False
-object q_obj_uint32List-wrapper
-member data: uint32List optional=False
-object q_obj_uint64List-wrapper
-member data: uint64List optional=False
-object q_obj_numberList-wrapper
-member data: numberList optional=False
-object q_obj_boolList-wrapper
-member data: boolList optional=False
-object q_obj_strList-wrapper
-member data: strList optional=False
-object q_obj_sizeList-wrapper
-member data: sizeList optional=False
-object q_obj_anyList-wrapper
-member data: anyList optional=False
-object q_obj_StatusList-wrapper
-member data: StatusList optional=False
-enum UserDefListUnionKind
-member integer
-member s8
-member s16
-member s32
-member s64
-member u8
-member u16
-member u32
-member u64
-member number
-member boolean
-member string
-member sizes
-member any
-member user
-object UserDefListUnion
-member type: UserDefListUnionKind optional=False
-tag type
-case integer: q_obj_intList-wrapper
-case s8: q_obj_int8List-wrapper
-case s16: q_obj_int16List-wrapper
-case s32: q_obj_int32List-wrapper
-case s64: q_obj_int64List-wrapper
-case u8: q_obj_uint8List-wrapper
-case u16: q_obj_uint16List-wrapper
-case u32: q_obj_uint32List-wrapper
-case u64: q_obj_uint64List-wrapper
-case number: q_obj_numberList-wrapper
-case boolean: q_obj_boolList-wrapper
-case string: q_obj_strList-wrapper
-case sizes: q_obj_sizeList-wrapper
-case any: q_obj_anyList-wrapper
-case user: q_obj_StatusList-wrapper
 object ArrayStruct
 member integer: intList optional=False
 member s8: int8List optional=False
-- 
2.31.1




[PULL 25/25] tests/qapi-schema: Make test-qapi.py -u work when files are absent

2021-09-24 Thread Markus Armbruster
test-qapi.py -u updates the expected files.  Since it fails when they
are absent, users have to create them manually before they can use
test-qapi.py to fill in the contents, say for a new test.  Silly.
Improve -u to create them.

Signed-off-by: Markus Armbruster 
Message-Id: <20210922125619.670673-3-arm...@redhat.com>
Reviewed-by: John Snow 
---
 tests/qapi-schema/test-qapi.py | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index 2e384f5efd..c717a7a90b 100755
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -132,6 +132,17 @@ def test_frontend(fname):
 print('section=%s\n%s' % (section.name, section.text))
 
 
+def open_test_result(dir_name, file_name, update):
+mode = 'r+' if update else 'r'
+try:
+fp = open(os.path.join(dir_name, file_name), mode)
+except FileNotFoundError:
+if not update:
+raise
+fp = open(os.path.join(dir_name, file_name), 'w+')
+return fp
+
+
 def test_and_diff(test_name, dir_name, update):
 sys.stdout = StringIO()
 try:
@@ -148,10 +159,9 @@ def test_and_diff(test_name, dir_name, update):
 sys.stdout.close()
 sys.stdout = sys.__stdout__
 
-mode = 'r+' if update else 'r'
 try:
-outfp = open(os.path.join(dir_name, test_name + '.out'), mode)
-errfp = open(os.path.join(dir_name, test_name + '.err'), mode)
+outfp = open_test_result(dir_name, test_name + '.out', update)
+errfp = open_test_result(dir_name, test_name + '.err', update)
 expected_out = outfp.readlines()
 expected_err = errfp.readlines()
 except OSError as err:
-- 
2.31.1




[PULL 14/25] test-clone-visitor: Wean off UserDefListUnion

2021-09-24 Thread Markus Armbruster
test_clone_complex1() uses simple union UserDefListUnion to cover
unions.  Use UserDefFlatUnion instead.  Arrays are still covered by
test_clone_complex3().

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-15-arm...@redhat.com>
---
 tests/unit/test-clone-visitor.c | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/tests/unit/test-clone-visitor.c b/tests/unit/test-clone-visitor.c
index 4944b3d857..8357a90e60 100644
--- a/tests/unit/test-clone-visitor.c
+++ b/tests/unit/test-clone-visitor.c
@@ -99,18 +99,26 @@ static void test_clone_empty(void)
 
 static void test_clone_complex1(void)
 {
-UserDefListUnion *src, *dst;
+UserDefFlatUnion *src, *dst;
 
-src = g_new0(UserDefListUnion, 1);
-src->type = USER_DEF_LIST_UNION_KIND_STRING;
+src = g_new0(UserDefFlatUnion, 1);
+src->integer = 123;
+src->string = g_strdup("abc");
+src->enum1 = ENUM_ONE_VALUE1;
+src->u.value1.boolean = true;
 
-dst = QAPI_CLONE(UserDefListUnion, src);
+dst = QAPI_CLONE(UserDefFlatUnion, src);
 g_assert(dst);
-g_assert_cmpint(dst->type, ==, src->type);
-g_assert(!dst->u.string.data);
 
-qapi_free_UserDefListUnion(src);
-qapi_free_UserDefListUnion(dst);
+g_assert_cmpint(dst->integer, ==, 123);
+g_assert_cmpstr(dst->string, ==, "abc");
+g_assert_cmpint(dst->enum1, ==, ENUM_ONE_VALUE1);
+g_assert(dst->u.value1.boolean);
+g_assert(!dst->u.value1.has_a_b);
+g_assert_cmpint(dst->u.value1.a_b, ==, 0);
+
+qapi_free_UserDefFlatUnion(src);
+qapi_free_UserDefFlatUnion(dst);
 }
 
 static void test_clone_complex2(void)
-- 
2.31.1




[PULL 12/25] test-qobject-input-visitor: Wean off UserDefListUnion

2021-09-24 Thread Markus Armbruster
The test_visitor_in_list_union_FOO() use simple union UserDefListUnion
to cover lists of builtin types.  Rewrite as
test_visitor_in_list_struct(), using struct ArrayStruct and a lot less
code.

test_visitor_in_fail_union_list() uses UserDefListUnion to cover
"variant members don't match the discriminator value".  Cover that in
test_visitor_in_fail_union_flat() instead, and drop
test_visitor_in_fail_union_list().  Appropriating the former for this
purpose is okay, because it actually failed due to missing
discriminator, which is still covered by
test_visitor_in_fail_union_flat_no_discrim().

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-13-arm...@redhat.com>
---
 tests/unit/test-qobject-input-visitor.c | 460 
 1 file changed, 148 insertions(+), 312 deletions(-)

diff --git a/tests/unit/test-qobject-input-visitor.c 
b/tests/unit/test-qobject-input-visitor.c
index e41b91a2a6..6f59a7f432 100644
--- a/tests/unit/test-qobject-input-visitor.c
+++ b/tests/unit/test-qobject-input-visitor.c
@@ -464,6 +464,151 @@ static void test_visitor_in_list(TestInputVisitorData 
*data,
 g_assert(!head);
 }
 
+static void test_visitor_in_list_struct(TestInputVisitorData *data,
+const void *unused)
+{
+const char *int_member[] = {
+"integer", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64" };
+g_autoptr(GString) json = g_string_new("");
+int i, j;
+const char *sep;
+g_autoptr(ArrayStruct) arrs = NULL;
+Visitor *v;
+intList *int_list;
+int8List *s8_list;
+int16List *s16_list;
+int32List *s32_list;
+int64List *s64_list;
+uint8List *u8_list;
+uint16List *u16_list;
+uint32List *u32_list;
+uint64List *u64_list;
+numberList *num_list;
+boolList *bool_list;
+strList *str_list;
+
+g_string_append_printf(json, "{");
+
+for (i = 0; i < G_N_ELEMENTS(int_member); i++) {
+g_string_append_printf(json, "'%s': [", int_member[i]);
+sep = "";
+for (j = 0; j < 32; j++) {
+g_string_append_printf(json, "%s%d", sep, j);
+sep = ", ";
+}
+g_string_append_printf(json, "], ");
+}
+
+g_string_append_printf(json, "'number': [");
+sep = "";
+for (i = 0; i < 32; i++) {
+g_string_append_printf(json, "%s%f", sep, (double)i / 3);
+sep = ", ";
+}
+g_string_append_printf(json, "], ");
+
+g_string_append_printf(json, "'boolean': [");
+sep = "";
+for (i = 0; i < 32; i++) {
+g_string_append_printf(json, "%s%s",
+   sep, i % 3 == 0 ? "true" : "false");
+sep = ", ";
+}
+g_string_append_printf(json, "], ");
+
+g_string_append_printf(json, "'string': [");
+sep = "";
+for (i = 0; i < 32; i++) {
+g_string_append_printf(json, "%s'%d'", sep, i);
+sep = ", ";
+}
+g_string_append_printf(json, "]");
+
+g_string_append_printf(json, "}");
+
+v = visitor_input_test_init_raw(data, json->str);
+visit_type_ArrayStruct(v, NULL, &arrs, &error_abort);
+
+i = 0;
+for (int_list = arrs->integer; int_list; int_list = int_list->next) {
+g_assert_cmpint(int_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (s8_list = arrs->s8; s8_list; s8_list = s8_list->next) {
+g_assert_cmpint(s8_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (s16_list = arrs->s16; s16_list; s16_list = s16_list->next) {
+g_assert_cmpint(s16_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (s32_list = arrs->s32; s32_list; s32_list = s32_list->next) {
+g_assert_cmpint(s32_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (s64_list = arrs->s64; s64_list; s64_list = s64_list->next) {
+g_assert_cmpint(s64_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (u8_list = arrs->u8; u8_list; u8_list = u8_list->next) {
+g_assert_cmpint(u8_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (u16_list = arrs->u16; u16_list; u16_list = u16_list->next) {
+g_assert_cmpint(u16_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (u32_list = arrs->u32; u32_list; u32_list = u32_list->next) {
+g_assert_cmpint(u32_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (u64_list = arrs->u64; u64_list; u64_list = u64_list->next) {
+g_assert_cmpint(u64_list->value, ==, i);
+i++;
+}
+
+i = 0;
+for (num_list = arrs->number; num_list; num_list = num_list->next) {
+char expected[32], actual[32];
+
+sprintf(expected, "%.6f", (double)i / 3);
+sprintf(actual, "%.6f", num_list->value);
+g_assert_cmpstr(expected, ==, actual);
+i++;
+}
+
+i = 0;
+for (bool_list = arrs->boolean; bool_list; bool_list = bool_list->next) {
+g_assert_cmpint(bool_list->value, ==, i % 3 == 0);
+

[PULL 10/25] qapi: Convert simple union TransactionAction to flat one

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, convert simple union TransactionAction
to an equivalent flat one.  Adds some boilerplate to the schema, which
is a bit ugly, but a lot easier to maintain than the simple union
feature.

Cc: Kevin Wolf 
Cc: Hanna Reitz 
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Acked-by: Hanna Reitz 
Message-Id: <20210917143134.412106-11-arm...@redhat.com>
---
 qapi/transaction.json | 139 ++
 1 file changed, 113 insertions(+), 26 deletions(-)

diff --git a/qapi/transaction.json b/qapi/transaction.json
index 894258d9e2..d175b5f863 100644
--- a/qapi/transaction.json
+++ b/qapi/transaction.json
@@ -38,41 +38,128 @@
 { 'enum': 'ActionCompletionMode',
   'data': [ 'individual', 'grouped' ] }
 
+##
+# @TransactionActionKind:
+#
+# @abort: Since 1.6
+# @block-dirty-bitmap-add: Since 2.5
+# @block-dirty-bitmap-remove: Since 4.2
+# @block-dirty-bitmap-clear: Since 2.5
+# @block-dirty-bitmap-enable: Since 4.0
+# @block-dirty-bitmap-disable: Since 4.0
+# @block-dirty-bitmap-merge: Since 4.0
+# @blockdev-backup: Since 2.3
+# @blockdev-snapshot: Since 2.5
+# @blockdev-snapshot-internal-sync: Since 1.7
+# @blockdev-snapshot-sync: since 1.1
+# @drive-backup: Since 1.6
+#
+# Since: 1.1
+##
+{ 'enum': 'TransactionActionKind',
+  'data': [ 'abort', 'block-dirty-bitmap-add', 'block-dirty-bitmap-remove',
+'block-dirty-bitmap-clear', 'block-dirty-bitmap-enable',
+'block-dirty-bitmap-disable', 'block-dirty-bitmap-merge',
+'blockdev-backup', 'blockdev-snapshot',
+'blockdev-snapshot-internal-sync', 'blockdev-snapshot-sync',
+'drive-backup' ] }
+
+##
+# @AbortWrapper:
+#
+# Since: 1.6
+##
+{ 'struct': 'AbortWrapper',
+  'data': { 'data': 'Abort' } }
+
+##
+# @BlockDirtyBitmapAddWrapper:
+#
+# Since: 2.5
+##
+{ 'struct': 'BlockDirtyBitmapAddWrapper',
+  'data': { 'data': 'BlockDirtyBitmapAdd' } }
+
+##
+# @BlockDirtyBitmapWrapper:
+#
+# Since: 2.5
+##
+{ 'struct': 'BlockDirtyBitmapWrapper',
+  'data': { 'data': 'BlockDirtyBitmap' } }
+
+##
+# @BlockDirtyBitmapMergeWrapper:
+#
+# Since: 4.0
+##
+{ 'struct': 'BlockDirtyBitmapMergeWrapper',
+  'data': { 'data': 'BlockDirtyBitmapMerge' } }
+
+##
+# @BlockdevBackupWrapper:
+#
+# Since: 2.3
+##
+{ 'struct': 'BlockdevBackupWrapper',
+  'data': { 'data': 'BlockdevBackup' } }
+
+##
+# @BlockdevSnapshotWrapper:
+#
+# Since: 2.5
+##
+{ 'struct': 'BlockdevSnapshotWrapper',
+  'data': { 'data': 'BlockdevSnapshot' } }
+
+##
+# @BlockdevSnapshotInternalWrapper:
+#
+# Since: 1.7
+##
+{ 'struct': 'BlockdevSnapshotInternalWrapper',
+  'data': { 'data': 'BlockdevSnapshotInternal' } }
+
+##
+# @BlockdevSnapshotSyncWrapper:
+#
+# Since: 1.1
+##
+{ 'struct': 'BlockdevSnapshotSyncWrapper',
+  'data': { 'data': 'BlockdevSnapshotSync' } }
+
+##
+# @DriveBackupWrapper:
+#
+# Since: 1.6
+##
+{ 'struct': 'DriveBackupWrapper',
+  'data': { 'data': 'DriveBackup' } }
+
 ##
 # @TransactionAction:
 #
 # A discriminated record of operations that can be performed with
-# @transaction. Action @type can be:
-#
-# - @abort: since 1.6
-# - @block-dirty-bitmap-add: since 2.5
-# - @block-dirty-bitmap-remove: since 4.2
-# - @block-dirty-bitmap-clear: since 2.5
-# - @block-dirty-bitmap-enable: since 4.0
-# - @block-dirty-bitmap-disable: since 4.0
-# - @block-dirty-bitmap-merge: since 4.0
-# - @blockdev-backup: since 2.3
-# - @blockdev-snapshot: since 2.5
-# - @blockdev-snapshot-internal-sync: since 1.7
-# - @blockdev-snapshot-sync: since 1.1
-# - @drive-backup: since 1.6
+# @transaction.
 #
 # Since: 1.1
 ##
 { 'union': 'TransactionAction',
+  'base': { 'type': 'TransactionActionKind' },
+  'discriminator': 'type',
   'data': {
-   'abort': 'Abort',
-   'block-dirty-bitmap-add': 'BlockDirtyBitmapAdd',
-   'block-dirty-bitmap-remove': 'BlockDirtyBitmap',
-   'block-dirty-bitmap-clear': 'BlockDirtyBitmap',
-   'block-dirty-bitmap-enable': 'BlockDirtyBitmap',
-   'block-dirty-bitmap-disable': 'BlockDirtyBitmap',
-   'block-dirty-bitmap-merge': 'BlockDirtyBitmapMerge',
-   'blockdev-backup': 'BlockdevBackup',
-   'blockdev-snapshot': 'BlockdevSnapshot',
-   'blockdev-snapshot-internal-sync': 'BlockdevSnapshotInternal',
-   'blockdev-snapshot-sync': 'BlockdevSnapshotSync',
-   'drive-backup': 'DriveBackup'
+   'abort': 'AbortWrapper',
+   'block-dirty-bitmap-add': 'BlockDirtyBitmapAddWrapper',
+   'block-dirty-bitmap-remove': 'BlockDirtyBitmapWrapper',
+   'block-dirty-bitmap-clear': 'BlockDirtyBitmapWrapper',
+   'block-dirty-bitmap-enable': 'BlockDirtyBitmapWrapper',
+   'block-dirty-bitmap-disable': 'BlockDirtyBitmapWrapper',
+   'block-dirty-bitmap-merge': 'BlockDirtyBitmapMergeWrapper',

[PULL 06/25] qapi: Convert simple union MemoryDeviceInfo to flat one

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, convert simple union MemoryDeviceInfo to
an equivalent flat one.  Adds some boilerplate to the schema, which is
a bit ugly, but a lot easier to maintain than the simple union
feature.

Cc: Eduardo Habkost 
Cc: Marcel Apfelbaum 
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-7-arm...@redhat.com>
---
 qapi/machine.json | 42 ++
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/qapi/machine.json b/qapi/machine.json
index 157712f006..32d47f4e35 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1194,6 +1194,38 @@
   }
 }
 
+##
+# @MemoryDeviceInfoKind:
+#
+# Since: 2.1
+##
+{ 'enum': 'MemoryDeviceInfoKind',
+  'data': [ 'dimm', 'nvdimm', 'virtio-pmem', 'virtio-mem' ] }
+
+##
+# @PCDIMMDeviceInfoWrapper:
+#
+# Since: 2.1
+##
+{ 'struct': 'PCDIMMDeviceInfoWrapper',
+  'data': { 'data': 'PCDIMMDeviceInfo' } }
+
+##
+# @VirtioPMEMDeviceInfoWrapper:
+#
+# Since: 2.1
+##
+{ 'struct': 'VirtioPMEMDeviceInfoWrapper',
+  'data': { 'data': 'VirtioPMEMDeviceInfo' } }
+
+##
+# @VirtioMEMDeviceInfoWrapper:
+#
+# Since: 2.1
+##
+{ 'struct': 'VirtioMEMDeviceInfoWrapper',
+  'data': { 'data': 'VirtioMEMDeviceInfo' } }
+
 ##
 # @MemoryDeviceInfo:
 #
@@ -1205,10 +1237,12 @@
 # Since: 2.1
 ##
 { 'union': 'MemoryDeviceInfo',
-  'data': { 'dimm': 'PCDIMMDeviceInfo',
-'nvdimm': 'PCDIMMDeviceInfo',
-'virtio-pmem': 'VirtioPMEMDeviceInfo',
-'virtio-mem': 'VirtioMEMDeviceInfo'
+  'base': { 'type': 'MemoryDeviceInfoKind' },
+  'discriminator': 'type',
+  'data': { 'dimm': 'PCDIMMDeviceInfoWrapper',
+'nvdimm': 'PCDIMMDeviceInfoWrapper',
+'virtio-pmem': 'VirtioPMEMDeviceInfoWrapper',
+'virtio-mem': 'VirtioMEMDeviceInfoWrapper'
   }
 }
 
-- 
2.31.1




[PULL 00/25] QAPI patches patches for 2021-09-25

2021-09-24 Thread Markus Armbruster
The following changes since commit 11a11998460ed84d9a127c025f50f7234e5a483f:

  Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20210921' into 
staging (2021-09-24 13:21:18 -0400)

are available in the Git repository at:

  git://repo.or.cz/qemu/armbru.git tags/pull-qapi-2021-09-25

for you to fetch changes up to 5757c0904e2e8a7f5d9ff359b30542cfcb70556b:

  tests/qapi-schema: Make test-qapi.py -u work when files are absent 
(2021-09-25 07:00:50 +0200)


QAPI patches patches for 2021-09-25


Markus Armbruster (25):
  qapi: Tidy up unusual line breaks
  qapi: Stop enforcing "type name should not end in 'Kind'
  qapi: Convert simple union KeyValue to flat one
  qapi: Convert simple union InputEvent to flat one
  qapi: Convert simple union TpmTypeOptions to flat one
  qapi: Convert simple union MemoryDeviceInfo to flat one
  qapi: Convert simple union ChardevBackend to flat one
  qapi: Convert simple union SocketAddressLegacy to flat one
  qapi: Convert simple union ImageInfoSpecific to flat one
  qapi: Convert simple union TransactionAction to flat one
  tests/qapi-schema: Prepare for simple union UserDefListUnion removal
  test-qobject-input-visitor: Wean off UserDefListUnion
  test-qobject-output-visitor: Wean off UserDefListUnion
  test-clone-visitor: Wean off UserDefListUnion
  tests/qapi-schema: Wean off UserDefListUnion
  tests/qapi-schema: Simple union UserDefListUnion is now unused, drop
  tests/qapi-schema: Rewrite simple union TestIfUnion to be flat
  test-clone-visitor: Wean off __org.qemu_x-Union1
  tests/qapi-schema: Drop simple union __org.qemu_x-Union1
  tests/qapi-schema: Purge simple unions from tests
  qapi: Drop simple unions
  tests/qapi-schema: Rename flat-union-* test cases to union-*
  test-clone-visitor: Correct an accidental rename
  tests/qapi-schema: Use Python OSError instead of outmoded IOError
  tests/qapi-schema: Make test-qapi.py -u work when files are absent

 docs/devel/qapi-code-gen.rst   | 137 ++
 qapi/block-core.json   |  59 ++-
 qapi/char.json | 187 -
 qapi/machine.json  |  42 +-
 qapi/sockets.json  |  46 ++-
 qapi/tpm.json  |  24 +-
 qapi/transaction.json  | 139 +--
 qapi/ui.json   |  72 +++-
 backends/tpm/tpm_emulator.c|   2 +-
 backends/tpm/tpm_passthrough.c |   2 +-
 chardev/char-socket.c  |   6 +-
 chardev/char-udp.c |   4 +-
 monitor/hmp-cmds.c |   8 +-
 tests/unit/test-clone-visitor.c|  98 +++--
 tests/unit/test-qmp-cmds.c |  18 +-
 tests/unit/test-qobject-input-visitor.c| 460 +++--
 tests/unit/test-qobject-output-visitor.c   | 391 +-
 tests/unit/test-yank.c |   6 +-
 util/qemu-sockets.c|   8 +-
 scripts/qapi/expr.py   |  27 +-
 scripts/qapi/schema.py | 101 +
 tests/qapi-schema/args-union.err   |   2 +-
 tests/qapi-schema/args-union.json  |   8 +-
 tests/qapi-schema/bad-base.err |   2 +-
 tests/qapi-schema/bad-base.json|   8 +-
 tests/qapi-schema/doc-good.json|  13 +-
 tests/qapi-schema/doc-good.out |  22 -
 tests/qapi-schema/doc-good.txt |  20 -
 tests/qapi-schema/enum-if-invalid.json |   4 +-
 tests/qapi-schema/flat-union-array-branch.err  |   2 -
 tests/qapi-schema/flat-union-bad-base.err  |   2 -
 tests/qapi-schema/flat-union-bad-discriminator.err |   2 -
 tests/qapi-schema/flat-union-base-any.err  |   2 -
 tests/qapi-schema/flat-union-base-union.err|   2 -
 tests/qapi-schema/flat-union-clash-member.err  |   2 -
 .../flat-union-discriminator-bad-name.err  |   2 -
 tests/qapi-schema/flat-union-empty.err |   2 -
 tests/qapi-schema/flat-union-empty.json|   4 -
 .../qapi-schema/flat-union-inline-invalid-dict.err |   2 -
 tests/qapi-schema/flat-union-int-branch.err|   2 -
 .../qapi-schema/flat-union-invalid-branch-key.err  |   2 -
 .../flat-union-invalid-discriminator.err   |   2 -
 .../flat-union-invalid-if-discriminator.err|   2 -
 tests/qapi-schema/flat-union-no-base.err   |   2 -
 .../flat-union-optional-discriminator.err  |   2 -
 .../flat-union-string-discriminator.err|

[PULL 13/25] test-qobject-output-visitor: Wean off UserDefListUnion

2021-09-24 Thread Markus Armbruster
The test_visitor_out_list_union_FOO() use simple union
UserDefListUnion to cover lists of builtin types.  Rewrite as
test_visitor_out_list_struct(), using struct ArrayStruct and a lot
less code.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-14-arm...@redhat.com>
---
 tests/unit/test-qobject-output-visitor.c | 391 ++-
 1 file changed, 93 insertions(+), 298 deletions(-)

diff --git a/tests/unit/test-qobject-output-visitor.c 
b/tests/unit/test-qobject-output-visitor.c
index 9dc1e075e7..34d67a439a 100644
--- a/tests/unit/test-qobject-output-visitor.c
+++ b/tests/unit/test-qobject-output-visitor.c
@@ -437,289 +437,118 @@ static void test_visitor_out_null(TestOutputVisitorData 
*data,
 g_assert(qobject_type(nil) == QTYPE_QNULL);
 }
 
-static void init_list_union(UserDefListUnion *cvalue)
-{
-int i;
-switch (cvalue->type) {
-case USER_DEF_LIST_UNION_KIND_INTEGER: {
-intList **tail = &cvalue->u.integer.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_S8: {
-int8List **tail = &cvalue->u.s8.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_S16: {
-int16List **tail = &cvalue->u.s16.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_S32: {
-int32List **tail = &cvalue->u.s32.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_S64: {
-int64List **tail = &cvalue->u.s64.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_U8: {
-uint8List **tail = &cvalue->u.u8.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_U16: {
-uint16List **tail = &cvalue->u.u16.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_U32: {
-uint32List **tail = &cvalue->u.u32.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_U64: {
-uint64List **tail = &cvalue->u.u64.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, i);
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_BOOLEAN: {
-boolList **tail = &cvalue->u.boolean.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, QEMU_IS_ALIGNED(i, 3));
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_STRING: {
-strList **tail = &cvalue->u.string.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, g_strdup_printf("%d", i));
-}
-break;
-}
-case USER_DEF_LIST_UNION_KIND_NUMBER: {
-numberList **tail = &cvalue->u.number.data;
-for (i = 0; i < 32; i++) {
-QAPI_LIST_APPEND(tail, (double)i / 3);
-}
-break;
-}
-default:
-g_assert_not_reached();
-}
-}
-
-static void check_list_union(QObject *qobj,
- UserDefListUnionKind kind)
+static void test_visitor_out_list_struct(TestOutputVisitorData *data,
+ const void *unused)
 {
+const char *int_member[] = {
+"integer", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64" };
+g_autoptr(ArrayStruct) arrs = g_new0(ArrayStruct, 1);
+int i, j;
 QDict *qdict;
 QList *qlist;
-int i;
+QListEntry *e;
 
-qdict = qobject_to(QDict, qobj);
-g_assert(qdict);
-g_assert(qdict_haskey(qdict, "data"));
-qlist = qlist_copy(qobject_to(QList, qdict_get(qdict, "data")));
-
-switch (kind) {
-case USER_DEF_LIST_UNION_KIND_U8:
-case USER_DEF_LIST_UNION_KIND_U16:
-case USER_DEF_LIST_UNION_KIND_U32:
-case USER_DEF_LIST_UNION_KIND_U64:
-for (i = 0; i < 32; i++) {
-QObject *tmp;
-QNum *qvalue;
-uint64_t val;
-
-tmp = qlist_peek(qlist);
-g_assert(tmp);
-qvalue = qobject_to(QNum, tmp);
-g_assert(qnum_get_try_uint(qvalue, &val));
-g_assert_cmpint(val, ==, i);
-qobject_unref(qlist_pop(qlist));
-}
-break;
-
-case USER_DEF_LIST_UNION_KIND_S8:
-case USER_DEF_LIST_UNION_KIND_S16:
-case USER_DEF_LIST_UNION_KIND_S32:
-case USER_DEF_LIST_UNION_KIND_S64:
-/*
- * All integer elements in JSON arrays get stored into QNums
- * when we convert to QObjects, so we 

[PULL 11/25] tests/qapi-schema: Prepare for simple union UserDefListUnion removal

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, simple union UserDefListUnion has to go.
It is used to cover arrays.  The next few commits will eliminate its
uses, and then it gets deleted.  As a first step, provide struct
ArrayStruct for the tests to be rewritten.

Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-12-arm...@redhat.com>
---
 tests/qapi-schema/qapi-schema-test.json | 16 
 tests/qapi-schema/qapi-schema-test.out  | 16 
 2 files changed, 32 insertions(+)

diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index 3c43e14e22..b2d795cb19 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -140,6 +140,22 @@
 'sizes': ['size'],
 'any': ['any'],
 'user': ['Status'] } } # intentional forward ref. to sub-module
+{ 'struct': 'ArrayStruct',
+  'data': { 'integer': ['int'],
+'s8': ['int8'],
+'s16': ['int16'],
+'s32': ['int32'],
+'s64': ['int64'],
+'u8': ['uint8'],
+'u16': ['uint16'],
+'u32': ['uint32'],
+'u64': ['uint64'],
+'number': ['number'],
+'boolean': ['bool'],
+'string': ['str'],
+'*sz': ['size'],
+'*any': ['any'],
+'*user': ['Status'] } } # intentional forward ref. to sub-module
 
 # for testing sub-modules
 { 'include': 'include/sub-module.json' }
diff --git a/tests/qapi-schema/qapi-schema-test.out 
b/tests/qapi-schema/qapi-schema-test.out
index d557fe2d89..7a488c1d06 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -189,6 +189,22 @@ object UserDefListUnion
 case sizes: q_obj_sizeList-wrapper
 case any: q_obj_anyList-wrapper
 case user: q_obj_StatusList-wrapper
+object ArrayStruct
+member integer: intList optional=False
+member s8: int8List optional=False
+member s16: int16List optional=False
+member s32: int32List optional=False
+member s64: int64List optional=False
+member u8: uint8List optional=False
+member u16: uint16List optional=False
+member u32: uint32List optional=False
+member u64: uint64List optional=False
+member number: numberList optional=False
+member boolean: boolList optional=False
+member string: strList optional=False
+member sz: sizeList optional=True
+member any: anyList optional=True
+member user: StatusList optional=True
 include include/sub-module.json
 command user-def-cmd None -> None
 gen=True success_response=True boxed=False oob=False preconfig=False
-- 
2.31.1




[PULL 03/25] qapi: Convert simple union KeyValue to flat one

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, convert simple union KeyValue to an
equivalent flat one.  Adds some boilerplate to the schema, which is a
bit ugly, but a lot easier to maintain than the simple union feature.

Cc: Gerd Hoffmann 
Signed-off-by: Markus Armbruster 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-4-arm...@redhat.com>
---
 qapi/ui.json | 30 --
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/qapi/ui.json b/qapi/ui.json
index b2cf7a6759..9e04f9d65d 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -824,6 +824,30 @@
 'ac_home', 'ac_back', 'ac_forward', 'ac_refresh', 'ac_bookmarks',
 'lang1', 'lang2' ] }
 
+##
+# @KeyValueKind:
+#
+# Since: 1.3
+##
+{ 'enum': 'KeyValueKind',
+  'data': [ 'number', 'qcode' ] }
+
+##
+# @IntWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'IntWrapper',
+  'data': { 'data': 'int' } }
+
+##
+# @QKeyCodeWrapper:
+#
+# Since: 1.3
+##
+{ 'struct': 'QKeyCodeWrapper',
+  'data': { 'data': 'QKeyCode' } }
+
 ##
 # @KeyValue:
 #
@@ -832,9 +856,11 @@
 # Since: 1.3
 ##
 { 'union': 'KeyValue',
+  'base': { 'type': 'KeyValueKind' },
+  'discriminator': 'type',
   'data': {
-'number': 'int',
-'qcode': 'QKeyCode' } }
+'number': 'IntWrapper',
+'qcode': 'QKeyCodeWrapper' } }
 
 ##
 # @send-key:
-- 
2.31.1




[PULL 05/25] qapi: Convert simple union TpmTypeOptions to flat one

2021-09-24 Thread Markus Armbruster
Simple unions predate flat unions.  Having both complicates the QAPI
schema language and the QAPI generator.  We haven't been using simple
unions in new code for a long time, because they are less flexible and
somewhat awkward on the wire.

To prepare for their removal, convert simple union TpmTypeOptions to
an equivalent flat one, with existing enum TpmType replacing implicit
enum TpmTypeOptionsKind.  Adds some boilerplate to the schema, which
is a bit ugly, but a lot easier to maintain than the simple union
feature.

Cc: Stefan Berger 
Signed-off-by: Markus Armbruster 
Acked-by: Stefan Berger 
Reviewed-by: Eric Blake 
Message-Id: <20210917143134.412106-6-arm...@redhat.com>
---
 qapi/tpm.json  | 24 ++--
 backends/tpm/tpm_emulator.c|  2 +-
 backends/tpm/tpm_passthrough.c |  2 +-
 monitor/hmp-cmds.c |  8 
 4 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/qapi/tpm.json b/qapi/tpm.json
index f4dde2f646..3e7669facf 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -99,6 +99,24 @@
 { 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' },
   'if': 'CONFIG_TPM' }
 
+##
+# @TPMPassthroughOptionsWrapper:
+#
+# Since: 1.5
+##
+{ 'struct': 'TPMPassthroughOptionsWrapper',
+  'data': { 'data': 'TPMPassthroughOptions' },
+  'if': 'CONFIG_TPM' }
+
+##
+# @TPMEmulatorOptionsWrapper:
+#
+# Since: 2.11
+##
+{ 'struct': 'TPMEmulatorOptionsWrapper',
+  'data': { 'data': 'TPMEmulatorOptions' },
+  'if': 'CONFIG_TPM' }
+
 ##
 # @TpmTypeOptions:
 #
@@ -110,8 +128,10 @@
 # Since: 1.5
 ##
 { 'union': 'TpmTypeOptions',
-   'data': { 'passthrough' : 'TPMPassthroughOptions',
- 'emulator': 'TPMEmulatorOptions' },
+  'base': { 'type': 'TpmType' },
+  'discriminator': 'type',
+   'data': { 'passthrough' : 'TPMPassthroughOptionsWrapper',
+ 'emulator': 'TPMEmulatorOptionsWrapper' },
   'if': 'CONFIG_TPM' }
 
 ##
diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c
index f8095d23d5..87d061e9bb 100644
--- a/backends/tpm/tpm_emulator.c
+++ b/backends/tpm/tpm_emulator.c
@@ -623,7 +623,7 @@ static TpmTypeOptions 
*tpm_emulator_get_tpm_options(TPMBackend *tb)
 TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
 TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
 
-options->type = TPM_TYPE_OPTIONS_KIND_EMULATOR;
+options->type = TPM_TYPE_EMULATOR;
 options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, 
tpm_emu->options);
 
 return options;
diff --git a/backends/tpm/tpm_passthrough.c b/backends/tpm/tpm_passthrough.c
index 21b7459183..d5558fae6c 100644
--- a/backends/tpm/tpm_passthrough.c
+++ b/backends/tpm/tpm_passthrough.c
@@ -321,7 +321,7 @@ static TpmTypeOptions 
*tpm_passthrough_get_tpm_options(TPMBackend *tb)
 {
 TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
 
-options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
+options->type = TPM_TYPE_PASSTHROUGH;
 options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,
  TPM_PASSTHROUGH(tb)->options);
 
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index e00255f7ee..d6858407ad 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -925,10 +925,10 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
c, TpmModel_str(ti->model));
 
 monitor_printf(mon, "  \\ %s: type=%s",
-   ti->id, TpmTypeOptionsKind_str(ti->options->type));
+   ti->id, TpmType_str(ti->options->type));
 
 switch (ti->options->type) {
-case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
+case TPM_TYPE_PASSTHROUGH:
 tpo = ti->options->u.passthrough.data;
 monitor_printf(mon, "%s%s%s%s",
tpo->has_path ? ",path=" : "",
@@ -936,11 +936,11 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
tpo->has_cancel_path ? ",cancel-path=" : "",
tpo->has_cancel_path ? tpo->cancel_path : "");
 break;
-case TPM_TYPE_OPTIONS_KIND_EMULATOR:
+case TPM_TYPE_EMULATOR:
 teo = ti->options->u.emulator.data;
 monitor_printf(mon, ",chardev=%s", teo->chardev);
 break;
-case TPM_TYPE_OPTIONS_KIND__MAX:
+case TPM_TYPE__MAX:
 break;
 }
 monitor_printf(mon, "\n");
-- 
2.31.1




Re: [PATCH v2 23/23] test-clone-visitor: Correct an accidental rename

2021-09-24 Thread Markus Armbruster
Philippe Mathieu-Daudé  writes:

> On 9/17/21 16:31, Markus Armbruster wrote:
>> Commit b359f4b203 "tests: Rename UserDefNativeListUnion to
>> UserDefListUnion" renamed test_clone_native_list() to
>> test_clone_list_union().  The function has nothing to do with unions.
>> Rename it to test_clone_list().
>> 
>> Signed-off-by: Markus Armbruster 
>> Reviewed-by: Eric Blake 
>> ---
>>  tests/unit/test-clone-visitor.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> Maybe nitpicking, while this patch is related to the series,
> although I understand you noticed the mistake while working
> on this series, I'd move this cleanup as 1/23.

Not worth a respin.  Next time!

> Reviewed-by: Philippe Mathieu-Daudé 

Thanks!




Re: [PATCH v5 04/30] tcg/loongarch64: Add generated instruction opcodes and encoding helpers

2021-09-24 Thread WANG Xuerui

Hi all,

On 9/25/21 01:25, WANG Xuerui wrote:

Signed-off-by: WANG Xuerui 
Acked-by: Richard Henderson 
---
  tcg/loongarch64/tcg-insn-defs.c.inc | 979 
  1 file changed, 979 insertions(+)
  create mode 100644 tcg/loongarch64/tcg-insn-defs.c.inc
This patch series is only lacking Reviewed-by tag for this commit now; 
may I ask whose review do I additionally need to get this across the 
finish line? Or is this series waiting for upstream merge of toolchain 
and kernel support too?




Re: [PATCH v5 23/30] tcg/loongarch64: Add softmmu load/store helpers, implement qemu_ld/qemu_st ops

2021-09-24 Thread Richard Henderson

On 9/24/21 1:25 PM, WANG Xuerui wrote:

Signed-off-by: WANG Xuerui
---
  tcg/loongarch64/tcg-target-con-set.h |   2 +
  tcg/loongarch64/tcg-target.c.inc | 353 +++
  2 files changed, 355 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 14/14] bsd-user/signal: Create a dummy signal queueing function

2021-09-24 Thread Richard Henderson

On 9/24/21 4:11 PM, Warner Losh wrote:

It brings to mind something else... There's times it might be easier
to refactor between bsd-user and linux-user rather than upstream
something that's largely copied from linux-user. Is there a good
way to do that and talk about the design before I sink a ton of time
into something that's the wrong direction?


I certainly wouldn't mind a top-level user-only/ or posix-only/ in which we could share 
code between {linux,bsd}-user/, but I don't have a good idea of what that would look like.


Already you have code for MAP_EXCL that doesn't exist for linux (though there is a new, 
related, MAP_FIXED_NOREPLACE, which linux-user/ does not yet support).  So even with 
"obvious" routines I'm not sure how much real sharing we can get away with.


All I can say is: patches welcome, and we'll bike-shed them as they come.


r~



[PATCH v2] ui/gtk: skip any extra draw of same guest scanout blob res

2021-09-24 Thread Dongwon Kim
Any extra draw call for the same blob resource representing guest scanout
before the previous drawing is not finished can break synchronous draw
sequence. To prevent this, drawing is now done only once for each draw
submission (when draw_submitted == true).

v2:
 - removed mutex
 - updated commit msg

Cc: Gerd Hoffmann 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 hw/display/virtio-gpu-udmabuf.c |  2 +-
 include/ui/console.h|  1 +
 ui/gtk-egl.c| 40 ++-
 ui/gtk-gl-area.c| 49 -
 4 files changed, 59 insertions(+), 33 deletions(-)

diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index c6f7f58784..60ea7f8f49 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -186,7 +186,7 @@ static VGPUDMABuf
 dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
 dmabuf->buf.fd = res->dmabuf_fd;
 dmabuf->buf.allow_fences = true;
-
+dmabuf->buf.draw_submitted = false;
 dmabuf->scanout_id = scanout_id;
 QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next);
 
diff --git a/include/ui/console.h b/include/ui/console.h
index 244664d727..b6bedc5f41 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -171,6 +171,7 @@ typedef struct QemuDmaBuf {
 void  *sync;
 int   fence_fd;
 bool  allow_fences;
+bool  draw_submitted;
 } QemuDmaBuf;
 
 typedef struct DisplayState DisplayState;
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 72ce5e1f8f..e912b20075 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -63,6 +63,9 @@ void gd_egl_init(VirtualConsole *vc)
 void gd_egl_draw(VirtualConsole *vc)
 {
 GdkWindow *window;
+#ifdef CONFIG_GBM
+QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
 int ww, wh;
 
 if (!vc->gfx.gls) {
@@ -74,10 +77,31 @@ void gd_egl_draw(VirtualConsole *vc)
 wh = gdk_window_get_height(window);
 
 if (vc->gfx.scanout_mode) {
+#ifdef CONFIG_GBM
+if (dmabuf) {
+if (!dmabuf->draw_submitted) {
+return;
+} else {
+dmabuf->draw_submitted = false;
+}
+}
+#endif
 gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
 
 vc->gfx.scale_x = (double)ww / vc->gfx.w;
 vc->gfx.scale_y = (double)wh / vc->gfx.h;
+
+glFlush();
+#ifdef CONFIG_GBM
+if (dmabuf) {
+egl_dmabuf_create_fence(dmabuf);
+if (dmabuf->fence_fd > 0) {
+qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, 
vc);
+return;
+}
+graphic_hw_gl_block(vc->gfx.dcl.con, false);
+}
+#endif
 } else {
 if (!vc->gfx.ds) {
 return;
@@ -92,21 +116,10 @@ void gd_egl_draw(VirtualConsole *vc)
 
 vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
 vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
-}
-
-glFlush();
-#ifdef CONFIG_GBM
-if (vc->gfx.guest_fb.dmabuf) {
-QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
 
-egl_dmabuf_create_fence(dmabuf);
-if (dmabuf->fence_fd > 0) {
-qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
-return;
-}
-graphic_hw_gl_block(vc->gfx.dcl.con, false);
+glFlush();
 }
-#endif
+
 graphic_hw_gl_flushed(vc->gfx.dcl.con);
 }
 
@@ -317,6 +330,7 @@ void gd_egl_flush(DisplayChangeListener *dcl,
 
 if (vc->gfx.guest_fb.dmabuf) {
 graphic_hw_gl_block(vc->gfx.dcl.con, true);
+vc->gfx.guest_fb.dmabuf->draw_submitted = true;
 gtk_widget_queue_draw_area(area, x, y, w, h);
 return;
 }
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index b23523748e..20035aae38 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -38,6 +38,9 @@ static void gtk_gl_area_set_scanout_mode(VirtualConsole *vc, 
bool scanout)
 
 void gd_gl_area_draw(VirtualConsole *vc)
 {
+#ifdef CONFIG_GBM
+QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
 int ww, wh, y1, y2;
 
 if (!vc->gfx.gls) {
@@ -53,6 +56,16 @@ void gd_gl_area_draw(VirtualConsole *vc)
 return;
 }
 
+#ifdef CONFIG_GBM
+if (dmabuf) {
+if (!dmabuf->draw_submitted) {
+return;
+} else {
+dmabuf->draw_submitted = false;
+}
+}
+#endif
+
 glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer);
 /* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */
 
@@ -62,6 +75,22 @@ void gd_gl_area_draw(VirtualConsole *vc)
 glBlitFramebuffer(0, y1, vc->gfx.w, y2,
   0, 0, ww, wh,
   GL_COLOR_BUFFER_BIT, GL_NEAREST);
+#ifdef CONFIG_GBM
+if (dmabuf) {
+egl_dmabuf_create_sync(dmabuf);
+}
+#endif
+glFlush();
+#ifdef CONFIG_GBM
+if (dmab

Re: [PATCH v2 2/6] qapi/parser: Allow empty QAPIDoc Sections

2021-09-24 Thread John Snow
On Tue, Sep 7, 2021 at 4:28 AM Markus Armbruster  wrote:

> John Snow  writes:
>
> > It simplifies the typing to say that _section is always a
> > QAPIDoc.Section().
>
> If you say so
>
>
I mean, I thought so at the time. I have an aversion to making optional
types and then littering isinstance() checks in places. I like keeping as
much of the typing statically provable as I can without adding runtime
checks. I'm re-evaluating this patch now, and I'll see if there's anything
I can do, but it's hard to predict differences in matters of taste and
style.

One thing an Optional[T] class instance variable can do that might be
helpful is to remind users that they need to check to see if it's present
or not. If I see a path to eliminate those checks, though, I will generally
always take it - eliminates the need to check everywhere else and puts all
the information you need into the static typing. As a habit, I prefer that
when feasible.

> To accommodate this change, we must allow for this object to evaluate to
> > False for functions like _end_section which behave differently based on
> > whether or not a Section has been started.
> >
> > Signed-off-by: John Snow 
> >
> > ---
> >
> > Probably a better fix is to restructure the code to prevent empty
> > sections from being "ended", but that seems like a bigger whale than
> > what I'm after at the immediate moment.
>
> Do we have a TODO comment for that?
>
>
Nope. I'll either add one or just fix the root issue, because I want to go
back to writing the cross-referenceable QAPI symbol plugin for sphinx now.
At the time I thought I'd get to fixing some of the issues raised by pt5 a
lot sooner, but.


> >
> > Signed-off-by: John Snow 
> > ---
> >  scripts/qapi/parser.py | 5 -
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
> > index b6a5e661215..3ddde318376 100644
> > --- a/scripts/qapi/parser.py
> > +++ b/scripts/qapi/parser.py
> > @@ -456,6 +456,9 @@ def __init__(self, parser, name=None, indent=0):
> >  # the expected indent level of the text of this section
> >  self._indent = indent
> >
> > +def __bool__(self) -> bool:
> > +return bool(self.name or self.text)
> > +
> >  def append(self, line):
> >  # Strip leading spaces corresponding to the expected indent
> level
> >  # Blank lines are always OK.
>
> Overriding __bool__() is the minimally invasive compensation for the
> next hunk's replacement of None by a QAPIDoc.Section
>
> However, I'm wary of overriding __bool__().  It creates a difference
> between "if object:" and "if object is not None:".  Gives me a queasy
> feeling, as shortening the latter to the former is pretty much
> automatic.
>
>
That's just Python, though. If collections are empty, they're falsey. If
QAPIDoc is a collection of documentation lines and we have no lines,
shouldn't that also be falsey?

Nah, I get the apprehension. It's not a strictly linear collection and I
didn't check *every* last field, just name and text. It's kind of a hack
because I'm trying to paper over some deeper(?) problem(??), but it felt
safe because the static typing means we're not likely to confuse the two
cases -- we don't need to distinguish "Absent" from "empty". Or at least,
after this patch we don't need to, anymore. (We'll always have a section,
so an empty section versus no section makes no difference.)

A boring .is_empty() would avoid that, but we'd have to adjust "if S" to
> "if S.is_empty()" wherever we changed S from Optional[Section] to
> Section.  Which S could be affected?
>
>
Feels deeply against the grain of how Python is written to go out of your
way to create an .is_empty() function.


> The following variables get assigned Section or ArgSection:
>
> QAPIDoc.body
> QAPIDoc._section
> QAPIDoc.args[NAME]
> QAPIDoc.features[NAME]
>
> .body, .args[NAME] and .features[NAME] are never None I believe.
>
> ._section is also assigned None, in ._end_section().  It remains None
> until the next ._start*_section().
>
> The only use of .section that doesn't dot into it is in ._end_section().
> That's the only spot to adjust.
>
> Confirm by testing: in all of "make check", Section.__bool__() is only
> ever called from QAPIDoc._end_section().  Checked by sticking
> traceback.print_stack() into .__bool__().
>
>
If that's the only caller, isn't it then perfectly safe to just use the
patch as written?


> > @@ -722,7 +725,7 @@ def _end_section(self):
> >  raise QAPIParseError(
> >  self._parser,
> >  "empty doc section '%s'" % self._section.name)
> > -self._section = None
> > +self._section = QAPIDoc.Section(self._parser)
> >
> >  def _append_freeform(self, line):
> >  match = re.match(r'(@\S+:)', line)
>
> Replacing None by QAPIDoc.Section doesn't just simplify the typing!  It
> also creates a bogus "addi

Re: [External] Re: [RFC v7] virtio/vsock: add two more queues for datagram types

2021-09-24 Thread Jiang Wang .
On Thu, Sep 23, 2021 at 2:18 AM Stefano Garzarella  wrote:
>
> On Wed, Sep 22, 2021 at 10:36:24AM -0700, Jiang Wang . wrote:
> >On Wed, Sep 22, 2021 at 2:23 AM Stefano Garzarella  
> >wrote:
> >>
> >> On Wed, Sep 22, 2021 at 12:00:24AM +, Jiang Wang wrote:
> >> >Datagram sockets are connectionless and unreliable.
> >> >The sender does not know the capacity of the receiver
> >> >and may send more packets than the receiver can handle.
> >> >
> >> >Add two more dedicate virtqueues for datagram sockets,
> >> >so that it will not unfairly steal resources from
> >> >stream and future connection-oriented sockets.
> >> >
> >> >The two new virtqueues are enabled by default and will
> >> >be removed if the guest does not support. This will help
> >> >migration work.
> >> >
> >> >btw: enable_dgram argument in vhost_vsock_common_realize
> >> >is redundant for now, but will be used later when we
> >> >want to disable DGRAM feature bit for old versions.
> >> >
> >> >Signed-off-by: Jiang Wang 
> >> >---
> >> >v1 -> v2: use qemu cmd option to control number of queues,
> >> >removed configuration settings for dgram.
> >> >v2 -> v3: use ioctl to get features and decide number of
> >> >virt queues, instead of qemu cmd option.
> >> >v3 -> v4: change DGRAM feature bit value to 2. Add an argument
> >> >in vhost_vsock_common_realize to indicate dgram is supported or 
> >> > not.
> >> >v4 -> v5: don't open dev to get vhostfd. Removed leftover definition of
> >> >enable_dgram
> >> >v5 -> v6: fix style errors. Imporve error handling of
> >> >vhost_vsock_dgram_supported. Rename MAX_VQS_WITH_DGRAM and 
> >> > another one.
> >> >v6 -> v7: Always enable dgram for vhost-user and vhost kernel.
> >> >Delete unused virtqueues at the beginning of
> >> >vhost_vsock_common_start for migration. Otherwise, migration will 
> >> > fail.
> >> >
> >> > hw/virtio/vhost-user-vsock.c  |  2 +-
> >> > hw/virtio/vhost-vsock-common.c| 32 +--
> >> > hw/virtio/vhost-vsock.c   |  6 +++-
> >> > include/hw/virtio/vhost-vsock-common.h|  6 ++--
> >> > include/hw/virtio/vhost-vsock.h   |  3 ++
> >> > include/standard-headers/linux/virtio_vsock.h |  1 +
> >> > 6 files changed, 43 insertions(+), 7 deletions(-)
> >> >
> >> >diff --git a/hw/virtio/vhost-user-vsock.c b/hw/virtio/vhost-user-vsock.c
> >> >index 6095ed7349..9823a2f3bd 100644
> >> >--- a/hw/virtio/vhost-user-vsock.c
> >> >+++ b/hw/virtio/vhost-user-vsock.c
> >> >@@ -105,7 +105,7 @@ static void vuv_device_realize(DeviceState *dev, 
> >> >Error **errp)
> >> > return;
> >> > }
> >> >
> >> >-vhost_vsock_common_realize(vdev, "vhost-user-vsock");
> >> >+vhost_vsock_common_realize(vdev, "vhost-user-vsock", true);
> >> >
> >> > vhost_dev_set_config_notifier(&vvc->vhost_dev, &vsock_ops);
> >> >
> >> >diff --git a/hw/virtio/vhost-vsock-common.c 
> >> >b/hw/virtio/vhost-vsock-common.c
> >> >index 4ad6e234ad..7d89b4d242 100644
> >> >--- a/hw/virtio/vhost-vsock-common.c
> >> >+++ b/hw/virtio/vhost-vsock-common.c
> >> >@@ -26,6 +26,18 @@ int vhost_vsock_common_start(VirtIODevice *vdev)
> >> > int ret;
> >> > int i;
> >> >
> >> >+if (!virtio_has_feature(vdev->guest_features, VIRTIO_VSOCK_F_DGRAM)) 
> >> >{
> >> >+struct vhost_virtqueue *vqs;
> >> >+virtio_delete_queue(vvc->dgram_recv_vq);
> >> >+virtio_delete_queue(vvc->dgram_trans_vq);
> >> >+
> >>
> >> Are you sure it works removing queues here?
> >> The event_queue would always be #4, but the guest will use #2 which
> >> we're removing.
> >>
> >Yes, this works. In fact, I should include this in v6 and my tests done
> >in my previous emails have these changes. But before I submitted the patch,
> >I thought this code was redundant and removed it without further testing.
>
> Just tried on an host that doesn't support F_DGRAM and I have the
> following errors:
> qemu-system-x86_64: -device vhost-vsock-pci,guest-cid=6: vhost_set_vring_call 
> failed: No buffer space available (105)
> qemu-system-x86_64: -device vhost-vsock-pci,guest-cid=6: Failed to initialize 
> virtqueue 2: No buffer space available
>
> I thinks we should re-add the feature discovery before call
> vhost_dev_init().
>

Yes. You are right. I will add it back.

> >
> >To explain it, I think the event queue number does not matter for the
> >vhost and qemu. The vhost-vsock kernel module does not allocate any
> >data structure for the event queue.  Qemu also only allocates an array of
> >size 2 or 4 for the tx, rx queues. The event queue is handled separately.
> >
> >The event queue number only shows up in the spec, but in real code, I don't
> >see anywhere that the event queue number is used explicitly or implicitly.
> >The Event queue looks independent of tx, rx queues.
>
> Yep, it is used in the linux driver. Look at
> virtio_transport_event_work(), it uses VSOCK_VQ_EVENT (2).
>
Agree, it is used in vi

Re: [PATCH v4 01/35] acpi: add helper routines to initialize ACPI tables

2021-09-24 Thread Stefan Berger



On 9/24/21 8:27 AM, Igor Mammedov wrote:

Patch introduces acpi_table_begin()/ acpi_table_end() API
that hides pointer/offset arithmetic from user as opposed
to build_header(), to prevent errors caused by it [1].

  acpi_table_begin():
  initializes table header and keeps track of
  table data/offsets
  acpi_table_end():
  sets actual table length and tells bios loader
  where table is for the later initialization on
  guest side.

1) commits
bb9feea43179 x86: acpi: use offset instead of pointer when using 
build_header()
4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data 
address

Signed-off-by: Igor Mammedov 
Reviewed-by: Eric Auger 


Tested-by: Stefan Berger 



---
CC: eric.au...@redhat.com
---
  include/hw/acpi/aml-build.h | 31 +++
  hw/acpi/aml-build.c | 62 +
  2 files changed, 93 insertions(+)

diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 471266d739..4242382399 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -413,6 +413,37 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml 
*target);
  Aml *aml_object_type(Aml *object);

  void build_append_int_noprefix(GArray *table, uint64_t value, int size);
+
+typedef struct AcpiTable {
+const char *sig;
+const uint8_t rev;
+const char *oem_id;
+const char *oem_table_id;
+/* private vars tracking table state */
+GArray *array;
+unsigned table_offset;
+} AcpiTable;
+
+/**
+ * acpi_table_begin:
+ * initializes table header and keeps track of
+ * table data/offsets
+ * @desc: ACPI table descriptor
+ * @array: blob where the ACPI table will be composed/stored.
+ */
+void acpi_table_begin(AcpiTable *desc, GArray *array);
+
+/**
+ * acpi_table_end:
+ * sets actual table length and tells bios loader
+ * where table is for the later initialization on
+ * guest side.
+ * @linker: reference to BIOSLinker object to use for the table
+ * @table: ACPI table descriptor that was used with @acpi_table_begin
+ * counterpart
+ */
+void acpi_table_end(BIOSLinker *linker, AcpiTable *table);
+
  void
  build_header(BIOSLinker *linker, GArray *table_data,
   AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index d5103e6d7b..229a3eb654 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
  g_array_append_val(array, val);
  }

+static void build_append_padded_str(GArray *array, const char *str,
+size_t maxlen, char pad)
+{
+size_t i;
+size_t len = strlen(str);
+
+g_assert(len <= maxlen);
+g_array_append_vals(array, str, len);
+for (i = maxlen - len; i > 0; i--) {
+g_array_append_val(array, pad);
+}
+}
+
  static void build_append_array(GArray *array, GArray *val)
  {
  g_array_append_vals(array, val->data, val->len);
@@ -1692,6 +1705,55 @@ Aml *aml_object_type(Aml *object)
  return var;
  }

+void acpi_table_begin(AcpiTable *desc, GArray *array)
+{
+
+desc->array = array;
+desc->table_offset = array->len;
+
+/*
+ * ACPI spec 1.0b
+ * 5.2.3 System Description Table Header
+ */
+g_assert(strlen(desc->sig) == 4);
+g_array_append_vals(array, desc->sig, 4); /* Signature */
+/*
+ * reserve space for Length field, which will be patched by
+ * acpi_table_end() when the table creation is finished.
+ */
+build_append_int_noprefix(array, 0, 4); /* Length */
+build_append_int_noprefix(array, desc->rev, 1); /* Revision */
+build_append_int_noprefix(array, 0, 1); /* Checksum */
+build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
+/* OEM Table ID */
+build_append_padded_str(array, desc->oem_table_id, 8, ' ');
+build_append_int_noprefix(array, 1, 4); /* OEM Revision */
+g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
+build_append_int_noprefix(array, 1, 4); /* Creator Revision */
+}
+
+void acpi_table_end(BIOSLinker *linker, AcpiTable *desc)
+{
+/*
+ * ACPI spec 1.0b
+ * 5.2.3 System Description Table Header
+ * Table 5-2 DESCRIPTION_HEADER Fields
+ */
+const unsigned checksum_offset = 9;
+uint32_t table_len = desc->array->len - desc->table_offset;
+uint32_t table_len_le = cpu_to_le32(table_len);
+gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
+
+/* patch "Length" field that has been reserved by acpi_table_begin()
+ * to the actual length, i.e. accumulated table length from
+ * acpi_table_begin() till acpi_table_end()
+ */
+memcpy(len_ptr, &table_len_le, sizeof table_len_le);
+
+bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
+desc->table_offset, table_len, desc->table_offset + checksum_offset);
+}
+
  void
  build_header(BIOSLinker *linker, GArray *

Re: [PATCH v4 15/35] acpi: build_tpm_tcpa: use acpi_table_begin()/acpi_table_end() instead of build_header()

2021-09-24 Thread Stefan Berger

On 9/24/21 8:27 AM, Igor Mammedov wrote:


it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

While at it switch to build_append_int_noprefix() to build
table entries (which also removes some manual offset
calculations).

Signed-off-by: Igor Mammedov 
Reviewed-by: Eric Auger 


Tested-by: Stefan Berger 



---
v2:
   * fix assert when starting QEMU with TPM 1.2
   Stefan Berger 
v3:
  * fix invalid checksum, by putting acpi_table_composed()
after pointer patching
  * s/acpi_init_table|acpi_table_composed/acpi_table_begin|acpi_table_end/

CC: stef...@linux.vnet.ibm.com
---
  include/hw/acpi/acpi-defs.h | 14 --
  hw/i386/acpi-build.c| 38 ++---
  2 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 4d8f8b34b0..3b42b138f0 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -418,20 +418,6 @@ struct AcpiSratProcessorGiccAffinity {

  typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity;

-/*
- * TCPA Description Table
- *
- * Following Level 00, Rev 00.37 of specs:
- * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
- */
-struct Acpi20Tcpa {
-ACPI_TABLE_HEADER_DEF/* ACPI common table header */
-uint16_t platform_class;
-uint32_t log_area_minimum_length;
-uint64_t log_area_start_address;
-} QEMU_PACKED;
-typedef struct Acpi20Tcpa Acpi20Tcpa;
-
  /* DMAR - DMA Remapping table r2.2 */
  struct AcpiTableDmar {
  ACPI_TABLE_HEADER_DEF
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1587fe5a20..9fa6d7665b 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1878,31 +1878,39 @@ build_hpet(GArray *table_data, BIOSLinker *linker, 
const char *oem_id,
  }

  #ifdef CONFIG_TPM
+/*
+ * TCPA Description Table
+ *
+ * Following Level 00, Rev 00.37 of specs:
+ * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
+ * 7.1.2 ACPI Table Layout
+ */
  static void
  build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
 const char *oem_id, const char *oem_table_id)
  {
-int tcpa_start = table_data->len;
-Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);
-unsigned log_addr_size = sizeof(tcpa->log_area_start_address);
-unsigned log_addr_offset =
-(char *)&tcpa->log_area_start_address - table_data->data;
+unsigned log_addr_offset;
+AcpiTable table = { .sig = "TCPA", .rev = 2,
+.oem_id = oem_id, .oem_table_id = oem_table_id };

-tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
-tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
-acpi_data_push(tcpalog, le32_to_cpu(tcpa->log_area_minimum_length));
+acpi_table_begin(&table, table_data);
+/* Platform Class */
+build_append_int_noprefix(table_data, TPM_TCPA_ACPI_CLASS_CLIENT, 2);
+/* Log Area Minimum Length (LAML) */
+build_append_int_noprefix(table_data, TPM_LOG_AREA_MINIMUM_SIZE, 4);
+/* Log Area Start Address (LASA) */
+log_addr_offset = table_data->len;
+build_append_int_noprefix(table_data, 0, 8);

+/* allocate/reserve space for TPM log area */
+acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
  bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,
   false /* high memory */);
-
  /* log area start address to be filled by Guest linker */
-bios_linker_loader_add_pointer(linker,
-ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
-ACPI_BUILD_TPMLOG_FILE, 0);
+bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+log_addr_offset, 8, ACPI_BUILD_TPMLOG_FILE, 0);

-build_header(linker, table_data,
- (void *)(table_data->data + tcpa_start),
- "TCPA", sizeof(*tcpa), 2, oem_id, oem_table_id);
+acpi_table_end(linker, &table);
  }
  #endif





Re: [PATCH 14/14] bsd-user/signal: Create a dummy signal queueing function

2021-09-24 Thread Kyle Evans
On Fri, Sep 24, 2021 at 3:11 PM Warner Losh  wrote:
>
>
>
> On Fri, Sep 24, 2021 at 6:00 AM Richard Henderson 
>  wrote:
>>
>> On 9/21/21 11:14 PM, Warner Losh wrote:
>> > Create dummy signal queueing function so we can start to integrate other
>> > architectures (at the cost of signals remaining broken) to tame the
>> > dependency graph a bit and to bring in signals in a more controlled
>> > fashion.
>> >
>> > Signed-off-by: Warner Losh 
>> > ---
>> >   bsd-user/qemu.h   | 1 +
>> >   bsd-user/signal.c | 8 
>> >   2 files changed, 9 insertions(+)
>> >
>> > diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
>> > index 5a2fd87e44..85d1f8fd2a 100644
>> > --- a/bsd-user/qemu.h
>> > +++ b/bsd-user/qemu.h
>> > @@ -209,6 +209,7 @@ void process_pending_signals(CPUArchState *cpu_env);
>> >   void signal_init(void);
>> >   long do_sigreturn(CPUArchState *env);
>> >   long do_rt_sigreturn(CPUArchState *env);
>> > +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
>> >   abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, 
>> > abi_ulong sp);
>> >
>> >   /* mmap.c */
>> > diff --git a/bsd-user/signal.c b/bsd-user/signal.c
>> > index ad6d935569..4e7f618944 100644
>> > --- a/bsd-user/signal.c
>> > +++ b/bsd-user/signal.c
>> > @@ -19,6 +19,14 @@
>> >   #include "qemu/osdep.h"
>> >
>> >   #include "qemu.h"
>> > +/*
>>
>> Whacky whitespace.
>
>
> fixed.
>
>>
>> > + * Queue a signal so that it will be send to the virtual CPU as soon as
>> > + * possible.
>> > + */
>> > +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
>> > +{
>> > +return 1;
>> > +}
>>
>> Both here and in linux-user, there are no error conditions.  We should 
>> change the return
>> to void.
>
>
> I'll prep a patch to follow up for both linux and bsd user.
>
>>
>> Also, consider folding in the signal-common.h cleanup soon.
>> But don't let either hold you up too much with rebasing.
>
>
> It's on my list. This 'dummy' routine is just to get things linking to
> help simplify the rather tangled dependency tree to get things
> in, still have them compile and still have at least simple hello
> world continue to work. Behind these reviews are three streams
> of patches for 3 more architectures: arm, aarch64 and riscv64.
>
> I'll create a patch for both linux-user and fix in bsd-user as part of the
> signal.c upstreaming I'm working on.
>
> It brings to mind something else... There's times it might be easier
> to refactor between bsd-user and linux-user rather than upstream
> something that's largely copied from linux-user. Is there a good
> way to do that and talk about the design before I sink a ton of time
> into something that's the wrong direction?
>

I had a proposal on this list a long while back to refactor some stuff
into a top-level qemu-user that could be shared between the two,
starting with safe_syscall (which syscall can be substantially
shared), but it hadn't received any traction at that time.

Thanks,

Kyle Evans



Re: [PATCH 14/14] bsd-user/signal: Create a dummy signal queueing function

2021-09-24 Thread Warner Losh
On Fri, Sep 24, 2021 at 6:00 AM Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 9/21/21 11:14 PM, Warner Losh wrote:
> > Create dummy signal queueing function so we can start to integrate other
> > architectures (at the cost of signals remaining broken) to tame the
> > dependency graph a bit and to bring in signals in a more controlled
> > fashion.
> >
> > Signed-off-by: Warner Losh 
> > ---
> >   bsd-user/qemu.h   | 1 +
> >   bsd-user/signal.c | 8 
> >   2 files changed, 9 insertions(+)
> >
> > diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
> > index 5a2fd87e44..85d1f8fd2a 100644
> > --- a/bsd-user/qemu.h
> > +++ b/bsd-user/qemu.h
> > @@ -209,6 +209,7 @@ void process_pending_signals(CPUArchState *cpu_env);
> >   void signal_init(void);
> >   long do_sigreturn(CPUArchState *env);
> >   long do_rt_sigreturn(CPUArchState *env);
> > +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
> >   abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr,
> abi_ulong sp);
> >
> >   /* mmap.c */
> > diff --git a/bsd-user/signal.c b/bsd-user/signal.c
> > index ad6d935569..4e7f618944 100644
> > --- a/bsd-user/signal.c
> > +++ b/bsd-user/signal.c
> > @@ -19,6 +19,14 @@
> >   #include "qemu/osdep.h"
> >
> >   #include "qemu.h"
> > +/*
>
> Whacky whitespace.
>

fixed.


> > + * Queue a signal so that it will be send to the virtual CPU as soon as
> > + * possible.
> > + */
> > +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
> > +{
> > +return 1;
> > +}
>
> Both here and in linux-user, there are no error conditions.  We should
> change the return
> to void.
>

I'll prep a patch to follow up for both linux and bsd user.


> Also, consider folding in the signal-common.h cleanup soon.
> But don't let either hold you up too much with rebasing.
>

It's on my list. This 'dummy' routine is just to get things linking to
help simplify the rather tangled dependency tree to get things
in, still have them compile and still have at least simple hello
world continue to work. Behind these reviews are three streams
of patches for 3 more architectures: arm, aarch64 and riscv64.

I'll create a patch for both linux-user and fix in bsd-user as part of the
signal.c upstreaming I'm working on.

It brings to mind something else... There's times it might be easier
to refactor between bsd-user and linux-user rather than upstream
something that's largely copied from linux-user. Is there a good
way to do that and talk about the design before I sink a ton of time
into something that's the wrong direction?

Thanks for the reviews and feedback.

Warner


> Reviewed-by: Richard Henderson 
>
> r~
>


[PATCH 1/5] fuse: Header file changes for FUSE_SECURITY_CTX

2021-09-24 Thread Vivek Goyal
These are just header file changes which should show up in qemu if
corresponding kernel changes get merged.

Signed-off-by: Vivek Goyal 
---
 include/standard-headers/linux/fuse.h | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/include/standard-headers/linux/fuse.h 
b/include/standard-headers/linux/fuse.h
index cce105bfba..9e1672fbb2 100644
--- a/include/standard-headers/linux/fuse.h
+++ b/include/standard-headers/linux/fuse.h
@@ -181,6 +181,10 @@
  *  - add FUSE_OPEN_KILL_SUIDGID
  *  - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT
  *  - add FUSE_SETXATTR_ACL_KILL_SGID
+ *
+ *  7.35
+ *  - add FUSE_SECURITY_CTX flag for fuse_init_out
+ *  - add security context to create, mkdir, symlink, and mknod requests
  */
 
 #ifndef _LINUX_FUSE_H
@@ -212,7 +216,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 33
+#define FUSE_KERNEL_MINOR_VERSION 35
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -329,6 +333,8 @@ struct fuse_file_lock {
  * write/truncate sgid is killed only if file has group
  * execute permission. (Same as Linux VFS behavior).
  * FUSE_SETXATTR_EXT:  Server supports extended struct fuse_setxattr_in
+ * FUSE_SECURITY_CTX:  add security context to create, mkdir, symlink, and
+ * mknod
  */
 #define FUSE_ASYNC_READ(1 << 0)
 #define FUSE_POSIX_LOCKS   (1 << 1)
@@ -360,6 +366,7 @@ struct fuse_file_lock {
 #define FUSE_SUBMOUNTS (1 << 27)
 #define FUSE_HANDLE_KILLPRIV_V2(1 << 28)
 #define FUSE_SETXATTR_EXT  (1 << 29)
+#define FUSE_SECURITY_CTX  (1 << 30)
 
 /**
  * CUSE INIT request/reply flags
@@ -967,4 +974,9 @@ struct fuse_removemapping_one {
 #define FUSE_REMOVEMAPPING_MAX_ENTRY   \
(PAGE_SIZE / sizeof(struct fuse_removemapping_one))
 
+struct fuse_secctx {
+   uint32_tsize;
+   uint32_tpadding;
+};
+
 #endif /* _LINUX_FUSE_H */
-- 
2.31.1




[PATCH 2/5] fuse_lowlevel.c: Add capability to parse security context

2021-09-24 Thread Vivek Goyal
Add capability to enable and parse security context as sent by client
and put into fuse_req. Filesystems now can get security context from
request and set it on files during creation.

Signed-off-by: Vivek Goyal 
---
 tools/virtiofsd/fuse_common.h   |  5 +++
 tools/virtiofsd/fuse_i.h|  7 
 tools/virtiofsd/fuse_lowlevel.c | 74 +
 3 files changed, 86 insertions(+)

diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h
index 0c2665b977..6f3485d1dc 100644
--- a/tools/virtiofsd/fuse_common.h
+++ b/tools/virtiofsd/fuse_common.h
@@ -377,6 +377,11 @@ struct fuse_file_info {
  */
 #define FUSE_CAP_SETXATTR_EXT (1 << 29)
 
+/**
+ * Indicates that file server supports creating file security context
+ */
+#define FUSE_CAP_SECURITY_CTX (1 << 30)
+
 /**
  * Ioctl flags
  *
diff --git a/tools/virtiofsd/fuse_i.h b/tools/virtiofsd/fuse_i.h
index 492e002181..a5572fa4ae 100644
--- a/tools/virtiofsd/fuse_i.h
+++ b/tools/virtiofsd/fuse_i.h
@@ -15,6 +15,12 @@
 struct fv_VuDev;
 struct fv_QueueInfo;
 
+struct fuse_security_context {
+const char *name;
+uint32_t ctxlen;
+const void *ctx;
+};
+
 struct fuse_req {
 struct fuse_session *se;
 uint64_t unique;
@@ -35,6 +41,7 @@ struct fuse_req {
 } u;
 struct fuse_req *next;
 struct fuse_req *prev;
+struct fuse_security_context secctx;
 };
 
 struct fuse_notify_req {
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index e4679c73ab..fae92e0f3f 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -886,11 +886,41 @@ static void do_readlink(fuse_req_t req, fuse_ino_t nodeid,
 }
 }
 
+static int parse_secctx_fill_req(fuse_req_t req, struct fuse_mbuf_iter *iter)
+{
+struct fuse_secctx *fsecctx;
+const void *secctx;
+
+fsecctx = fuse_mbuf_iter_advance(iter, sizeof(*fsecctx));
+if (!fsecctx) {
+return -EINVAL;
+}
+
+if (fsecctx->size) {
+const char *name = fuse_mbuf_iter_advance_str(iter);
+if (!name) {
+return -EINVAL;
+}
+
+secctx = fuse_mbuf_iter_advance(iter, fsecctx->size);
+if (!secctx) {
+return -EINVAL;
+}
+
+req->secctx.name = name;
+req->secctx.ctx = secctx;
+req->secctx.ctxlen = fsecctx->size;
+}
+return 0;
+}
+
 static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
  struct fuse_mbuf_iter *iter)
 {
 struct fuse_mknod_in *arg;
 const char *name;
+bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+int err;
 
 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
 name = fuse_mbuf_iter_advance_str(iter);
@@ -901,6 +931,13 @@ static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
 
 req->ctx.umask = arg->umask;
 
+if (secctx_enabled) {
+err = parse_secctx_fill_req(req, iter);
+if (err) {
+fuse_reply_err(req, -err);
+}
+}
+
 if (req->se->op.mknod) {
 req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
 } else {
@@ -913,6 +950,8 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
 {
 struct fuse_mkdir_in *arg;
 const char *name;
+bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+int err;
 
 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
 name = fuse_mbuf_iter_advance_str(iter);
@@ -923,6 +962,13 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
 
 req->ctx.umask = arg->umask;
 
+if (secctx_enabled) {
+err = parse_secctx_fill_req(req, iter);
+if (err) {
+fuse_reply_err(req, err);
+}
+}
+
 if (req->se->op.mkdir) {
 req->se->op.mkdir(req, nodeid, name, arg->mode);
 } else {
@@ -969,12 +1015,21 @@ static void do_symlink(fuse_req_t req, fuse_ino_t nodeid,
 {
 const char *name = fuse_mbuf_iter_advance_str(iter);
 const char *linkname = fuse_mbuf_iter_advance_str(iter);
+bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+int err;
 
 if (!name || !linkname) {
 fuse_reply_err(req, EINVAL);
 return;
 }
 
+if (secctx_enabled) {
+err = parse_secctx_fill_req(req, iter);
+if (err) {
+fuse_reply_err(req, err);
+}
+}
+
 if (req->se->op.symlink) {
 req->se->op.symlink(req, linkname, nodeid, name);
 } else {
@@ -1048,6 +1103,8 @@ static void do_link(fuse_req_t req, fuse_ino_t nodeid,
 static void do_create(fuse_req_t req, fuse_ino_t nodeid,
   struct fuse_mbuf_iter *iter)
 {
+bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+
 if (req->se->op.create) {
 struct fuse_create_in *arg;
 struct fuse_file_info fi;
@@ -1060,6 +1117,15 @@ static void do_create(fuse_req_t req, fuse_ino_t nodeid,
 return;
 }
 
+if (secctx_enabled) {
+int err

[PATCH 3/5] virtiofsd: Move core file creation code in separate function

2021-09-24 Thread Vivek Goyal
Move core file creation bits in a separate function. Soon this is going
to get more complex as file creation need to set security context also.
And there will be multiple modes of file creation in next patch.

Signed-off-by: Vivek Goyal 
---
 tools/virtiofsd/passthrough_ll.c | 36 ++--
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 64b5b4fbb1..54978b7fae 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -1976,6 +1976,30 @@ static int lo_do_open(struct lo_data *lo, struct 
lo_inode *inode,
 return 0;
 }
 
+static int do_lo_create(fuse_req_t req, struct lo_inode *parent_inode,
+const char *name, mode_t mode,
+struct fuse_file_info *fi, int* open_fd)
+{
+int err = 0, fd;
+struct lo_cred old = {};
+struct lo_data *lo = lo_data(req);
+
+err = lo_change_cred(req, &old, lo->change_umask);
+if (err) {
+return err;
+}
+
+/* Try to create a new file but don't open existing files */
+fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode);
+if (fd == -1) {
+err = errno;
+} else {
+*open_fd = fd;
+}
+lo_restore_cred(&old, lo->change_umask);
+return err;
+}
+
 static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
   mode_t mode, struct fuse_file_info *fi)
 {
@@ -1985,7 +2009,6 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, 
const char *name,
 struct lo_inode *inode = NULL;
 struct fuse_entry_param e;
 int err;
-struct lo_cred old = {};
 
 fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=%" PRIu64 ", name=%s)"
  " kill_priv=%d\n", parent, name, fi->kill_priv);
@@ -2001,18 +2024,9 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, 
const char *name,
 return;
 }
 
-err = lo_change_cred(req, &old, lo->change_umask);
-if (err) {
-goto out;
-}
-
 update_open_flags(lo->writeback, lo->allow_direct_io, fi);
 
-/* Try to create a new file but don't open existing files */
-fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode);
-err = fd == -1 ? errno : 0;
-
-lo_restore_cred(&old, lo->change_umask);
+err = do_lo_create(req, parent_inode, name, mode, fi, &fd);
 
 /* Ignore the error if file exists and O_EXCL was not given */
 if (err && (err != EEXIST || (fi->flags & O_EXCL))) {
-- 
2.31.1




[PATCH 0/5] virtiofsd: Add support for file security context at creation

2021-09-24 Thread Vivek Goyal
Hi,

These patches add support to receive and set file security context at
the time of file creation. This is one of the components needed to
support SELinux on virtiofs.

I have posted kernel patches here just now.

https://lore.kernel.org/linux-fsdevel/20210924192442.916927-1-vgo...@redhat.com/T/#m971f9001dd622b3f7a96a65899e3f146d2185841

These patches will allow users to configure virtiofsd in multiple modes
to set security context.

A. Guest and host selinux policies can work with each other.
- virtiofsd will use /proc/thread-self/attr/fscreate knob to
  set security context before file creation.

B. Remap guest selinux security xattr to something else say,
   trusted.virtiofs.security.selinux.
- Give CAP_SYS_ADMIN to virtiofsd.
- "-o -o xattrmap=:map:security.selinux:trusted.virtiofsd.:"

C. If no SELinux on host.
- Give CAP_SYS_ADMIN to virtiofsd. 

I have tested mode A and B but yet to test mode C.

I think either mode B or mode C will be most commonly used mode when
guest does need SELinux support in virtiofs.

With these patches, I am able to boot a guest VM with rootfs on virtiofs
and with SELinux enabled in guest. 

Please review.

Thanks
Vivek


Vivek Goyal (5):
  fuse: Header file changes for FUSE_SECURITY_CTX
  fuse_lowlevel.c: Add capability to parse security context
  virtiofsd: Move core file creation code in separate function
  virtiofsd: Create new file with fscreate set
  virtiofsd: Create new file using O_TMPFILE and set security context

 include/standard-headers/linux/fuse.h |  14 +-
 tools/virtiofsd/fuse_common.h |   5 +
 tools/virtiofsd/fuse_i.h  |   7 +
 tools/virtiofsd/fuse_lowlevel.c   |  74 ++
 tools/virtiofsd/passthrough_ll.c  | 366 --
 5 files changed, 436 insertions(+), 30 deletions(-)

-- 
2.31.1




[PATCH 4/5] virtiofsd: Create new file with fscreate set

2021-09-24 Thread Vivek Goyal
This patch adds support to set /proc/thread-self/attr/fscreate before
file creation. It is set to a value as sent by client. This will allow
for atomic creation of security context on files w.r.t file creation.

This is primarily useful when either there is no SELinux enabled on
host or host and guest policies are in sync and don't conflict.

Signed-off-by: Vivek Goyal 
---
 tools/virtiofsd/passthrough_ll.c | 284 ---
 1 file changed, 257 insertions(+), 27 deletions(-)

diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 54978b7fae..d8c14d3220 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -172,6 +172,8 @@ struct lo_data {
 
 /* An O_PATH file descriptor to /proc/self/fd/ */
 int proc_self_fd;
+/* An O_PATH file descriptor to /proc/self/task/ */
+int proc_self_task;
 int user_killpriv_v2, killpriv_v2;
 /* If set, virtiofsd is responsible for setting umask during creation */
 bool change_umask;
@@ -229,6 +231,11 @@ static struct lo_inode *lo_find(struct lo_data *lo, struct 
stat *st,
 static int xattr_map_client(const struct lo_data *lo, const char *client_name,
 char **out_name);
 
+#define FCHDIR_NOFAIL(fd) do { \
+int fchdir_res = fchdir(fd);   \
+assert(fchdir_res == 0);   \
+} while (0)
+
 static bool is_dot_or_dotdot(const char *name)
 {
 return name[0] == '.' &&
@@ -1259,16 +1266,140 @@ static void lo_restore_cred_gain_cap(struct lo_cred 
*old, bool restore_umask,
 }
 }
 
+/* Helpers to set/reset fscreate */
+static int open_set_proc_fscreate(struct lo_data *lo, const void *ctx,
+  size_t ctxlen, int *fd)
+{
+char procname[64];
+int fscreate_fd, err = 0;
+size_t written;
+
+sprintf(procname, "%d/attr/fscreate", gettid());
+fscreate_fd = openat(lo->proc_self_task, procname, O_WRONLY);
+err = fscreate_fd == -1 ? errno : 0;
+if (err) {
+return err;
+}
+
+written = write(fscreate_fd, ctx, ctxlen);
+err = written == -1 ? errno : 0;
+if (err) {
+goto out;
+}
+
+*fd = fscreate_fd;
+return 0;
+out:
+close(fscreate_fd);
+return err;
+}
+
+static void close_reset_proc_fscreate(int fd)
+{
+if ((write(fd, NULL, 0)) == -1) {
+fuse_log(FUSE_LOG_WARNING, "Failed to reset fscreate. err=%d\n", 
errno);
+}
+close(fd);
+return;
+}
+
+static int do_mknod_symlink_secctx(fuse_req_t req, struct lo_inode *dir,
+   const char *name, const char *secctx_name)
+{
+int path_fd, err;
+char procname[64];
+struct lo_data *lo = lo_data(req);
+
+if (!req->secctx.ctxlen) {
+return 0;
+}
+
+/* Open newly created element with O_PATH */
+path_fd = openat(dir->fd, name, O_PATH | O_NOFOLLOW);
+err = path_fd == -1 ? errno : 0;
+if (err) {
+return err;
+}
+sprintf(procname, "%i", path_fd);
+FCHDIR_NOFAIL(lo->proc_self_fd);
+/* Set security context. This is not atomic w.r.t file creation */
+err = setxattr(procname, secctx_name, req->secctx.ctx, req->secctx.ctxlen,
+   0);
+if (err) {
+err = errno;
+}
+FCHDIR_NOFAIL(lo->root.fd);
+close(path_fd);
+return err;
+}
+
+static int do_mknod_symlink(fuse_req_t req, struct lo_inode *dir,
+const char *name, mode_t mode, dev_t rdev,
+const char *link)
+{
+int err, fscreate_fd = -1;
+const char *secctx_name = req->secctx.name;
+struct lo_cred old = {};
+struct lo_data *lo = lo_data(req);
+char *mapped_name = NULL;
+bool secctx_enabled = req->secctx.ctxlen;
+bool do_fscreate = false;
+
+if (secctx_enabled && lo->xattrmap) {
+err = xattr_map_client(lo, req->secctx.name, &mapped_name);
+if (err < 0) {
+return -err;
+}
+secctx_name = mapped_name;
+}
+
+/*
+ * If security xattr has not been remapped, set fscreate and no
+ * need to do a setxattr() after file creation
+ */
+if (secctx_enabled && !mapped_name) {
+do_fscreate = true;
+err = open_set_proc_fscreate(lo, req->secctx.ctx, req->secctx.ctxlen,
+ &fscreate_fd);
+if (err) {
+goto out;
+}
+}
+
+err = lo_change_cred(req, &old, lo->change_umask && !S_ISLNK(mode));
+if (err) {
+goto out;
+}
+
+err = mknod_wrapper(dir->fd, name, link, mode, rdev);
+err = err == -1 ? errno : 0;
+lo_restore_cred(&old, lo->change_umask && !S_ISLNK(mode));
+if (err) {
+goto out;
+}
+
+if (!do_fscreate) {
+err = do_mknod_symlink_secctx(req, dir, name, secctx_name);
+if (err) {
+unlinkat(dir->fd, name, S_ISDIR(mode) ? AT_REMOVEDIR : 0);
+

[PATCH 5/5] virtiofsd: Create new file using O_TMPFILE and set security context

2021-09-24 Thread Vivek Goyal
If guest and host policies can't work with each other, then guest security
context (selinux label) needs to be set into an xattr. Say remap guest
security.selinux xattr to trusted.virtiofs.security.selinux.

That means setting "fscreate" is not going to help as that's ony useful
for security.selinux xattr on host.

So we need another method which is atomic. Use O_TMPFILE to create new
file, set xattr and then linkat() to proper place.

But this works only for regular files. So dir, symlinks will continue
to be non-atomic.

Also if host filesystem does not support O_TMPFILE, we fallback to
non-atomic behavior.

Signed-off-by: Vivek Goyal 
---
 tools/virtiofsd/passthrough_ll.c | 78 +---
 1 file changed, 71 insertions(+), 7 deletions(-)

diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index d8c14d3220..f5c3746510 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -2099,14 +2099,29 @@ static int lo_do_open(struct lo_data *lo, struct 
lo_inode *inode,
 
 static int do_create_nosecctx(fuse_req_t req, struct lo_inode *parent_inode,
const char *name, mode_t mode,
-   struct fuse_file_info *fi, int *open_fd)
+   struct fuse_file_info *fi, int *open_fd,
+  bool tmpfile)
 {
 int err, fd;
 struct lo_cred old = {};
 struct lo_data *lo = lo_data(req);
 int flags;
 
-flags = fi->flags | O_CREAT | O_EXCL;
+if (tmpfile) {
+flags = fi->flags | O_TMPFILE;
+/*
+ * Don't use O_EXCL as we want to link file later. Also reset O_CREAT
+ * otherwise openat() returns -EINVAL.
+ */
+flags &= ~(O_CREAT | O_EXCL);
+
+/* O_TMPFILE needs either O_RDWR or O_WRONLY */
+if ((flags & O_ACCMODE) == O_RDONLY) {
+flags |= O_RDWR;
+}
+} else {
+flags = fi->flags | O_CREAT | O_EXCL;
+}
 
 err = lo_change_cred(req, &old, lo->change_umask);
 if (err) {
@@ -2137,7 +2152,7 @@ static int do_create_secctx_fscreate(fuse_req_t req,
 return err;
 }
 
-err = do_create_nosecctx(req, parent_inode, name, mode, fi, &fd);
+err = do_create_nosecctx(req, parent_inode, name, mode, fi, &fd, false);
 
 close_reset_proc_fscreate(fscreate_fd);
 if (!err) {
@@ -2146,6 +2161,44 @@ static int do_create_secctx_fscreate(fuse_req_t req,
 return err;
 }
 
+static int do_create_secctx_tmpfile(fuse_req_t req,
+struct lo_inode *parent_inode,
+const char *name, mode_t mode,
+struct fuse_file_info *fi,
+const char *secctx_name, int *open_fd)
+{
+int err, fd = -1;
+struct lo_data *lo = lo_data(req);
+char procname[64];
+
+err = do_create_nosecctx(req, parent_inode, ".", mode, fi, &fd, true);
+if (err) {
+return err;
+}
+
+err = fsetxattr(fd, secctx_name, req->secctx.ctx, req->secctx.ctxlen, 0);
+if (err) {
+err = errno;
+goto out;
+}
+
+/* Security context set on file. Link it in place */
+sprintf(procname, "%d", fd);
+FCHDIR_NOFAIL(lo->proc_self_fd);
+err = linkat(AT_FDCWD, procname, parent_inode->fd, name,
+ AT_SYMLINK_FOLLOW);
+err = err == -1 ? errno : 0;
+FCHDIR_NOFAIL(lo->root.fd);
+
+out:
+if (!err) {
+*open_fd = fd;
+} else if (fd != -1) {
+close(fd);
+}
+return err;
+}
+
 static int do_create_secctx_noatomic(fuse_req_t req,
  struct lo_inode *parent_inode,
  const char *name, mode_t mode,
@@ -2154,7 +2207,7 @@ static int do_create_secctx_noatomic(fuse_req_t req,
 {
 int err = 0, fd = -1;
 
-err = do_create_nosecctx(req, parent_inode, name, mode, fi, &fd);
+err = do_create_nosecctx(req, parent_inode, name, mode, fi, &fd, false);
 if (err) {
 goto out;
 }
@@ -2196,20 +2249,31 @@ static int do_lo_create(fuse_req_t req, struct lo_inode 
*parent_inode,
 if (secctx_enabled) {
 /*
  * If security.selinux has not been remapped. Use fscreate to set
- * context before file creation.
- * Otherwise fallback to non-atomic method of file creation
+ * context before file creation. Use tempfile method for regular
+ * files. Otherwise fallback to non-atomic method of file creation
  * and xattr settting.
  */
 if (!mapped_name) {
 err = do_create_secctx_fscreate(req, parent_inode, name, mode, fi,
 open_fd);
 goto out;
+} else if (S_ISREG(mode)) {
+err = do_create_secctx_tmpfile(req, parent_inode, name, mode, fi,
+   ctxname, open_fd);
+/

Re: [PATCH 05/16] Acceptance Tests: add standard clean up at test tearDown()

2021-09-24 Thread Willian Rampazzo
Hi, Cleber,

On Fri, Sep 24, 2021 at 3:57 PM Cleber Rosa  wrote:
>
> The avocado.Test class, used as the basis of the avocado_qemu.Test
> class, performs a clean of temporary directories up as part of its own
> tearDown() implementation.
>
> But the avocado_qemu.Test class is currently missing the same clean
> up, as it implemented its own tearDown() method without resorting to
> the upper class behavior.
>
> This brings avocado_qemu.Test behavior in sync with the standard
> avocado.Test behavior and prevents temporary directories from
> cluttering the test results directory (unless instructed to do so with
> Avocado's "--keep-tmp" option).
>
> Reported-by: Peter Maydell 
> Signed-off-by: Cleber Rosa 
> ---
>  tests/acceptance/avocado_qemu/__init__.py | 1 +
>  1 file changed, 1 insertion(+)
>

There was a comment from Wainer in the original patch and as you were
on vacation I submitted a respin last Monday:

https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg05117.html

I also did some refactoring/fixes to the avocado_qemu here:

https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg05212.html




Re: [PATCH v3 1/9] nbd/client-connection: nbd_co_establish_connection(): fix non set errp

2021-09-24 Thread Eric Blake
On Tue, Sep 07, 2021 at 12:44:53PM -0500, Eric Blake wrote:
> On Mon, Sep 06, 2021 at 10:06:46PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> > When we don't have a connection and blocking is false, we return NULL
> > but don't set errp. That's wrong.
> 
> Oops...
> 
> > 
> > We have two paths for calling nbd_co_establish_connection():
> > 
> > 1. nbd_open() -> nbd_do_establish_connection() -> ...
> >   but that will never set blocking=false
> > 
> > 2. nbd_reconnect_attempt() -> nbd_co_do_establish_connection() -> ...
> >   but that uses errp=NULL
> > 
> > So, we are safe with our wrong errp policy in
> > nbd_co_establish_connection(). Still let's fix it.
> 
> ...phew!  Thus, it's not critical to backport.
> 
> Reviewed-by: Eric Blake 

Queuing this one through my NBD tree.  Given the discussion on 2/9,
I'll leave the rest of the series for later.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH] nbd/server: Allow LIST_META_CONTEXT without STRUCTURED_REPLY

2021-09-24 Thread Eric Blake
On Tue, Sep 14, 2021 at 05:19:42PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> 07.09.2021 20:35, Eric Blake wrote:
> > The NBD protocol just relaxed the requirements on
> > NBD_OPT_LIST_META_CONTEXT:
> > 
> > https://github.com/NetworkBlockDevice/nbd/commit/13a4e33a87
> > 
> > Since listing is not stateful (unlike SET_META_CONTEXT), we don't care
> > if a client asks for meta contexts without first requesting structured
> > replies.  Well-behaved clients will still ask for structured reply
> > first (if for no other reason than for back-compat to older servers),
> > but that's no reason to avoid this change.
> > 
> > Signed-off-by: Eric Blake
> 
> Reviewed-by: Vladimir Sementsov-Ogievskiy 

Thanks; queuing this one through my NBD tree.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 14/16] tests/acceptance/ppc_prep_40p.py: NetBSD 7.1.2 location update

2021-09-24 Thread Cleber Rosa
The NetBSD-7.1.2-prep.iso is no longer available on the CDN, but it's
still available in the archive.

Let's update its location so that users without the file on cache can
still fetch it and run the test.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/ppc_prep_40p.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py
index 2993ee3b07..6b28a69ea5 100644
--- a/tests/acceptance/ppc_prep_40p.py
+++ b/tests/acceptance/ppc_prep_40p.py
@@ -67,8 +67,8 @@ def test_openbios_and_netbsd(self):
 :avocado: tags=machine:40p
 :avocado: tags=os:netbsd
 """
-drive_url = ('https://cdn.netbsd.org/pub/NetBSD/iso/7.1.2/'
- 'NetBSD-7.1.2-prep.iso')
+drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/'
+ 'NetBSD-7.1.2/iso/NetBSD-7.1.2-prep.iso')
 drive_hash = 'ac6fa2707d888b36d6fa64de6e7fe48e'
 drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash,
   algorithm='md5')
-- 
2.31.1




Re: [PATCH v2] nbd/server: Add --selinux-label option

2021-09-24 Thread Eric Blake
Ping

On Wed, Aug 25, 2021 at 02:35:04PM -0500, Eric Blake wrote:
> On Fri, Jul 23, 2021 at 05:38:06PM +0100, Daniel P. Berrangé wrote:
> > On Fri, Jul 23, 2021 at 06:18:55PM +0200, Kevin Wolf wrote:
> > > Am 23.07.2021 um 12:33 hat Richard W.M. Jones geschrieben:
> > > > Under SELinux, Unix domain sockets have two labels.  One is on the
> > > > disk and can be set with commands such as chcon(1).  There is a
> > > > different label stored in memory (called the process label).  This can
> > > > only be set by the process creating the socket.  When using SELinux +
> > > > SVirt and wanting qemu to be able to connect to a qemu-nbd instance,
> > > > you must set both labels correctly first.
> > > > 
> > > > For qemu-nbd the options to set the second label are awkward.  You can
> > > > create the socket in a wrapper program and then exec into qemu-nbd.
> > > > Or you could try something with LD_PRELOAD.
> > > > 
> > > > This commit adds the ability to set the label straightforwardly on the
> > > > command line, via the new --selinux-label flag.  (The name of the flag
> > > > is the same as the equivalent nbdkit option.)
> > > > 
> > > > A worked example showing how to use the new option can be found in
> > > > this bug: https://bugzilla.redhat.com/show_bug.cgi?id=1984938
> > > > 
> > > > Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1984938
> > > > Signed-off-by: Richard W.M. Jones 
> > > 
> > > I suppose this would also be relevant for the built-in NBD server,
> > > especially in the context of qemu-storage-daemon?
> > 
> > It depends on the usage scenario really. nbdkit / qemu-nbd are
> > not commonly run under any SELinux policy, so then end up being
> > unconfined_t. A QEMU NBD client can't connect to an unconfined_t
> > socket, so we need to override it with this arg.
> > 
> > In the case of qemu system emulator, under libvirt, it will
> > already have a svirt_t type, so in that case there is no need
> > to override the type for the socket.
> > 
> > For qsd there's not really any strong practice established
> > but i expect most current usage is unconfined_t too and
> > would benefit from setting label.
> > 
> > > If so, is this something specific to NBD sockets, or would it actually
> > > make sense to have it as a generic option in UnixSocketAddress?
> > 
> > It is applicable to inet sockets too in fact.
> 
> So now that 6.2 is open, should I queue the patch as is, or wait for a
> v3 that makes the option more generic to all socket usage?
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 16/16] tests/acceptance/ppc_prep_40p.py: unify tags

2021-09-24 Thread Cleber Rosa
The arch and machine tags apply to all tests, so let's define them
only once.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/ppc_prep_40p.py | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py
index 5e61e686bd..d1e5674673 100644
--- a/tests/acceptance/ppc_prep_40p.py
+++ b/tests/acceptance/ppc_prep_40p.py
@@ -13,6 +13,10 @@
 
 
 class IbmPrep40pMachine(Test):
+"""
+:avocado: tags=arch:ppc
+:avocado: tags=machine:40p
+"""
 
 timeout = 60
 
@@ -24,8 +28,6 @@ class IbmPrep40pMachine(Test):
 @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
 def test_factory_firmware_and_netbsd(self):
 """
-:avocado: tags=arch:ppc
-:avocado: tags=machine:40p
 :avocado: tags=os:netbsd
 :avocado: tags=slowness:high
 """
@@ -48,10 +50,6 @@ def test_factory_firmware_and_netbsd(self):
 wait_for_console_pattern(self, 'Model: IBM PPS Model 6015')
 
 def test_openbios_192m(self):
-"""
-:avocado: tags=arch:ppc
-:avocado: tags=machine:40p
-"""
 self.vm.set_console()
 self.vm.add_args('-m', '192') # test fw_cfg
 
@@ -62,8 +60,6 @@ def test_openbios_192m(self):
 
 def test_openbios_and_netbsd(self):
 """
-:avocado: tags=arch:ppc
-:avocado: tags=machine:40p
 :avocado: tags=os:netbsd
 """
 drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/'
-- 
2.31.1




[PATCH 13/16] tests/acceptance/boot_xen.py: use class attribute

2021-09-24 Thread Cleber Rosa
Rather than defining a single use variable, let's just use the class
attribute directly.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index 66621fd14d..8eec465414 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -49,11 +49,10 @@ def launch_xen(self, xen_path):
 
 self.vm.set_console()
 
-xen_command_line = self.XEN_COMMON_COMMAND_LINE
 self.vm.add_args('-machine', 'virtualization=on',
  '-m', '768',
  '-kernel', xen_path,
- '-append', xen_command_line,
+ '-append', self.XEN_COMMON_COMMAND_LINE,
  '-device',
  
'guest-loader,addr=0x4700,kernel=%s,bootargs=console=hvc0'
  % (self.kernel_path))
-- 
2.31.1




Re: [PATCH 10/11] vl: Enable JSON syntax for -device

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:26AM +0200, Kevin Wolf wrote:
> Like we already do for -object, introduce support for JSON syntax in
> -device, which can be kept stable in the long term and guarantees that a
> single code path with identical behaviour is used for both QMP and the
> command line. Compared to the QemuOpts based code, the parser contains
> less surprises and has support for non-scalar options (lists and
> structs). Switching management tools to JSON means that we can more
> easily change the "human" CLI syntax from QemuOpts to the keyval parser
> later.
> 
> In the QAPI schema, a feature flag is added to the device-add command to
> allow management tools to detect support for this.
> 
> Signed-off-by: Kevin Wolf 
> ---
>  qapi/qdev.json | 15 +
>  softmmu/vl.c   | 58 --
>  2 files changed, 62 insertions(+), 11 deletions(-)
> 
> diff --git a/qapi/qdev.json b/qapi/qdev.json
> index b83178220b..cdc8f911b5 100644
> --- a/qapi/qdev.json
> +++ b/qapi/qdev.json
> @@ -32,17 +32,23 @@
>  ##
>  # @device_add:
>  #
> +# Add a device.
> +#
>  # @driver: the name of the new device's driver
>  #
>  # @bus: the device's parent bus (device tree path)
>  #
>  # @id: the device's ID, must be unique
>  #
> -# Additional arguments depend on the type.
> -#
> -# Add a device.
> +# Features:
> +# @json-cli: If present, the "-device" command line option supports JSON
> +#syntax with a structure identical to the arguments of this
> +#command.
>  #
>  # Notes:
> +#
> +# Additional arguments depend on the type.
> +#
>  # 1. For detailed information about this command, please refer to the
>  #'docs/qdev-device-use.txt' file.
>  #
> @@ -67,7 +73,8 @@
>  ##
>  { 'command': 'device_add',
>'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
> -  'gen': false } # so we can get the additional arguments
> +  'gen': false, # so we can get the additional arguments
> +  'features': ['json-cli'] }

Eventually, we'll get rid of this 'gen':false, but this patch series
is already an improvement towards that goal.

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 04/16] Acceptance Tests: keep track and disable tests with known issues

2021-09-24 Thread Cleber Rosa
This introduces a convention, under which tests with known open
issues, will be automatically excluded from execution via "make
check-acceptance".  It should by itself improve the reliability
of test jobs, even those with rare failures.

Those tests can still be run with:

  ./tests/venv/bin/avocado run $TEST_ID

With the test identification are obtainable via:

  ./tests/venv/bin/avocado list tests/acceptance

And for tests with known issues:

  ./tests/venv/bin/avocado list -t issue tests/acceptance

A list of tests that are enabled (that is, match the currently
configured targets, and do not have known issues) can be obtained
with:

  make list-acceptance

As a future improvement, a tool can be added to sync the "issue" tags
with issues that end up being resolved closed.

Signed-off-by: Cleber Rosa 
---
 docs/devel/testing.rst | 28 ++
 tests/Makefile.include |  3 ++-
 tests/acceptance/boot_linux_console.py |  3 +++
 tests/acceptance/machine_rx_gdbsim.py  |  3 +++
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index 2818c58ff8..f93a9bed3f 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -1147,6 +1147,34 @@ variable as shown on the code snippet below to skip the 
test:
   def test(self):
   do_something()
 
+Disabling tests
+---
+
+If you want to have a test temporarily disabled (from ``make
+check-acceptance``), you can add an Avocado ``issue`` tag to the test.  
Example::
+
+  class Feature(Test):
+
+  def test(self):
+"""
+:avocado: tags=issue
+"""
+do_something()
+
+Rather than simply adding an ``issue`` tag, it may be helpful to point
+to an actual issue on the project's issue tracker::
+
+  class Feature(Test):
+
+  def test(self):
+"""
+Reason for disabling this test is documented and tracked at
+https://gitlab.com/qemu-project/qemu/-/issues/
+
+:avocado: tags=issue:
+"""
+do_something()
+
 Uninstalling Avocado
 
 
diff --git a/tests/Makefile.include b/tests/Makefile.include
index d1f90572a7..eb3e5d2aa6 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -94,7 +94,8 @@ TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results
 # information please refer to "avocado --help".
 AVOCADO_SHOW=app
 AVOCADO_RUNNER=runner
-AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGETS)))
+comma := ,
+AVOCADO_TAGS=$(patsubst %-softmmu,--filter-by-tags=-issue$(comma)arch:%, 
$(filter %-softmmu,$(TARGETS)))
 
 $(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
$(call quiet-command, \
diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 0a49c0e276..4c824bc161 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -485,6 +485,9 @@ def test_arm_raspi2_initrd(self):
 """
 :avocado: tags=arch:arm
 :avocado: tags=machine:raspi2b
+
+# https://gitlab.com/qemu-project/qemu/-/issues/636
+:avocado: tags=issue:636
 """
 deb_url = ('http://archive.raspberrypi.org/debian/'
'pool/main/r/raspberrypi-firmware/'
diff --git a/tests/acceptance/machine_rx_gdbsim.py 
b/tests/acceptance/machine_rx_gdbsim.py
index 32b737b6d8..62893a9989 100644
--- a/tests/acceptance/machine_rx_gdbsim.py
+++ b/tests/acceptance/machine_rx_gdbsim.py
@@ -54,6 +54,9 @@ def test_linux_sash(self):
 :avocado: tags=arch:rx
 :avocado: tags=machine:gdbsim-r5f562n7
 :avocado: tags=endian:little
+
+# https://gitlab.com/qemu-project/qemu/-/issues/507
+:avocado: tags=issue:507
 """
 dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb')
 dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18'
-- 
2.31.1




[PATCH 12/16] tests/acceptance/boot_xen.py: removed unused import

2021-09-24 Thread Cleber Rosa
Just a clean up for an unused import.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index cd916ddba4..66621fd14d 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -13,7 +13,6 @@
 
 import os
 
-from avocado import skipIf
 from avocado_qemu import wait_for_console_pattern
 from boot_linux_console import LinuxKernelTest
 
-- 
2.31.1




[PATCH 02/16] Acceptance Tests: improve check-acceptance description

2021-09-24 Thread Cleber Rosa
The "check-acceptance" make rule won't necessarily run *all* available
tests, because it employs a filter based on the currently configured
targets.  This change in the description of the rule makes that
behavior extra clear.

Signed-off-by: Cleber Rosa 
---
 tests/Makefile.include | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index ac289a2e41..2c03256ae8 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -16,7 +16,7 @@ ifneq ($(filter $(all-check-targets), check-softfloat),)
@echo " $(MAKE) check-tcgRun TCG tests"
@echo " $(MAKE) check-softfloat  Run FPU emulation tests"
 endif
-   @echo " $(MAKE) check-acceptance Run all acceptance (functional) 
tests"
+   @echo " $(MAKE) check-acceptance Run acceptance (functional) tests 
for currently configured targets"
@echo
@echo " $(MAKE) check-report.tap Generates an aggregated TAP test 
report"
@echo " $(MAKE) check-venv   Creates a Python venv for tests"
-- 
2.31.1




[PATCH 15/16] tests/acceptance/ppc_prep_40p.py: clean up unused import

2021-09-24 Thread Cleber Rosa
Just a removal of an unused imported symbol.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/ppc_prep_40p.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py
index 6b28a69ea5..5e61e686bd 100644
--- a/tests/acceptance/ppc_prep_40p.py
+++ b/tests/acceptance/ppc_prep_40p.py
@@ -7,7 +7,6 @@
 
 import os
 
-from avocado import skipIf
 from avocado import skipUnless
 from avocado_qemu import Test
 from avocado_qemu import wait_for_console_pattern
-- 
2.31.1




[PATCH 11/16] tests/acceptance/boot_xen.py: fetch kernel during test setUp()

2021-09-24 Thread Cleber Rosa
The kernel is a common blob used in all tests.  By moving it to the
setUp() method, the "fetch asset" plugin will recognize the kernel and
attempt to fetch it and cache it before the tests are started.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index e2c59f6592..cd916ddba4 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -31,23 +31,22 @@ class BootXen(LinuxKernelTest):
 timeout = 90
 XEN_COMMON_COMMAND_LINE = 'dom0_mem=128M loglvl=all guest_loglvl=all'
 
-def fetch_guest_kernel(self):
+def setUp(self):
+super(BootXen, self).setUp()
+
 # Using my own built kernel - which works
 kernel_url = ('https://fileserver.linaro.org/'
   's/JSsewXGZ6mqxPr5/download?path=%2F&files='
   'linux-5.9.9-arm64-ajb')
 kernel_sha1 = '4f92bc4b9f88d5ab792fa7a43a68555d344e1b83'
-kernel_path = self.fetch_asset(kernel_url,
-   asset_hash=kernel_sha1)
-
-return kernel_path
+self.kernel_path = self.fetch_asset(kernel_url,
+asset_hash=kernel_sha1)
 
 def launch_xen(self, xen_path):
 """
 Launch Xen with a dom0 guest kernel
 """
 self.log.info("launch with xen_path: %s", xen_path)
-kernel_path = self.fetch_guest_kernel()
 
 self.vm.set_console()
 
@@ -58,7 +57,7 @@ def launch_xen(self, xen_path):
  '-append', xen_command_line,
  '-device',
  
'guest-loader,addr=0x4700,kernel=%s,bootargs=console=hvc0'
- % (kernel_path))
+ % (self.kernel_path))
 
 self.vm.launch()
 
-- 
2.31.1




[PATCH 10/16] tests/acceptance/boot_xen.py: unify tags

2021-09-24 Thread Cleber Rosa
Because all tests share the same tags, it's possible to have all of
them at the class level.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 26 +-
 1 file changed, 5 insertions(+), 21 deletions(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index 4c14f9e2e7..e2c59f6592 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -21,6 +21,11 @@
 class BootXen(LinuxKernelTest):
 """
 Boots a Xen hypervisor with a Linux DomU kernel.
+
+:avocado: tags=arch:aarch64
+:avocado: tags=accel:tcg
+:avocado: tags=cpu:cortex-a57
+:avocado: tags=machine:virt
 """
 
 timeout = 90
@@ -61,13 +66,6 @@ def launch_xen(self, xen_path):
 wait_for_console_pattern(self, console_pattern, "Panic on CPU 0:")
 
 def test_arm64_xen_411_and_dom0(self):
-"""
-:avocado: tags=arch:aarch64
-:avocado: tags=accel:tcg
-:avocado: tags=cpu:cortex-a57
-:avocado: tags=machine:virt
-"""
-
 # archive of file from https://deb.debian.org/debian/pool/main/x/xen/
 xen_url = ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/'
'download?path=%2F&files='
@@ -79,13 +77,6 @@ def test_arm64_xen_411_and_dom0(self):
 self.launch_xen(xen_path)
 
 def test_arm64_xen_414_and_dom0(self):
-"""
-:avocado: tags=arch:aarch64
-:avocado: tags=accel:tcg
-:avocado: tags=cpu:cortex-a57
-:avocado: tags=machine:virt
-"""
-
 # archive of file from https://deb.debian.org/debian/pool/main/x/xen/
 xen_url = ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/'
'download?path=%2F&files='
@@ -97,13 +88,6 @@ def test_arm64_xen_414_and_dom0(self):
 self.launch_xen(xen_path)
 
 def test_arm64_xen_415_and_dom0(self):
-"""
-:avocado: tags=arch:aarch64
-:avocado: tags=accel:tcg
-:avocado: tags=cpu:cortex-a57
-:avocado: tags=machine:virt
-"""
-
 xen_url = ('https://fileserver.linaro.org/'
's/JSsewXGZ6mqxPr5/download'
'?path=%2F&files=xen-upstream-4.15-unstable.deb')
-- 
2.31.1




[PATCH 07/16] Acceptance Tests: workaround expired mipsdistros.mips.com HTTPS cert

2021-09-24 Thread Cleber Rosa
The certficiate at https://mipsdistros.mips.com/ is currently
expired (since Jan 23, 2021).

Instead of failing to obtaining the files, let's downgrade to HTTP
instead, given that the integrity of the files are already performed
locally, after the download, using the recorded hash.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_linux_console.py | 6 +++---
 tests/acceptance/replay_kernel.py  | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 80e3a2f7a6..bc0caa1099 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -278,7 +278,7 @@ def test_mips_malta32el_nanomips_4k(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page4k.xz')
 kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6'
@@ -291,7 +291,7 @@ def test_mips_malta32el_nanomips_16k_up(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page16k_up.xz')
 kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc'
@@ -304,7 +304,7 @@ def test_mips_malta32el_nanomips_64k_dbg(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page64k_dbg.xz')
 kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180'
diff --git a/tests/acceptance/replay_kernel.py 
b/tests/acceptance/replay_kernel.py
index cfca71e65f..cac795ab4f 100644
--- a/tests/acceptance/replay_kernel.py
+++ b/tests/acceptance/replay_kernel.py
@@ -434,7 +434,7 @@ def test_mips_malta32el_nanomips_4k(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page4k.xz')
 kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6'
@@ -448,7 +448,7 @@ def test_mips_malta32el_nanomips_16k_up(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page16k_up.xz')
 kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc'
@@ -462,7 +462,7 @@ def test_mips_malta32el_nanomips_64k_dbg(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page64k_dbg.xz')
 kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180'
-- 
2.31.1




[PATCH 09/16] tests/acceptance/boot_xen.py: merge base classes

2021-09-24 Thread Cleber Rosa
While it's a good practice to have reusable base classes, in this
specific case there's no other user of the BootXenBase class.

By unifying the class used in this test, we can improve readability
and have the opportunity to add some future improvements in a clearer
fashion.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index b5860b7d88..4c14f9e2e7 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -18,7 +18,7 @@
 from boot_linux_console import LinuxKernelTest
 
 
-class BootXenBase(LinuxKernelTest):
+class BootXen(LinuxKernelTest):
 """
 Boots a Xen hypervisor with a Linux DomU kernel.
 """
@@ -60,9 +60,6 @@ def launch_xen(self, xen_path):
 console_pattern = 'VFS: Cannot open root device'
 wait_for_console_pattern(self, console_pattern, "Panic on CPU 0:")
 
-
-class BootXen(BootXenBase):
-
 def test_arm64_xen_411_and_dom0(self):
 """
 :avocado: tags=arch:aarch64
-- 
2.31.1




[PATCH 03/16] Acceptance Tests: add mechanism for listing tests

2021-09-24 Thread Cleber Rosa
It is helpful to know the tests that would be executed with a "make
check-acceptance" without executing them.  Let's introduce a "make
list-acceptance" rule for that purpose.

Signed-off-by: Cleber Rosa 
---
 tests/Makefile.include | 8 
 1 file changed, 8 insertions(+)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 2c03256ae8..d1f90572a7 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -17,6 +17,7 @@ ifneq ($(filter $(all-check-targets), check-softfloat),)
@echo " $(MAKE) check-softfloat  Run FPU emulation tests"
 endif
@echo " $(MAKE) check-acceptance Run acceptance (functional) tests 
for currently configured targets"
+   @echo " $(MAKE) check-acceptance List acceptance (functional) tests 
for currently configured targets"
@echo
@echo " $(MAKE) check-report.tap Generates an aggregated TAP test 
report"
@echo " $(MAKE) check-venv   Creates a Python venv for tests"
@@ -135,6 +136,13 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) 
get-vm-images
 $(if $(GITLAB_CI),,--failfast) tests/acceptance, \
 "AVOCADO", "tests/acceptance")
 
+list-acceptance: check-venv
+   $(call quiet-command, \
+$(TESTS_VENV_DIR)/bin/python -m avocado list \
+--filter-by-tags-include-empty --filter-by-tags-include-empty-key \
+$(AVOCADO_TAGS) tests/acceptance, \
+"AVOCADO", "list tests/acceptance")
+
 # Consolidated targets
 
 .PHONY: check-block check check-clean get-vm-images
-- 
2.31.1




Re: [PATCH v3 03/15] target/ppc: PMU basic cycle count for pseries TCG

2021-09-24 Thread Daniel Henrique Barboza




On 9/24/21 15:34, Matheus K. Ferst wrote:

On 24/09/2021 11:41, Daniel Henrique Barboza wrote:

On 9/22/21 08:24, Matheus K. Ferst wrote:

On 03/09/2021 17:31, Daniel Henrique Barboza wrote:

[E-MAIL EXTERNO] Não clique em links ou abra anexos, a menos que você possa 
confirmar o remetente e saber que o conteúdo é seguro. Em caso de e-mail 
suspeito entre imediatamente em contato com o DTI.

This patch adds the barebones of the PMU logic by enabling cycle
counting, done via the performance monitor counter 6. The overall logic
goes as follows:

- a helper is added to control the PMU state on each MMCR0 write. This
allows for the PMU to start/stop as the frozen counter bit (MMCR0_FC)
is cleared or set;

- MMCR0 reg initial value is set to 0x8000 (MMCR0_FC set) to avoid
having to spin the PMU right at system init;

- the intended usage is to freeze the counters by setting MMCR0_FC, do
any additional setting of events to be counted via MMCR1 (not
implemented yet) and enable the PMU by zeroing MMCR0_FC. Software must
freeze counters to read the results - on the fly reading of the PMCs
will return the starting value of each one.

Since there will be more PMU exclusive code to be added next, put the
PMU logic in its own helper to keep all in the same place. The name of
the new helper file, power8_pmu.c, is an indicative that the PMU logic
has been tested with the IBM POWER chip family, POWER8 being the oldest
version tested. This doesn't mean that this PMU logic will break with
any other PPC64 chip that implements Book3s, but since we can't assert
that this PMU will work with all available Book3s emulated processors
we're choosing to be explicit.

Signed-off-by: Daniel Henrique Barboza 
---





diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 0babde3131..c3e2e3d329 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -401,6 +401,24 @@ void spr_write_generic(DisasContext *ctx, int sprn, int 
gprn)
  spr_store_dump_spr(sprn);
  }

+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
+{
+    /*
+ * helper_store_mmcr0 will make clock based operations that
+ * will cause 'bad icount read' errors if we do not execute
+ * gen_icount_io_start() beforehand.
+ */
+    gen_icount_io_start(ctx);
+    gen_helper_store_mmcr0(cpu_env, cpu_gpr[gprn]);
+}
+#else
+void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
+{
+    spr_write_generic(ctx, sprn, gprn);
+}
+#endif
+
  #if !defined(CONFIG_USER_ONLY)
  void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
  {
@@ -596,7 +614,10 @@ void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int 
gprn)
  tcg_gen_andi_tl(t1, t1, ~(MMCR0_UREG_MASK));
  /* Keep all other bits intact */
  tcg_gen_or_tl(t1, t1, t0);
-    gen_store_spr(SPR_POWER_MMCR0, t1);
+
+    /* Overwrite cpu_gpr[gprn] and use spr_write_MMCR0() */
+    tcg_gen_mov_tl(cpu_gpr[gprn], t1);
+    spr_write_MMCR0(ctx, sprn + 0x10, gprn);


IIUC, this makes writing to MMCR0 change the GPR value and expose the 
unfiltered content of the SPR to problem state. It might be better to call the 
helper directly or create another method that takes a TCGv as an argument and 
call it from spr_write_MMCR0_ureg and spr_write_MMCR0.


I'm overwriting cpu_gpr[gprn] with t1, which is filtered by MMCR0_REG_MASK
right before, to re-use spr_write_MMCR0() since its API requires a gprn
index. The reason I'm re-using spr_write_MMCR0() here is to avoid code 
repetition
in spr_write_MMCR0_ureg(), which would need to repeat the same steps as
spr_write_MMCR0 (calling icount_io_start(), calling the helper, and then setting
DISAS_EXIT_UPDATE in a later patch).

The idea behind is that all PMU user_write() functions works the same as its
privileged counterparts but with some form of filtering done beforehand. Note
that this is kind of true in the previous patch as well - gen_store_spr() is
similar to the privileged function MMCR0 was using (spr_write_generic()) with
the exception of an optional qemu_log().

Maybe I should've made this clear in the previous patch, using 
spr_write_generic()
and overwriting cpu_gpr[gprn] with the filtered t1 content back there.

Speaking of which, since t1 is being filtered by MMCR0_REG_MASK before being 
used to
overwrite cpu_gpr[gprn], I'm not sure how this is exposing unfiltered content to
problem state. Can you elaborate?


Suppose MMCR0 has the value 0x8001 (FC and FCH) and problem state executes 
an mtspr with the value 0x400 (unset FC and set PMAE) in the GPR. The 
proposed code will do the following:

 > tcg_gen_andi_tl(t0, cpu_gpr[gprn], MMCR0_UREG_MASK);

t0 = GPR & MMCR0_UREG_MASK = 0x400 & 0x8480 = 0x400

 > gen_load_spr(t1, SPR_POWER_MMCR0);

t1 = MMCR0 = 0x8001

 > tcg_gen_andi_tl(t1, t1, ~(MMCR0_UREG_MASK));

t1 = t1 & ~MMCR0_UREG_MASK = 0x8001 & ~0x8480 = 0x1

 > tcg_gen_or_tl(t1, t1, t0);

t1 = t1 | t0 = 0x400 | 0x1 

[PATCH 06/16] Acceptance Tests: use extract from package from avocado.utils

2021-09-24 Thread Cleber Rosa
There's code in avocado.utils to handle package extractions in various
(currently rpm, and deb) formats.  Let's use it.

Reference: 
https://avocado-framework.readthedocs.io/en/91.0/api/utils/avocado.utils.software_manager.html#avocado.utils.software_manager.SoftwareManager.extract_from_package
Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_linux_console.py | 84 ++
 tests/acceptance/boot_xen.py   |  6 +-
 tests/acceptance/replay_kernel.py  | 12 ++--
 tests/acceptance/tcg_plugins.py|  2 +-
 4 files changed, 41 insertions(+), 63 deletions(-)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 4c824bc161..80e3a2f7a6 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -23,6 +23,7 @@
 from avocado.utils import process
 from avocado.utils import archive
 from avocado.utils.path import find_command, CmdNotFoundError
+from avocado.utils.software_manager import SoftwareManager
 
 P7ZIP_AVAILABLE = True
 try:
@@ -54,42 +55,19 @@ def wait_for_console_pattern(self, success_message, 
vm=None):
  failure_message='Kernel panic - not syncing',
  vm=vm)
 
-def extract_from_deb(self, deb, path):
+def extract_from_pkg(self, pkg, path):
 """
-Extracts a file from a deb package into the test workdir
+Extracts a file from a DEB or RPM package into the test workdir
 
-:param deb: path to the deb archive
-:param path: path within the deb archive of the file to be extracted
+:param pkg: path to the DEB or RPM package
+:param path: path within the DEB or RPM archive of the file to
+  be extracted
 :returns: path of the extracted file
 """
-cwd = os.getcwd()
-os.chdir(self.workdir)
-file_path = process.run("ar t %s" % deb).stdout_text.split()[2]
-process.run("ar x %s %s" % (deb, file_path))
-archive.extract(file_path, self.workdir)
-os.chdir(cwd)
-# Return complete path to extracted file.  Because callers to
-# extract_from_deb() specify 'path' with a leading slash, it is
-# necessary to use os.path.relpath() as otherwise os.path.join()
-# interprets it as an absolute path and drops the self.workdir part.
+SoftwareManager.extract_from_package(pkg, self.workdir)
 return os.path.normpath(os.path.join(self.workdir,
  os.path.relpath(path, '/')))
 
-def extract_from_rpm(self, rpm, path):
-"""
-Extracts a file from an RPM package into the test workdir.
-
-:param rpm: path to the rpm archive
-:param path: path within the rpm archive of the file to be extracted
- needs to be a relative path (starting with './') because
- cpio(1), which is used to extract the file, expects that.
-:returns: path of the extracted file
-"""
-cwd = os.getcwd()
-os.chdir(self.workdir)
-process.run("rpm2cpio %s | cpio -id %s" % (rpm, path), shell=True)
-os.chdir(cwd)
-return os.path.normpath(os.path.join(self.workdir, path))
 
 class BootLinuxConsole(LinuxKernelTest):
 """
@@ -128,7 +106,7 @@ def test_mips_malta(self):
'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb')
 deb_hash = 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04'
 deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
-kernel_path = self.extract_from_deb(deb_path,
+kernel_path = self.extract_from_pkg(deb_path,
 '/boot/vmlinux-2.6.32-5-4kc-malta')
 
 self.vm.set_console()
@@ -160,7 +138,7 @@ def test_mips64el_malta(self):
'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb')
 deb_hash = '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5'
 deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
-kernel_path = self.extract_from_deb(deb_path,
+kernel_path = self.extract_from_pkg(deb_path,
 '/boot/vmlinux-2.6.32-5-5kc-malta')
 
 self.vm.set_console()
@@ -181,7 +159,7 @@ def test_mips64el_fuloong2e(self):

'linux-image-3.16.0-6-loongson-2e_3.16.56-1+deb8u1_mipsel.deb')
 deb_hash = 'd04d446045deecf7b755ef576551de0c4184dd44'
 deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
-kernel_path = self.extract_from_deb(deb_path,
+kernel_path = self.extract_from_pkg(deb_path,
 
'/boot/vmlinux-3.16.0-6-loongson-2e')
 
 self.vm.set_console()
@@ -203,7 +181,7 @@ def test_mips_malta_cpio(self):
'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb')
 deb_hash = 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8'

Re: [PATCH 11/11] Deprecate stable non-JSON -device and -object

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:27AM +0200, Kevin Wolf wrote:
> We want to switch both from QemuOpts to the keyval parser in the future,
> which results in some incompatibilities, mainly around list handling.
> Mark the non-JSON version of both as unstable syntax so that management
> tools switch to JSON and we can later make the change without breaking
> things.
> 
> Signed-off-by: Kevin Wolf 
> ---
>  docs/about/deprecated.rst | 11 +++
>  1 file changed, 11 insertions(+)

Reviewed-by: Eric Blake 

> 
> diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
> index 3c2be84d80..42f6a478fb 100644
> --- a/docs/about/deprecated.rst
> +++ b/docs/about/deprecated.rst
> @@ -160,6 +160,17 @@ Use ``-display sdl`` instead.
>  
>  Use ``-display curses`` instead.
>  
> +Stable non-JSON ``-device`` and ``-object`` syntax (since 6.2)
> +''
> +
> +If you rely on a stable interface for ``-device`` and ``-object`` that 
> doesn't
> +change incompatibly between QEMU versions (e.g. because you are using the 
> QEMU
> +command line as a machine interface in scripts rather than interactively), 
> use
> +JSON syntax for these options instead.
> +
> +There is no intention to remove support for non-JSON syntax entirely, but
> +future versions may change the way to spell some options.
> +
>  
>  Plugin argument passing through ``arg=`` (since 6.1)
>  
> -- 
> 2.31.1
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 01/16] Acceptance Tests: bump Avocado requirement to 91.0

2021-09-24 Thread Cleber Rosa
Avocado 91.0, brings, among other changes, a switch to a new runner
implementation, known as "nrunner".  While my personal testing shows
that it's suitable for running the QEMU tests, there are some
considerations that should be addressed before the change.

For instance, the "nrunner" implementation will run tests in parallel
by default.  With more tests running, and resources shared, some tests
may fail with timeouts on some environments.

So, for now, let's bump the Avocado version to allow for the other
features to be used.  And the "nrunner" implementation to be used by
those that choose to do so.

More information can be found at the release notes at:
   https://avocado-framework.readthedocs.io/en/latest/releases/91_0.html

Signed-off-by: Cleber Rosa 
---
 docs/devel/testing.rst | 12 
 tests/Makefile.include |  2 ++
 tests/requirements.txt |  2 +-
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index 4a0abbf23d..2818c58ff8 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -740,6 +740,18 @@ may be invoked by running:
 
   tests/venv/bin/avocado run $OPTION1 $OPTION2 tests/acceptance/
 
+Running tests in parallel
+-
+
+The current ``make check-acceptance`` target continues to use the
+Avocado runner implementation simply known as "runner".  But, it's now
+possible to opt-in and choose the "nrunner" implementation, which,
+among other things, allows for parallel execution of tests:
+
+.. code::
+
+  make AVOCADO_RUNNER=nrunner check-acceptance
+
 Manual Installation
 ---
 
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 6e16c05f10..ac289a2e41 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -92,6 +92,7 @@ TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results
 # Any number of command separated loggers are accepted.  For more
 # information please refer to "avocado --help".
 AVOCADO_SHOW=app
+AVOCADO_RUNNER=runner
 AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGETS)))
 
 $(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
@@ -128,6 +129,7 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) 
get-vm-images
$(call quiet-command, \
 $(TESTS_VENV_DIR)/bin/python -m avocado \
 --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
+--test-runner=$(AVOCADO_RUNNER) \
 --filter-by-tags-include-empty --filter-by-tags-include-empty-key \
 $(AVOCADO_TAGS) \
 $(if $(GITLAB_CI),,--failfast) tests/acceptance, \
diff --git a/tests/requirements.txt b/tests/requirements.txt
index a21b59b443..40af24c664 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -1,5 +1,5 @@
 # Add Python module requirements, one per line, to be installed
 # in the tests/venv Python virtual environment. For more info,
 # refer to: https://pip.pypa.io/en/stable/user_guide/#id1
-avocado-framework==88.1
+avocado-framework==91.0
 pycdlib==1.11.0
-- 
2.31.1




[PATCH 08/16] acceptance/tests/vnc.py: use explicit syntax for enabling passwords

2021-09-24 Thread Cleber Rosa
This matches the command line on 82a17d1d67, where the "on" or "off"
should be explicitly given.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/vnc.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/acceptance/vnc.py b/tests/acceptance/vnc.py
index 22656bbcc2..f301fbb4f5 100644
--- a/tests/acceptance/vnc.py
+++ b/tests/acceptance/vnc.py
@@ -45,7 +45,7 @@ def test_change_password_requires_a_password(self):
  'Could not set password')
 
 def test_change_password(self):
-self.vm.add_args('-nodefaults', '-S', '-vnc', ':0,password')
+self.vm.add_args('-nodefaults', '-S', '-vnc', ':0,password=on')
 self.vm.launch()
 self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled'])
 set_password_response = self.vm.qmp('change-vnc-password',
-- 
2.31.1




[PATCH 00/16] Acceptance Tests: use Avocado 91.0 features and other improvements

2021-09-24 Thread Cleber Rosa
This is a collection of patches for the Acceptance Tests to leverage
some of the features of Avocado 91.0.  With the Avocado version bump
by itself, there would be a change in the default "test runner"
implementation that Avocado uses, from the one simply known as
"runner" to the new one called "nrunner".

Among the changes from one implementation to the other, is the fact
that "nrunner" will run tests in parallel by default.  This is *not
yet* enabled by default on "make check-acceptance", but users can
choose to use simply by setting the "AVOCADO_RUNNER" variable, that
is:

  make AVOCADO_RUNNER=nrunner check-acceptance

If you are curious about the architectural differences of the nrunner,
please refer to:

  
https://avocado-framework.readthedocs.io/en/91.0/guides/contributor/chapters/runners.html

One other noteworthy proposal is a convention to tag tests that either
have known issues, or that touch on QEMU features that have known
issues.  By tagging those tests accordingly, they will be
automatically excluded from the regular execution with "make
check-acceptance".

Finally, some updates to assets locations and some tests refactors and
cleanups.

Cleber Rosa (16):
  Acceptance Tests: bump Avocado requirement to 91.0
  Acceptance Tests: improve check-acceptance description
  Acceptance Tests: add mechanism for listing tests
  Acceptance Tests: keep track and disable tests with known issues
  Acceptance Tests: add standard clean up at test tearDown()
  Acceptance Tests: use extract from package from avocado.utils
  Acceptance Tests: workaround expired mipsdistros.mips.com HTTPS cert
  acceptance/tests/vnc.py: use explicit syntax for enabling passwords
  tests/acceptance/boot_xen.py: merge base classes
  tests/acceptance/boot_xen.py: unify tags
  tests/acceptance/boot_xen.py: fetch kernel during test setUp()
  tests/acceptance/boot_xen.py: removed unused import
  tests/acceptance/boot_xen.py: use class attribute
  tests/acceptance/ppc_prep_40p.py: NetBSD 7.1.2 location update
  tests/acceptance/ppc_prep_40p.py: clean up unused import
  tests/acceptance/ppc_prep_40p.py: unify tags

 docs/devel/testing.rst| 40 ++
 tests/Makefile.include| 15 +++-
 tests/acceptance/avocado_qemu/__init__.py |  1 +
 tests/acceptance/boot_linux_console.py| 93 +--
 tests/acceptance/boot_xen.py  | 54 -
 tests/acceptance/machine_rx_gdbsim.py |  3 +
 tests/acceptance/ppc_prep_40p.py  | 17 ++---
 tests/acceptance/replay_kernel.py | 18 ++---
 tests/acceptance/tcg_plugins.py   |  2 +-
 tests/acceptance/vnc.py   |  2 +-
 tests/requirements.txt|  2 +-
 11 files changed, 128 insertions(+), 119 deletions(-)

-- 
2.31.1





Re: [PATCH 09/11] qdev: Avoid QemuOpts in QMP device_add

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:25AM +0200, Kevin Wolf wrote:
> Directly call qdev_device_add_from_qdict() for QMP device_add instead of
> first going through QemuOpts and converting back to QDict.
> 
> Note that this changes the behaviour of device_add, though in ways that
> should be considered bug fixes:
> 
> QemuOpts ignores differences between data types, so you could
> successfully pass a string "123" for an integer property, or a string
> "on" for a boolean property (and vice versa).  After this change, the
> correct data type for the property must be used in the JSON input.
> 
> qemu_opts_from_qdict() also silently ignores any options whose value is
> a QDict, QList or QNull.
> 
> To illustrate, the following QMP command was accepted before and is now
> rejected for both reasons:
> 
> { "execute": "device_add",
>   "arguments": { "driver": "scsi-cd",
>  "drive": { "completely": "invalid" },
>  "physical_block_size": "4096" } }
> 
> Signed-off-by: Kevin Wolf 
> ---
>  softmmu/qdev-monitor.c | 18 +++---
>  1 file changed, 11 insertions(+), 7 deletions(-)
>

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 05/16] Acceptance Tests: add standard clean up at test tearDown()

2021-09-24 Thread Cleber Rosa
The avocado.Test class, used as the basis of the avocado_qemu.Test
class, performs a clean of temporary directories up as part of its own
tearDown() implementation.

But the avocado_qemu.Test class is currently missing the same clean
up, as it implemented its own tearDown() method without resorting to
the upper class behavior.

This brings avocado_qemu.Test behavior in sync with the standard
avocado.Test behavior and prevents temporary directories from
cluttering the test results directory (unless instructed to do so with
Avocado's "--keep-tmp" option).

Reported-by: Peter Maydell 
Signed-off-by: Cleber Rosa 
---
 tests/acceptance/avocado_qemu/__init__.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/acceptance/avocado_qemu/__init__.py 
b/tests/acceptance/avocado_qemu/__init__.py
index 2c4fef3e14..1e807e2e55 100644
--- a/tests/acceptance/avocado_qemu/__init__.py
+++ b/tests/acceptance/avocado_qemu/__init__.py
@@ -276,6 +276,7 @@ def tearDown(self):
 for vm in self._vms.values():
 vm.shutdown()
 self._sd = None
+super(Test, self).tearDown()
 
 def fetch_asset(self, name,
 asset_hash=None, algorithm=None,
-- 
2.31.1




Re: [PATCH 08/11] qdev: Base object creation on QDict rather than QemuOpts

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:24AM +0200, Kevin Wolf wrote:
> QDicts are both what QMP natively uses and what the keyval parser
> produces. Going through QemuOpts isn't useful for either one, so switch
> the main device creation function to QDicts. By sharing more code with
> the -object/object-add code path, we can even reduce the code size a
> bit.
> 
> This commit doesn't remove the detour through QemuOpts from any code
> path yet, but it allows the following commits to do so.
> 
> Signed-off-by: Kevin Wolf 
> ---
>  include/hw/qdev-core.h |  8 ++---
>  hw/core/qdev.c |  5 ++--
>  hw/net/virtio-net.c|  4 +--
>  hw/vfio/pci.c  |  4 +--
>  softmmu/qdev-monitor.c | 67 +++---
>  5 files changed, 41 insertions(+), 47 deletions(-)
>

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




RE: [PATCH v3 08/27] linux-user/hexagon: Implement setup_sigtramp

2021-09-24 Thread Taylor Simpson


> -Original Message-
> From: Richard Henderson 
> Sent: Friday, September 24, 2021 11:59 AM
> To: qemu-devel@nongnu.org
> Cc: laur...@vivier.eu; peter.mayd...@linaro.org; Taylor Simpson
> ; Philippe Mathieu-Daudé 
> Subject: [PATCH v3 08/27] linux-user/hexagon: Implement setup_sigtramp
> 
> Continue to initialize the words on the stack, as documented.
> However, use the off-stack trampoline.
> 
> Cc: Taylor Simpson 
> Reviewed-by: Philippe Mathieu-Daudé 
> Signed-off-by: Richard Henderson 
> ---
>  linux-user/hexagon/target_signal.h |  2 ++
>  linux-user/hexagon/signal.c| 19 +--
>  2 files changed, 19 insertions(+), 2 deletions(-)

Reviewed-by: Taylor Simpson 


RE: [PATCH v6 21/40] target/hexagon: Remove unused has_work() handler

2021-09-24 Thread Taylor Simpson


> -Original Message-
> From: Philippe Mathieu-Daudé  On
> Behalf Of Philippe Mathieu-Daudé
> Sent: Friday, September 24, 2021 4:38 AM
> To: qemu-devel@nongnu.org
> Cc: Richard Henderson ; Philippe Mathieu-
> Daudé ; Taylor Simpson 
> Subject: [PATCH v6 21/40] target/hexagon: Remove unused has_work()
> handler
> 
> has_work() is sysemu specific, and Hexagon target only provides a linux-user
> implementation. Remove the unused hexagon_cpu_has_work().
> 
> Reviewed-by: Richard Henderson 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  target/hexagon/cpu.c | 6 --
>  1 file changed, 6 deletions(-)
> 
> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index
> 3338365c16e..aa01974807c 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -189,11 +189,6 @@ static void
> hexagon_cpu_synchronize_from_tb(CPUState *cs,
>  env->gpr[HEX_REG_PC] = tb->pc;
>  }
> 
> -static bool hexagon_cpu_has_work(CPUState *cs) -{
> -return true;
> -}
> -
>  void restore_state_to_opc(CPUHexagonState *env, TranslationBlock *tb,
>target_ulong *data)  { @@ -287,7 +282,6 @@ static 
> void
> hexagon_cpu_class_init(ObjectClass *c, void *data)
>  device_class_set_parent_reset(dc, hexagon_cpu_reset, &mcc-
> >parent_reset);
> 
>  cc->class_by_name = hexagon_cpu_class_by_name;
> -cc->has_work = hexagon_cpu_has_work;
>  cc->dump_state = hexagon_dump_state;
>  cc->set_pc = hexagon_cpu_set_pc;
>  cc->gdb_read_register = hexagon_gdb_read_register;


Reviewed-by: Taylor Simpson 



Re: [PATCH] hw/misc: Add an iBT device model

2021-09-24 Thread Titus Rwantare
On Fri, 24 Sept 2021 at 03:55, Cédric Le Goater  wrote:
>
> Hello Titus,
>
> On 9/24/21 10:42, Philippe Mathieu-Daudé wrote:
> > On 9/24/21 01:48, Titus Rwantare wrote:
> >> Hello all,
> >>
> >> I'd like some clarification on how the following code transfers irqs
> >> back and forth:
> >>> b/hw/arm/aspeed_soc.c
> >>> +/* iBT */
> >>> +if (!sysbus_realize(SYS_BUS_DEVICE(&s->ibt), errp)) {
> >>> +return;
> >>> +}
> >>> +memory_region_add_subregion(&s->lpc.iomem,
> >>> +   sc->memmap[ASPEED_DEV_IBT] - 
> >>> sc->memmap[ASPEED_DEV_LPC],
> >>> +   &s->ibt.iomem);
> >>> +sysbus_connect_irq(SYS_BUS_DEVICE(&s->lpc), 1 + aspeed_lpc_ibt,
>
>
> The iBT device IRQ is connected to a subdevice irq of the LPC device.
> See aspeed_lpc_realize(). And triggered in aspeed_lpc_set_irq()

Yes, that side makes sense. I tried to get at that irq from
aspeed_ibt.c as follows:

qemu_irq_lower(ibt->lpc->subdevice_irqs[aspeed_lpc_ibt]); // or raise

static void aspeed_ibt_realize(DeviceState *dev, Error **errp)
{
AspeedIBTState *ibt = ASPEED_IBT(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
IPMIInterface *ii = IPMI_INTERFACE(dev);
ibt->lpc = ASPEED_LPC(dev);
...

but this doesn't work and maybe I'm misusing the dynamic cast?

> >>> +   qdev_get_gpio_in(DEVICE(&s->lpc), 
> >>> aspeed_lpc_ibt));
> >>> }
> >>
> >> and
> >>
> >>> hw/misc/aspeed_ibt.c
> >>> +static void aspeed_ibt_realize(DeviceState *dev, Error **errp)
> >>> +{
> >>> +SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> >>> +AspeedIBTState *ibt = ASPEED_IBT(dev);
> >> ...
> >>> +
> >>> +sysbus_init_irq(sbd, &ibt->irq);
> >>
> >> I ask because the code in aspeed_soc.c seems to connect to the
> >> lpc->subdevice_irqs[aspeed_lpc_ibt], initialised on
> >> hw/misc/aspeed_lpc.c:408.
> >> I noticed that bmc firmware running in qemu was checking the BT_CTRL
> >> register less frequently than I'd like while editing this patch to use
> >> the IPMIInterface.
>
> OK.
>
> This might be a problem in aspeed_ibt_update_irq(). This patch is
> an experiment from some few years ago. It still works good enough
> for the witherspoon-bmc and powernv9 machines for simple IPMI
> commands: fru, sdr, lan, power off (to be checked).
>
> Could you share your BMC and host command line ?
>

Host:
-chardev socket,id=ipmichr1,host=localhost,port=,reconnect=10 \
-device ipmi-bmc-extern,chardev=ipmichr1,id=bmc0 \
-device isa-ipmi-bt,bmc=bmc0,irq=10 -nodefaults

BMC:
-chardev socket,id=ipmichr1,host=localhost,port=,server=on,wait=off \
-device ipmi-host-extern,chardev=ipmichr1,responder=/machine/soc/ibt

But for this to work you need Hao's patch as well: [PATCH 7/8]
hw/ipmi: Add an IPMI external host device.



Re: [PATCH 04/11] qdev: Avoid using string visitor for properties

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:20AM +0200, Kevin Wolf wrote:
> The only thing the string visitor adds compared to a keyval visitor is
> list support. git grep for 'visit_start_list' and 'visit.*List' shows
> that devices don't make use of this.
> 
> In a world with a QAPIfied command line interface, the keyval visitor is
> used to parse the command line. In order to make sure that no devices
> start using this feature that would make backwards compatibility harder,
> just switch away from object_property_parse(), which internally uses the
> string visitor, to a keyval visitor and object_property_set().
> 
> Signed-off-by: Kevin Wolf 
> ---
>  softmmu/qdev-monitor.c | 20 +---
>  1 file changed, 17 insertions(+), 3 deletions(-)

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v3 03/15] target/ppc: PMU basic cycle count for pseries TCG

2021-09-24 Thread Matheus K. Ferst

On 24/09/2021 11:41, Daniel Henrique Barboza wrote:

On 9/22/21 08:24, Matheus K. Ferst wrote:

On 03/09/2021 17:31, Daniel Henrique Barboza wrote:
[E-MAIL EXTERNO] Não clique em links ou abra anexos, a menos que você 
possa confirmar o remetente e saber que o conteúdo é seguro. Em caso 
de e-mail suspeito entre imediatamente em contato com o DTI.


This patch adds the barebones of the PMU logic by enabling cycle
counting, done via the performance monitor counter 6. The overall logic
goes as follows:

- a helper is added to control the PMU state on each MMCR0 write. This
allows for the PMU to start/stop as the frozen counter bit (MMCR0_FC)
is cleared or set;

- MMCR0 reg initial value is set to 0x8000 (MMCR0_FC set) to avoid
having to spin the PMU right at system init;

- the intended usage is to freeze the counters by setting MMCR0_FC, do
any additional setting of events to be counted via MMCR1 (not
implemented yet) and enable the PMU by zeroing MMCR0_FC. Software must
freeze counters to read the results - on the fly reading of the PMCs
will return the starting value of each one.

Since there will be more PMU exclusive code to be added next, put the
PMU logic in its own helper to keep all in the same place. The name of
the new helper file, power8_pmu.c, is an indicative that the PMU logic
has been tested with the IBM POWER chip family, POWER8 being the oldest
version tested. This doesn't mean that this PMU logic will break with
any other PPC64 chip that implements Book3s, but since we can't assert
that this PMU will work with all available Book3s emulated processors
we're choosing to be explicit.

Signed-off-by: Daniel Henrique Barboza 
---





diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 0babde3131..c3e2e3d329 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -401,6 +401,24 @@ void spr_write_generic(DisasContext *ctx, int 
sprn, int gprn)

  spr_store_dump_spr(sprn);
  }

+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
+{
+    /*
+ * helper_store_mmcr0 will make clock based operations that
+ * will cause 'bad icount read' errors if we do not execute
+ * gen_icount_io_start() beforehand.
+ */
+    gen_icount_io_start(ctx);
+    gen_helper_store_mmcr0(cpu_env, cpu_gpr[gprn]);
+}
+#else
+void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
+{
+    spr_write_generic(ctx, sprn, gprn);
+}
+#endif
+
  #if !defined(CONFIG_USER_ONLY)
  void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
  {
@@ -596,7 +614,10 @@ void spr_write_MMCR0_ureg(DisasContext *ctx, int 
sprn, int gprn)

  tcg_gen_andi_tl(t1, t1, ~(MMCR0_UREG_MASK));
  /* Keep all other bits intact */
  tcg_gen_or_tl(t1, t1, t0);
-    gen_store_spr(SPR_POWER_MMCR0, t1);
+
+    /* Overwrite cpu_gpr[gprn] and use spr_write_MMCR0() */
+    tcg_gen_mov_tl(cpu_gpr[gprn], t1);
+    spr_write_MMCR0(ctx, sprn + 0x10, gprn);


IIUC, this makes writing to MMCR0 change the GPR value and expose the 
unfiltered content of the SPR to problem state. It might be better to 
call the helper directly or create another method that takes a TCGv as 
an argument and call it from spr_write_MMCR0_ureg and spr_write_MMCR0.


I'm overwriting cpu_gpr[gprn] with t1, which is filtered by MMCR0_REG_MASK
right before, to re-use spr_write_MMCR0() since its API requires a gprn
index. The reason I'm re-using spr_write_MMCR0() here is to avoid code 
repetition

in spr_write_MMCR0_ureg(), which would need to repeat the same steps as
spr_write_MMCR0 (calling icount_io_start(), calling the helper, and then 
setting

DISAS_EXIT_UPDATE in a later patch).

The idea behind is that all PMU user_write() functions works the same as 
its
privileged counterparts but with some form of filtering done beforehand. 
Note
that this is kind of true in the previous patch as well - 
gen_store_spr() is
similar to the privileged function MMCR0 was using (spr_write_generic()) 
with

the exception of an optional qemu_log().

Maybe I should've made this clear in the previous patch, using 
spr_write_generic()

and overwriting cpu_gpr[gprn] with the filtered t1 content back there.

Speaking of which, since t1 is being filtered by MMCR0_REG_MASK before 
being used to
overwrite cpu_gpr[gprn], I'm not sure how this is exposing unfiltered 
content to

problem state. Can you elaborate?


Suppose MMCR0 has the value 0x8001 (FC and FCH) and problem state 
executes an mtspr with the value 0x400 (unset FC and set PMAE) in 
the GPR. The proposed code will do the following:


> tcg_gen_andi_tl(t0, cpu_gpr[gprn], MMCR0_UREG_MASK);

t0 = GPR & MMCR0_UREG_MASK = 0x400 & 0x8480 = 0x400

> gen_load_spr(t1, SPR_POWER_MMCR0);

t1 = MMCR0 = 0x8001

> tcg_gen_andi_tl(t1, t1, ~(MMCR0_UREG_MASK));

t1 = t1 & ~MMCR0_UREG_MASK = 0x8001 & ~0x8480 = 0x1

> tcg_gen_or_tl(t1, t1, t0);

t1 = t1 | t0 = 0x400 | 0x1 = 0x401

> tcg_gen_mov_tl(cpu_gp

Re: Ping: [PATCH 0/2] cocoa.m: keyboard quality of life reborn

2021-09-24 Thread Programmingkid



> On Sep 24, 2021, at 5:26 AM, Peter Maydell  wrote:
> 
> On Fri, 24 Sept 2021 at 00:08, Programmingkid  
> wrote:
>> 
>> Hi Peter, are you reviewing cocoa patches? Should someone else see these 
>> patches?
> 
> Gerd sent out a message a while back suggesting that people interested
> in the cocoa UI (we have had several people recently submit patches)
> ought to start reviewing each others' patches. I would certainly
> prefer it if those people who are actively using and working on
> the cocoa UI could take on more of this review work.
> 
> -- PMM

Problem is there isn't anyone else who does actually review cocoa patches. Even 
if there were others, there is no guarantee their suggestions would be 
something you agree with. Since you are the cocoa maintainer the only opinion 
that ultimately matters is yours 😁.





Re: [PATCH 01/11] qom: Reduce use of error_propagate()

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:17AM +0200, Kevin Wolf wrote:
> ERRP_GUARD() makes debugging easier by making sure that &error_abort
> still fails at the real origin of the error instead of
> error_propagate().
> 
> Signed-off-by: Kevin Wolf 
> ---
>  qom/object.c|  7 +++
>  qom/object_interfaces.c | 17 ++---
>  2 files changed, 9 insertions(+), 15 deletions(-)

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v2 0/6] iotests: update environment and linting configuration

2021-09-24 Thread John Snow
On Thu, Sep 23, 2021 at 2:07 PM John Snow  wrote:

> GitLab: https://gitlab.com/jsnow/qemu/-/commits/python-package-iotest-pt1
> CI: https://gitlab.com/jsnow/qemu/-/pipelines/376236687
>
> This series partially supersedes:
>   [PATCH v3 00/16] python/iotests: Run iotest linters during Python CI'
>
> Howdy, this is good stuff we want even if we aren't yet in agreement
> about the best way to run iotest 297 from CI.
>
> - Update linting config to tolerate pylint 2.11.1
> - Eliminate sys.path hacking in individual test files
> - make mypy execution in test 297 faster
>
> The rest of the actual "run at CI time" stuff can get handled separately
> and later pending some discussion on the other series.
>
> V2:
>
> 001/6:[0011] [FC] 'iotests: add 'qemu' package location to PYTHONPATH in
> testenv'
> 002/6:[0025] [FC] 'iotests: add warning for rogue 'qemu' packages'
>
> - Squashed in a small optimization from Vladimir to 001, kept R-Bs.
> - Fixed the package detection logic to not panic if it can't find
>   'qemu' at all (kwolf)
> - Updated commit messages for the first two patches.
>
> --js
>
> John Snow (6):
>   iotests: add 'qemu' package location to PYTHONPATH in testenv
>   iotests: add warning for rogue 'qemu' packages
>   iotests/linters: check mypy files all at once
>   iotests/mirror-top-perms: Adjust imports
>   iotests/migrate-bitmaps-test: delint
>   iotests: Update for pylint 2.11.1
>
>  tests/qemu-iotests/235|  2 -
>  tests/qemu-iotests/297| 50 ---
>  tests/qemu-iotests/300|  7 ++-
>  tests/qemu-iotests/iotests.py |  2 -
>  tests/qemu-iotests/pylintrc   |  6 ++-
>  tests/qemu-iotests/testenv.py | 39 ---
>  tests/qemu-iotests/testrunner.py  |  7 +--
>  tests/qemu-iotests/tests/migrate-bitmaps-test | 50 +++
>  tests/qemu-iotests/tests/mirror-top-perms | 12 ++---
>  9 files changed, 99 insertions(+), 76 deletions(-)
>
> --
> 2.31.1
>
>
>
Patch 2 can just be dropped, and everything else is reviewed, so I think
this can be staged at your leisure.

--js


Re: [PATCH v2 2/6] iotests: add warning for rogue 'qemu' packages

2021-09-24 Thread John Snow
On Thu, Sep 23, 2021 at 4:27 PM Vladimir Sementsov-Ogievskiy <
vsement...@virtuozzo.com> wrote:

> 23.09.2021 21:44, John Snow wrote:
> >
> >
> > On Thu, Sep 23, 2021 at 2:32 PM Vladimir Sementsov-Ogievskiy <
> vsement...@virtuozzo.com > wrote:
> >
> > 23.09.2021 21:07, John Snow wrote:
> >  > Add a warning for when 'iotests' runs against a qemu namespace
> that
> >  > isn't the one in the source tree. This might occur if you have
> >  > (accidentally) installed the Python namespace package to your
> local
> >  > packages.
> >  >
> >  > (I'm not going to say that this is because I bit myself with this,
> >  > but you can fill in the blanks.)
> >  >
> >  > In the future, we will pivot to always preferring a specific
> installed
> >  > instance of qemu python packages managed directly by iotests. For
> now
> >  > simply warn if there is an ambiguity over which instance that
> iotests
> >  > might use.
> >  >
> >  > Example: If a user has navigated to ~/src/qemu/python and executed
> >  > `pip install .`, you will see output like this when running
> `./check`:
> >  >
> >  > WARNING: 'qemu' python packages will be imported from outside the
> source tree ('/home/jsnow/src/qemu/python')
> >  >   Importing instead from
> '/home/jsnow/.local/lib/python3.9/site-packages/qemu'
> >  >
> >  > Signed-off-by: John Snow  js...@redhat.com>>
> >  > ---
> >  >   tests/qemu-iotests/testenv.py | 24 
> >  >   1 file changed, 24 insertions(+)
> >  >
> >  > diff --git a/tests/qemu-iotests/testenv.py
> b/tests/qemu-iotests/testenv.py
> >  > index 99a57a69f3a..1c0f6358538 100644
> >  > --- a/tests/qemu-iotests/testenv.py
> >  > +++ b/tests/qemu-iotests/testenv.py
> >  > @@ -16,6 +16,8 @@
> >  >   # along with this program.  If not, see <
> http://www.gnu.org/licenses/ >.
> >  >   #
> >  >
> >  > +import importlib.util
> >  > +import logging
> >  >   import os
> >  >   import sys
> >  >   import tempfile
> >  > @@ -112,6 +114,27 @@ def init_directories(self) -> None:
> >  >   # Path where qemu goodies live in this source tree.
> >  >   qemu_srctree_path = Path(__file__,
> '../../../python').resolve()
> >  >
> >  > +# Warn if we happen to be able to find qemu namespace
> packages
> >  > +# (using qemu.qmp as a bellwether) from an unexpected
> location.
> >  > +# i.e. the package is already installed in the user's
> environment.
> >  > +try:
> >  > +qemu_spec = importlib.util.find_spec('qemu.qmp')
> >  > +except ModuleNotFoundError:
> >  > +qemu_spec = None
> >  > +
> >  > +if qemu_spec and qemu_spec.origin:
> >  > +spec_path = Path(qemu_spec.origin)
> >  > +try:
> >  > +_ = spec_path.relative_to(qemu_srctree_path)
> >
> > It took some time and looking at specification trying to understand
> what's going on here :)
> >
> > Could we just use:
> >
> > if not Path(qemu_spec.origin).is_relative_to(qemu_srctree_path):
> >  ... logging ...
> >
> >
> > Nope, that's 3.9+ only. (I made the same mistake.)
>
> Oh :(
>
> OK
>
> >
> >
> >  > +except ValueError:
> >
> >  > +self._logger.warning(
> >  > +"WARNING: 'qemu' python packages will be
> imported from"
> >  > +" outside the source tree ('%s')",
> >  > +qemu_srctree_path)
>
> why not use f-strings ? :)
>
>
The logging subsystem still uses % formatting by default, you can see I'm
not actually using the % operator to apply the values -- the Python docs
claim this is for "efficiency" because the string doesn't have to be
evaluated unless the logging statement is actually emitted, but that gain
sounds mostly theoretical to me, because Python still has eager evaluation
of passed arguments ... unless I've missed something.

Either way, using f-strings on logging calls gives you a pylint warning
that I'd just have to then disable, so I just skip the hassle.

Now, the logging system *does* allow you to use new-style python strings [
https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles ]
but given that the default is still %-style and virtually every library
uses that style, I thought it might cause more problems than it creates by
trying to use a different style for just one portion of the codebase. Mind
you, I've never even bothered to try, so my apprehensions might not be
strictly factual ;)


> >  > +self._logger.warning(
> >  > +" Importing instead from '%s'",
> >  > +spec_path.parents[1])
> >  > +
> >
> > Also, I'd move this new chunk o

Re: [PATCH v6 4/5] block/nbd: drop connection_co

2021-09-24 Thread Eric Blake
On Thu, Sep 02, 2021 at 01:38:04PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> OK, that's a big rewrite of the logic.

And a time-consuming review on my part!

> 
> Pre-patch we have an always running coroutine - connection_co. It does
> reply receiving and reconnecting. And it leads to a lot of difficult
> and unobvious code around drained sections and context switch. We also
> abuse bs->in_flight counter which is increased for connection_co and
> temporary decreased in points where we want to allow drained section to
> begin. One of these place is in another file: in nbd_read_eof() in
> nbd/client.c.
> 
> We also cancel reconnect and requests waiting for reconnect on drained
> begin which is not correct. And this patch fixes that.
> 
> Let's finally drop this always running coroutine and go another way:
> do both reconnect and receiving in request coroutines.
> 
> The detailed list of changes below (in the sequence of diff hunks).

Well, depending on the git order file in use ;)

> 
> 1. receiving coroutines are woken directly from nbd_channel_error, when
>we change s->state
> 
> 2. nbd_co_establish_connection_cancel(): we don't have drain_begin now,
>and in nbd_teardown_connection() all requests should already be
>finished (and reconnect is done from request). So
>nbd_co_establish_connection_cancel() is called from
>nbd_cancel_in_flight() (to cancel the request that is doing
>nbd_co_establish_connection()) and from reconnect_delay_timer_cb()
>(previously we didn't need it, as reconnect delay only should cancel
>active requests not the reconnection itself. But now reconnection

Missing )

>itself is done in the separate thread (we now call
>nbd_client_connection_enable_retry() in nbd_open()), and we need to
>cancel the requests that waits in nbd_co_establish_connection()

Singular/plural disagreement. I think the intended meaning is
'requests that wait' and not 'request that waits'.

>now).
> 
> 2. We do receive headers in request coroutine. But we also should

Second point 2; I'll call it 2A below, because it looks related to
point 8.

>dispatch replies for another pending requests. So,

s/another/other/

>nbd_connection_entry() is turned into nbd_receive_replies(), which
>does reply dispatching until it receive another request headers, and

s/until/while/, s/another/other/

>returns when it receive the requested header.

receives

> 
> 3. All old staff around drained sections and context switch is dropped.
>In details:
>- we don't need to move connection_co to new aio context, as we
>  don't have connection_co anymore
>- we don't have a fake "request" of connection_co (extra increasing
>  in_flight), so don't care with it in drain_begin/end
>- we don't stop reconnection during drained section anymore. This
>  means that drain_begin may wait for a long time (up to
>  reconnect_delay). But that's an improvement and more correct
>  behavior see below[*]
> 
> 4. In nbd_teardown_connection() we don't have to wait for
>connection_co, as it is dropped. And cleanup for s->ioc and nbd_yank
>is moved here from removed connection_co.
> 
> 5. In nbd_co_do_establish_connection() we now should handle
>NBD_CLIENT_CONNECTING_NOWAIT: if new request comes when we are in
>NBD_CLIENT_CONNECTING_NOWAIT, it still should call
>nbd_co_establish_connection() (who knows, maybe connection already
>established by thread in background). But we shouldn't wait: if

maybe the connection was already established by another thread in the background

>nbd_co_establish_connection() can't return new channel immediately
>the request should fail (we are in NBD_CLIENT_CONNECTING_NOWAIT
>state).
> 
> 6. nbd_reconnect_attempt() is simplified: it's now easier to wait for
>other requests in the caller, so here we just assert that fact.
>Also delay time is now initialized here: we can easily detect first
>attempt and start a timer.
> 
> 7. nbd_co_reconnect_loop() is dropped, we don't need it. Reconnect
>retries are fully handle by thread (nbd/client-connection.c), delay
>timer we initialize in nbd_reconnect_attempt(), we don't have to
>bother with s->drained and friends. nbd_reconnect_attempt() now
>called from nbd_co_send_request().

A lot going on there, but it's making sense so far.

> 
> 8. nbd_connection_entry is dropped: reconnect is now handled by
>nbd_co_send_request(), receiving reply is now handled by
>nbd_receive_replies(): all handled from request coroutines.
> 
> 9. So, welcome new nbd_receive_replies() called from request coroutine,
>that receives reply header instead of nbd_connection_entry().
>Like with sending requests, only one coroutine may receive in a
>moment. So we introduce receive_mutex, which is locked around
>nbd_receive_reply(). It also protects some related fields. Still,
>full audit of thread-safety in nbd driver is a separate ta

Re: [PATCH v3 20/27] linux-user/ppc: Simplify encode_trampoline

2021-09-24 Thread Philippe Mathieu-Daudé

On 9/24/21 18:59, Richard Henderson wrote:

The sigret parameter is never 0, and even if it was the encoding
of the LI instruction would still work.

Reported-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
  linux-user/ppc/signal.c | 6 ++
  1 file changed, 2 insertions(+), 4 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH v3 2/3] QIOChannelSocket: Implement io_async_write & io_async_flush

2021-09-24 Thread Daniel P . Berrangé
On Wed, Sep 22, 2021 at 07:24:22PM -0300, Leonardo Bras wrote:
> Implement the new optional callbacks io_async_write and io_async_flush on
> QIOChannelSocket, but enables it only when MSG_ZEROCOPY feature is
> available in the host kernel, and TCP sockets are used.
> 
> qio_channel_socket_writev() contents were moved to a helper function
> __qio_channel_socket_writev() which accepts an extra 'flag' argument.
> This helper function is used to implement qio_channel_socket_writev(), with
> flags = 0, keeping it's behavior unchanged, and
> qio_channel_socket_async_writev() with flags = MSG_ZEROCOPY.
> 
> qio_channel_socket_async_flush() was implemented by reading the socket's error
> queue, which will have information on MSG_ZEROCOPY send completion.
> There is no need to worry with re-sending packets in case any error happens, 
> as
> MSG_ZEROCOPY only works with TCP and it will re-tranmsmit if any error ocurs.
> 
> Notes on using async_write():
> - As MSG_ZEROCOPY tells the kernel to use the same user buffer to avoid 
> copying,
> some caution is necessary to avoid overwriting any buffer before it's sent.
> If something like this happen, a newer version of the buffer may be sent 
> instead.
> - If this is a problem, it's recommended to use async_flush() before freeing 
> or
> re-using the buffer.
> - When using MSG_ZERCOCOPY, the buffer memory will be locked, so it may 
> require
> a larger amount than usually available to non-root user.
> - If the required amount of locked memory is not available, it falls-back to
> buffer copying behavior, and synchronous sending.
> 
> Signed-off-by: Leonardo Bras 
> ---
>  include/io/channel-socket.h |   2 +
>  include/io/channel.h|   1 +
>  io/channel-socket.c | 176 ++--
>  3 files changed, 169 insertions(+), 10 deletions(-)
> 
> diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h
> index e747e63514..4d1be0637a 100644
> --- a/include/io/channel-socket.h
> +++ b/include/io/channel-socket.h
> @@ -47,6 +47,8 @@ struct QIOChannelSocket {
>  socklen_t localAddrLen;
>  struct sockaddr_storage remoteAddr;
>  socklen_t remoteAddrLen;
> +ssize_t async_queued;
> +ssize_t async_sent;
>  };
>  
>  
> diff --git a/include/io/channel.h b/include/io/channel.h
> index 74f2e3ae8a..611bb2ea26 100644
> --- a/include/io/channel.h
> +++ b/include/io/channel.h
> @@ -31,6 +31,7 @@ OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass,
>  
>  
>  #define QIO_CHANNEL_ERR_BLOCK -2
> +#define QIO_CHANNEL_ERR_NOBUFS -3
>  
>  typedef enum QIOChannelFeature QIOChannelFeature;
>  
> diff --git a/io/channel-socket.c b/io/channel-socket.c
> index 606ec97cf7..c67832d0bb 100644
> --- a/io/channel-socket.c
> +++ b/io/channel-socket.c
> @@ -26,9 +26,23 @@
>  #include "io/channel-watch.h"
>  #include "trace.h"
>  #include "qapi/clone-visitor.h"
> +#ifdef CONFIG_LINUX
> +#include 
> +#include 
> +#endif
>  
>  #define SOCKET_MAX_FDS 16
>  
> +static ssize_t qio_channel_socket_async_writev(QIOChannel *ioc,
> +   const struct iovec *iov,
> +   size_t niov,
> +   int *fds,
> +   size_t nfds,
> +   Error **errp);
> +
> +static void qio_channel_socket_async_flush(QIOChannel *ioc,
> +   Error **errp);
> +
>  SocketAddress *
>  qio_channel_socket_get_local_address(QIOChannelSocket *ioc,
>   Error **errp)
> @@ -55,6 +69,8 @@ qio_channel_socket_new(void)
>  
>  sioc = QIO_CHANNEL_SOCKET(object_new(TYPE_QIO_CHANNEL_SOCKET));
>  sioc->fd = -1;
> +sioc->async_queued = 0;
> +sioc->async_sent = 0;
>  
>  ioc = QIO_CHANNEL(sioc);
>  qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
> @@ -140,6 +156,7 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
>  Error **errp)
>  {
>  int fd;
> +int ret, v = 1;
>  
>  trace_qio_channel_socket_connect_sync(ioc, addr);
>  fd = socket_connect(addr, errp);
> @@ -154,6 +171,19 @@ int qio_channel_socket_connect_sync(QIOChannelSocket 
> *ioc,
>  return -1;
>  }
>  
> +#ifdef CONFIG_LINUX
> +if (addr->type != SOCKET_ADDRESS_TYPE_INET) {
> +return 0;
> +}
> +
> +ret = qemu_setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &v, sizeof(v));
> +if (ret >= 0) {
> +QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
> +klass->io_async_writev = qio_channel_socket_async_writev;
> +klass->io_async_flush = qio_channel_socket_async_flush;
> +}
> +#endif

This is not write - the async APIs should not be tied 1:1 to ZEROCOPY
usage - we should have them take a flag to request ZEROCOPY behaviour.

> +
>  return 0;
>  }
>  
> @@ -520,12 +550,13 @@ static ssize_t qio_channel_socket_rea

Re: [PATCH v3 26/27] linux-user/xtensa: Implement setup_sigtramp

2021-09-24 Thread Philippe Mathieu-Daudé

On 9/24/21 18:59, Richard Henderson wrote:

Create and record the rt signal trampoline.
Use it when the guest does not use SA_RESTORER.

Reviewed-by: Max Filippov 
Signed-off-by: Richard Henderson 
---
  linux-user/xtensa/target_signal.h |  2 ++
  linux-user/xtensa/signal.c| 56 ---
  2 files changed, 38 insertions(+), 20 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v5 27/30] tcg/loongarch64: Register the JIT

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 44 
 1 file changed, 44 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index c34683b2d0..39938fd5c2 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1603,3 +1603,47 @@ static void tcg_target_init(TCGContext *s)
 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
 tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED);
 }
+
+typedef struct {
+DebugFrameHeader h;
+uint8_t fde_def_cfa[4];
+uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
+} DebugFrame;
+
+#define ELF_HOST_MACHINE EM_LOONGARCH
+
+static const DebugFrame debug_frame = {
+.h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
+.h.cie.id = -1,
+.h.cie.version = 1,
+.h.cie.code_align = 1,
+.h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
+.h.cie.return_column = TCG_REG_RA,
+
+/* Total FDE size does not include the "len" member.  */
+.h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
+
+.fde_def_cfa = {
+12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ...  */
+(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
+(FRAME_SIZE >> 7)
+},
+.fde_reg_ofs = {
+0x80 + 23, 11,  /* DW_CFA_offset, s0, -88 */
+0x80 + 24, 10,  /* DW_CFA_offset, s1, -80 */
+0x80 + 25, 9,   /* DW_CFA_offset, s2, -72 */
+0x80 + 26, 8,   /* DW_CFA_offset, s3, -64 */
+0x80 + 27, 7,   /* DW_CFA_offset, s4, -56 */
+0x80 + 28, 6,   /* DW_CFA_offset, s5, -48 */
+0x80 + 29, 5,   /* DW_CFA_offset, s6, -40 */
+0x80 + 30, 4,   /* DW_CFA_offset, s7, -32 */
+0x80 + 31, 3,   /* DW_CFA_offset, s8, -24 */
+0x80 + 22, 2,   /* DW_CFA_offset, s9, -16 */
+0x80 + 1 , 1,   /* DW_CFA_offset, ra, -8 */
+}
+};
+
+void tcg_register_jit(const void *buf, size_t buf_size)
+{
+tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
+}
-- 
2.33.0




Re: [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp

2021-09-24 Thread Philippe Mathieu-Daudé

On 9/24/21 18:59, Richard Henderson wrote:

Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.
Note that x86_64 does not use this code.

Signed-off-by: Richard Henderson 
---
  linux-user/i386/target_signal.h   |  2 ++
  linux-user/x86_64/target_signal.h |  3 ++
  linux-user/i386/signal.c  | 56 +--
  3 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h
index 50361af874..64d09f2e75 100644
--- a/linux-user/i386/target_signal.h
+++ b/linux-user/i386/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
  #include "../generic/signal.h"
  
  #define TARGET_ARCH_HAS_SETUP_FRAME

+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
  #endif /* I386_TARGET_SIGNAL_H */
diff --git a/linux-user/x86_64/target_signal.h 
b/linux-user/x86_64/target_signal.h
index 4ea74f20dd..4673c5a886 100644
--- a/linux-user/x86_64/target_signal.h
+++ b/linux-user/x86_64/target_signal.h
@@ -21,4 +21,7 @@ typedef struct target_sigaltstack {
  
  #include "../generic/signal.h"
  
+/* For x86_64, use of SA_RESTORER is mandatory. */

+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+
  #endif /* X86_64_TARGET_SIGNAL_H */
diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 3b4b55fc0a..94ab6396a0 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -310,6 +310,22 @@ get_sigframe(struct target_sigaction *ka, CPUX86State 
*env, size_t frame_size)
  }
  
  #ifndef TARGET_X86_64

+static void install_sigtramp(void *tramp)
+{
+/* This is popl %eax ; movl $syscall,%eax ; int $0x80 */
+__put_user(0xb858, (uint16_t *)(tramp + 0));
+__put_user(TARGET_NR_sigreturn, (int *)(tramp + 2));


I know this is mostly code movement, but using uint32_t would
make it easier to read.


+__put_user(0x80cd, (uint16_t *)(tramp + 6));
+}
+
+static void install_rt_sigtramp(void *tramp)
+{
+/* This is movl $syscall,%eax ; int $0x80 */
+__put_user(0xb8, (char *)(tramp + 0));


Ditto uint8_t,


+__put_user(TARGET_NR_rt_sigreturn, (int *)(tramp + 1));


and uint32_t.


+__put_user(0x80cd, (uint16_t *)(tramp + 5));
+}
+
  /* compare linux/arch/i386/kernel/signal.c:setup_frame() */
  void setup_frame(int sig, struct target_sigaction *ka,
   target_sigset_t *set, CPUX86State *env)
@@ -338,16 +354,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
  if (ka->sa_flags & TARGET_SA_RESTORER) {
  __put_user(ka->sa_restorer, &frame->pretcode);
  } else {
-uint16_t val16;
-abi_ulong retcode_addr;
-retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
-__put_user(retcode_addr, &frame->pretcode);
-/* This is popl %eax ; movl $,%eax ; int $0x80 */
-val16 = 0xb858;
-__put_user(val16, (uint16_t *)(frame->retcode+0));
-__put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
-val16 = 0x80cd;
-__put_user(val16, (uint16_t *)(frame->retcode+6));
+/* This is no longer used, but is retained for ABI compatibility. */
+install_sigtramp(frame->retcode);
+__put_user(default_sigreturn, &frame->pretcode);
  }
  
  /* Set up registers for signal handler */

@@ -416,14 +425,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
  if (ka->sa_flags & TARGET_SA_RESTORER) {
  __put_user(ka->sa_restorer, &frame->pretcode);
  } else {
-uint16_t val16;
-addr = frame_addr + offsetof(struct rt_sigframe, retcode);
-__put_user(addr, &frame->pretcode);
-/* This is movl $,%eax ; int $0x80 */
-__put_user(0xb8, (char *)(frame->retcode+0));
-__put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
-val16 = 0x80cd;
-__put_user(val16, (uint16_t *)(frame->retcode+5));
+/* This is no longer used, but is retained for ABI compatibility. */
+install_rt_sigtramp(frame->retcode);
+__put_user(default_rt_sigreturn, &frame->pretcode);
  }
  #else
  /* XXX: Would be slightly better to return -EFAULT here if test fails
@@ -592,3 +596,19 @@ badframe:
  force_sig(TARGET_SIGSEGV);
  return -TARGET_QEMU_ESIGRETURN;
  }
+
+#ifndef TARGET_X86_64
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);


Shouldn't this be 8 + 7?


+assert(tramp != NULL);
+
+default_sigreturn = sigtramp_page;
+install_sigtramp(tramp);
+
+default_rt_sigreturn = sigtramp_page + 8;
+install_rt_sigtramp(tramp + 8);
+
+unlock_user(tramp, sigtramp_page, 2 * 8);
+}
+#endif






Re: [PATCH v3 3/3] multifd: Send using asynchronous write on nocomp to send RAM pages.

2021-09-24 Thread Daniel P . Berrangé
On Wed, Sep 22, 2021 at 07:24:23PM -0300, Leonardo Bras wrote:
> Change multifd nocomp version to use asynchronous write for RAM pages, and
> benefit of MSG_ZEROCOPY when it's available.
> 
> The asynchronous flush happens on cleanup only, before destroying the 
> QIOChannel.
> 
> This will work fine on RAM migration because the RAM pages are not usually 
> freed,
> and there is no problem on changing the pages content between async_send() and
> the actual sending of the buffer, because this change will dirty the page and
> cause it to be re-sent on a next iteration anyway.
> 
> Signed-off-by: Leonardo Bras 
> ---
>  migration/multifd.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/migration/multifd.c b/migration/multifd.c
> index 377da78f5b..d247207a0a 100644
> --- a/migration/multifd.c
> +++ b/migration/multifd.c
> @@ -105,7 +105,7 @@ static int nocomp_send_prepare(MultiFDSendParams *p, 
> uint32_t used,
>   */
>  static int nocomp_send_write(MultiFDSendParams *p, uint32_t used, Error 
> **errp)
>  {
> -return qio_channel_writev_all(p->c, p->pages->iov, used, errp);
> +return qio_channel_async_writev_all(p->c, p->pages->iov, used, errp);
>  }

This needs to be made conditional so zeroopy is only used if rquested
by the mgmt app, and it isn't going to work in all cases (eg TLS) so
silently enabling it is not good.

>  
>  /**
> @@ -546,6 +546,7 @@ void multifd_save_cleanup(void)
>  MultiFDSendParams *p = &multifd_send_state->params[i];
>  Error *local_err = NULL;
>  
> +qio_channel_async_flush(p->c, NULL);
>  socket_send_channel_destroy(p->c);
>  p->c = NULL;
>  qemu_mutex_destroy(&p->mutex);

This isn't reliable beucase qio_channel_async_flush will return early
even if not everything is flushed.

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH v5 28/30] linux-user: Add safe syscall handling for loongarch64 hosts

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 linux-user/host/loongarch64/hostdep.h | 34 
 .../host/loongarch64/safe-syscall.inc.S   | 80 +++
 2 files changed, 114 insertions(+)
 create mode 100644 linux-user/host/loongarch64/hostdep.h
 create mode 100644 linux-user/host/loongarch64/safe-syscall.inc.S

diff --git a/linux-user/host/loongarch64/hostdep.h 
b/linux-user/host/loongarch64/hostdep.h
new file mode 100644
index 00..e3d5fa703f
--- /dev/null
+++ b/linux-user/host/loongarch64/hostdep.h
@@ -0,0 +1,34 @@
+/*
+ * hostdep.h : things which are dependent on the host architecture
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LOONGARCH64_HOSTDEP_H
+#define LOONGARCH64_HOSTDEP_H
+
+/* We have a safe-syscall.inc.S */
+#define HAVE_SAFE_SYSCALL
+
+#ifndef __ASSEMBLER__
+
+/* These are defined by the safe-syscall.inc.S file */
+extern char safe_syscall_start[];
+extern char safe_syscall_end[];
+
+/* Adjust the signal context to rewind out of safe-syscall if we're in it */
+static inline void rewind_if_in_safe_syscall(void *puc)
+{
+ucontext_t *uc = puc;
+unsigned long long *pcreg = &uc->uc_mcontext.__pc;
+
+if (*pcreg > (uintptr_t)safe_syscall_start
+&& *pcreg < (uintptr_t)safe_syscall_end) {
+*pcreg = (uintptr_t)safe_syscall_start;
+}
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif
diff --git a/linux-user/host/loongarch64/safe-syscall.inc.S 
b/linux-user/host/loongarch64/safe-syscall.inc.S
new file mode 100644
index 00..bb530248b3
--- /dev/null
+++ b/linux-user/host/loongarch64/safe-syscall.inc.S
@@ -0,0 +1,80 @@
+/*
+ * safe-syscall.inc.S : host-specific assembly fragment
+ * to handle signals occurring at the same time as system calls.
+ * This is intended to be included by linux-user/safe-syscall.S
+ *
+ * Ported to LoongArch by WANG Xuerui 
+ *
+ * Based on safe-syscall.inc.S code for every other architecture,
+ * originally written by Richard Henderson 
+ * Copyright (C) 2018 Linaro, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+   .global safe_syscall_base
+   .global safe_syscall_start
+   .global safe_syscall_end
+   .type   safe_syscall_base, @function
+   .type   safe_syscall_start, @function
+   .type   safe_syscall_end, @function
+
+   /*
+* This is the entry point for making a system call. The calling
+* convention here is that of a C varargs function with the
+* first argument an 'int *' to the signal_pending flag, the
+* second one the system call number (as a 'long'), and all further
+* arguments being syscall arguments (also 'long').
+* We return a long which is the syscall's return value, which
+* may be negative-errno on failure. Conversion to the
+* -1-and-errno-set convention is done by the calling wrapper.
+*/
+safe_syscall_base:
+   .cfi_startproc
+   /*
+* The syscall calling convention is nearly the same as C:
+* we enter with a0 == *signal_pending
+*   a1 == syscall number
+*   a2 ... a7 == syscall arguments
+*   and return the result in a0
+* and the syscall instruction needs
+*   a7 == syscall number
+*   a0 ... a5 == syscall arguments
+*   and returns the result in a0
+* Shuffle everything around appropriately.
+*/
+   move$t0, $a0/* signal_pending pointer */
+   move$t1, $a1/* syscall number */
+   move$a0, $a2/* syscall arguments */
+   move$a1, $a3
+   move$a2, $a4
+   move$a3, $a5
+   move$a4, $a6
+   move$a5, $a7
+   move$a7, $t1
+
+   /*
+* This next sequence of code works in conjunction with the
+* rewind_if_safe_syscall_function(). If a signal is taken
+* and the interrupted PC is anywhere between 'safe_syscall_start'
+* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
+* The code sequence must therefore be able to cope with this, and
+* the syscall instruction must be the final one in the sequence.
+*/
+safe_syscall_start:
+   /* If signal_pending is non-zero, don't do the call */
+   ld.w$t1, $t0, 0
+   bnez$t1, 0f
+   syscall 0
+safe_syscall_end:
+   /* code path for having successfully executed the syscall */
+   jr  $ra
+
+0:
+   /* code path when we didn't execute the syscall */
+   li.w$a0, -TARGET_ERESTARTSYS
+   jr  $ra
+   .cfi_endproc
+
+   .size   safe_syscall_base, .-safe_syscall_base
-- 
2.33.0




[PATCH v5 29/30] accel/tcg/user-exec: Implement CPU-specific signal handler for loongarch64 hosts

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 accel/tcg/user-exec.c | 73 +++
 1 file changed, 73 insertions(+)

diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 8fed542622..38d4ad8a7d 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -878,6 +878,79 @@ int cpu_signal_handler(int host_signum, void *pinfo,
 return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
 }
 
+#elif defined(__loongarch64)
+
+int cpu_signal_handler(int host_signum, void *pinfo,
+   void *puc)
+{
+siginfo_t *info = pinfo;
+ucontext_t *uc = puc;
+greg_t pc = uc->uc_mcontext.__pc;
+uint32_t insn = *(uint32_t *)pc;
+int is_write = 0;
+
+/* Detect store by reading the instruction at the program counter.  */
+switch ((insn >> 26) & 0b11) {
+case 0b001000: /* {ll,sc}.[wd] */
+switch ((insn >> 24) & 0b11) {
+case 0b01: /* sc.w */
+case 0b11: /* sc.d */
+is_write = 1;
+break;
+}
+break;
+case 0b001001: /* {ld,st}ox4.[wd] ({ld,st}ptr.[wd]) */
+switch ((insn >> 24) & 0b11) {
+case 0b01: /* stox4.w (stptr.w) */
+case 0b11: /* stox4.d (stptr.d) */
+is_write = 1;
+break;
+}
+break;
+case 0b001010: /* {ld,st}.* family */
+switch ((insn >> 22) & 0b) {
+case 0b0100: /* st.b */
+case 0b0101: /* st.h */
+case 0b0110: /* st.w */
+case 0b0111: /* st.d */
+case 0b1101: /* fst.s */
+case 0b: /* fst.d */
+is_write = 1;
+break;
+}
+break;
+case 0b001110: /* indexed, atomic, bounds-checking memory operations */
+uint32_t sel = (insn >> 15) & 0b111;
+
+switch (sel) {
+case 0b010: /* stx.b */
+case 0b0101000: /* stx.h */
+case 0b011: /* stx.w */
+case 0b0111000: /* stx.d */
+case 0b111: /* fstx.s */
+case 0b000: /* fstx.d */
+case 0b00011101100: /* fstgt.s */
+case 0b00011101101: /* fstgt.d */
+case 0b00011101110: /* fstle.s */
+case 0b0001110: /* fstle.d */
+case 0b0001000: /* stgt.b */
+case 0b0001001: /* stgt.h */
+case 0b0001010: /* stgt.w */
+case 0b0001011: /* stgt.d */
+case 0b0001100: /* stle.b */
+case 0b0001101: /* stle.h */
+case 0b0001110: /* stle.w */
+case 0b000: /* stle.d */
+case 0b0001100 ... 0b00011100011: /* am* insns */
+is_write = 1;
+break;
+}
+break;
+}
+
+return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
+}
+
 #else
 
 #error host CPU specific signal handler needed
-- 
2.33.0




[PATCH v5 23/30] tcg/loongarch64: Add softmmu load/store helpers, implement qemu_ld/qemu_st ops

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
---
 tcg/loongarch64/tcg-target-con-set.h |   2 +
 tcg/loongarch64/tcg-target.c.inc | 353 +++
 2 files changed, 355 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index e54ca9b2de..349c672687 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -17,7 +17,9 @@
 C_O0_I1(r)
 C_O0_I2(rZ, r)
 C_O0_I2(rZ, rZ)
+C_O0_I2(LZ, L)
 C_O1_I1(r, r)
+C_O1_I1(r, L)
 C_O1_I2(r, r, rC)
 C_O1_I2(r, r, ri)
 C_O1_I2(r, r, rI)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index c4dcb120cf..d4f1fe5d58 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -117,6 +117,11 @@ static const int tcg_target_call_oarg_regs[] = {
 TCG_REG_A1,
 };
 
+#ifndef CONFIG_SOFTMMU
+#define USE_GUEST_BASE (guest_base != 0)
+#define TCG_GUEST_BASE_REG TCG_REG_S1
+#endif
+
 #define TCG_CT_CONST_ZERO  0x100
 #define TCG_CT_CONST_S12   0x200
 #define TCG_CT_CONST_N12   0x400
@@ -604,6 +609,333 @@ static bool tcg_out_sti(TCGContext *s, TCGType type, 
TCGArg val,
 return false;
 }
 
+/*
+ * Load/store helpers for SoftMMU, and qemu_ld/st implementations
+ */
+
+#if defined(CONFIG_SOFTMMU)
+#include "../tcg-ldst.c.inc"
+
+/*
+ * helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
+ * TCGMemOpIdx oi, uintptr_t ra)
+ */
+static void * const qemu_ld_helpers[4] = {
+[MO_8]  = helper_ret_ldub_mmu,
+[MO_16] = helper_le_lduw_mmu,
+[MO_32] = helper_le_ldul_mmu,
+[MO_64] = helper_le_ldq_mmu,
+};
+
+/*
+ * helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
+ * uintxx_t val, TCGMemOpIdx oi,
+ * uintptr_t ra)
+ */
+static void * const qemu_st_helpers[4] = {
+[MO_8]  = helper_ret_stb_mmu,
+[MO_16] = helper_le_stw_mmu,
+[MO_32] = helper_le_stl_mmu,
+[MO_64] = helper_le_stq_mmu,
+};
+
+/* We expect to use a 12-bit negative offset from ENV.  */
+QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
+QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11));
+
+static bool tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
+{
+tcg_out_opc_b(s, 0);
+return reloc_br_sd10k16(s->code_ptr - 1, target);
+}
+
+/*
+ * Emits common code for TLB addend lookup, that eventually loads the
+ * addend in TCG_REG_TMP2.
+ */
+static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, TCGMemOpIdx oi,
+ tcg_insn_unit **label_ptr, bool is_load)
+{
+MemOp opc = get_memop(oi);
+unsigned s_bits = opc & MO_SIZE;
+unsigned a_bits = get_alignment_bits(opc);
+tcg_target_long compare_mask;
+int mem_index = get_mmuidx(oi);
+int fast_ofs = TLB_MASK_TABLE_OFS(mem_index);
+int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
+int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
+
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
+
+tcg_out_opc_srli_d(s, TCG_REG_TMP2, addrl,
+TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
+tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
+
+/* Load the tlb comparator and the addend.  */
+tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2,
+   is_load ? offsetof(CPUTLBEntry, addr_read)
+   : offsetof(CPUTLBEntry, addr_write));
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
+   offsetof(CPUTLBEntry, addend));
+
+/* We don't support unaligned accesses.  */
+if (a_bits < s_bits) {
+a_bits = s_bits;
+}
+/* Clear the non-page, non-alignment bits from the address.  */
+compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1);
+tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask);
+tcg_out_opc_and(s, TCG_REG_TMP1, TCG_REG_TMP1, addrl);
+
+/* Compare masked address with the TLB entry.  */
+label_ptr[0] = s->code_ptr;
+tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0);
+
+/* TLB Hit - addend in TCG_REG_TMP2, ready for use.  */
+}
+
+static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
+TCGType type,
+TCGReg datalo, TCGReg addrlo,
+void *raddr, tcg_insn_unit **label_ptr)
+{
+TCGLabelQemuLdst *label = new_ldst_label(s);
+
+label->is_ld = is_ld;
+label->oi = oi;
+label->type = type;
+label->datalo_reg = datalo;
+label->datahi_reg = 0; /* unused */
+label->addrlo_reg = addrlo;
+label->addrhi_reg = 0; /* unused */
+label->raddr = tcg_splitwx_to_rx(raddr);
+label->label_ptr[0] = label_ptr[0];
+}
+
+static bool tcg_out_qemu_ld_slow_path(TCG

[PATCH v5 25/30] tcg/loongarch64: Implement exit_tb/goto_tb

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 19 +++
 1 file changed, 19 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 4900af1853..4437b07541 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -952,6 +952,25 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 int c2 = const_args[2];
 
 switch (opc) {
+case INDEX_op_exit_tb:
+/* Reuse the zeroing that exists for goto_ptr.  */
+if (a0 == 0) {
+tcg_out_call_int(s, tcg_code_gen_epilogue, true);
+} else {
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
+tcg_out_call_int(s, tb_ret_addr, true);
+}
+break;
+
+case INDEX_op_goto_tb:
+assert(s->tb_jmp_insn_offset == 0);
+/* indirect jump method */
+tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
+   (uintptr_t)(s->tb_jmp_target_addr + a0));
+tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0);
+set_jmp_reset_offset(s, a0);
+break;
+
 case INDEX_op_mb:
 tcg_out_mb(s, a0);
 break;
-- 
2.33.0




[PATCH v5 16/30] tcg/loongarch64: Implement shl/shr/sar/rotl/rotr ops

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 91 
 tcg/loongarch64/tcg-target.h |  4 +-
 3 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 2975e03127..42f8e28741 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -17,6 +17,7 @@
 C_O0_I1(r)
 C_O1_I1(r, r)
 C_O1_I2(r, r, rC)
+C_O1_I2(r, r, ri)
 C_O1_I2(r, r, rU)
 C_O1_I2(r, r, rW)
 C_O1_I2(r, 0, rZ)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 1ab690bab6..32676e83af 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -580,6 +580,85 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false);
 break;
 
+case INDEX_op_shl_i32:
+if (c2) {
+tcg_out_opc_slli_w(s, a0, a1, a2 & 0x1f);
+} else {
+tcg_out_opc_sll_w(s, a0, a1, a2);
+}
+break;
+case INDEX_op_shl_i64:
+if (c2) {
+tcg_out_opc_slli_d(s, a0, a1, a2 & 0x3f);
+} else {
+tcg_out_opc_sll_d(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_shr_i32:
+if (c2) {
+tcg_out_opc_srli_w(s, a0, a1, a2 & 0x1f);
+} else {
+tcg_out_opc_srl_w(s, a0, a1, a2);
+}
+break;
+case INDEX_op_shr_i64:
+if (c2) {
+tcg_out_opc_srli_d(s, a0, a1, a2 & 0x3f);
+} else {
+tcg_out_opc_srl_d(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_sar_i32:
+if (c2) {
+tcg_out_opc_srai_w(s, a0, a1, a2 & 0x1f);
+} else {
+tcg_out_opc_sra_w(s, a0, a1, a2);
+}
+break;
+case INDEX_op_sar_i64:
+if (c2) {
+tcg_out_opc_srai_d(s, a0, a1, a2 & 0x3f);
+} else {
+tcg_out_opc_sra_d(s, a0, a1, a2);
+}
+break;
+
+case INDEX_op_rotl_i32:
+/* transform into equivalent rotr/rotri */
+if (c2) {
+tcg_out_opc_rotri_w(s, a0, a1, (32 - a2) & 0x1f);
+} else {
+tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2);
+tcg_out_opc_rotr_w(s, a0, a1, TCG_REG_TMP0);
+}
+break;
+case INDEX_op_rotl_i64:
+/* transform into equivalent rotr/rotri */
+if (c2) {
+tcg_out_opc_rotri_d(s, a0, a1, (64 - a2) & 0x3f);
+} else {
+tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2);
+tcg_out_opc_rotr_d(s, a0, a1, TCG_REG_TMP0);
+}
+break;
+
+case INDEX_op_rotr_i32:
+if (c2) {
+tcg_out_opc_rotri_w(s, a0, a1, a2 & 0x1f);
+} else {
+tcg_out_opc_rotr_w(s, a0, a1, a2);
+}
+break;
+case INDEX_op_rotr_i64:
+if (c2) {
+tcg_out_opc_rotri_d(s, a0, a1, a2 & 0x3f);
+} else {
+tcg_out_opc_rotr_d(s, a0, a1, a2);
+}
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
@@ -629,6 +708,18 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
  */
 return C_O1_I2(r, r, rC);
 
+case INDEX_op_shl_i32:
+case INDEX_op_shl_i64:
+case INDEX_op_shr_i32:
+case INDEX_op_shr_i64:
+case INDEX_op_sar_i32:
+case INDEX_op_sar_i64:
+case INDEX_op_rotl_i32:
+case INDEX_op_rotl_i64:
+case INDEX_op_rotr_i32:
+case INDEX_op_rotr_i64:
+return C_O1_I2(r, r, ri);
+
 case INDEX_op_and_i32:
 case INDEX_op_and_i64:
 case INDEX_op_nor_i32:
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index ef489cbc86..e59c2a7bec 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -96,7 +96,7 @@ typedef enum {
 #define TCG_TARGET_HAS_div_i32  0
 #define TCG_TARGET_HAS_rem_i32  0
 #define TCG_TARGET_HAS_div2_i32 0
-#define TCG_TARGET_HAS_rot_i32  0
+#define TCG_TARGET_HAS_rot_i32  1
 #define TCG_TARGET_HAS_deposit_i32  1
 #define TCG_TARGET_HAS_extract_i32  1
 #define TCG_TARGET_HAS_sextract_i32 0
@@ -133,7 +133,7 @@ typedef enum {
 #define TCG_TARGET_HAS_div_i64  0
 #define TCG_TARGET_HAS_rem_i64  0
 #define TCG_TARGET_HAS_div2_i64 0
-#define TCG_TARGET_HAS_rot_i64  0
+#define TCG_TARGET_HAS_rot_i64  1
 #define TCG_TARGET_HAS_deposit_i64  1
 #define TCG_TARGET_HAS_extract_i64  1
 #define TCG_TARGET_HAS_sextract_i64 0
-- 
2.33.0




[PATCH v5 24/30] tcg/loongarch64: Implement tcg_target_qemu_prologue

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 68 
 1 file changed, 68 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index d4f1fe5d58..4900af1853 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -940,6 +940,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg 
*args)
  * Entry-points
  */
 
+static const tcg_insn_unit *tb_ret_addr;
+
 static void tcg_out_op(TCGContext *s, TCGOpcode opc,
const TCGArg args[TCG_MAX_OP_ARGS],
const int const_args[TCG_MAX_OP_ARGS])
@@ -1489,3 +1491,69 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 g_assert_not_reached();
 }
 }
+
+static const int tcg_target_callee_save_regs[] = {
+TCG_REG_S0, /* used for the global env (TCG_AREG0) */
+TCG_REG_S1,
+TCG_REG_S2,
+TCG_REG_S3,
+TCG_REG_S4,
+TCG_REG_S5,
+TCG_REG_S6,
+TCG_REG_S7,
+TCG_REG_S8,
+TCG_REG_S9,
+TCG_REG_RA, /* should be last for ABI compliance */
+};
+
+/* Stack frame parameters.  */
+#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
+#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
+#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
+#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
+ + TCG_TARGET_STACK_ALIGN - 1) \
+& -TCG_TARGET_STACK_ALIGN)
+#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
+
+/* We're expecting to be able to use an immediate for frame allocation.  */
+QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
+
+/* Generate global QEMU prologue and epilogue code */
+static void tcg_target_qemu_prologue(TCGContext *s)
+{
+int i;
+
+tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
+
+/* TB prologue */
+tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
+for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
+}
+
+#if !defined(CONFIG_SOFTMMU)
+if (USE_GUEST_BASE) {
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
+tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+}
+#endif
+
+/* Call generated code */
+tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+tcg_out_opc_jirl(s, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
+
+/* Return path for goto_ptr. Set return value to 0 */
+tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
+tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
+
+/* TB epilogue */
+tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
+for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
+}
+
+tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
+tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0);
+}
-- 
2.33.0




[PATCH v5 11/30] tcg/loongarch64: Implement sign-/zero-extension ops

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 82 
 tcg/loongarch64/tcg-target.h | 24 
 3 files changed, 95 insertions(+), 12 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 5cc4407367..7e459490ea 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -15,3 +15,4 @@
  * tcg-target-con-str.h; the constraint combination is inclusive or.
  */
 C_O0_I1(r)
+C_O1_I1(r, r)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index d23be24211..00dff8b8aa 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -354,6 +354,36 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
TCGReg rd,
 }
 }
 
+static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_andi(s, ret, arg, 0xff);
+}
+
+static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15);
+}
+
+static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31);
+}
+
+static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_sext_b(s, ret, arg);
+}
+
+static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_sext_h(s, ret, arg);
+}
+
+static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+tcg_out_opc_addi_w(s, ret, arg, 0);
+}
+
 /*
  * Entry-points
  */
@@ -363,6 +393,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
const int const_args[TCG_MAX_OP_ARGS])
 {
 TCGArg a0 = args[0];
+TCGArg a1 = args[1];
 
 switch (opc) {
 case INDEX_op_mb:
@@ -373,6 +404,41 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0);
 break;
 
+case INDEX_op_ext8s_i32:
+case INDEX_op_ext8s_i64:
+tcg_out_ext8s(s, a0, a1);
+break;
+
+case INDEX_op_ext8u_i32:
+case INDEX_op_ext8u_i64:
+tcg_out_ext8u(s, a0, a1);
+break;
+
+case INDEX_op_ext16s_i32:
+case INDEX_op_ext16s_i64:
+tcg_out_ext16s(s, a0, a1);
+break;
+
+case INDEX_op_ext16u_i32:
+case INDEX_op_ext16u_i64:
+tcg_out_ext16u(s, a0, a1);
+break;
+
+case INDEX_op_ext32u_i64:
+case INDEX_op_extu_i32_i64:
+tcg_out_ext32u(s, a0, a1);
+break;
+
+case INDEX_op_ext32s_i64:
+case INDEX_op_extrl_i64_i32:
+case INDEX_op_ext_i32_i64:
+tcg_out_ext32s(s, a0, a1);
+break;
+
+case INDEX_op_extrh_i64_i32:
+tcg_out_opc_srai_d(s, a0, a1, 32);
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
@@ -386,6 +452,22 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_goto_ptr:
 return C_O0_I1(r);
 
+case INDEX_op_ext8s_i32:
+case INDEX_op_ext8s_i64:
+case INDEX_op_ext8u_i32:
+case INDEX_op_ext8u_i64:
+case INDEX_op_ext16s_i32:
+case INDEX_op_ext16s_i64:
+case INDEX_op_ext16u_i32:
+case INDEX_op_ext16u_i64:
+case INDEX_op_ext32s_i64:
+case INDEX_op_ext32u_i64:
+case INDEX_op_extu_i32_i64:
+case INDEX_op_extrl_i64_i32:
+case INDEX_op_extrh_i64_i32:
+case INDEX_op_ext_i32_i64:
+return C_O1_I1(r, r);
+
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 5fc097b3c1..2b7d5a19b9 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -107,10 +107,10 @@ typedef enum {
 #define TCG_TARGET_HAS_muls2_i320
 #define TCG_TARGET_HAS_muluh_i320
 #define TCG_TARGET_HAS_mulsh_i320
-#define TCG_TARGET_HAS_ext8s_i320
-#define TCG_TARGET_HAS_ext16s_i32   0
-#define TCG_TARGET_HAS_ext8u_i320
-#define TCG_TARGET_HAS_ext16u_i32   0
+#define TCG_TARGET_HAS_ext8s_i321
+#define TCG_TARGET_HAS_ext16s_i32   1
+#define TCG_TARGET_HAS_ext8u_i321
+#define TCG_TARGET_HAS_ext16u_i32   1
 #define TCG_TARGET_HAS_bswap16_i32  0
 #define TCG_TARGET_HAS_bswap32_i32  0
 #define TCG_TARGET_HAS_not_i32  0
@@ -138,14 +138,14 @@ typedef enum {
 #define TCG_TARGET_HAS_extract_i64  0
 #define TCG_TARGET_HAS_sextract_i64 0
 #define TCG_TARGET_HAS_extract2_i64 0
-#define TCG_TARGET_HAS_extrl_i64_i320
-#define TCG_TARGET_HAS_extrh_i64_i320
-#define TCG_TARGET_HAS_ext8s_i640
-#define TCG_TARGET_HAS_ext16s_i64   0
-#define TCG_TARGET_HAS_ext32s_i64   0
-#define TCG_TARGET_HAS_ext8u_i640
-#define TCG_TARGET_HAS_ext16u_i64   0
-#define TCG_TARGET_HAS_ext32u_i64   0
+#define TCG_TARGET_HAS_extrl_i64_i321
+#def

[PATCH v5 22/30] tcg/loongarch64: Implement simple load/store ops

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |   1 +
 tcg/loongarch64/tcg-target.c.inc | 131 +++
 2 files changed, 132 insertions(+)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index a2ec61237e..e54ca9b2de 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -15,6 +15,7 @@
  * tcg-target-con-str.h; the constraint combination is inclusive or.
  */
 C_O0_I1(r)
+C_O0_I2(rZ, r)
 C_O0_I2(rZ, rZ)
 C_O1_I1(r, r)
 C_O1_I2(r, r, rC)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 0f02f4be04..c4dcb120cf 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -537,6 +537,73 @@ static void tcg_out_call(TCGContext *s, const 
tcg_insn_unit *arg)
 tcg_out_call_int(s, arg, false);
 }
 
+/*
+ * Load/store helpers
+ */
+
+static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data,
+ TCGReg addr, intptr_t offset)
+{
+intptr_t imm12 = sextreg(offset, 0, 12);
+
+if (offset != imm12) {
+intptr_t diff = offset - (uintptr_t)s->code_ptr;
+
+if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
+imm12 = sextreg(diff, 0, 12);
+tcg_out_opc_pcaddu12i(s, TCG_REG_TMP2, (diff - imm12) >> 12);
+} else {
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
+if (addr != TCG_REG_ZERO) {
+tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, addr);
+}
+}
+addr = TCG_REG_TMP2;
+}
+
+switch (opc) {
+case OPC_LD_B:
+case OPC_LD_BU:
+case OPC_LD_H:
+case OPC_LD_HU:
+case OPC_LD_W:
+case OPC_LD_WU:
+case OPC_LD_D:
+case OPC_ST_B:
+case OPC_ST_H:
+case OPC_ST_W:
+case OPC_ST_D:
+tcg_out32(s, encode_djsk12_insn(opc, data, addr, imm12));
+break;
+default:
+g_assert_not_reached();
+}
+}
+
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+   TCGReg arg1, intptr_t arg2)
+{
+bool is_32bit = type == TCG_TYPE_I32;
+tcg_out_ldst(s, is_32bit ? OPC_LD_W : OPC_LD_D, arg, arg1, arg2);
+}
+
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+   TCGReg arg1, intptr_t arg2)
+{
+bool is_32bit = type == TCG_TYPE_I32;
+tcg_out_ldst(s, is_32bit ? OPC_ST_W : OPC_ST_D, arg, arg1, arg2);
+}
+
+static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
+TCGReg base, intptr_t ofs)
+{
+if (val == 0) {
+tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
+return true;
+}
+return false;
+}
+
 /*
  * Entry-points
  */
@@ -885,6 +952,49 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_setcond(s, args[3], a0, a1, a2, c2);
 break;
 
+case INDEX_op_ld8s_i32:
+case INDEX_op_ld8s_i64:
+tcg_out_ldst(s, OPC_LD_B, a0, a1, a2);
+break;
+case INDEX_op_ld8u_i32:
+case INDEX_op_ld8u_i64:
+tcg_out_ldst(s, OPC_LD_BU, a0, a1, a2);
+break;
+case INDEX_op_ld16s_i32:
+case INDEX_op_ld16s_i64:
+tcg_out_ldst(s, OPC_LD_H, a0, a1, a2);
+break;
+case INDEX_op_ld16u_i32:
+case INDEX_op_ld16u_i64:
+tcg_out_ldst(s, OPC_LD_HU, a0, a1, a2);
+break;
+case INDEX_op_ld_i32:
+case INDEX_op_ld32s_i64:
+tcg_out_ldst(s, OPC_LD_W, a0, a1, a2);
+break;
+case INDEX_op_ld32u_i64:
+tcg_out_ldst(s, OPC_LD_WU, a0, a1, a2);
+break;
+case INDEX_op_ld_i64:
+tcg_out_ldst(s, OPC_LD_D, a0, a1, a2);
+break;
+
+case INDEX_op_st8_i32:
+case INDEX_op_st8_i64:
+tcg_out_ldst(s, OPC_ST_B, a0, a1, a2);
+break;
+case INDEX_op_st16_i32:
+case INDEX_op_st16_i64:
+tcg_out_ldst(s, OPC_ST_H, a0, a1, a2);
+break;
+case INDEX_op_st_i32:
+case INDEX_op_st32_i64:
+tcg_out_ldst(s, OPC_ST_W, a0, a1, a2);
+break;
+case INDEX_op_st_i64:
+tcg_out_ldst(s, OPC_ST_D, a0, a1, a2);
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 case INDEX_op_call: /* Always emitted via tcg_out_call.  */
@@ -899,6 +1009,15 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_goto_ptr:
 return C_O0_I1(r);
 
+case INDEX_op_st8_i32:
+case INDEX_op_st8_i64:
+case INDEX_op_st16_i32:
+case INDEX_op_st16_i64:
+case INDEX_op_st32_i64:
+case INDEX_op_st_i32:
+case INDEX_op_st_i64:
+return C_O0_I2(rZ, r);
+
 case INDEX_op_brcond_i32:
 case INDEX_op_brcond_i64:
 return C_O0_I2(rZ, rZ);
@@ -926,6 +1045,18 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_bswap32_i32:
 case INDEX_op_bswap

[PATCH v5 15/30] tcg/loongarch64: Implement clz/ctz ops

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 42 
 tcg/loongarch64/tcg-target.h |  8 +++---
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index d958183020..2975e03127 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -18,4 +18,5 @@ C_O0_I1(r)
 C_O1_I1(r, r)
 C_O1_I2(r, r, rC)
 C_O1_I2(r, r, rU)
+C_O1_I2(r, r, rW)
 C_O1_I2(r, 0, rZ)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 51f0e3b1f1..1ab690bab6 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -384,6 +384,28 @@ static void tcg_out_ext32s(TCGContext *s, TCGReg ret, 
TCGReg arg)
 tcg_out_opc_addi_w(s, ret, arg, 0);
 }
 
+static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
+   TCGReg a0, TCGReg a1, TCGReg a2,
+   bool c2, bool is_32bit)
+{
+if (c2) {
+/*
+ * Fast path: semantics already satisfied due to constraint and
+ * insn behavior, single instruction is enough.
+ */
+tcg_debug_assert(a2 == (is_32bit ? 32 : 64));
+/* all clz/ctz insns belong to DJ-format */
+tcg_out32(s, encode_dj_insn(opc, a0, a1));
+return;
+}
+
+tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1));
+/* a0 = a1 ? REG_TMP0 : a2 */
+tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1);
+tcg_out_opc_masknez(s, a0, a2, a1);
+tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
+}
+
 /*
  * Entry-points
  */
@@ -544,6 +566,20 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_opc_revb_d(s, a0, a1);
 break;
 
+case INDEX_op_clz_i32:
+tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true);
+break;
+case INDEX_op_clz_i64:
+tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false);
+break;
+
+case INDEX_op_ctz_i32:
+tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true);
+break;
+case INDEX_op_ctz_i64:
+tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false);
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
@@ -604,6 +640,12 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 /* LoongArch reg-imm bitops have their imms ZERO-extended */
 return C_O1_I2(r, r, rU);
 
+case INDEX_op_clz_i32:
+case INDEX_op_clz_i64:
+case INDEX_op_ctz_i32:
+case INDEX_op_ctz_i64:
+return C_O1_I2(r, r, rW);
+
 case INDEX_op_deposit_i32:
 case INDEX_op_deposit_i64:
 /* Must deposit into the same register as input */
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index 02d17d2f6d..ef489cbc86 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -120,8 +120,8 @@ typedef enum {
 #define TCG_TARGET_HAS_eqv_i32  0
 #define TCG_TARGET_HAS_nand_i32 0
 #define TCG_TARGET_HAS_nor_i32  1
-#define TCG_TARGET_HAS_clz_i32  0
-#define TCG_TARGET_HAS_ctz_i32  0
+#define TCG_TARGET_HAS_clz_i32  1
+#define TCG_TARGET_HAS_ctz_i32  1
 #define TCG_TARGET_HAS_ctpop_i320
 #define TCG_TARGET_HAS_direct_jump  0
 #define TCG_TARGET_HAS_brcond2  0
@@ -156,8 +156,8 @@ typedef enum {
 #define TCG_TARGET_HAS_eqv_i64  0
 #define TCG_TARGET_HAS_nand_i64 0
 #define TCG_TARGET_HAS_nor_i64  1
-#define TCG_TARGET_HAS_clz_i64  0
-#define TCG_TARGET_HAS_ctz_i64  0
+#define TCG_TARGET_HAS_clz_i64  1
+#define TCG_TARGET_HAS_ctz_i64  1
 #define TCG_TARGET_HAS_ctpop_i640
 #define TCG_TARGET_HAS_add2_i64 0
 #define TCG_TARGET_HAS_sub2_i64 0
-- 
2.33.0




[PATCH v5 30/30] configure, meson.build: Mark support for loongarch64 hosts

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 configure   | 7 ++-
 meson.build | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 1043ccce4f..3a9035385d 100755
--- a/configure
+++ b/configure
@@ -659,6 +659,8 @@ elif check_define __arm__ ; then
   cpu="arm"
 elif check_define __aarch64__ ; then
   cpu="aarch64"
+elif check_define __loongarch64 ; then
+  cpu="loongarch64"
 else
   cpu=$(uname -m)
 fi
@@ -667,7 +669,7 @@ ARCH=
 # Normalise host CPU name and set ARCH.
 # Note that this case should only have supported host CPUs, not guests.
 case "$cpu" in
-  ppc|ppc64|s390x|sparc64|x32|riscv32|riscv64)
+  ppc|ppc64|s390x|sparc64|x32|riscv32|riscv64|loongarch64)
   ;;
   ppc64le)
 ARCH="ppc64"
@@ -4969,6 +4971,9 @@ if test "$linux" = "yes" ; then
   aarch64)
 linux_arch=arm64
 ;;
+  loongarch*)
+linux_arch=loongarch
+;;
   mips64)
 linux_arch=mips
 ;;
diff --git a/meson.build b/meson.build
index 15ef4d3c41..fc55712ac3 100644
--- a/meson.build
+++ b/meson.build
@@ -57,7 +57,7 @@ python = import('python').find_installation()
 
 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 
'sunos', 'linux']
 supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 
'x86_64',
-  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
+  'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc', 'sparc64']
 
 cpu = host_machine.cpu_family()
 targetos = host_machine.system()
-- 
2.33.0




[PATCH v5 21/30] tcg/loongarch64: Implement tcg_out_call

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 34 
 1 file changed, 34 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 4e34f4ac97..0f02f4be04 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -504,6 +504,39 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, 
TCGReg arg1,
 tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0));
 }
 
+static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool 
tail)
+{
+TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
+ptrdiff_t offset = tcg_pcrel_diff(s, arg);
+
+tcg_debug_assert((offset & 3) == 0);
+if (offset == sextreg(offset, 0, 28)) {
+/* short jump: +/- 256MiB */
+if (tail) {
+tcg_out_opc_b(s, offset >> 2);
+} else {
+tcg_out_opc_bl(s, offset >> 2);
+}
+} else if (offset == sextreg(offset, 0, 38)) {
+/* long jump: +/- 256GiB */
+tcg_target_long lo = sextreg(offset, 0, 18);
+tcg_target_long hi = offset - lo;
+tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18);
+tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2);
+} else {
+/* far jump: 64-bit */
+tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18);
+tcg_target_long hi = (tcg_target_long)arg - lo;
+tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi);
+tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2);
+}
+}
+
+static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg)
+{
+tcg_out_call_int(s, arg, false);
+}
+
 /*
  * Entry-points
  */
@@ -854,6 +887,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
+case INDEX_op_call: /* Always emitted via tcg_out_call.  */
 default:
 g_assert_not_reached();
 }
-- 
2.33.0




[PATCH v5 10/30] tcg/loongarch64: Implement goto_ptr

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h | 17 +
 tcg/loongarch64/tcg-target.c.inc | 15 +++
 2 files changed, 32 insertions(+)
 create mode 100644 tcg/loongarch64/tcg-target-con-set.h

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
new file mode 100644
index 00..5cc4407367
--- /dev/null
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Define LoongArch target-specific constraint sets.
+ *
+ * Copyright (c) 2021 WANG Xuerui 
+ *
+ * Based on tcg/riscv/tcg-target-con-set.h
+ *
+ * Copyright (c) 2021 Linaro
+ */
+
+/*
+ * C_On_Im(...) defines a constraint set with  outputs and  inputs.
+ * Each operand should be a sequence of constraint letters as defined by
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
+ */
+C_O0_I1(r)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index f1d0047f5b..d23be24211 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -369,9 +369,24 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_mb(s, a0);
 break;
 
+case INDEX_op_goto_ptr:
+tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0);
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
 g_assert_not_reached();
 }
 }
+
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+{
+switch (op) {
+case INDEX_op_goto_ptr:
+return C_O0_I1(r);
+
+default:
+g_assert_not_reached();
+}
+}
-- 
2.33.0




[PATCH v5 18/30] tcg/loongarch64: Implement mul/mulsh/muluh/div/divu/rem/remu ops

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h |  1 +
 tcg/loongarch64/tcg-target.c.inc | 65 
 tcg/loongarch64/tcg-target.h | 16 +++
 3 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
index 4b8ce85897..fb56f3a295 100644
--- a/tcg/loongarch64/tcg-target-con-set.h
+++ b/tcg/loongarch64/tcg-target-con-set.h
@@ -23,3 +23,4 @@ C_O1_I2(r, r, rU)
 C_O1_I2(r, r, rW)
 C_O1_I2(r, 0, rZ)
 C_O1_I2(r, rZ, rN)
+C_O1_I2(r, rZ, rZ)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 6ad3cddcee..e3aac6c3de 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -689,6 +689,55 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 }
 break;
 
+case INDEX_op_mul_i32:
+tcg_out_opc_mul_w(s, a0, a1, a2);
+break;
+case INDEX_op_mul_i64:
+tcg_out_opc_mul_d(s, a0, a1, a2);
+break;
+
+case INDEX_op_mulsh_i32:
+tcg_out_opc_mulh_w(s, a0, a1, a2);
+break;
+case INDEX_op_mulsh_i64:
+tcg_out_opc_mulh_d(s, a0, a1, a2);
+break;
+
+case INDEX_op_muluh_i32:
+tcg_out_opc_mulh_wu(s, a0, a1, a2);
+break;
+case INDEX_op_muluh_i64:
+tcg_out_opc_mulh_du(s, a0, a1, a2);
+break;
+
+case INDEX_op_div_i32:
+tcg_out_opc_div_w(s, a0, a1, a2);
+break;
+case INDEX_op_div_i64:
+tcg_out_opc_div_d(s, a0, a1, a2);
+break;
+
+case INDEX_op_divu_i32:
+tcg_out_opc_div_wu(s, a0, a1, a2);
+break;
+case INDEX_op_divu_i64:
+tcg_out_opc_div_du(s, a0, a1, a2);
+break;
+
+case INDEX_op_rem_i32:
+tcg_out_opc_mod_w(s, a0, a1, a2);
+break;
+case INDEX_op_rem_i64:
+tcg_out_opc_mod_d(s, a0, a1, a2);
+break;
+
+case INDEX_op_remu_i32:
+tcg_out_opc_mod_wu(s, a0, a1, a2);
+break;
+case INDEX_op_remu_i64:
+tcg_out_opc_mod_du(s, a0, a1, a2);
+break;
+
 case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
 case INDEX_op_mov_i64:
 default:
@@ -780,6 +829,22 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_sub_i64:
 return C_O1_I2(r, rZ, rN);
 
+case INDEX_op_mul_i32:
+case INDEX_op_mul_i64:
+case INDEX_op_mulsh_i32:
+case INDEX_op_mulsh_i64:
+case INDEX_op_muluh_i32:
+case INDEX_op_muluh_i64:
+case INDEX_op_div_i32:
+case INDEX_op_div_i64:
+case INDEX_op_divu_i32:
+case INDEX_op_divu_i64:
+case INDEX_op_rem_i32:
+case INDEX_op_rem_i64:
+case INDEX_op_remu_i32:
+case INDEX_op_remu_i64:
+return C_O1_I2(r, rZ, rZ);
+
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
index e59c2a7bec..2ac2c342c7 100644
--- a/tcg/loongarch64/tcg-target.h
+++ b/tcg/loongarch64/tcg-target.h
@@ -93,8 +93,8 @@ typedef enum {
 
 /* optional instructions */
 #define TCG_TARGET_HAS_movcond_i32  0
-#define TCG_TARGET_HAS_div_i32  0
-#define TCG_TARGET_HAS_rem_i32  0
+#define TCG_TARGET_HAS_div_i32  1
+#define TCG_TARGET_HAS_rem_i32  1
 #define TCG_TARGET_HAS_div2_i32 0
 #define TCG_TARGET_HAS_rot_i32  1
 #define TCG_TARGET_HAS_deposit_i32  1
@@ -105,8 +105,8 @@ typedef enum {
 #define TCG_TARGET_HAS_sub2_i32 0
 #define TCG_TARGET_HAS_mulu2_i320
 #define TCG_TARGET_HAS_muls2_i320
-#define TCG_TARGET_HAS_muluh_i320
-#define TCG_TARGET_HAS_mulsh_i320
+#define TCG_TARGET_HAS_muluh_i321
+#define TCG_TARGET_HAS_mulsh_i321
 #define TCG_TARGET_HAS_ext8s_i321
 #define TCG_TARGET_HAS_ext16s_i32   1
 #define TCG_TARGET_HAS_ext8u_i321
@@ -130,8 +130,8 @@ typedef enum {
 
 /* 64-bit operations */
 #define TCG_TARGET_HAS_movcond_i64  0
-#define TCG_TARGET_HAS_div_i64  0
-#define TCG_TARGET_HAS_rem_i64  0
+#define TCG_TARGET_HAS_div_i64  1
+#define TCG_TARGET_HAS_rem_i64  1
 #define TCG_TARGET_HAS_div2_i64 0
 #define TCG_TARGET_HAS_rot_i64  1
 #define TCG_TARGET_HAS_deposit_i64  1
@@ -163,8 +163,8 @@ typedef enum {
 #define TCG_TARGET_HAS_sub2_i64 0
 #define TCG_TARGET_HAS_mulu2_i640
 #define TCG_TARGET_HAS_muls2_i640
-#define TCG_TARGET_HAS_muluh_i640
-#define TCG_TARGET_HAS_mulsh_i640
+#define TCG_TARGET_HAS_muluh_i641
+#define TCG_TARGET_HAS_mulsh_i641
 
 /* not defined -- call should be eliminated at compile time */
 void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
-- 
2.33.0




[PATCH v5 07/30] tcg/loongarch64: Implement necessary relocation operations

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 66 
 1 file changed, 66 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index f0930f77ef..6967f143e9 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -168,3 +168,69 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct)
 }
 return 0;
 }
+
+/*
+ * Relocations
+ */
+
+/*
+ * Relocation records defined in LoongArch ELF psABI v1.00 is way too
+ * complicated; a whopping stack machine is needed to stuff the fields, at
+ * the very least one SOP_PUSH and one SOP_POP (of the correct format) are
+ * needed.
+ *
+ * Hence, define our own simpler relocation types. Numbers are chosen as to
+ * not collide with potential future additions to the true ELF relocation
+ * type enum.
+ */
+
+/* Field Sk16, shifted right by 2; suitable for conditional jumps */
+#define R_LOONGARCH_BR_SK16 256
+/* Field Sd10k16, shifted right by 2; suitable for B and BL */
+#define R_LOONGARCH_BR_SD10K16  257
+
+static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
+{
+const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
+intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
+
+tcg_debug_assert((offset & 3) == 0);
+offset >>= 2;
+if (offset == sextreg(offset, 0, 16)) {
+*src_rw = deposit64(*src_rw, 10, 16, offset);
+return true;
+}
+
+return false;
+}
+
+static bool reloc_br_sd10k16(tcg_insn_unit *src_rw,
+ const tcg_insn_unit *target)
+{
+const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
+intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
+
+tcg_debug_assert((offset & 3) == 0);
+offset >>= 2;
+if (offset == sextreg(offset, 0, 26)) {
+*src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */
+*src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */
+return true;
+}
+
+return false;
+}
+
+static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
+intptr_t value, intptr_t addend)
+{
+tcg_debug_assert(addend == 0);
+switch (type) {
+case R_LOONGARCH_BR_SK16:
+return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value);
+case R_LOONGARCH_BR_SD10K16:
+return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value);
+default:
+g_assert_not_reached();
+}
+}
-- 
2.33.0




[PATCH v5 26/30] tcg/loongarch64: Implement tcg_target_init

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 4437b07541..c34683b2d0 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1576,3 +1576,30 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
 tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0);
 }
+
+static void tcg_target_init(TCGContext *s)
+{
+tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
+tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS;
+
+tcg_target_call_clobber_regs = ALL_GENERAL_REGS;
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
+tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
+
+s->reserved_regs = 0;
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
+tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED);
+}
-- 
2.33.0




  1   2   3   4   >