Re: [Qemu-devel] [PATCH v2 02/19] spapr: introduce a skeleton for the XIVE interrupt controller
On Thu, Jan 18, 2018 at 08:27:52AM +1100, Benjamin Herrenschmidt wrote: > On Wed, 2018-01-17 at 15:39 +0100, Cédric Le Goater wrote: > > Migration is a problem. We will need both backend QEMU objects to be > > available anyhow if we want to migrate. So we are back to the current > > solution creating both QEMU objects but we can try to defer some of the > > KVM inits and create the KVM device on demand at CAS time. > > Do we have a way to migrate a piece of info from the machine *first* > that indicate what type of XICS/XIVE to instanciate ? Nope. qemu migration doesn't work like that. Yes, it should, and everyone knows it, but changing it is a really long term project. > > > The next problem is the ICP object that currently needs the KVM device > > fd to connect the vcpus ... So, we will need to change that also. > > That is probably the biggest problem today. We need a way to disconnect > > the vpcu from the KVM device and see how we can defer the connection. > > I need to make sure this is possible, I can check that without XIVE > > Ben. > -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
[Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor
Rename the variable holding the QAPISchemaGenFOOVisitor from gen to vis, to avoid confusion in the next commit. Signed-off-by: Markus Armbruster --- scripts/qapi-commands.py | 8 scripts/qapi-event.py | 8 scripts/qapi-introspect.py | 8 scripts/qapi-types.py | 8 scripts/qapi-visit.py | 8 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 84a980d882..c3aa52fce1 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -291,9 +291,9 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); prefix=prefix, c_prefix=c_name(prefix, protect=False))) schema = QAPISchema(input_file) -gen = QAPISchemaGenCommandVisitor() -schema.visit(gen) -fdef.write(gen.defn) -fdecl.write(gen.decl) +vis = QAPISchemaGenCommandVisitor() +schema.visit(vis) +fdef.write(vis.defn) +fdecl.write(vis.decl) close_output(fdef, fdecl) diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index 0a098803e2..edb9ddb650 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -203,9 +203,9 @@ fdecl.write(mcgen(''' event_enum_name = c_name(prefix + 'QAPIEvent', protect=False) schema = QAPISchema(input_file) -gen = QAPISchemaGenEventVisitor() -schema.visit(gen) -fdef.write(gen.defn) -fdecl.write(gen.decl) +vis = QAPISchemaGenEventVisitor() +schema.visit(vis) +fdef.write(vis.defn) +fdecl.write(vis.decl) close_output(fdef, fdecl) diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index bd9253a172..ebe8706f41 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -193,9 +193,9 @@ fdef.write(mcgen(''' prefix=prefix)) schema = QAPISchema(input_file) -gen = QAPISchemaGenIntrospectVisitor(opt_unmask) -schema.visit(gen) -fdef.write(gen.defn) -fdecl.write(gen.decl) +vis = QAPISchemaGenIntrospectVisitor(opt_unmask) +schema.visit(vis) +fdef.write(vis.defn) +fdecl.write(vis.decl) close_output(fdef, fdecl) diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 1103dbda2d..4db8424da1 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -273,9 +273,9 @@ fdecl.write(mcgen(''' ''')) schema = QAPISchema(input_file) -gen = QAPISchemaGenTypeVisitor() -schema.visit(gen) -fdef.write(gen.defn) -fdecl.write(gen.decl) +vis = QAPISchemaGenTypeVisitor() +schema.visit(vis) +fdef.write(vis.defn) +fdecl.write(vis.decl) close_output(fdef, fdecl) diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index e56b3c1256..3c1a0e2544 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -360,9 +360,9 @@ fdecl.write(mcgen(''' prefix=prefix)) schema = QAPISchema(input_file) -gen = QAPISchemaGenVisitVisitor() -schema.visit(gen) -fdef.write(gen.defn) -fdecl.write(gen.decl) +vis = QAPISchemaGenVisitVisitor() +schema.visit(vis) +fdef.write(vis.defn) +fdecl.write(vis.decl) close_output(fdef, fdecl) -- 2.13.6
[Qemu-devel] [PATCH v2 12/29] qapi/common: Eliminate QAPISchema.exprs
Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Marc-André Lureau --- scripts/qapi/common.py | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 3e92b38ade..d72c339ad5 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1461,13 +1461,13 @@ class QAPISchema(object): def __init__(self, fname): try: parser = QAPISchemaParser(open(fname, 'r')) -self.exprs = check_exprs(parser.exprs) +exprs = check_exprs(parser.exprs) self.docs = parser.docs self._entity_dict = {} self._predefining = True self._def_predefineds() self._predefining = False -self._def_exprs() +self._def_exprs(exprs) self.check() except QAPIError as err: print(err, file=sys.stderr) @@ -1652,8 +1652,8 @@ class QAPISchema(object): name, info, doc, 'arg', self._make_members(data, info)) self._def_entity(QAPISchemaEvent(name, info, doc, data, boxed)) -def _def_exprs(self): -for expr_elem in self.exprs: +def _def_exprs(self, exprs): +for expr_elem in exprs: expr = expr_elem['expr'] info = expr_elem['info'] doc = expr_elem.get('doc') -- 2.13.6
[Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice
Each generator carries a copyright notice for the generator itself, and another one for the files it generates. Only the former have been updated along the way, the latter have not, and are all out of date. Fix by copying the generator's copyright notice to the generated files instead. Note that the fix doesn't copy the "Authors:" part; the generated files' outdated Authors list goes away without replacement. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Marc-André Lureau --- scripts/qapi-commands.py | 34 +++--- scripts/qapi-event.py | 32 ++-- scripts/qapi-introspect.py | 25 - scripts/qapi-types.py | 32 ++-- scripts/qapi-visit.py | 34 +++--- scripts/qapi.py| 7 +-- 6 files changed, 75 insertions(+), 89 deletions(-) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 8e8da7c796..84a980d882 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -1,16 +1,17 @@ -# -# QAPI command marshaller generator -# -# Copyright IBM, Corp. 2011 -# Copyright (C) 2014-2016 Red Hat, Inc. -# -# Authors: -# Anthony Liguori -# Michael Roth -# Markus Armbruster -# -# This work is licensed under the terms of the GNU GPL, version 2. -# See the COPYING file in the top-level directory. +""" +QAPI command marshaller generator + +Copyright IBM, Corp. 2011 +Copyright (C) 2014-2018 Red Hat, Inc. + +Authors: + Anthony Liguori + Michael Roth + Markus Armbruster + +This work is licensed under the terms of the GNU GPL, version 2. +See the COPYING file in the top-level directory. +""" from qapi import * @@ -257,16 +258,11 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor): blurb = ''' * Schema-defined QAPI/QMP commands - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori ''' (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, 'qmp-marshal.c', 'qmp-commands.h', -blurb) +blurb, __doc__) fdef.write(mcgen(''' diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index 2b7d720c08..0a098803e2 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -1,15 +1,16 @@ -# -# QAPI event generator -# -# Copyright (c) 2014 Wenchao Xia -# Copyright (c) 2015-2016 Red Hat Inc. -# -# Authors: -# Wenchao Xia -# Markus Armbruster -# -# This work is licensed under the terms of the GNU GPL, version 2. -# See the COPYING file in the top-level directory. +""" +QAPI event generator + +Copyright (c) 2014 Wenchao Xia +Copyright (c) 2015-2018 Red Hat Inc. + +Authors: + Wenchao Xia + Markus Armbruster + +This work is licensed under the terms of the GNU GPL, version 2. +See the COPYING file in the top-level directory. +""" from qapi import * @@ -173,16 +174,11 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor): blurb = ''' * Schema-defined QAPI/QMP events - * - * Copyright (c) 2014 Wenchao Xia - * - * Authors: - * Wenchao Xia ''' (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, 'qapi-event.c', 'qapi-event.h', -blurb) +blurb, __doc__) fdef.write(mcgen(''' #include "qemu/osdep.h" diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index 83da2bdb94..bd9253a172 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -1,13 +1,14 @@ -# -# QAPI introspection generator -# -# Copyright (C) 2015-2016 Red Hat, Inc. -# -# Authors: -# Markus Armbruster -# -# This work is licensed under the terms of the GNU GPL, version 2. -# See the COPYING file in the top-level directory. +""" +QAPI introspection generator + +Copyright (C) 2015-2018 Red Hat, Inc. + +Authors: + Markus Armbruster + +This work is licensed under the terms of the GNU GPL, version 2. +See the COPYING file in the top-level directory. +""" from qapi import * @@ -178,13 +179,11 @@ for o, a in opts: blurb = ''' * QAPI/QMP schema introspection - * - * Copyright (C) 2015 Red Hat, Inc. ''' (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, 'qmp-introspect.c', 'qmp-introspect.h', -blurb) +blurb, __doc__) fdef.write(mcgen(''' #include "qemu/osdep.h" diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 86afc57f92..1103dbda2d 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -1,15 +1,17 @@ -# -# QAPI types generator -# -# Copyright IBM, Corp. 2011 -# Copyright (c) 2013-2016 Red Hat Inc. -# -# Authors: -# Anthony Liguori -# Markus Armbruster -# -# This work is licensed under the terms of the GNU GPL, version 2. +""" +QAPI types generator + +Copyright IBM, Corp. 2011 +Copyright (c) 2013-2018 Red Hat Inc. + +Authors: + Anthony Ligu
[Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI
With modular code generation, putting stuff right into qapi-schema.json is a bad idea. Update writing-qmp-commands.txt accordingly. Signed-off-by: Markus Armbruster --- docs/devel/writing-qmp-commands.txt | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt index 4f5b24c0c4..776b3b41ca 100644 --- a/docs/devel/writing-qmp-commands.txt +++ b/docs/devel/writing-qmp-commands.txt @@ -15,8 +15,8 @@ start with docs/interop/qmp-intro.txt. Generally speaking, the following steps should be taken in order to write a new QMP command. -1. Write the command's and type(s) specification in the QAPI schema file - (qapi-schema.json in the root source directory) +1. Define the command and any types it needs in the appropriate QAPI + schema module. 2. Write the QMP command itself, which is a regular C function. Preferably, the command should be exported by some QEMU subsystem. But it can also be @@ -88,8 +88,9 @@ command carries some meaningful action in QEMU but here it will just print Our command will be called "hello-world". It takes no arguments, nor does it return any data. -The first step is to add the following line to the bottom of the -qapi-schema.json file: +The first step is defining the command in the appropriate QAPI schema +module. We pick module qapi/misc.json, and add the following line at +the bottom: { 'command': 'hello-world' } @@ -245,7 +246,7 @@ This is very important. No QMP command will be accepted in QEMU without proper documentation. There are many examples of such documentation in the schema file already, but -here goes "hello-world"'s new entry for the qapi-schema.json file: +here goes "hello-world"'s new entry for qapi/misc.json: ## # @hello-world @@ -425,8 +426,7 @@ There are a number of things to be noticed: allocated by the implementation. This is so because the QAPI also generates a function to free its types and it cannot distinguish between dynamically or statically allocated strings -6. You have to include the "qmp-commands.h" header file in qemu-timer.c, - otherwise qemu won't build +6. You have to include "qapi/qmp-commands-misc.h" in qemu-timer.c Time to test the new command. Build qemu, run it as described in the "Testing" section and try this: -- 2.13.6
[Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__()
Signed-off-by: Markus Armbruster Reviewed-by: Marc-André Lureau --- scripts/qapi/common.py | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index dce289ae21..cc5a5941dd 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -290,8 +290,12 @@ class QAPISchemaParser(object): if not isinstance(include, str): raise QAPISemError(info, "Value of 'include' must be a string") -self._include(include, info, os.path.dirname(self.fname), - previously_included) +exprs_include = self._include(include, info, + os.path.dirname(self.fname), + previously_included) +if exprs_include: +self.exprs.extend(exprs_include.exprs) +self.docs.extend(exprs_include.docs) elif "pragma" in expr: self.reject_expr_doc(cur_doc) if len(expr) != 1: @@ -334,14 +338,13 @@ class QAPISchemaParser(object): # skip multiple include of the same file if incl_abs_fname in previously_included: -return +return None + try: fobj = open(incl_fname, 'r') except IOError as e: raise QAPISemError(info, '%s: %s' % (e.strerror, incl_fname)) -exprs_include = QAPISchemaParser(fobj, previously_included, info) -self.exprs.extend(exprs_include.exprs) -self.docs.extend(exprs_include.docs) +return QAPISchemaParser(fobj, previously_included, info) def _pragma(self, name, value, info): global doc_required, returns_whitelist, name_case_whitelist -- 2.13.6
[Qemu-devel] [PATCH v2 21/29] qapi/common: Fix guardname() for funny filenames
guardname() fails to return a valid C identifier for arguments containing anything but [A-Za-z0-9_.-']. Fix that. Don't bother protecting ticklish identifiers; header guards are all-caps, and no ticklish identifiers are. Signed-off-by: Markus Armbruster Reviewed-by: Marc-André Lureau Reviewed-by: Eric Blake --- scripts/qapi/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index de12f8469a..6e5152b173 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1867,7 +1867,7 @@ def mcgen(code, **kwds): def guardname(filename): -return c_name(filename, protect=False).upper() +return re.sub(r'[^A-Za-z0-9_]', '_', filename).upper() def guardstart(name): -- 2.13.6
[Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change
A massive number of objects depends on QAPI-generated headers. In my "build everything" tree, it's roughly 4800 out of 5100. This is particularly annoying when only some of the generated files change, say for a doc fix. Improve qapi-gen.py to touch its output files only if they actually change. Rebuild time for a QAPI doc fix drops from many minutes to a few seconds. Rebuilds get faster for certain code changes, too. For instance, adding a simple QMP event now recompiles less than 200 instead of 4800 objects. But adding a QAPI type is as bad as ever; we've clearly got more work to do. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake --- scripts/qapi/common.py | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 8290795dc1..2e58573a39 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1951,9 +1951,16 @@ class QAPIGen(object): except os.error as e: if e.errno != errno.EEXIST: raise -f = open(os.path.join(output_dir, fname), 'w') -f.write(self._top(fname) + self._preamble + self._body +fd = os.open(os.path.join(output_dir, fname), + os.O_RDWR | os.O_CREAT, 0666) +f = os.fdopen(fd, 'r+') +text = (self._top(fname) + self._preamble + self._body + self._bottom(fname)) +oldtext = f.read(len(text) + 1) +if text != oldtext: +f.seek(0) +f.truncate(0) +f.write(text) f.close() -- 2.13.6
[Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc
Fix up the reference to qmp-commands.hx in qmp.c. Missed in commit 5032a16d1d. Fix up the reference to qmp-commands.txt in docs/xen-save-devices-state.txt. Missed in commit 4d8bb958fa. Signed-off-by: Markus Armbruster --- docs/xen-save-devices-state.txt | 3 +-- qmp.c | 14 +++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/xen-save-devices-state.txt b/docs/xen-save-devices-state.txt index a72ecc8081..1912ecad25 100644 --- a/docs/xen-save-devices-state.txt +++ b/docs/xen-save-devices-state.txt @@ -8,8 +8,7 @@ These operations are normally used with migration (see migration.txt), however it is also possible to save the state of all devices to file, without saving the RAM or the block devices of the VM. -This operation is called "xen-save-devices-state" (see -qmp-commands.txt) +The save operation is available as QMP command xen-save-devices-state. The binary format used in the file is the following: diff --git a/qmp.c b/qmp.c index a8d4eba973..ba82e1df9f 100644 --- a/qmp.c +++ b/qmp.c @@ -147,13 +147,13 @@ VncInfo2List *qmp_query_vnc_servers(Error **errp) #ifndef CONFIG_SPICE /* - * qmp-commands.hx ensures that QMP command query-spice exists only - * #ifdef CONFIG_SPICE. Necessary for an accurate query-commands - * result. However, the QAPI schema is blissfully unaware of that, - * and the QAPI code generator happily generates a dead - * qmp_marshal_query_spice() that calls qmp_query_spice(). Provide it - * one, or else linking fails. FIXME Educate the QAPI schema on - * CONFIG_SPICE. + * qmp_unregister_commands_hack() ensures that QMP command query-spice + * exists only #ifdef CONFIG_SPICE. Necessary for an accurate + * query-commands result. However, the QAPI schema is blissfully + * unaware of that, and the QAPI code generator happily generates a + * dead qmp_marshal_query_spice() that calls qmp_query_spice(). + * Provide it one, or else linking fails. FIXME Educate the QAPI + * schema on CONFIG_SPICE. */ SpiceInfo *qmp_query_spice(Error **errp) { -- 2.13.6
[Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI
* Fix guidance on error classes * Point to generated documentation * Drop plea for documentation, because the QAPI code generator enforces it since commit 3313b6124b * Minor tweaks here and there Signed-off-by: Markus Armbruster --- docs/devel/writing-qmp-commands.txt | 25 + docs/interop/qmp-intro.txt | 3 ++- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/docs/devel/writing-qmp-commands.txt b/docs/devel/writing-qmp-commands.txt index 776b3b41ca..50385eff27 100644 --- a/docs/devel/writing-qmp-commands.txt +++ b/docs/devel/writing-qmp-commands.txt @@ -36,9 +36,9 @@ very simple and get more complex as we progress. For all the examples in the next sections, the test setup is the same and is shown here. -First, QEMU should be started as: +First, QEMU should be started like this: -# /path/to/your/source/qemu [...] \ +# qemu-system-TARGET [...] \ -chardev socket,id=qmp,port=,host=localhost,server \ -mon chardev=qmp,mode=control,pretty=on @@ -179,7 +179,7 @@ described in the "Testing" section and then send two commands: } } -You should see "Hello, world" and "we love qemu" in the terminal running qemu, +You should see "Hello, world" and "We love qemu" in the terminal running qemu, if you don't see these strings, then something went wrong. === Errors === @@ -221,30 +221,23 @@ The QMP server's response should be: } } -As a general rule, all QMP errors should use ERROR_CLASS_GENERIC_ERROR -(done by default when using error_setg()). There are two exceptions to -this rule: +Note that error_setg() produces a "GenericError" class. In general, +all QMP errors should have that error class. There are two exceptions +to this rule: - 1. A non-generic ErrorClass value exists* for the failure you want to report -(eg. DeviceNotFound) + 1. To support a management application's need to recognize a specific +error for special handling - 2. Management applications have to take special action on the failure you -want to report, hence you have to add a new ErrorClass value so that they -can check for it + 2. Backward compatibility If the failure you want to report falls into one of the two cases above, use error_set() with a second argument of an ErrorClass value. - * All existing ErrorClass values are defined in the qapi-schema.json file - === Command Documentation === There's only one step missing to make "hello-world"'s implementation complete, and that's its documentation in the schema file. -This is very important. No QMP command will be accepted in QEMU without proper -documentation. - There are many examples of such documentation in the schema file already, but here goes "hello-world"'s new entry for qapi/misc.json: diff --git a/docs/interop/qmp-intro.txt b/docs/interop/qmp-intro.txt index adbc94abb1..430fe1b747 100644 --- a/docs/interop/qmp-intro.txt +++ b/docs/interop/qmp-intro.txt @@ -78,7 +78,8 @@ Escape character is '^]'. } } -Please, refer to the qapi-schema.json file for a complete command reference. +Please refer to docs/interop/qemu-qmp-ref.* for a complete command +reference, generated from qapi-schema.json. QMP wiki page - -- 2.13.6
[Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation
The include directive permits modular QAPI schemata, but the generated code is monolithic all the same. To permit generating modular code, the front end needs to pass more information on inclusions to the back ends. The commit before last added the necessary information to the parse tree. This commit adds it to the intermediate representation and its QAPISchemaVisitor. A later commit will use this to to generate modular code. New entity QAPISchemaInclude represents inclusions. Call new visitor method visit_include() for it, so visitors can see the sub-modules a module includes. Note that unlike other entities, QAPISchemaInclude has no name, and is therefore not added to entity_dict. New QAPISchemaEntity attribute @module names the entity's source file. Call new visitor method visit_module() when it changes during a visit, so visitors can keep track of the module being visited. Signed-off-by: Markus Armbruster Reviewed-by: Marc-André Lureau --- scripts/qapi/common.py | 44 tests/qapi-schema/comments.out | 1 + tests/qapi-schema/doc-bad-section.out| 1 + tests/qapi-schema/doc-good.out | 1 + tests/qapi-schema/event-case.out | 1 + tests/qapi-schema/ident-with-escape.out | 1 + tests/qapi-schema/include-relpath.out| 5 tests/qapi-schema/include-repetition.out | 10 tests/qapi-schema/include-simple.out | 3 +++ tests/qapi-schema/indented-expr.out | 1 + tests/qapi-schema/qapi-schema-test.out | 1 + tests/qapi-schema/test-qapi.py | 7 + 12 files changed, 71 insertions(+), 5 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index b531ab519f..29d98ca934 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -985,8 +985,9 @@ def check_exprs(exprs): class QAPISchemaEntity(object): def __init__(self, name, info, doc): -assert isinstance(name, str) +assert name is None or isinstance(name, str) self.name = name +self.module = None # For explicitly defined entities, info points to the (explicit) # definition. For builtins (and their arrays), info is None. # For implicitly defined entities, info points to a place that @@ -1015,10 +1016,16 @@ class QAPISchemaVisitor(object): def visit_end(self): pass +def visit_module(self, fname): +pass + def visit_needed(self, entity): # Default to visiting everything return True +def visit_include(self, fname, info): +pass + def visit_builtin_type(self, name, info, json_type): pass @@ -1045,6 +1052,16 @@ class QAPISchemaVisitor(object): pass +class QAPISchemaInclude(QAPISchemaEntity): + +def __init__(self, fname, info): +QAPISchemaEntity.__init__(self, None, info, None) +self.fname = fname + +def visit(self, visitor): +visitor.visit_include(self.fname, self.info) + + class QAPISchemaType(QAPISchemaEntity): # Return the C type for common use. # For the types we commonly box, this is a pointer type. @@ -1472,6 +1489,7 @@ class QAPISchemaEvent(QAPISchemaEntity): class QAPISchema(object): def __init__(self, fname): +self._fname = fname parser = QAPISchemaParser(open(fname, 'r')) exprs = check_exprs(parser.exprs) self.docs = parser.docs @@ -1479,16 +1497,19 @@ class QAPISchema(object): self._entity_dict = {} self._predefining = True self._def_predefineds() -self._predefining = False self._def_exprs(exprs) self.check() def _def_entity(self, ent): # Only the predefined types are allowed to not have info assert ent.info or self._predefining -assert ent.name not in self._entity_dict +assert ent.name is None or ent.name not in self._entity_dict self._entity_list.append(ent) -self._entity_dict[ent.name] = ent +if ent.name is not None: +self._entity_dict[ent.name] = ent +if ent.info: +ent.module = os.path.relpath(ent.info['file'], + os.path.dirname(self._fname)) def lookup_entity(self, name, typ=None): ent = self._entity_dict.get(name) @@ -1499,6 +1520,15 @@ class QAPISchema(object): def lookup_type(self, name): return self.lookup_entity(name, QAPISchemaType) +def _def_include(self, expr, info, doc): +include = expr['include'] +assert doc is None +main_info = info +while main_info['parent']: +main_info = main_info['parent'] +fname = os.path.relpath(include, os.path.dirname(main_info['file'])) +self._def_entity(QAPISchemaInclude(fname, info)) + def _def_builtin_type(self, name, json_type, c_type): self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type)) # TO
[Qemu-devel] [PATCH v2 02/29] qapi: Streamline boilerplate comment generation
Every generator has separate boilerplate for .h and .c, and their differences are boring. All of them repeat the license note. Reduce the repetition as follows. Move common text like the license note to common open_output(), next to the existing common text there. For each generator, replace the two separate descriptions by a single one. While there, emit an "automatically generated" note into generated documentation, too. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Marc-André Lureau --- scripts/qapi-commands.py| 26 +++--- scripts/qapi-event.py | 26 +++--- scripts/qapi-introspect.py | 21 ++--- scripts/qapi-types.py | 26 +++--- scripts/qapi-visit.py | 26 +++--- scripts/qapi.py | 31 ++- scripts/qapi2texi.py| 3 ++- tests/qapi-schema/doc-good.texi | 3 ++- 8 files changed, 36 insertions(+), 126 deletions(-) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index f89d748ba4..8e8da7c796 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -255,38 +255,18 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor): (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line() -c_comment = ''' -/* - * schema-defined QMP->QAPI command dispatch +blurb = ''' + * Schema-defined QAPI/QMP commands * * Copyright IBM, Corp. 2011 * * Authors: * Anthony Liguori - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ -''' -h_comment = ''' -/* - * schema-defined QAPI function prototypes - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ ''' (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, 'qmp-marshal.c', 'qmp-commands.h', -c_comment, h_comment) +blurb) fdef.write(mcgen(''' diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index c710968dc2..2b7d720c08 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -171,38 +171,18 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor): (input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line() -c_comment = ''' -/* - * schema-defined QAPI event functions +blurb = ''' + * Schema-defined QAPI/QMP events * * Copyright (c) 2014 Wenchao Xia * * Authors: * Wenchao Xia - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ -''' -h_comment = ''' -/* - * schema-defined QAPI event functions - * - * Copyright (c) 2014 Wenchao Xia - * - * Authors: - * Wenchao Xia - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ ''' (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, 'qapi-event.c', 'qapi-event.h', -c_comment, h_comment) +blurb) fdef.write(mcgen(''' #include "qemu/osdep.h" diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index 032bcea491..83da2bdb94 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -176,32 +176,15 @@ for o, a in opts: if o in ('-u', '--unmask-non-abi-names'): opt_unmask = True -c_comment = ''' -/* +blurb = ''' * QAPI/QMP schema introspection * * Copyright (C) 2015 Red Hat, Inc. - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ -''' -h_comment = ''' -/* - * QAPI/QMP schema introspection - * - * Copyright (C) 2015 Red Hat, Inc. - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - * - */ ''' (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, 'qmp-introspect.c', 'qmp-introspect.h', -c_comment, h_comment) +blurb) fdef.write(mcgen(''' #include "qemu/osdep.h" diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 7e3051dbb9..86afc57f92 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -250,39 +250,19 @@ for o, a in opts: if o in ('-b', '--builtins'): do_builtins = True -c_comment = ''' -/* - * deallocation functions for schema-defined QAPI types +blurb = ''' + * Schema-defined QAPI types * * Copyright IBM, Corp. 2011 * * Authors: * Anthony Liguori * Michael Roth
[Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed
Signed-off-by: Markus Armbruster --- block.c | 1 - block/qcow2.c | 1 - chardev/char-fe.c | 1 + chardev/char.c | 1 + qom/object_interfaces.c | 1 + scripts/qapi-visit.py | 2 +- 6 files changed, 4 insertions(+), 3 deletions(-) diff --git a/block.c b/block.c index f94585b230..05a484b4b8 100644 --- a/block.c +++ b/block.c @@ -32,7 +32,6 @@ #include "qemu/module.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" -#include "qapi/qmp/qerror.h" #include "qapi/qmp/qjson.h" #include "qapi/qmp/qstring.h" #include "sysemu/block-backend.h" diff --git a/block/qcow2.c b/block/qcow2.c index a64a572785..9245deac19 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -30,7 +30,6 @@ #include "block/qcow2.h" #include "qemu/error-report.h" #include "qapi/error.h" -#include "qapi/qmp/qerror.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" #include "qapi-event.h" diff --git a/chardev/char-fe.c b/chardev/char-fe.c index c611b3fa3e..e5f870e4d2 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qapi/error.h" +#include "qapi/qmp/qerror.h" #include "qapi-visit.h" #include "sysemu/replay.h" diff --git a/chardev/char.c b/chardev/char.c index 01d979a1da..c9a4da5516 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -32,6 +32,7 @@ #include "qmp-commands.h" #include "qapi-visit.h" #include "qapi/error.h" +#include "qapi/qmp/qerror.h" #include "sysemu/replay.h" #include "qemu/help_option.h" #include "qemu/option.h" diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c index 80d09139be..43d9aa0946 100644 --- a/qom/object_interfaces.c +++ b/qom/object_interfaces.c @@ -1,6 +1,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" +#include "qapi/qmp/qerror.h" #include "qom/object_interfaces.h" #include "qemu/module.h" #include "qemu/option.h" diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 7e1cfc13f0..bc2b8b581a 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -371,13 +371,13 @@ fdef.write(mcgen(''' #include "qemu/osdep.h" #include "qemu-common.h" #include "qapi/error.h" +#include "qapi/qmp/qerror.h" #include "%(prefix)sqapi-visit.h" ''', prefix=prefix)) fdecl.write(mcgen(''' #include "qapi/visitor.h" -#include "qapi/qmp/qerror.h" #include "%(prefix)sqapi-types.h" ''', -- 2.13.6
[Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated
We used to generate first test and later QGA QAPI code into qapi-generated/. Commit b93b63f574 moved the test code to tests/. Commit 54c2e50205 moved the QGA code to qga/qapi-generated/. The directory has been unused since. Signed-off-by: Markus Armbruster --- .gitignore | 1 - Makefile | 1 - configure | 1 - 3 files changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index dabfe6bea8..4055e12ee8 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,6 @@ /libuser /linux-headers/asm /qga/qapi-generated -/qapi-generated /qapi-gen-timestamp /qapi/qapi-builtin-types.[ch] /qapi/qapi-builtin-visit.[ch] diff --git a/Makefile b/Makefile index 84411ee6ab..7eb1ede6f4 100644 --- a/Makefile +++ b/Makefile @@ -726,7 +726,6 @@ clean: rm -f trace/generated-tracers-dtrace.h* rm -f $(foreach f,$(GENERATED_FILES),$(f) $(f)-timestamp) rm -f qapi-gen-timestamp - rm -rf qapi-generated rm -rf qga/qapi-generated for d in $(ALL_SUBDIRS); do \ if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ diff --git a/configure b/configure index 62562f08cf..f564a1639e 100755 --- a/configure +++ b/configure @@ -7015,7 +7015,6 @@ DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-sche DIRS="$DIRS docs docs/interop fsdev scsi" DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw" DIRS="$DIRS roms/seabios roms/vgabios" -DIRS="$DIRS qapi-generated" FILES="Makefile tests/tcg/Makefile qdict-test-data.txt" FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit" FILES="$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile" -- 2.13.6
[Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse
argparse is nicer to use than getopt, and gives us --help almost for free. Signed-off-by: Markus Armbruster --- scripts/qapi-gen.py| 48 ++-- scripts/qapi/common.py | 43 --- 2 files changed, 30 insertions(+), 61 deletions(-) diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py index 2100ca1145..e5be484e3e 100755 --- a/scripts/qapi-gen.py +++ b/scripts/qapi-gen.py @@ -4,8 +4,11 @@ # This work is licensed under the terms of the GNU GPL, version 2 or later. # See the COPYING file in the top-level directory. +from __future__ import print_function +import argparse +import re import sys -from qapi.common import parse_command_line, QAPISchema +from qapi.common import QAPISchema from qapi.types import gen_types from qapi.visit import gen_visit from qapi.commands import gen_commands @@ -15,26 +18,35 @@ from qapi.doc import gen_doc def main(argv): -(input_file, output_dir, prefix, opts) = \ -parse_command_line('bu', ['builtins', 'unmask-non-abi-names']) +parser = argparse.ArgumentParser( +description='Generate code from a QAPI schema') +parser.add_argument('-b', '--builtins', action='store_true', +help="generate code for built-in types") +parser.add_argument('-o', '--output_dir', action='store', default='', +help="write output to directory OUTPUT_DIR") +parser.add_argument('-p', '--prefix', action='store', default='', +help="prefix for symbols") +parser.add_argument('-u', '--unmask-non-abi-names', action='store_true', +dest='unmask', +help="expose non-ABI names in introspection") +parser.add_argument('schema', action='store') +args = parser.parse_args() -opt_builtins = False -opt_unmask = False +match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', args.prefix) +if match.end() != len(args.prefix): +print("%s: 'funny character '%s' in argument of --prefix" + % (sys.argv[0], args.prefix[match.end()]), + file=sys.stderr) +sys.exit(1) -for o, a in opts: -if o in ('-b', '--builtins'): -opt_builtins = True -if o in ('-u', '--unmask-non-abi-names'): -opt_unmask = True +schema = QAPISchema(args.schema) -schema = QAPISchema(input_file) - -gen_types(schema, output_dir, prefix, opt_builtins) -gen_visit(schema, output_dir, prefix, opt_builtins) -gen_commands(schema, output_dir, prefix) -gen_events(schema, output_dir, prefix) -gen_introspect(schema, output_dir, prefix, opt_unmask) -gen_doc(schema, output_dir, prefix) +gen_types(schema, args.output_dir, args.prefix, args.builtins) +gen_visit(schema, args.output_dir, args.prefix, args.builtins) +gen_commands(schema, args.output_dir, args.prefix) +gen_events(schema, args.output_dir, args.prefix) +gen_introspect(schema, args.output_dir, args.prefix, args.unmask) +gen_doc(schema, args.output_dir, args.prefix) if __name__ == '__main__': diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 868ec25deb..8290795dc1 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -13,7 +13,6 @@ from __future__ import print_function import errno -import getopt import os import re import string @@ -1924,48 +1923,6 @@ def build_params(arg_type, boxed, extra): # -# Common command line parsing -# - - -def parse_command_line(extra_options='', extra_long_options=[]): - -try: -opts, args = getopt.gnu_getopt(sys.argv[1:], - 'p:o:' + extra_options, - ['prefix=', 'output-dir='] - + extra_long_options) -except getopt.GetoptError as err: -print("%s: %s" % (sys.argv[0], str(err)), file=sys.stderr) -sys.exit(1) - -output_dir = '' -prefix = '' -extra_opts = [] - -for oa in opts: -o, a = oa -if o in ('-p', '--prefix'): -match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', a) -if match.end() != len(a): -print("%s: 'funny character '%s' in argument of --prefix" \ - % (sys.argv[0], a[match.end()]), file=sys.stderr) -sys.exit(1) -prefix = a -elif o in ('-o', '--output-dir'): -output_dir = a + '/' -else: -extra_opts.append(oa) - -if len(args) != 1: -print("%s: need exactly one argument" % sys.argv[0], file=sys.stderr) -sys.exit(1) -fname = args[0] - -return (fname, output_dir, prefix, extra_opts) - - -# # Accumulate and write output # -- 2.13.6
[Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c
All generated .c are named like their .h, except for qmp-marshal.c and qmp-commands.h. To add to the confusion, tests-qmp-commands.c falsely matches generated test-qmp-commands.h. Get rid of this unnecessary complication. Signed-off-by: Markus Armbruster --- .gitignore | 3 +-- Makefile | 6 +++--- Makefile.objs | 2 +- docs/devel/qapi-code-gen.txt | 6 +++--- qga/Makefile.objs | 2 +- scripts/qapi/commands.py | 2 +- tests/.gitignore | 5 ++--- tests/Makefile.include | 10 +- tests/{test-qmp-commands.c => test-qmp-cmds.c} | 0 9 files changed, 17 insertions(+), 19 deletions(-) rename tests/{test-qmp-commands.c => test-qmp-cmds.c} (100%) diff --git a/.gitignore b/.gitignore index 2f9a92f6cc..7d783e6e66 100644 --- a/.gitignore +++ b/.gitignore @@ -33,9 +33,8 @@ /qapi-visit.[ch] /qapi-event.[ch] /qapi-doc.texi -/qmp-commands.h +/qmp-commands.[ch] /qmp-introspect.[ch] -/qmp-marshal.c /qemu-doc.html /qemu-doc.info /qemu-doc.txt diff --git a/Makefile b/Makefile index bd781c6aad..164a38578e 100644 --- a/Makefile +++ b/Makefile @@ -91,7 +91,7 @@ include $(SRC_PATH)/rules.mak GENERATED_FILES = qemu-version.h config-host.h qemu-options.def GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h -GENERATED_FILES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c +GENERATED_FILES += qmp-commands.c qapi-types.c qapi-visit.c qapi-event.c GENERATED_FILES += qmp-introspect.h GENERATED_FILES += qmp-introspect.c GENERATED_FILES += qapi-doc.texi @@ -496,7 +496,7 @@ $(SRC_PATH)/scripts/qapi-gen.py qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \ qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \ -qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c \ +qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-commands.c \ qga/qapi-generated/qga-qapi-doc.texi: \ qga/qapi-generated/qapi-gen-timestamp ; qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py) @@ -522,7 +522,7 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \ qapi-types.c qapi-types.h \ qapi-visit.c qapi-visit.h \ -qmp-commands.h qmp-marshal.c \ +qmp-commands.h qmp-commands.c \ qapi-event.c qapi-event.h \ qmp-introspect.h qmp-introspect.c \ qapi-doc.texi: \ diff --git a/Makefile.objs b/Makefile.objs index 2efba6d768..d255aaf194 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -78,7 +78,7 @@ common-obj-$(CONFIG_FDT) += device_tree.o ## # qapi -common-obj-y += qmp-marshal.o +common-obj-y += qmp-commands.o common-obj-y += qmp-introspect.o common-obj-y += qmp.o hmp.o endif diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 1a1cbaea7b..ba1dc73298 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -1147,8 +1147,8 @@ declares qmp_COMMAND() that the user must implement. The following files are generated: -$(prefix)qmp-marshal.c: Command marshal/dispatch functions for each -QMP command defined in the schema +$(prefix)qmp-commands.c: Command marshal/dispatch functions for each + QMP command defined in the schema $(prefix)qmp-commands.h: Function prototypes for the QMP commands specified in the schema @@ -1170,7 +1170,7 @@ Example: void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp); #endif -$ cat qapi-generated/example-qmp-marshal.c +$ cat qapi-generated/example-qmp-commands.c [Uninteresting stuff omitted...] static void qmp_marshal_output_UserDefOne(UserDefOne *ret_in, QObject **ret_out, Error **errp) diff --git a/qga/Makefile.objs b/qga/Makefile.objs index 1c5986c0bb..6151378ae4 100644 --- a/qga/Makefile.objs +++ b/qga/Makefile.objs @@ -3,6 +3,6 @@ qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o qga-obj-$(CONFIG_WIN32) += vss-win32.o qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o -qga-obj-y += qapi-generated/qga-qmp-marshal.o +qga-obj-y += qapi-generated/qga-qmp-commands.o qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/ diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index a744611d58..05fe33a03b 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -289,5 +289,5 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); schema.visit(vis) genc.add(vis.defn) genh.add(vis.decl) -genc.write(output_dir, prefix + 'qmp-marshal.c') +genc.write(output_dir, prefix + 'qmp-commands.c') genh.write(output_dir, prefi
[Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files
Move qapi-schema.json to qapi/, so it's next to its modules, and all files get generated to qapi/, not just the ones generated for modules. Consistently name the generated files qapi-MODULE.EXT: qmp-commands.[ch] become qapi-commands.[ch], qapi-event.[ch] become qapi-events.[ch], and qmp-introspect.[ch] become qapi-introspect.[ch]. This gets rid of the temporary hacks in scripts/qapi/commands.py and scripts/qapi/events.py. Signed-off-by: Markus Armbruster --- .gitignore| 16 ++-- Makefile | 42 +++ Makefile.objs | 21 backends/hostmem.c| 2 +- docs/devel/qapi-code-gen.txt | 30 +++--- docs/devel/writing-qmp-commands.txt | 2 +- docs/interop/qmp-intro.txt| 2 +- hmp.c | 2 +- include/qapi/qmp/qobject.h| 2 +- include/qapi/visitor.h| 2 +- include/qom/object.h | 2 +- monitor.c | 6 ++--- net/filter-buffer.c | 2 +- qapi/misc.json| 4 +-- qapi-schema.json => qapi/qapi-schema.json | 32 +++ qga/Makefile.objs | 2 +- qga/commands-posix.c | 2 +- qga/commands-win32.c | 2 +- qga/commands.c| 2 +- qga/main.c| 2 +- qom/object.c | 2 +- scripts/qapi/commands.py | 7 -- scripts/qapi/events.py| 9 +-- scripts/qapi/introspect.py| 4 +-- scripts/qapi/types.py | 6 ++--- scripts/qapi/visit.py | 6 ++--- tests/.gitignore | 6 ++--- tests/Makefile.include| 14 +-- tests/test-qmp-cmds.c | 2 +- tests/test-qmp-event.c| 2 +- tests/test-qobject-input-visitor.c| 6 ++--- tpm.c | 1 - ui/cocoa.m| 2 +- ui/vnc.c | 2 +- 34 files changed, 116 insertions(+), 130 deletions(-) rename qapi-schema.json => qapi/qapi-schema.json (85%) diff --git a/.gitignore b/.gitignore index 7f162e862f..dabfe6bea8 100644 --- a/.gitignore +++ b/.gitignore @@ -29,8 +29,8 @@ /qga/qapi-generated /qapi-generated /qapi-gen-timestamp -/qapi-builtin-types.[ch] -/qapi-builtin-visit.[ch] +/qapi/qapi-builtin-types.[ch] +/qapi/qapi-builtin-visit.[ch] /qapi/qapi-commands-block-core.[ch] /qapi/qapi-commands-block.[ch] /qapi/qapi-commands-char.[ch] @@ -47,6 +47,7 @@ /qapi/qapi-commands-trace.[ch] /qapi/qapi-commands-transaction.[ch] /qapi/qapi-commands-ui.[ch] +/qapi/qapi-commands.[ch] /qapi/qapi-events-block-core.[ch] /qapi/qapi-events-block.[ch] /qapi/qapi-events-char.[ch] @@ -63,6 +64,8 @@ /qapi/qapi-events-trace.[ch] /qapi/qapi-events-transaction.[ch] /qapi/qapi-events-ui.[ch] +/qapi/qapi-events.[ch] +/qapi/qapi-introspect.[ch] /qapi/qapi-types-block-core.[ch] /qapi/qapi-types-block.[ch] /qapi/qapi-types-char.[ch] @@ -79,7 +82,7 @@ /qapi/qapi-types-trace.[ch] /qapi/qapi-types-transaction.[ch] /qapi/qapi-types-ui.[ch] -/qapi-types.[ch] +/qapi/qapi-types.[ch] /qapi/qapi-visit-block-core.[ch] /qapi/qapi-visit-block.[ch] /qapi/qapi-visit-char.[ch] @@ -96,11 +99,8 @@ /qapi/qapi-visit-trace.[ch] /qapi/qapi-visit-transaction.[ch] /qapi/qapi-visit-ui.[ch] -/qapi-visit.[ch] -/qapi-event.[ch] -/qapi-doc.texi -/qmp-commands.[ch] -/qmp-introspect.[ch] +/qapi/qapi-visit.[ch] +/qapi/qapi-doc.texi /qemu-doc.html /qemu-doc.info /qemu-doc.txt diff --git a/Makefile b/Makefile index 50eb194877..84411ee6ab 100644 --- a/Makefile +++ b/Makefile @@ -90,8 +90,8 @@ endif include $(SRC_PATH)/rules.mak GENERATED_FILES = qemu-version.h config-host.h qemu-options.def -GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c -GENERATED_FILES += qapi-types.h qapi-types.c +GENERATED_FILES += qapi/qapi-builtin-types.h qapi/qapi-builtin-types.c +GENERATED_FILES += qapi/qapi-types.h qapi/qapi-types.c GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c GENERATED_FILES += qapi/qapi-types-block.h qapi/qapi-types-block.c GENERATED_FILES += qapi/qapi-types-char.h qapi/qapi-types-char.c @@ -108,8 +108,8 @@ GENERATED_FILES += qapi/qapi-types-tpm.h qapi/qapi-types-tpm.c GENERATED_FILES += qapi/qapi-types-trace.h qapi/qapi-types-trace.c GENERATED_FILES += qapi/qapi-types-transaction.h qapi/qapi-types-transaction.c GENERATED_FILES += qapi/qapi-types-ui.h qapi/qapi-types-ui.c -GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c -GENERATED_FILES += qapi-visit.h qapi-visit.c +GENERATED_FILES += qapi/qapi-builtin-visit.h qapi/qapi-builtin-
[Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc
These classes encapsulate accumulating and writing output. Convert C code generation to QAPIGenC and QAPIGenH. The conversion is rather shallow: most of the output accumulation is not converted. Left for later. The indentation machinery uses a single global variable indent_level, even though we generally interleave creation of a .c and its .h. It should become instance variable of QAPIGenC. Also left for later. Documentation generation isn't converted, and QAPIGenDoc isn't used. This will change shortly. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Marc-André Lureau --- scripts/qapi-commands.py | 23 +-- scripts/qapi-event.py | 22 ++- scripts/qapi-introspect.py | 18 + scripts/qapi-types.py | 22 ++- scripts/qapi-visit.py | 22 ++- scripts/qapi.py| 99 +- 6 files changed, 112 insertions(+), 94 deletions(-) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index c3aa52fce1..8d38ade076 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -260,12 +260,10 @@ blurb = ''' * Schema-defined QAPI/QMP commands ''' -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, -'qmp-marshal.c', 'qmp-commands.h', -blurb, __doc__) - -fdef.write(mcgen(''' +genc = QAPIGenC(blurb, __doc__) +genh = QAPIGenH(blurb, __doc__) +genc.add(mcgen(''' #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/module.h" @@ -280,20 +278,23 @@ fdef.write(mcgen(''' #include "%(prefix)sqmp-commands.h" ''', - prefix=prefix)) + prefix=prefix)) -fdecl.write(mcgen(''' +genh.add(mcgen(''' #include "%(prefix)sqapi-types.h" #include "qapi/qmp/dispatch.h" void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); ''', - prefix=prefix, c_prefix=c_name(prefix, protect=False))) + prefix=prefix, c_prefix=c_name(prefix, protect=False))) schema = QAPISchema(input_file) vis = QAPISchemaGenCommandVisitor() schema.visit(vis) -fdef.write(vis.defn) -fdecl.write(vis.decl) +genc.add(vis.defn) +genh.add(vis.decl) -close_output(fdef, fdecl) +if do_c: +genc.write(output_dir, prefix + 'qmp-marshal.c') +if do_h: +genh.write(output_dir, prefix + 'qmp-commands.h') diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index edb9ddb650..bd7a9be3dc 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -176,11 +176,10 @@ blurb = ''' * Schema-defined QAPI/QMP events ''' -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, -'qapi-event.c', 'qapi-event.h', -blurb, __doc__) +genc = QAPIGenC(blurb, __doc__) +genh = QAPIGenH(blurb, __doc__) -fdef.write(mcgen(''' +genc.add(mcgen(''' #include "qemu/osdep.h" #include "qemu-common.h" #include "%(prefix)sqapi-event.h" @@ -191,21 +190,24 @@ fdef.write(mcgen(''' #include "qapi/qmp-event.h" ''', - prefix=prefix)) + prefix=prefix)) -fdecl.write(mcgen(''' +genh.add(mcgen(''' #include "qapi/util.h" #include "%(prefix)sqapi-types.h" ''', - prefix=prefix)) + prefix=prefix)) event_enum_name = c_name(prefix + 'QAPIEvent', protect=False) schema = QAPISchema(input_file) vis = QAPISchemaGenEventVisitor() schema.visit(vis) -fdef.write(vis.defn) -fdecl.write(vis.decl) +genc.add(vis.defn) +genh.add(vis.decl) -close_output(fdef, fdecl) +if do_c: +genc.write(output_dir, prefix + 'qapi-event.c') +if do_h: +genh.write(output_dir, prefix + 'qapi-event.h') diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index ebe8706f41..3d65690fe3 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -181,21 +181,23 @@ blurb = ''' * QAPI/QMP schema introspection ''' -(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, -'qmp-introspect.c', 'qmp-introspect.h', -blurb, __doc__) +genc = QAPIGenC(blurb, __doc__) +genh = QAPIGenH(blurb, __doc__) -fdef.write(mcgen(''' +genc.add(mcgen(''' #include "qemu/osdep.h" #include "%(prefix)sqmp-introspect.h" ''', - prefix=prefix)) + prefix=prefix)) schema = QAPISchema(input_file) vis = QAPISchemaGenIntrospectVisitor(opt_unmask) schema.visit(vis) -fdef.write(vis.defn) -fdecl.write(vis.decl) +genc.add(vis.defn) +genh.add(vis.decl) -close_output(fdef, fdecl) +if do_c: +genc.write(output_dir, prefix + 'qmp-introspect.c') +if do_h: +genh.write(output_dir, prefix + 'qmp-introspect.h') diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 4db8424da1..c0ac879beb 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -180,7 +180,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor): self.decl = '' self.defn = '' self._fw
[Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files
Linking code from multiple separate QAPI schemata into the same program is possible, but involves some weirdness around built-in types: * We generate code for built-in types into .c only with option --builtins. The user is responsible for generating code for exactly one QAPI schema per program with --builtins. * We generate code for built-in types into .h regardless of --builtins, but guarded by #ifndef QAPI_VISIT_BUILTIN. Because all copies of this code are exactly the same, including any combination of these headers works. Replace this contraption by something more conventional: generate code for built-in types into their very own files: qapi-builtin-types.c, qapi-builtin-visit.c, qapi-builtin-types.h, qapi-builtin-visit.h, but only with --builtins. Obey --output-dir, but ignore --prefix for them. Make qapi-types.h include qapi-builtin-types.h. With multiple schemata you now have multiple qapi-types.[ch], but only one qapi-builtin-types.[ch]. Same for qapi-visit.[ch] and qapi-builtin-visit.[ch]. Bonus: if all you need is built-in stuff, you can include a much smaller header. To be exploited shortly. Signed-off-by: Markus Armbruster --- .gitignore | 2 ++ Makefile | 13 ++ Makefile.objs | 2 ++ scripts/qapi/common.py | 61 --- scripts/qapi/types.py | 61 +++ scripts/qapi/visit.py | 64 +- 6 files changed, 116 insertions(+), 87 deletions(-) diff --git a/.gitignore b/.gitignore index 7d783e6e66..9477a08b6b 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,8 @@ /qga/qapi-generated /qapi-generated /qapi-gen-timestamp +/qapi-builtin-types.[ch] +/qapi-builtin-visit.[ch] /qapi-types.[ch] /qapi-visit.[ch] /qapi-event.[ch] diff --git a/Makefile b/Makefile index 164a38578e..60ddc9c945 100644 --- a/Makefile +++ b/Makefile @@ -90,10 +90,13 @@ endif include $(SRC_PATH)/rules.mak GENERATED_FILES = qemu-version.h config-host.h qemu-options.def -GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h -GENERATED_FILES += qmp-commands.c qapi-types.c qapi-visit.c qapi-event.c -GENERATED_FILES += qmp-introspect.h -GENERATED_FILES += qmp-introspect.c +GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c +GENERATED_FILES += qapi-types.h qapi-types.c +GENERATED_FILES += qapi-builtin-visit.h qapi-builtin-visit.c +GENERATED_FILES += qapi-visit.h qapi-visit.c +GENERATED_FILES += qmp-commands.h qmp-commands.c +GENERATED_FILES += qapi-event.h qapi-event.c +GENERATED_FILES += qmp-introspect.c qmp-introspect.h GENERATED_FILES += qapi-doc.texi GENERATED_FILES += trace/generated-tcg-tracers.h @@ -520,7 +523,9 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \ $(SRC_PATH)/qapi/transaction.json \ $(SRC_PATH)/qapi/ui.json +qapi-builtin-types.c qapi-builtin-types.h \ qapi-types.c qapi-types.h \ +qapi-builtin-visit.c qapi-builtin-visit.h \ qapi-visit.c qapi-visit.h \ qmp-commands.h qmp-commands.c \ qapi-event.c qapi-event.h \ diff --git a/Makefile.objs b/Makefile.objs index d255aaf194..2813e984fd 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -2,6 +2,8 @@ # Common libraries for tools and emulators stub-obj-y = stubs/ crypto/ util-obj-y = util/ qobject/ qapi/ +util-obj-y += qapi-builtin-types.o +util-obj-y += qapi-builtin-visit.o util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o chardev-obj-y = chardev/ diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 31d2f73e7e..de12f8469a 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1531,11 +1531,10 @@ class QAPISchema(object): def _def_builtin_type(self, name, json_type, c_type): self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type)) -# TODO As long as we have QAPI_TYPES_BUILTIN to share multiple -# qapi-types.h from a single .c, all arrays of builtins must be -# declared in the first file whether or not they are used. Nicer -# would be to use lazy instantiation, while figuring out how to -# avoid compilation issues with multiple qapi-types.h. +# Instantiating only the arrays that are actually used would +# be nice, but we can't as long as their generated code +# (qapi-builtin-types.[ch]) may be shared by some other +# schema. self._make_array_type(name, None) def _def_predefineds(self): @@ -1992,14 +1991,15 @@ class QAPIGen(object): return '' def write(self, output_dir, fname): -if output_dir: +pathname = os.path.join(output_dir, fname) +dir = os.path.dirname(pathname) +if dir: try: -os.makedirs(output_dir) +os.makedirs(dir) except os.error as e: if e.errno != errno.EEXIST:
[Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more
The use of QAPIGen is rather shallow so far: most of the output accumulation is not converted. Take the next step: convert output accumulation in the code-generating visitor classes. Helper functions outside these classes are not converted. Signed-off-by: Markus Armbruster --- scripts/qapi/commands.py | 71 scripts/qapi/common.py | 13 scripts/qapi/doc.py| 74 -- scripts/qapi/events.py | 55 --- scripts/qapi/introspect.py | 56 +--- scripts/qapi/types.py | 81 +++--- scripts/qapi/visit.py | 80 +++-- 7 files changed, 188 insertions(+), 242 deletions(-) diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 05fe33a03b..46757db771 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -223,44 +223,15 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) return ret -class QAPISchemaGenCommandVisitor(QAPISchemaVisitor): +class QAPISchemaGenCommandVisitor(QAPISchemaMonolithicCVisitor): + def __init__(self, prefix): -self._prefix = prefix -self.decl = None -self.defn = None -self._regy = None -self._visited_ret_types = None - -def visit_begin(self, schema): -self.decl = '' -self.defn = '' +QAPISchemaMonolithicCVisitor.__init__( +self, prefix, 'qmp-commands', +' * Schema-defined QAPI/QMP commands', __doc__) self._regy = '' self._visited_ret_types = set() - -def visit_end(self): -self.defn += gen_registry(self._regy, self._prefix) -self._regy = None -self._visited_ret_types = None - -def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): -if not gen: -return -self.decl += gen_command_decl(name, arg_type, boxed, ret_type) -if ret_type and ret_type not in self._visited_ret_types: -self._visited_ret_types.add(ret_type) -self.defn += gen_marshal_output(ret_type) -self.decl += gen_marshal_decl(name) -self.defn += gen_marshal(name, arg_type, boxed, ret_type) -self._regy += gen_register_command(name, success_response) - - -def gen_commands(schema, output_dir, prefix): -blurb = ' * Schema-defined QAPI/QMP commands' -genc = QAPIGenC(blurb, __doc__) -genh = QAPIGenH(blurb, __doc__) - -genc.add(mcgen(''' +self._genc.add(mcgen(''' #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/module.h" @@ -275,19 +246,33 @@ def gen_commands(schema, output_dir, prefix): #include "%(prefix)sqmp-commands.h" ''', - prefix=prefix)) - -genh.add(mcgen(''' + prefix=prefix)) +self._genh.add(mcgen(''' #include "%(prefix)sqapi-types.h" #include "qapi/qmp/dispatch.h" void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); ''', - prefix=prefix, c_prefix=c_name(prefix, protect=False))) + prefix=prefix, + c_prefix=c_name(prefix, protect=False))) +def visit_end(self): +self._genc.add(gen_registry(self._regy, self._prefix)) + +def visit_command(self, name, info, arg_type, ret_type, + gen, success_response, boxed): +if not gen: +return +self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type)) +if ret_type and ret_type not in self._visited_ret_types: +self._visited_ret_types.add(ret_type) +self._genc.add(gen_marshal_output(ret_type)) +self._genh.add(gen_marshal_decl(name)) +self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) +self._regy += gen_register_command(name, success_response) + + +def gen_commands(schema, output_dir, prefix): vis = QAPISchemaGenCommandVisitor(prefix) schema.visit(vis) -genc.add(vis.defn) -genh.add(vis.decl) -genc.write(output_dir, prefix + 'qmp-commands.c') -genh.write(output_dir, prefix + 'qmp-commands.h') +vis.write(output_dir) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 29d98ca934..31d2f73e7e 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -2049,3 +2049,16 @@ class QAPIGenDoc(QAPIGen): def _top(self, fname): return (QAPIGen._top(self, fname) + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n') + + +class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor): + +def __init__(self, prefix, what, blurb, pydoc): +self._prefix = prefix +self._what = what +self._genc = QAPIGenC(blurb, pydoc) +self._genh = QAPIGenH(blurb, pydoc) + +def write(self, output_dir): +self._genc.write(output_dir, self.
[Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers
In my "build everything" tree, a change to the types in qapi-schema.json triggers a recompile of about 4800 out of 5100 objects. The previous commit split up qmp-commands.h, qmp-event.h, qmp-visit.h, qapi-types.h. Each of these headers still includes all its shards. Reduce compile time by including just the shards we actually need. To illustrate the benefits: adding a type to qapi/migration.json now recompiles some 2300 instead of 4800 objects. The next commit will improve it further. Signed-off-by: Markus Armbruster --- backends/cryptodev.c | 1 - backends/hostmem.c | 3 ++- block.c | 1 - block/block-backend.c| 2 +- block/crypto.c | 2 +- block/nbd.c | 2 +- block/nfs.c | 2 +- block/qapi.c | 4 ++-- block/qcow2.c| 3 +-- block/quorum.c | 2 +- block/sheepdog.c | 2 +- block/ssh.c | 2 +- block/throttle-groups.c | 2 +- block/write-threshold.c | 4 ++-- blockdev-nbd.c | 2 +- blockdev.c | 5 +++-- blockjob.c | 2 +- chardev/char-fe.c| 1 - chardev/char-ringbuf.c | 2 +- chardev/char-socket.c| 1 + chardev/char.c | 3 +-- cpus.c | 2 +- crypto/cipherpriv.h | 2 +- hmp.c| 2 +- hw/acpi/core.c | 2 +- hw/block/block.c | 1 + hw/block/hd-geometry.c | 1 + hw/char/virtio-console.c | 2 +- hw/core/machine.c| 2 +- hw/i386/pc.c | 2 +- hw/mem/nvdimm.c | 1 - hw/net/rocker/qmp-norocker.c | 2 +- hw/net/rocker/rocker.c | 2 +- hw/net/rocker/rocker_fp.c| 2 +- hw/net/rocker/rocker_of_dpa.c| 2 +- hw/net/virtio-net.c | 2 +- hw/ppc/spapr_rtas.c | 1 - hw/tpm/tpm_emulator.c| 1 + hw/tpm/tpm_passthrough.c | 1 + hw/watchdog/watchdog.c | 2 +- include/block/block.h| 2 +- include/block/dirty-bitmap.h | 2 +- include/block/nbd.h | 2 +- include/chardev/char.h | 1 + include/crypto/cipher.h | 2 +- include/crypto/hash.h| 2 +- include/crypto/hmac.h| 2 +- include/crypto/secret.h | 1 + include/crypto/tlscreds.h| 1 + include/hw/block/block.h | 2 +- include/hw/block/fdc.h | 2 +- include/hw/ppc/spapr_drc.h | 1 + include/hw/qdev-properties.h | 1 + include/io/dns-resolver.h| 1 + include/migration/colo.h | 2 +- include/migration/failover.h | 2 +- include/migration/global_state.h | 1 + include/monitor/monitor.h| 1 + include/net/filter.h | 1 + include/net/net.h| 2 +- include/qapi/clone-visitor.h | 1 - include/qapi/error.h | 2 +- include/qapi/qmp/qobject.h | 2 +- include/qapi/visitor.h | 2 +- include/qemu/sockets.h | 2 +- include/qemu/throttle.h | 2 +- include/qom/cpu.h| 1 + include/qom/object.h | 2 +- include/sysemu/dump.h| 2 ++ include/sysemu/hostmem.h | 1 + include/sysemu/replay.h | 1 + include/sysemu/sysemu.h | 1 + include/sysemu/tpm.h | 1 + include/sysemu/watchdog.h| 2 +- include/ui/input.h | 2 +- io/channel-socket.c | 1 + io/dns-resolver.c| 1 + migration/colo-failover.c| 2 +- migration/colo.c | 2 +- migration/migration.c| 4 ++-- migration/migration.h| 1 + migration/ram.c | 2 +- migration/ram.h | 2 +- net/colo-compare.c | 1 - net/filter-buffer.c | 2 +- net/filter-mirror.c | 1 - net/filter-rewriter.c| 1 - net/net.c| 4 ++-- net/tap_int.h| 2 +- net/vhost-user.c | 2 +- qemu-img.c | 2 +- qom/object.c | 2 +- qom/object_interfaces.c | 1 - replay/replay-input.c| 1 + replication.h| 1 + scripts/qapi/commands.py | 14 -- scripts/qapi/events.py | 10 ++ scripts/qapi/types.py| 8 +--- scripts/qapi/visit.py| 10 ++ stubs/tpm.c | 3 ++- target/s390x/kvm.c | 1 - tests/test-char.c| 2 +- tests/test-qmp-event.c | 1 - tpm.c| 2 +- trace/qmp.c | 2 +- ui/console.c | 2 +-
[Qemu-devel] [PATCH v2 11/29] qapi: Improve include file name reporting in error messages
Error messages print absolute file names of included files even if the user gave a relative one on the command line: $ PYTHONPATH=scripts python -B tests/qapi-schema/test-qapi.py tests/qapi-schema/include-cycle.json In file included from tests/qapi-schema/include-cycle.json:1: In file included from /work/armbru/qemu/tests/qapi-schema/include-cycle-b.json:1: /work/armbru/qemu/tests/qapi-schema/include-cycle-c.json:1: Inclusion loop for include-cycle.json Improve this to In file included from tests/qapi-schema/include-cycle.json:1: In file included from tests/qapi-schema/include-cycle-b.json:1: tests/qapi-schema/include-cycle-c.json:1: Inclusion loop for include-cycle.json The error message when an include file can't be opened prints the include directive's file name, which is relative to the including file. Change this to print the file name relative to the working directory. Visible in tests/qapi-schema/include-no-file.err. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Marc-André Lureau --- scripts/qapi/common.py| 12 ++-- tests/qapi-schema/include-no-file.err | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 2e58573a39..3e92b38ade 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -259,9 +259,8 @@ class QAPIDoc(object): class QAPISchemaParser(object): def __init__(self, fp, previously_included=[], incl_info=None): -abs_fname = os.path.abspath(fp.name) self.fname = fp.name -previously_included.append(abs_fname) +previously_included.append(os.path.abspath(fp.name)) self.incl_info = incl_info self.src = fp.read() if self.src == '' or self.src[-1] != '\n': @@ -292,7 +291,7 @@ class QAPISchemaParser(object): if not isinstance(include, str): raise QAPISemError(info, "Value of 'include' must be a string") -self._include(include, info, os.path.dirname(abs_fname), +self._include(include, info, os.path.dirname(self.fname), previously_included) elif "pragma" in expr: self.reject_expr_doc(cur_doc) @@ -325,7 +324,8 @@ class QAPISchemaParser(object): % doc.symbol) def _include(self, include, info, base_dir, previously_included): -incl_abs_fname = os.path.join(base_dir, include) +incl_fname = os.path.join(base_dir, include) +incl_abs_fname = os.path.abspath(incl_fname) # catch inclusion cycle inf = info while inf: @@ -337,9 +337,9 @@ class QAPISchemaParser(object): if incl_abs_fname in previously_included: return try: -fobj = open(incl_abs_fname, 'r') +fobj = open(incl_fname, 'r') except IOError as e: -raise QAPISemError(info, '%s: %s' % (e.strerror, include)) +raise QAPISemError(info, '%s: %s' % (e.strerror, incl_fname)) exprs_include = QAPISchemaParser(fobj, previously_included, info) self.exprs.extend(exprs_include.exprs) self.docs.extend(exprs_include.docs) diff --git a/tests/qapi-schema/include-no-file.err b/tests/qapi-schema/include-no-file.err index d5b9b22d85..e42bcf4bc1 100644 --- a/tests/qapi-schema/include-no-file.err +++ b/tests/qapi-schema/include-no-file.err @@ -1 +1 @@ -tests/qapi-schema/include-no-file.json:1: No such file or directory: include-no-file-sub.json +tests/qapi-schema/include-no-file.json:1: No such file or directory: tests/qapi-schema/include-no-file-sub.json -- 2.13.6
[Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers
Signed-off-by: Markus Armbruster Reviewed-by: Marc-André Lureau --- scripts/qapi-gen.py| 8 ++-- scripts/qapi/common.py | 23 +-- tests/qapi-schema/test-qapi.py | 10 -- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/scripts/qapi-gen.py b/scripts/qapi-gen.py index e5be484e3e..fea7d4589b 100755 --- a/scripts/qapi-gen.py +++ b/scripts/qapi-gen.py @@ -8,7 +8,7 @@ from __future__ import print_function import argparse import re import sys -from qapi.common import QAPISchema +from qapi.common import QAPIError, QAPISchema from qapi.types import gen_types from qapi.visit import gen_visit from qapi.commands import gen_commands @@ -39,7 +39,11 @@ def main(argv): file=sys.stderr) sys.exit(1) -schema = QAPISchema(args.schema) +try: +schema = QAPISchema(args.schema) +except QAPIError as err: +print(err, file=sys.stderr) +exit(1) gen_types(schema, args.output_dir, args.prefix, args.builtins) gen_visit(schema, args.output_dir, args.prefix, args.builtins) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index d72c339ad5..dce289ae21 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -16,7 +16,6 @@ import errno import os import re import string -import sys try: from collections import OrderedDict except: @@ -1459,19 +1458,15 @@ class QAPISchemaEvent(QAPISchemaEntity): class QAPISchema(object): def __init__(self, fname): -try: -parser = QAPISchemaParser(open(fname, 'r')) -exprs = check_exprs(parser.exprs) -self.docs = parser.docs -self._entity_dict = {} -self._predefining = True -self._def_predefineds() -self._predefining = False -self._def_exprs(exprs) -self.check() -except QAPIError as err: -print(err, file=sys.stderr) -exit(1) +parser = QAPISchemaParser(open(fname, 'r')) +exprs = check_exprs(parser.exprs) +self.docs = parser.docs +self._entity_dict = {} +self._predefining = True +self._def_predefineds() +self._predefining = False +self._def_exprs(exprs) +self.check() def _def_entity(self, ent): # Only the predefined types are allowed to not have info diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index bb1b6dd297..4da14b43af 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -12,7 +12,7 @@ from __future__ import print_function import sys -from qapi.common import QAPISchema, QAPISchemaVisitor +from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor class QAPISchemaTestVisitor(QAPISchemaVisitor): @@ -52,7 +52,13 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): for v in variants.variants: print('case %s: %s' % (v.name, v.type.name)) -schema = QAPISchema(sys.argv[1]) + +try: +schema = QAPISchema(sys.argv[1]) +except QAPIError as err: +print(err, file=sys.stderr) +exit(1) + schema.visit(QAPISchemaTestVisitor()) for doc in schema.docs: -- 2.13.6
[Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code
Our qapi-schema.json is composed of modules connected by include directives, but the generated code is monolithic all the same: one qapi-types.h with all the types, one qapi-visit.h with all the visitors, and so forth. These monolithic headers get included all over the place. In my "build everything" tree, adding a QAPI type recompiles about 4800 out of 5100 objects. We wouldn't write such monolithic headers by hand. It stands to reason that we shouldn't generate them, either. This series' basic idea is to split up generated headers to mirror the schema's modular structure: one header per module. That way, you can include just what you need. The compile-time improvements can be massive. Before this series, any QAPI schema change recompiles some 4800 out of 5100 objects in my "build everything" tree. Afterwards, adding a type to qapi/migration.json recompiles a bit over 100, and a documentation change no longer recompiles anything. Related: Marc-André's 'unit' pragma proposal. That's a different way to split off parts of the generated code, motivated by the desire to use poisoned identifiers such as TARGET_I386. I noted in my review of v3 that I "can either accept it, or come up with a better solution." This is my attempt at a better solution. It's a bit more ambitious, and thus more useful (I hope). The pragma has one theoretical advantage, though: you can modularize the generated output in different ways than the input. The patches using don't do that, however. v2: * Rebased, annoying conflicts due to the Python 2 rigmarole * PATCH 01: New * PATCH 02-03,08,10-11,17,19-24: Commit messages improved [Eric, Marc-André] * PATCH 04: Split off the next patch [Eric] * PATCH 05,07-08,10,19: QAPIGen methods renamed [Marc-André] * PATCH 08,20,22: fix missing .gitignore updates * PATCH 08: - generated doc renamed to qapi-doc.texi - qapi-code-gen.txt updated - useless options -c, -h dropped * PATCH 09: New, replacing old PATCH 07 * PATCH 16: Latent bug in QAPISchema.check() fixed * PATCH 18: New * PATCH 19-20,22-24: - Common code factored out into QAPISchemaMonolithicCVisitor and QAPISchemaModularCVisitor - All code-generating visitors covered - Consistent parameter order prefix, opt_builtins - R-bys dropped * PATCH 25-29: New Markus Armbruster (29): Include qapi/qmp/qerror.h exactly where needed qapi: Streamline boilerplate comment generation qapi: Generate up-to-date copyright notice qapi: Rename variable holding the QAPISchemaGenFOOVisitor qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc qapi: Reduce use of global variables in generators some qapi: Turn generators into modules qapi-gen: New common driver for code and doc generators qapi-gen: Convert from getopt to argparse qapi: Touch generated files only when they change qapi: Improve include file name reporting in error messages qapi/common: Eliminate QAPISchema.exprs qapi: Lift error reporting from QAPISchema.__init__() to callers qapi: Concentrate QAPISchemaParser.exprs updates in .__init__() qapi: Record 'include' directives in parse tree qapi: Generate in source order qapi: Record 'include' directives in intermediate representation qapi: Rename generated qmp-marshal.c to qmp-commands.c qapi: Make code-generating visitors use QAPIGen more qapi/types qapi/visit: Generate built-in stuff into separate files qapi/common: Fix guardname() for funny filenames qapi: Generate separate .h, .c for each module Include less of the generated modular QAPI headers qapi: Empty out qapi-schema.json docs/devel/writing-qmp-commands: Update for modular QAPI docs: Correct outdated information on QAPI qapi: Move qapi-schema.json to qapi/, rename generated files Fix up dangling references to qmp-commands.* in comment and doc qapi: Don't create useless directory qapi-generated .gitignore | 80 - Makefile | 233 ++ Makefile.objs | 80 - arch_init.c| 2 +- backends/cryptodev.c | 1 - backends/hostmem.c | 3 +- balloon.c | 2 +- block.c| 2 - block/block-backend.c | 2 +- block/crypto.c | 2 +- block/iscsi.c | 2 +- block/nbd.c| 2 +- block/nfs.c| 2 +- block/qapi.c | 4 +- block/qcow2.c | 4 +- block/quorum.c | 2 +- block/sheepdog.c | 2 +- block/ssh.c| 2 +- block/throttle-group
[Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree
The parse tree is a list of expressions. Except include expressions currently get replaced by the included file's parse tree. Instead of throwing away the include expression, keep it with the file name expanded so you don't have to track the including file's directory to make sense of it. A future commit will put this include expression to use. Signed-off-by: Markus Armbruster Reviewed-by: Marc-André Lureau --- scripts/qapi/common.py | 21 + 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index cc5a5941dd..6d49709784 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -290,8 +290,11 @@ class QAPISchemaParser(object): if not isinstance(include, str): raise QAPISemError(info, "Value of 'include' must be a string") -exprs_include = self._include(include, info, - os.path.dirname(self.fname), +incl_fname = os.path.join(os.path.dirname(self.fname), + include) +self.exprs.append({'expr': {'include': incl_fname}, + 'info': info}) +exprs_include = self._include(include, info, incl_fname, previously_included) if exprs_include: self.exprs.extend(exprs_include.exprs) @@ -326,8 +329,7 @@ class QAPISchemaParser(object): "Documentation for '%s' is not followed by the definition" % doc.symbol) -def _include(self, include, info, base_dir, previously_included): -incl_fname = os.path.join(base_dir, include) +def _include(self, include, info, incl_fname, previously_included): incl_abs_fname = os.path.abspath(incl_fname) # catch inclusion cycle inf = info @@ -893,6 +895,9 @@ def check_exprs(exprs): info = expr_elem['info'] doc = expr_elem.get('doc') +if 'include' in expr: +continue + if not doc and doc_required: raise QAPISemError(info, "Expression missing documentation comment") @@ -931,6 +936,9 @@ def check_exprs(exprs): # Try again for hidden UnionKind enum for expr_elem in exprs: +if 'include' in expr: +continue + expr = expr_elem['expr'] if 'union' in expr and not discriminator_find_enum_define(expr): name = '%sKind' % expr['union'] @@ -943,6 +951,9 @@ def check_exprs(exprs): # Validate that exprs make sense for expr_elem in exprs: +if 'include' in expr: +continue + expr = expr_elem['expr'] info = expr_elem['info'] doc = expr_elem.get('doc') @@ -1667,6 +1678,8 @@ class QAPISchema(object): self._def_command(expr, info, doc) elif 'event' in expr: self._def_event(expr, info, doc) +elif 'include' in expr: +pass else: assert False -- 2.13.6
Re: [Qemu-devel] [PATCH 0/3] QAPI file renames
Eric Blake writes: > This has been mentioned on list before as a possible improvement, > so I went ahead and did some renames to figure out how it would > look. Patch 1 is something I hit on the way while debugging > patch 2 and 3; patch 2 is rather non-controversial, and patch 3 > may or may not be worth doing (but if we do it, it is going > to cause a lot of rebase churn to anyone editing files in the > meantime, although git rename detection will probably get things > right more often than not). Conflicts with my "[PATCH v2 00/29] Modularize generated QAPI code". Your series is much smaller. Would you mind rebasing it?
[Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order
The generators' conversion to visitors (merge commit 9e72681d16) changed the processing order of entities from source order to alphabetical order. The next commit needs source order, so change it back. Signed-off-by: Markus Armbruster Reviewed-by: Marc-André Lureau --- scripts/qapi/common.py | 6 +- tests/qapi-schema/comments.out | 2 +- tests/qapi-schema/doc-bad-section.out| 4 +- tests/qapi-schema/doc-good.out | 32 ++-- tests/qapi-schema/empty.out | 2 +- tests/qapi-schema/event-case.out | 2 +- tests/qapi-schema/ident-with-escape.out | 6 +- tests/qapi-schema/include-relpath.out| 2 +- tests/qapi-schema/include-repetition.out | 2 +- tests/qapi-schema/include-simple.out | 2 +- tests/qapi-schema/indented-expr.out | 2 +- tests/qapi-schema/qapi-schema-test.out | 320 +++ 12 files changed, 192 insertions(+), 190 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 6d49709784..b531ab519f 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1475,6 +1475,7 @@ class QAPISchema(object): parser = QAPISchemaParser(open(fname, 'r')) exprs = check_exprs(parser.exprs) self.docs = parser.docs +self._entity_list = [] self._entity_dict = {} self._predefining = True self._def_predefineds() @@ -1486,6 +1487,7 @@ class QAPISchema(object): # Only the predefined types are allowed to not have info assert ent.info or self._predefining assert ent.name not in self._entity_dict +self._entity_list.append(ent) self._entity_dict[ent.name] = ent def lookup_entity(self, name, typ=None): @@ -1684,12 +1686,12 @@ class QAPISchema(object): assert False def check(self): -for (name, ent) in sorted(self._entity_dict.items()): +for ent in self._entity_list: ent.check(self) def visit(self, visitor): visitor.visit_begin(self) -for (name, entity) in sorted(self._entity_dict.items()): +for entity in self._entity_list: if visitor.visit_needed(entity): entity.visit(visitor) visitor.visit_end() diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out index 17e652535c..0261ddf202 100644 --- a/tests/qapi-schema/comments.out +++ b/tests/qapi-schema/comments.out @@ -1,4 +1,4 @@ +object q_empty enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool'] prefix QTYPE enum Status ['good', 'bad', 'ugly'] -object q_empty diff --git a/tests/qapi-schema/doc-bad-section.out b/tests/qapi-schema/doc-bad-section.out index 089bde1381..23bf8c71ab 100644 --- a/tests/qapi-schema/doc-bad-section.out +++ b/tests/qapi-schema/doc-bad-section.out @@ -1,7 +1,7 @@ -enum Enum ['one', 'two'] +object q_empty enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool'] prefix QTYPE -object q_empty +enum Enum ['one', 'two'] doc symbol=Enum body= == Produces *invalid* texinfo diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out index 1d2c250527..0c07301f07 100644 --- a/tests/qapi-schema/doc-good.out +++ b/tests/qapi-schema/doc-good.out @@ -1,35 +1,35 @@ +object q_empty +enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool'] +prefix QTYPE +enum Enum ['one', 'two'] object Base member base1: Enum optional=False -enum Enum ['one', 'two'] +object Variant1 +member var1: str optional=False +object Variant2 object Object base Base tag base1 case one: Variant1 case two: Variant2 -enum QType ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist', 'qbool'] -prefix QTYPE +object q_obj_Variant1-wrapper +member data: Variant1 optional=False +object q_obj_Variant2-wrapper +member data: Variant2 optional=False +enum SugaredUnionKind ['one', 'two'] object SugaredUnion member type: SugaredUnionKind optional=False tag type case one: q_obj_Variant1-wrapper case two: q_obj_Variant2-wrapper -enum SugaredUnionKind ['one', 'two'] -object Variant1 -member var1: str optional=False -object Variant2 -command cmd q_obj_cmd-arg -> Object - gen=True success_response=True boxed=False -command cmd-boxed Object -> None - gen=True success_response=True boxed=True -object q_empty -object q_obj_Variant1-wrapper -member data: Variant1 optional=False -object q_obj_Variant2-wrapper -member data: Variant2 optional=False object q_obj_cmd-arg member arg1: int optional=False member arg2: str optional=True member arg3: bool optional=False +command cmd q_obj_cmd-arg -> Object + gen=True success_response=True boxed=False +command cmd-boxed Object -> None + gen=True success_response=True boxed=True doc freeform body= = Section diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out in
[Qemu-devel] [PATCH v2 06/29] qapi: Reduce use of global variables in generators some
In preparation of the next commit, which will turn the generators into modules. These global variables will become local to main() then. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Marc-André Lureau --- scripts/qapi-commands.py | 9 + scripts/qapi-event.py | 15 +++ scripts/qapi-introspect.py | 7 --- scripts/qapi-types.py | 17 + scripts/qapi-visit.py | 17 + 5 files changed, 34 insertions(+), 31 deletions(-) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index 8d38ade076..e97e16e828 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -207,7 +207,7 @@ def gen_register_command(name, success_response): return ret -def gen_registry(registry): +def gen_registry(registry, prefix): ret = mcgen(''' void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) @@ -224,7 +224,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) class QAPISchemaGenCommandVisitor(QAPISchemaVisitor): -def __init__(self): +def __init__(self, prefix): +self._prefix = prefix self.decl = None self.defn = None self._regy = None @@ -237,7 +238,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor): self._visited_ret_types = set() def visit_end(self): -self.defn += gen_registry(self._regy) +self.defn += gen_registry(self._regy, self._prefix) self._regy = None self._visited_ret_types = None @@ -289,7 +290,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); prefix=prefix, c_prefix=c_name(prefix, protect=False))) schema = QAPISchema(input_file) -vis = QAPISchemaGenCommandVisitor() +vis = QAPISchemaGenCommandVisitor(prefix) schema.visit(vis) genc.add(vis.defn) genh.add(vis.decl) diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index bd7a9be3dc..3f98e2491a 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -58,7 +58,7 @@ def gen_param_var(typ): return ret -def gen_event_send(name, arg_type, boxed): +def gen_event_send(name, arg_type, boxed, event_enum_name): # FIXME: Our declaration of local variables (and of 'errp' in the # parameter list) can collide with exploded members of the event's # data type passed in as parameters. If this collision ever hits in @@ -149,7 +149,8 @@ out: class QAPISchemaGenEventVisitor(QAPISchemaVisitor): -def __init__(self): +def __init__(self, prefix): +self._enum_name = c_name(prefix + 'QAPIEvent', protect=False) self.decl = None self.defn = None self._event_names = None @@ -160,13 +161,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor): self._event_names = [] def visit_end(self): -self.decl += gen_enum(event_enum_name, self._event_names) -self.defn += gen_enum_lookup(event_enum_name, self._event_names) +self.decl += gen_enum(self._enum_name, self._event_names) +self.defn += gen_enum_lookup(self._enum_name, self._event_names) self._event_names = None def visit_event(self, name, info, arg_type, boxed): self.decl += gen_event_send_decl(name, arg_type, boxed) -self.defn += gen_event_send(name, arg_type, boxed) +self.defn += gen_event_send(name, arg_type, boxed, self._enum_name) self._event_names.append(name) @@ -199,10 +200,8 @@ genh.add(mcgen(''' ''', prefix=prefix)) -event_enum_name = c_name(prefix + 'QAPIEvent', protect=False) - schema = QAPISchema(input_file) -vis = QAPISchemaGenEventVisitor() +vis = QAPISchemaGenEventVisitor(prefix) schema.visit(vis) genc.add(vis.defn) genh.add(vis.decl) diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index 3d65690fe3..2418b80a82 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -41,7 +41,8 @@ def to_c_string(string): class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor): -def __init__(self, unmask): +def __init__(self, prefix, unmask): +self._prefix = prefix self._unmask = unmask self.defn = None self.decl = None @@ -65,7 +66,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaVisitor): # generate C # TODO can generate awfully long lines jsons.extend(self._jsons) -name = c_name(prefix, protect=False) + 'qmp_schema_json' +name = c_name(self._prefix, protect=False) + 'qmp_schema_json' self.decl = mcgen(''' extern const char %(c_name)s[]; ''', @@ -192,7 +193,7 @@ genc.add(mcgen(''' prefix=prefix)) schema = QAPISchema(input_file) -vis = QAPISchemaGenIntrospectVisitor(opt_unmask) +vis = QAPISchemaGenIntrospectVisitor(prefix, opt_unmask) schema.visit(vis) genc.add(vis.defn) genh.add(vis.decl) diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index c0ac879beb..5ff2bfcf41 100644 --- a/script
Re: [Qemu-devel] [PATCH 2/3] qapi: Rename QMP and QGA schema files
Eric Blake writes: > Having two files in the tree both named qapi-schema.json just adds > confusion. Rename these files, and relocate them into the common > qapi/ subdirectory. Update all build rules that refer to the file > names, and adjust other documentation and comment references to > either track the new name or be rewritten so as to not mention > the file name. > > Maintainer-wise, this means that qapi/qga-schema.json continues > to belong to Michael as QGA maintainer, but now also notifies > Markus and Eric as QAPI maintainers, alongside all the other > QMP QAPI files, matching how other .json QAPI modules belong > to multiple maintainer blurbs. > > Signed-off-by: Eric Blake > --- > docs/devel/writing-qmp-commands.txt | 13 ++- > docs/interop/qmp-intro.txt | 3 ++- > Makefile | 10 > qga/qapi-schema.json => qapi/qga-schema.json | 0 This move is up to the QGA maintainer. My usual argument for keeping the schema in one place is weak for the QGA schema: it's maintained separately, and ususuall grepped separately, too. > qapi-schema.json => qapi/qmp-schema.json | 34 > ++-- While it was certainly created for QMP, it's now used for non-QMP stuff, too. Do we mind? > tpm.c| 2 +- > MAINTAINERS | 2 +- > 7 files changed, 33 insertions(+), 31 deletions(-) > rename qga/qapi-schema.json => qapi/qga-schema.json (100%) > rename qapi-schema.json => qapi/qmp-schema.json (99%)
[Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules
The next commit will introduce a common driver program for all generators. The generators need to be modules for that. qapi2texi.py already is. Make the other generators follow suit. The changes are actually trivial. Obvious in the diffs once you view them with whitespace changes ignored. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Marc-André Lureau --- scripts/qapi-commands.py | 43 ++-- scripts/qapi-event.py | 43 ++-- scripts/qapi-introspect.py | 54 ++-- scripts/qapi-types.py | 56 ++--- scripts/qapi-visit.py | 62 +- 5 files changed, 143 insertions(+), 115 deletions(-) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index e97e16e828..8584cb5873 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -255,16 +255,17 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor): self._regy += gen_register_command(name, success_response) -(input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line() +def main(argv): +(input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line() -blurb = ''' +blurb = ''' * Schema-defined QAPI/QMP commands ''' -genc = QAPIGenC(blurb, __doc__) -genh = QAPIGenH(blurb, __doc__) +genc = QAPIGenC(blurb, __doc__) +genh = QAPIGenH(blurb, __doc__) -genc.add(mcgen(''' +genc.add(mcgen(''' #include "qemu/osdep.h" #include "qemu-common.h" #include "qemu/module.h" @@ -279,23 +280,27 @@ genc.add(mcgen(''' #include "%(prefix)sqmp-commands.h" ''', - prefix=prefix)) + prefix=prefix)) -genh.add(mcgen(''' +genh.add(mcgen(''' #include "%(prefix)sqapi-types.h" #include "qapi/qmp/dispatch.h" void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); ''', - prefix=prefix, c_prefix=c_name(prefix, protect=False))) - -schema = QAPISchema(input_file) -vis = QAPISchemaGenCommandVisitor(prefix) -schema.visit(vis) -genc.add(vis.defn) -genh.add(vis.decl) - -if do_c: -genc.write(output_dir, prefix + 'qmp-marshal.c') -if do_h: -genh.write(output_dir, prefix + 'qmp-commands.h') + prefix=prefix, c_prefix=c_name(prefix, protect=False))) + +schema = QAPISchema(input_file) +vis = QAPISchemaGenCommandVisitor(prefix) +schema.visit(vis) +genc.add(vis.defn) +genh.add(vis.decl) + +if do_c: +genc.write(output_dir, prefix + 'qmp-marshal.c') +if do_h: +genh.write(output_dir, prefix + 'qmp-commands.h') + + +if __name__ == '__main__': +main(sys.argv) diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py index 3f98e2491a..e7e07f0055 100644 --- a/scripts/qapi-event.py +++ b/scripts/qapi-event.py @@ -171,16 +171,17 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor): self._event_names.append(name) -(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line() +def main(argv): +(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line() -blurb = ''' +blurb = ''' * Schema-defined QAPI/QMP events ''' -genc = QAPIGenC(blurb, __doc__) -genh = QAPIGenH(blurb, __doc__) +genc = QAPIGenC(blurb, __doc__) +genh = QAPIGenH(blurb, __doc__) -genc.add(mcgen(''' +genc.add(mcgen(''' #include "qemu/osdep.h" #include "qemu-common.h" #include "%(prefix)sqapi-event.h" @@ -191,22 +192,26 @@ genc.add(mcgen(''' #include "qapi/qmp-event.h" ''', - prefix=prefix)) + prefix=prefix)) -genh.add(mcgen(''' +genh.add(mcgen(''' #include "qapi/util.h" #include "%(prefix)sqapi-types.h" ''', - prefix=prefix)) - -schema = QAPISchema(input_file) -vis = QAPISchemaGenEventVisitor(prefix) -schema.visit(vis) -genc.add(vis.defn) -genh.add(vis.decl) - -if do_c: -genc.write(output_dir, prefix + 'qapi-event.c') -if do_h: -genh.write(output_dir, prefix + 'qapi-event.h') + prefix=prefix)) + +schema = QAPISchema(input_file) +vis = QAPISchemaGenEventVisitor(prefix) +schema.visit(vis) +genc.add(vis.defn) +genh.add(vis.decl) + +if do_c: +genc.write(output_dir, prefix + 'qapi-event.c') +if do_h: +genh.write(output_dir, prefix + 'qapi-event.h') + + +if __name__ == '__main__': +main(sys.argv) diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py index 2418b80a82..b098b95053 100644 --- a/scripts/qapi-introspect.py +++ b/scripts/qapi-introspect.py @@ -167,38 +167,44 @@ const char %(c_name)s[] = %(c_string)s; arg_type = arg_type or self._schema.the_empty_object_type self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)}) -# Debugging aid: unmask QAPI schema's type names -# We normally mask them, because they're not QMP wire ABI -opt_unmask = False -(input_file, output_dir,
[Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module
Our qapi-schema.json is composed of modules connected by include directives, but the generated code is monolithic all the same: one qapi-types.h with all the types, one qapi-visit.h with all the visitors, and so forth. These monolithic headers get included all over the place. In my "build everything" tree, adding a QAPI type recompiles about 4800 out of 5100 objects. We wouldn't write such monolithic headers by hand. It stands to reason that we shouldn't generate them, either. Split up generated qapi-types.h to mirror the schema's modular structure: one header per module. Name the main module's header qapi-types.h, and sub-module D/B.json's header D/qapi-types-B.h. Mirror the schema's includes in the headers, so that qapi-types.h gets you everything exactly as before. If you need less, you can include one or more of the sub-module headers. To be exploited shortly. Split up qapi-types.c, qapi-visit.h, qapi-visit.c, qmp-commands.h, qmp-commands.c, qapi-event.h, qapi-event.c the same way. qmp-introspect.h, qmp-introspect.c and qapi.texi remain monolithic. The split of qmp-commands.c duplicates static helper function qmp_marshal_output_str() in qapi-commands-char.c and qapi-commands-misc.c. This happens when commands returning the same type occur in multiple modules. Not worth avoiding. Since I'm going to rename qapi-event.[ch] to qapi-events.[ch], and qmp-commands.[ch] to qapi-commands.[ch], name the shards that way already, to reduce churn. This requires temporary hacks in commands.py and events.py. They'll go away with the rename. Signed-off-by: Markus Armbruster --- .gitignore | 60 Makefile | 120 +++ Makefile.objs| 65 - scripts/qapi/commands.py | 35 +- scripts/qapi/common.py | 21 +++-- scripts/qapi/events.py | 19 ++-- 6 files changed, 300 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 9477a08b6b..42c57998fd 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,67 @@ /qapi-gen-timestamp /qapi-builtin-types.[ch] /qapi-builtin-visit.[ch] +/qapi/qapi-commands-block-core.[ch] +/qapi/qapi-commands-block.[ch] +/qapi/qapi-commands-char.[ch] +/qapi/qapi-commands-common.[ch] +/qapi/qapi-commands-crypto.[ch] +/qapi/qapi-commands-introspect.[ch] +/qapi/qapi-commands-migration.[ch] +/qapi/qapi-commands-net.[ch] +/qapi/qapi-commands-rocker.[ch] +/qapi/qapi-commands-run-state.[ch] +/qapi/qapi-commands-sockets.[ch] +/qapi/qapi-commands-tpm.[ch] +/qapi/qapi-commands-trace.[ch] +/qapi/qapi-commands-transaction.[ch] +/qapi/qapi-commands-ui.[ch] +/qapi/qapi-events-block-core.[ch] +/qapi/qapi-events-block.[ch] +/qapi/qapi-events-char.[ch] +/qapi/qapi-events-common.[ch] +/qapi/qapi-events-crypto.[ch] +/qapi/qapi-events-introspect.[ch] +/qapi/qapi-events-migration.[ch] +/qapi/qapi-events-net.[ch] +/qapi/qapi-events-rocker.[ch] +/qapi/qapi-events-run-state.[ch] +/qapi/qapi-events-sockets.[ch] +/qapi/qapi-events-tpm.[ch] +/qapi/qapi-events-trace.[ch] +/qapi/qapi-events-transaction.[ch] +/qapi/qapi-events-ui.[ch] +/qapi/qapi-types-block-core.[ch] +/qapi/qapi-types-block.[ch] +/qapi/qapi-types-char.[ch] +/qapi/qapi-types-common.[ch] +/qapi/qapi-types-crypto.[ch] +/qapi/qapi-types-introspect.[ch] +/qapi/qapi-types-migration.[ch] +/qapi/qapi-types-net.[ch] +/qapi/qapi-types-rocker.[ch] +/qapi/qapi-types-run-state.[ch] +/qapi/qapi-types-sockets.[ch] +/qapi/qapi-types-tpm.[ch] +/qapi/qapi-types-trace.[ch] +/qapi/qapi-types-transaction.[ch] +/qapi/qapi-types-ui.[ch] /qapi-types.[ch] +/qapi/qapi-visit-block-core.[ch] +/qapi/qapi-visit-block.[ch] +/qapi/qapi-visit-char.[ch] +/qapi/qapi-visit-common.[ch] +/qapi/qapi-visit-crypto.[ch] +/qapi/qapi-visit-introspect.[ch] +/qapi/qapi-visit-migration.[ch] +/qapi/qapi-visit-net.[ch] +/qapi/qapi-visit-rocker.[ch] +/qapi/qapi-visit-run-state.[ch] +/qapi/qapi-visit-sockets.[ch] +/qapi/qapi-visit-tpm.[ch] +/qapi/qapi-visit-trace.[ch] +/qapi/qapi-visit-transaction.[ch] +/qapi/qapi-visit-ui.[ch] /qapi-visit.[ch] /qapi-event.[ch] /qapi-doc.texi diff --git a/Makefile b/Makefile index 60ddc9c945..ac9a7627a2 100644 --- a/Makefile +++ b/Makefile @@ -92,10 +92,70 @@ include $(SRC_PATH)/rules.mak GENERATED_FILES = qemu-version.h config-host.h qemu-options.def GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c GENERATED_FILES += qapi-types.h qapi-types.c +GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c +GENERATED_FILES += qapi/qapi-types-block.h qapi/qapi-types-block.c +GENERATED_FILES += qapi/qapi-types-char.h qapi/qapi-types-char.c +GENERATED_FILES += qapi/qapi-types-common.h qapi/qapi-types-common.c +GENERATED_FILES += qapi/qapi-types-crypto.h qapi/qapi-types-crypto.c +GENERATED_FILES += qapi/qapi-types-introspect.h qapi/qapi-types-introspect.c +GENERATED_FILES += qapi/qapi-types-migration.h qapi/qapi-types-migration.c +GENERATED_FILES += qapi/qap
[Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators
Whenever qapi-schema.json changes, we run six programs eleven times to update eleven files. Similar for qga/qapi-schema.json. This is silly. Replace the six programs by a single program that spits out all eleven files. The programs become modules in new Python package qapi, along with the helper library. This requires moving them to scripts/qapi/. Signed-off-by: Markus Armbruster Reviewed-by: Marc-André Lureau --- .gitignore | 2 + Makefile | 86 +-- docs/devel/qapi-code-gen.txt | 97 ++ monitor.c | 2 +- qapi-schema.json | 2 +- scripts/qapi-gen.py| 41 + scripts/qapi/__init__.py | 0 scripts/{qapi-commands.py => qapi/commands.py} | 23 ++--- scripts/{qapi.py => qapi/common.py}| 18 +--- scripts/{qapi2texi.py => qapi/doc.py} | 29 ++- scripts/{qapi-event.py => qapi/events.py} | 23 ++--- scripts/{qapi-introspect.py => qapi/introspect.py} | 32 ++- scripts/{qapi-types.py => qapi/types.py} | 34 ++-- scripts/{qapi-visit.py => qapi/visit.py} | 34 ++-- tests/Makefile.include | 56 ++--- tests/qapi-schema/test-qapi.py | 4 +- 16 files changed, 193 insertions(+), 290 deletions(-) create mode 100755 scripts/qapi-gen.py create mode 100644 scripts/qapi/__init__.py rename scripts/{qapi-commands.py => qapi/commands.py} (94%) rename scripts/{qapi.py => qapi/common.py} (99%) rename scripts/{qapi2texi.py => qapi/doc.py} (92%) mode change 100755 => 100644 rename scripts/{qapi-event.py => qapi/events.py} (92%) rename scripts/{qapi-introspect.py => qapi/introspect.py} (90%) rename scripts/{qapi-types.py => qapi/types.py} (90%) rename scripts/{qapi-visit.py => qapi/visit.py} (92%) diff --git a/.gitignore b/.gitignore index 704b22285d..2f9a92f6cc 100644 --- a/.gitignore +++ b/.gitignore @@ -28,9 +28,11 @@ /linux-headers/asm /qga/qapi-generated /qapi-generated +/qapi-gen-timestamp /qapi-types.[ch] /qapi-visit.[ch] /qapi-event.[ch] +/qapi-doc.texi /qmp-commands.h /qmp-introspect.[ch] /qmp-marshal.c diff --git a/Makefile b/Makefile index 4ec7a3cb82..bd781c6aad 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,7 @@ GENERATED_FILES += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h GENERATED_FILES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c GENERATED_FILES += qmp-introspect.h GENERATED_FILES += qmp-introspect.c +GENERATED_FILES += qapi-doc.texi GENERATED_FILES += trace/generated-tcg-tracers.h @@ -483,25 +484,26 @@ qemu-ga$(EXESUF): QEMU_CFLAGS += -I qga/qapi-generated qemu-keymap$(EXESUF): LIBS += $(XKBCOMMON_LIBS) qemu-keymap$(EXESUF): QEMU_CFLAGS += $(XKBCOMMON_CFLAGS) -gen-out-type = $(subst .,-,$(suffix $@)) +qapi-py = $(SRC_PATH)/scripts/qapi/commands.py \ +$(SRC_PATH)/scripts/qapi/events.py \ +$(SRC_PATH)/scripts/qapi/introspect.py \ +$(SRC_PATH)/scripts/qapi/types.py \ +$(SRC_PATH)/scripts/qapi/visit.py \ +$(SRC_PATH)/scripts/qapi/common.py \ +$(SRC_PATH)/scripts/qapi/doc.py \ +$(SRC_PATH)/scripts/ordereddict.py \ +$(SRC_PATH)/scripts/qapi-gen.py -qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py - -qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\ -$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py) - $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-types.py \ - $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \ - "GEN","$@") -qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\ -$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py) - $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-visit.py \ - $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \ - "GEN","$@") -qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\ -$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py) - $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-commands.py \ - $(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \ - "GEN","$@") +qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h \ +qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h \ +qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c \ +qga/qapi-generated/qga-qapi-doc.texi: \ +qga/qapi-generated/qapi-gen-timestamp ; +qga/qapi-generated/qapi-gen-timestamp: $(SRC_PATH)/qga/qapi-schema.json $(qapi-py) + $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \ + -o qga/qapi-generated -p "qga-" $<, \ + "GEN
Re: [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code
Hi, This series failed docker-mingw@fedora build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. Type: series Message-id: 20180211093607.27351-1-arm...@redhat.com Subject: [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code === TEST SCRIPT BEGIN === #!/bin/bash set -e git submodule update --init dtc # Let docker tests dump environment info export SHOW_ENV=1 export J=8 time make docker-test-mingw@fedora === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 88c36fed50 qapi: Don't create useless directory qapi-generated 8695c58a23 Fix up dangling references to qmp-commands.* in comment and doc cb0173d2de qapi: Move qapi-schema.json to qapi/, rename generated files 0163832937 docs: Correct outdated information on QAPI 0e8593c3cc docs/devel/writing-qmp-commands: Update for modular QAPI 610c107fba qapi: Empty out qapi-schema.json 978b56117d Include less of the generated modular QAPI headers b9fbec1f14 qapi: Generate separate .h, .c for each module 349f60fd78 qapi/common: Fix guardname() for funny filenames 7d0c330c11 qapi/types qapi/visit: Generate built-in stuff into separate files 6be749acd0 qapi: Make code-generating visitors use QAPIGen more 26fb1118b1 qapi: Rename generated qmp-marshal.c to qmp-commands.c 3373ff0b73 qapi: Record 'include' directives in intermediate representation 992e298bed qapi: Generate in source order 27ec87b85b qapi: Record 'include' directives in parse tree 704eb94f85 qapi: Concentrate QAPISchemaParser.exprs updates in .__init__() 679e456092 qapi: Lift error reporting from QAPISchema.__init__() to callers b6747d37d3 qapi/common: Eliminate QAPISchema.exprs 12c8bc8c3c qapi: Improve include file name reporting in error messages 15d87d797d qapi: Touch generated files only when they change c1fb7b93d8 qapi-gen: Convert from getopt to argparse 8174e1f7f9 qapi-gen: New common driver for code and doc generators 76b229359e qapi: Turn generators into modules e9687814c8 qapi: Reduce use of global variables in generators some df03d3d345 qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc 8dcb95864b qapi: Rename variable holding the QAPISchemaGenFOOVisitor 176807c729 qapi: Generate up-to-date copyright notice 57f04f7bcd qapi: Streamline boilerplate comment generation dc8f4505cb Include qapi/qmp/qerror.h exactly where needed === OUTPUT BEGIN === Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc' Cloning into '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/dtc'... Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42' BUILD fedora GEN /var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660/qemu.tar Cloning into '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660/qemu.tar.vroot'... done. Your branch is up-to-date with 'origin/test'. Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc' Cloning into '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660/qemu.tar.vroot/dtc'... Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42' Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered for path 'ui/keycodemapdb' Cloning into '/var/tmp/patchew-tester-tmp-7cnnoaxn/src/docker-src.2018-02-11-05.15.21.19660/qemu.tar.vroot/ui/keycodemapdb'... Submodule path 'ui/keycodemapdb': checked out '6b3d716e2b6472eb7189d3220552280ef3d832ce' COPYRUNNER RUN test-mingw in qemu:fedora Packages installed: PyYAML-3.12-5.fc27.x86_64 SDL-devel-1.2.15-29.fc27.x86_64 bc-1.07.1-3.fc27.x86_64 bison-3.0.4-8.fc27.x86_64 bzip2-1.0.6-24.fc27.x86_64 ccache-3.3.5-1.fc27.x86_64 clang-5.0.1-1.fc27.x86_64 findutils-4.6.0-14.fc27.x86_64 flex-2.6.1-5.fc27.x86_64 gcc-7.3.1-2.fc27.x86_64 gcc-c++-7.3.1-2.fc27.x86_64 gettext-0.19.8.1-12.fc27.x86_64 git-2.14.3-2.fc27.x86_64 glib2-devel-2.54.3-2.fc27.x86_64 hostname-3.18-4.fc27.x86_64 libaio-devel-0.3.110-9.fc27.x86_64 libasan-7.3.1-2.fc27.x86_64 libfdt-devel-1.4.6-1.fc27.x86_64 libubsan-7.3.1-2.fc27.x86_64 make-4.2.1-4.fc27.x86_64 mingw32-SDL-1.2.15-9.fc27.noarch mingw32-bzip2-1.0.6-9.fc27.noarch mingw32-curl-7.54.1-2.fc27.noarch mingw32-glib2-2.54.1-1.fc27.noarch mingw32-gmp-6.1.2-2.fc27.noarch mingw32-gnutls-3.5.13-2.fc27.noarch mingw32-gtk2-2.24.31-4.fc27.noarch mingw32-gtk3-3.22.16-1.fc27.noarch mingw32-libjpeg-turbo-1.5.1-3.fc27.noarch mingw32-libpng-1.6.29-2.fc27.noarch mingw32-libssh2-1.8.0-3.fc27.noarch mingw32-libtasn1-4.13-1.fc27.noarch mingw32-nettle-3.3-3.fc27.noarch mingw32-pixman-0.34.0-3.fc27.noarch mingw32-pkg-config-0.28-9.fc27.x86_64 mingw64-SDL-1.2.15-9.fc27.noarch mingw64-bzip2-1.0.6-9.fc27.noarch mingw64-curl-7.54.1-2.fc27.noarch mingw64-glib2-2.54.1-1.fc27.noarch mingw64-gmp-6.1.2-2.fc27.noarch mingw64-gnutls-3.5.13-2.fc27.noarch mingw64-gtk2-2.24.31-4.fc27.noarch mingw64-gtk3-3.22.16-1.fc27.noarch mingw64-libjpeg-turbo-1.5
Re: [Qemu-devel] [PATCHv2 05/12] cuda: rename frequency property to tb_frequency
On 10/02/18 23:11, David Gibson wrote: On Sun, Feb 11, 2018 at 09:32:14AM +1100, David Gibson wrote: On Fri, Feb 09, 2018 at 06:51:35PM +, Mark Cave-Ayland wrote: This allows us to more easily differentiate between the timebase frequency used to calibrate the MacOS timers and the actual frequency of the hardware clock as indicated by CUDA_TIMER_FREQ. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Applied, thanks. Actually, this patch doesn't compile, because you've changed ti->frequency in a couple of places where you should only be changing s->frequency. I've fixed it up in my tree. Ah apologies there - this was a mistake I made quite early on in the patchset which I must have accidentally brought back in during a subsequent rebase :( I've just done a check on patch 7 ("cuda: set timer 1 frequency property to CUDA_TIMER_FREQ") and confirmed that the cuda.c version in your ppc-for-2.12 branch matches that in my local branch, so your fixups are good. Any thoughts on the last few patches? I know Philippe had a question for Stefan re: the trace-events patch, however it would be useful for patches 10/11 to be applied as they complete the transition from CUDA over to using the mos6522 device (also providing an initial example as to how it can be used). ATB, Mark.
Re: [Qemu-devel] [PATCHv2 05/12] cuda: rename frequency property to tb_frequency
On Sun, Feb 11, 2018 at 10:59:05AM +, Mark Cave-Ayland wrote: > On 10/02/18 23:11, David Gibson wrote: > > > On Sun, Feb 11, 2018 at 09:32:14AM +1100, David Gibson wrote: > > > On Fri, Feb 09, 2018 at 06:51:35PM +, Mark Cave-Ayland wrote: > > > > This allows us to more easily differentiate between the timebase > > > > frequency used > > > > to calibrate the MacOS timers and the actual frequency of the hardware > > > > clock as > > > > indicated by CUDA_TIMER_FREQ. > > > > > > > > Signed-off-by: Mark Cave-Ayland > > > > Reviewed-by: Philippe Mathieu-Daudé > > > > > > Applied, thanks. > > > > Actually, this patch doesn't compile, because you've changed > > ti->frequency in a couple of places where you should only be changing > > s->frequency. I've fixed it up in my tree. > > Ah apologies there - this was a mistake I made quite early on in the > patchset which I must have accidentally brought back in during a subsequent > rebase :( > > I've just done a check on patch 7 ("cuda: set timer 1 frequency property to > CUDA_TIMER_FREQ") and confirmed that the cuda.c version in your ppc-for-2.12 > branch matches that in my local branch, so your fixups are good. Ok, great. > Any thoughts on the last few patches? I know Philippe had a question for > Stefan re: the trace-events patch, however it would be useful for patches > 10/11 to be applied as they complete the transition from CUDA over to using > the mos6522 device (also providing an initial example as to how it can be > used). Haven't had a chance to look at them yet. -- David Gibson| I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson signature.asc Description: PGP signature
Re: [Qemu-devel] [PATCH] net: fix misaligned member access
Hi On Fri, Feb 9, 2018 at 8:50 PM, Philippe Mathieu-Daudé wrote: > Hi Marc-André, > > On 02/09/2018 04:03 PM, Marc-André Lureau wrote: >> Fixes the following ASAN warnings: >> >> /home/elmarco/src/qemu/hw/net/net_tx_pkt.c:201:27: runtime error: member >> access within misaligned address 0x63128846 for type 'struct ip_header', >> which requires 4 byte alignment >> 0x63128846: note: pointer points here >> 01 00 00 00 45 00 01 a9 01 00 00 00 40 11 78 45 00 00 00 00 ff ff ff ff >> 00 00 00 00 00 00 00 00 >> ^ >> /home/elmarco/src/qemu/hw/net/net_tx_pkt.c:208:63: runtime error: member >> access within misaligned address 0x63128846 for type 'struct ip_header', >> which requires 4 byte alignment >> 0x63128846: note: pointer points here >> 01 00 00 00 45 00 01 a9 01 00 00 00 40 11 78 45 00 00 00 00 ff ff ff ff >> 00 00 00 00 00 00 00 00 >> ^ >> /home/elmarco/src/qemu/hw/net/net_tx_pkt.c:210:13: runtime error: member >> access within misaligned address 0x63128846 for type 'struct ip_header', >> which requires 4 byte alignment >> 0x63128846: note: pointer points here >> 01 00 00 00 45 00 01 a9 01 00 00 00 40 11 78 45 00 00 00 00 ff ff ff ff >> 00 00 00 00 00 00 00 00 >> >> Signed-off-by: Marc-André Lureau >> --- >> include/net/eth.h | 4 +++- >> hw/net/net_tx_pkt.c | 2 +- >> 2 files changed, 4 insertions(+), 2 deletions(-) >> >> diff --git a/include/net/eth.h b/include/net/eth.h >> index 09054a506d..e6dc8a7ba0 100644 >> --- a/include/net/eth.h >> +++ b/include/net/eth.h >> @@ -194,7 +194,9 @@ struct tcp_hdr { >> #define PKT_GET_IP_HDR(p) \ >> ((struct ip_header *)(((uint8_t *)(p)) + eth_get_l2_hdr_length(p))) >> #define IP_HDR_GET_LEN(p) \ >> -struct ip_header *)(p))->ip_ver_len & 0x0F) << 2) >> +((ldub_p(p + offsetof(struct ip_header, ip_ver_len)) & 0x0F) << 2) > > I like the idea of using the ldst API and offsetof() macro, > however I think it would be cleaner to use inlined static functions. Could be a different patch. I don't see much reason to mix this with the alignment fix. Then you need to review the rest of the define too. Thanks > >> +#define IP_HDR_GET_P(p) \ >> +(ldub_p(p + offsetof(struct ip_header, ip_p))) >> #define PKT_GET_IP_HDR_LEN(p) \ >> (IP_HDR_GET_LEN(PKT_GET_IP_HDR(p))) >> #define PKT_GET_IP6_HDR(p)\ >> diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c >> index e29c881bc2..162f802dd7 100644 >> --- a/hw/net/net_tx_pkt.c >> +++ b/hw/net/net_tx_pkt.c >> @@ -205,7 +205,7 @@ static bool net_tx_pkt_parse_headers(struct NetTxPkt >> *pkt) >> return false; >> } >> >> -pkt->l4proto = ((struct ip_header *) l3_hdr->iov_base)->ip_p; >> +pkt->l4proto = IP_HDR_GET_P(l3_hdr->iov_base); >> >> if (IP_HDR_GET_LEN(l3_hdr->iov_base) != sizeof(struct ip_header)) { >> /* copy optional IPv4 header data if any*/ >> > -- Marc-André Lureau
Re: [Qemu-devel] [PATCH 1/3] qapi: Pass '-u' when doing non-silent diff
Eric Blake writes: > Ed-script diffs are awful compared to context diffs. Fix another > 'diff -q' while in the area (if the files are different, being > noisy makes it easier to diagnose why). > > Fixes: 46ec4fce > Signed-off-by: Eric Blake > --- > tests/Makefile.include | 8 > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/tests/Makefile.include b/tests/Makefile.include > index f41da235aef..375f31b5bc0 100644 > --- a/tests/Makefile.include > +++ b/tests/Makefile.include > @@ -919,14 +919,14 @@ $(patsubst %, check-%, $(check-qapi-schema-y)): > check-%.json: $(SRC_PATH)/%.json > $^ >$*.test.out 2>$*.test.err; \ > echo $$? >$*.test.exit, \ > "TEST","$*.out") > - @diff $(SRC_PATH)/$*.out $*.test.out > + @diff -u $(SRC_PATH)/$*.out $*.test.out > @# Sanitize error messages (make them independent of build directory) > - @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff > $(SRC_PATH)/$*.err - > - @diff $(SRC_PATH)/$*.exit $*.test.exit > + @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -u > $(SRC_PATH)/$*.err - > + @diff -u $(SRC_PATH)/$*.exit $*.test.exit Let's diff .err before .out, because when .err differs, .out is usually useless. > > .PHONY: check-tests/qapi-schema/doc-good.texi > check-tests/qapi-schema/doc-good.texi: tests/qapi-schema/doc-good.test.texi > - @diff -q $(SRC_PATH)/tests/qapi-schema/doc-good.texi $< > + @diff -u $(SRC_PATH)/tests/qapi-schema/doc-good.texi $< > > # Consolidated targets
[Qemu-devel] [Bug 1748756] [NEW] [Feature request] Support of TI AM1808 for Lego EV3
Public bug reported: It would be great if emulating TI AM1808 would be possible. It will be a big step towards Lego Mindstorms EV3 emulation. ** Affects: qemu Importance: Undecided Status: New -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1748756 Title: [Feature request] Support of TI AM1808 for Lego EV3 Status in QEMU: New Bug description: It would be great if emulating TI AM1808 would be possible. It will be a big step towards Lego Mindstorms EV3 emulation. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1748756/+subscriptions
[Qemu-devel] [PATCHv2] linux-user: Fix sched_getaffinity mask size
We properly computed the capped mask size to be put to the application buffer, but didn't actually used it. Also, we need to return the capped mask size instead of 0 on success. Signed-off-by: Samuel Thibault --- Difference from v1: - simplify fix --- linux-user/syscall.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 82b35a6bdf..bcda3362fc 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -10493,7 +10493,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = arg2; } -ret = host_to_target_cpu_mask(mask, mask_size, arg3, arg2); +if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) { +goto efault; +} } } break; -- 2.15.1
[Qemu-devel] Fan mail
Thanks a lot for this software! Now I can make Windows tutorials without having to buy a new hard drive. (I asked Microsoft support how to install Windows on a hard drive with other operating systems on it. Their reply was to start diskpart, select a drive and type the command "clean".) Regards, Per Gunnarsson
[Qemu-devel] [PATCH] tcg: Improve tcg_gen_muli_i32/i64
Convert multiplication by power of two to left shift. Signed-off-by: Richard Henderson --- tcg/tcg-op.c | 24 ++-- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index 3467787323..34b96d68f3 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -277,9 +277,15 @@ void tcg_gen_setcondi_i32(TCGCond cond, TCGv_i32 ret, void tcg_gen_muli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2) { -TCGv_i32 t0 = tcg_const_i32(arg2); -tcg_gen_mul_i32(ret, arg1, t0); -tcg_temp_free_i32(t0); +if (arg2 == 0) { +tcg_gen_movi_i32(ret, 0); +} else if (is_power_of_2(arg2)) { +tcg_gen_shli_i32(ret, arg1, ctz32(arg2)); +} else { +TCGv_i32 t0 = tcg_const_i32(arg2); +tcg_gen_mul_i32(ret, arg1, t0); +tcg_temp_free_i32(t0); +} } void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) @@ -1430,9 +1436,15 @@ void tcg_gen_setcondi_i64(TCGCond cond, TCGv_i64 ret, void tcg_gen_muli_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2) { -TCGv_i64 t0 = tcg_const_i64(arg2); -tcg_gen_mul_i64(ret, arg1, t0); -tcg_temp_free_i64(t0); +if (arg2 == 0) { +tcg_gen_movi_i64(ret, 0); +} else if (is_power_of_2(arg2)) { +tcg_gen_shli_i64(ret, arg1, ctz64(arg2)); +} else { +TCGv_i64 t0 = tcg_const_i64(arg2); +tcg_gen_mul_i64(ret, arg1, t0); +tcg_temp_free_i64(t0); +} } void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) -- 2.14.3
[Qemu-devel] [PATCH v2 1/7] target/arm: Remove ARM_CP_64BIT from ZCR_EL registers
Because they are ARM_CP_STATE_AA64, ARM_CP_64BIT is implied. Signed-off-by: Richard Henderson --- target/arm/helper.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 180ab75458..4b102ec356 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -4357,7 +4357,7 @@ static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, static const ARMCPRegInfo zcr_el1_reginfo = { .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0, -.access = PL1_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT, +.access = PL1_RW, .accessfn = zcr_access, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]), .writefn = zcr_write, .raw_writefn = raw_write }; @@ -4365,7 +4365,7 @@ static const ARMCPRegInfo zcr_el1_reginfo = { static const ARMCPRegInfo zcr_el2_reginfo = { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0, -.access = PL2_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT, +.access = PL2_RW, .accessfn = zcr_access, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]), .writefn = zcr_write, .raw_writefn = raw_write }; @@ -4373,14 +4373,14 @@ static const ARMCPRegInfo zcr_el2_reginfo = { static const ARMCPRegInfo zcr_no_el2_reginfo = { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0, -.access = PL2_RW, .type = ARM_CP_64BIT, +.access = PL2_RW, .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore }; static const ARMCPRegInfo zcr_el3_reginfo = { .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0, -.access = PL3_RW, .accessfn = zcr_access, .type = ARM_CP_64BIT, +.access = PL3_RW, .accessfn = zcr_access, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]), .writefn = zcr_write, .raw_writefn = raw_write }; -- 2.14.3
[Qemu-devel] [PATCH v2 0/7] target/arm: More SVE prep work
Changes for v2: Include signal frames and PR_SVE_SET/GET_VL. Blurb for v1: First, we had noted that ARM_CP_64BIT needed to be removed from the ZCR_EL registers, but the patch set was applied without actually fixing that. Second, there's an existing bug by which the FPCR/FPSR registers are not properly trapped when FP is disabled. Fix that with a translation-time check. Third, my attempt at using .accessfn for ZCR_EL fails to take into account the two different exception syndromes that must be raised. Although they probably aren't as important as FPCR/FPSR, handle them at translation time too. Fourth, when writing to an AdvSIMD register, zero the rest of the SVE register. r~ Richard Henderson (7): target/arm: Remove ARM_CP_64BIT from ZCR_EL registers target/arm: Enforce FP access to FPCR/FPSR target/arm: Suppress TB end for FPCR/FPSR target/arm: Enforce access to ZCR_EL at translation target/arm: Handle SVE registers when using clear_vec_high linux-user: Support SVE in aarch64 signal frames linux-user: Implement aarch64 PR_SVE_SET/GET_VL target/arm/cpu.h | 38 ++--- target/arm/internals.h | 6 + linux-user/signal.c| 348 - linux-user/syscall.c | 20 +++ target/arm/cpu64.c | 61 target/arm/helper.c| 28 ++-- target/arm/translate-a64.c | 181 +++ 7 files changed, 480 insertions(+), 202 deletions(-) -- 2.14.3
[Qemu-devel] [PATCH v2 3/7] target/arm: Suppress TB end for FPCR/FPSR
Nothing in either register affects the TB. Signed-off-by: Richard Henderson --- target/arm/helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index d41fb8371f..e0184c7162 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3356,11 +3356,11 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore }, { .name = "FPCR", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4, - .access = PL0_RW, .type = ARM_CP_FPU, + .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write }, { .name = "FPSR", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4, - .access = PL0_RW, .type = ARM_CP_FPU, + .access = PL0_RW, .type = ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write }, { .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0, -- 2.14.3
[Qemu-devel] [PATCH v2 5/7] target/arm: Handle SVE registers when using clear_vec_high
When storing to an AdvSIMD FP register, all of the high bits of the SVE register are zeroed. Therefore, call it more often with is_q as a parameter. Signed-off-by: Richard Henderson --- target/arm/translate-a64.c | 162 + 1 file changed, 62 insertions(+), 100 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index e3881d4999..1c88539d62 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -602,13 +602,30 @@ static TCGv_i32 read_fp_sreg(DisasContext *s, int reg) return v; } +/* Clear the bits above an N-bit vector, for N = (is_q ? 128 : 64). + * If SVE is not enabled, then there are only 128 bits in the vector. + */ +static void clear_vec_high(DisasContext *s, bool is_q, int rd) +{ +unsigned ofs = fp_reg_offset(s, rd, MO_64); +unsigned vsz = vec_full_reg_size(s); + +if (!is_q) { +TCGv_i64 tcg_zero = tcg_const_i64(0); +tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8); +tcg_temp_free_i64(tcg_zero); +} +if (vsz > 16) { +tcg_gen_gvec_dup8i(ofs + 16, vsz - 16, vsz - 16, 0); +} +} + static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v) { -TCGv_i64 tcg_zero = tcg_const_i64(0); +unsigned ofs = fp_reg_offset(s, reg, MO_64); -tcg_gen_st_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64)); -tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(s, reg)); -tcg_temp_free_i64(tcg_zero); +tcg_gen_st_i64(v, cpu_env, ofs); +clear_vec_high(s, false, reg); } static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v) @@ -1009,6 +1026,8 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size) tcg_temp_free_i64(tmplo); tcg_temp_free_i64(tmphi); + +clear_vec_high(s, true, destidx); } /* @@ -1124,17 +1143,6 @@ static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src, } } -/* Clear the high 64 bits of a 128 bit vector (in general non-quad - * vector ops all need to do this). - */ -static void clear_vec_high(DisasContext *s, int rd) -{ -TCGv_i64 tcg_zero = tcg_const_i64(0); - -write_vec_element(s, tcg_zero, rd, 1, MO_64); -tcg_temp_free_i64(tcg_zero); -} - /* Store from vector register to memory */ static void do_vec_st(DisasContext *s, int srcidx, int element, TCGv_i64 tcg_addr, int size) @@ -2794,12 +2802,13 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) /* For non-quad operations, setting a slice of the low * 64 bits of the register clears the high 64 bits (in * the ARM ARM pseudocode this is implicit in the fact - * that 'rval' is a 64 bit wide variable). We optimize - * by noticing that we only need to do this the first - * time we touch a register. + * that 'rval' is a 64 bit wide variable). + * For quad operations, we might still need to zero the + * high bits of SVE. We optimize by noticing that we only + * need to do this the first time we touch a register. */ -if (!is_q && e == 0 && (r == 0 || xs == selem - 1)) { -clear_vec_high(s, tt); +if (e == 0 && (r == 0 || xs == selem - 1)) { +clear_vec_high(s, is_q, tt); } } tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes); @@ -2942,10 +2951,9 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) write_vec_element(s, tcg_tmp, rt, 0, MO_64); if (is_q) { write_vec_element(s, tcg_tmp, rt, 1, MO_64); -} else { -clear_vec_high(s, rt); } tcg_temp_free_i64(tcg_tmp); +clear_vec_high(s, is_q, rt); } else { /* Load/store one element per register */ if (is_load) { @@ -6718,7 +6726,6 @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q, } if (!is_q) { -clear_vec_high(s, rd); write_vec_element(s, tcg_final, rd, 0, MO_64); } else { write_vec_element(s, tcg_final, rd, 1, MO_64); @@ -6731,7 +6738,8 @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q, tcg_temp_free_i64(tcg_rd); tcg_temp_free_i32(tcg_rd_narrowed); tcg_temp_free_i64(tcg_final); -return; + +clear_vec_high(s, is_q, rd); } /* SQSHLU, UQSHL, SQSHL: saturating left shifts */ @@ -6795,10 +6803,7 @@ static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q, tcg_temp_free_i64(tcg_op); } tcg_temp_free_i64(tcg_shift); - -if (!is_q) { -clear_vec_high(s, rd); -} +clear_vec_high(s, is_q, rd);
[Qemu-devel] [PATCH v2 2/7] target/arm: Enforce FP access to FPCR/FPSR
Signed-off-by: Richard Henderson --- target/arm/cpu.h | 35 ++- target/arm/helper.c| 6 -- target/arm/translate-a64.c | 3 +++ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 521444a5a1..e966a57f8a 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1714,7 +1714,7 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) } /* ARMCPRegInfo type field bits. If the SPECIAL bit is set this is a - * special-behaviour cp reg and bits [15..8] indicate what behaviour + * special-behaviour cp reg and bits [11..8] indicate what behaviour * it has. Otherwise it is a simple cp reg, where CONST indicates that * TCG can assume the value to be constant (ie load at translate time) * and 64BIT indicates a 64 bit wide coprocessor register. SUPPRESS_TB_END @@ -1735,24 +1735,25 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) * need to be surrounded by gen_io_start()/gen_io_end(). In particular, * registers which implement clocks or timers require this. */ -#define ARM_CP_SPECIAL 1 -#define ARM_CP_CONST 2 -#define ARM_CP_64BIT 4 -#define ARM_CP_SUPPRESS_TB_END 8 -#define ARM_CP_OVERRIDE 16 -#define ARM_CP_ALIAS 32 -#define ARM_CP_IO 64 -#define ARM_CP_NO_RAW 128 -#define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8)) -#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8)) -#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8)) -#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8)) -#define ARM_CP_DC_ZVA (ARM_CP_SPECIAL | (5 << 8)) -#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA +#define ARM_CP_SPECIAL 0x0001 +#define ARM_CP_CONST 0x0002 +#define ARM_CP_64BIT 0x0004 +#define ARM_CP_SUPPRESS_TB_END 0x0008 +#define ARM_CP_OVERRIDE 0x0010 +#define ARM_CP_ALIAS 0x0020 +#define ARM_CP_IO0x0040 +#define ARM_CP_NO_RAW0x0080 +#define ARM_CP_NOP (ARM_CP_SPECIAL | 0x0100) +#define ARM_CP_WFI (ARM_CP_SPECIAL | 0x0200) +#define ARM_CP_NZCV (ARM_CP_SPECIAL | 0x0300) +#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | 0x0400) +#define ARM_CP_DC_ZVA(ARM_CP_SPECIAL | 0x0500) +#define ARM_LAST_SPECIAL ARM_CP_DC_ZVA +#define ARM_CP_FPU 0x1000 /* Used only as a terminator for ARMCPRegInfo lists */ -#define ARM_CP_SENTINEL 0x +#define ARM_CP_SENTINEL 0x /* Mask of only the flag bits in a type field */ -#define ARM_CP_FLAG_MASK 0xff +#define ARM_CP_FLAG_MASK 0x10ff /* Valid values for ARMCPRegInfo state field, indicating which of * the AArch32 and AArch64 execution states this register is visible in. diff --git a/target/arm/helper.c b/target/arm/helper.c index 4b102ec356..d41fb8371f 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3356,10 +3356,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .writefn = aa64_daif_write, .resetfn = arm_cp_reset_ignore }, { .name = "FPCR", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4, - .access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write }, + .access = PL0_RW, .type = ARM_CP_FPU, + .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write }, { .name = "FPSR", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4, - .access = PL0_RW, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write }, + .access = PL0_RW, .type = ARM_CP_FPU, + .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write }, { .name = "DCZID_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0, .access = PL0_R, .type = ARM_CP_NO_RAW, diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index fb1a4cb532..89f50558a7 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1631,6 +1631,9 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread, default: break; } +if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) { +return; +} if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) { gen_io_start(); -- 2.14.3
[Qemu-devel] [PATCH v2 4/7] target/arm: Enforce access to ZCR_EL at translation
This also makes sure that we get the correct ordering of SVE vs FP exceptions. Signed-off-by: Richard Henderson --- target/arm/cpu.h | 3 ++- target/arm/internals.h | 6 ++ target/arm/helper.c| 22 -- target/arm/translate-a64.c | 16 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index e966a57f8a..51a3e16275 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1750,10 +1750,11 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid) #define ARM_CP_DC_ZVA(ARM_CP_SPECIAL | 0x0500) #define ARM_LAST_SPECIAL ARM_CP_DC_ZVA #define ARM_CP_FPU 0x1000 +#define ARM_CP_SVE 0x2000 /* Used only as a terminator for ARMCPRegInfo lists */ #define ARM_CP_SENTINEL 0x /* Mask of only the flag bits in a type field */ -#define ARM_CP_FLAG_MASK 0x10ff +#define ARM_CP_FLAG_MASK 0x30ff /* Valid values for ARMCPRegInfo state field, indicating which of * the AArch32 and AArch64 execution states this register is visible in. diff --git a/target/arm/internals.h b/target/arm/internals.h index 89f5d2fe12..47cc224a46 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -243,6 +243,7 @@ enum arm_exception_class { EC_AA64_HVC = 0x16, EC_AA64_SMC = 0x17, EC_SYSTEMREGISTERTRAP = 0x18, +EC_SVEACCESSTRAP = 0x19, EC_INSNABORT = 0x20, EC_INSNABORT_SAME_EL = 0x21, EC_PCALIGNMENT= 0x22, @@ -381,6 +382,11 @@ static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit) | (cv << 24) | (cond << 20); } +static inline uint32_t syn_sve_access_trap(void) +{ +return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT; +} + static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc) { return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT) diff --git a/target/arm/helper.c b/target/arm/helper.c index e0184c7162..550dc3d290 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -4335,20 +4335,6 @@ static int sve_exception_el(CPUARMState *env) return 0; } -static CPAccessResult zcr_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ -switch (sve_exception_el(env)) { -case 3: -return CP_ACCESS_TRAP_EL3; -case 2: -return CP_ACCESS_TRAP_EL2; -case 1: -return CP_ACCESS_TRAP; -} -return CP_ACCESS_OK; -} - static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -4359,7 +4345,7 @@ static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, static const ARMCPRegInfo zcr_el1_reginfo = { .name = "ZCR_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 1, .crm = 2, .opc2 = 0, -.access = PL1_RW, .accessfn = zcr_access, +.access = PL1_RW, .type = ARM_CP_SVE | ARM_CP_FPU, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[1]), .writefn = zcr_write, .raw_writefn = raw_write }; @@ -4367,7 +4353,7 @@ static const ARMCPRegInfo zcr_el1_reginfo = { static const ARMCPRegInfo zcr_el2_reginfo = { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0, -.access = PL2_RW, .accessfn = zcr_access, +.access = PL2_RW, .type = ARM_CP_SVE | ARM_CP_FPU, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[2]), .writefn = zcr_write, .raw_writefn = raw_write }; @@ -4375,14 +4361,14 @@ static const ARMCPRegInfo zcr_el2_reginfo = { static const ARMCPRegInfo zcr_no_el2_reginfo = { .name = "ZCR_EL2", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 0, -.access = PL2_RW, +.access = PL2_RW, .type = ARM_CP_SVE | ARM_CP_FPU, .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore }; static const ARMCPRegInfo zcr_el3_reginfo = { .name = "ZCR_EL3", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 2, .opc2 = 0, -.access = PL3_RW, .accessfn = zcr_access, +.access = PL3_RW, .type = ARM_CP_SVE | ARM_CP_FPU, .fieldoffset = offsetof(CPUARMState, vfp.zcr_el[3]), .writefn = zcr_write, .raw_writefn = raw_write }; diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 89f50558a7..e3881d4999 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1182,6 +1182,19 @@ static inline bool fp_access_check(DisasContext *s) return false; } +/* Check that SVE access is enabled. If it is, return true. + * If not, emit code to generate an appropriate exception and return false. + */ +static inline bool sve_access_check(DisasContext *s) +{ +if (s->sve_excp_el) { +gen_exception_insn(s, 4, EXCP_UDEF, syn_sve_access_trap(), + s->sve_excp_el); +return false; +} +ret
[Qemu-devel] [PATCH v2 7/7] linux-user: Implement aarch64 PR_SVE_SET/GET_VL
As an implementation choice, widening VL has zeroed the previously inaccessible portion of the sve registers. Signed-off-by: Richard Henderson --- target/arm/cpu.h | 2 ++ linux-user/syscall.c | 20 + target/arm/cpu64.c | 61 3 files changed, 83 insertions(+) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 51a3e16275..8e1016cfd6 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -842,6 +842,8 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, #ifdef TARGET_AARCH64 int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +unsigned aarch64_get_sve_vlen(CPUARMState *env); +unsigned aarch64_set_sve_vlen(CPUARMState *env, unsigned vlen); #endif target_ulong do_arm_semihosting(CPUARMState *env); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 82b35a6bdf..4840bf502f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -10659,6 +10659,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; } #endif +#ifdef TARGET_AARCH64 +case 50: /* PR_SVE_SET_VL */ +/* We cannot support either PR_SVE_SET_VL_ONEXEC + or PR_SVE_VL_INHERIT. Therefore, anything above + ARM_MAX_VQ results in EINVAL. */ +if (!arm_feature(cpu_env, ARM_FEATURE_SVE) +|| arg2 > ARM_MAX_VQ * 16 || arg2 & 15) { +ret = -TARGET_EINVAL; +} else { +ret = aarch64_set_sve_vlen(cpu_env, arg2); +} +break; +case 51: /* PR_SVE_GET_VL */ +if (arm_feature(cpu_env, ARM_FEATURE_SVE)) { +ret = aarch64_get_sve_vlen(cpu_env); +} else { +ret = -TARGET_EINVAL; +} +break; +#endif /* AARCH64 */ case PR_GET_SECCOMP: case PR_SET_SECCOMP: /* Disable seccomp to prevent the target disabling syscalls we diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 1c330adc28..6dee78f006 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -363,3 +363,64 @@ static void aarch64_cpu_register_types(void) } type_init(aarch64_cpu_register_types) + +/* Return the current cumulative SVE VLEN. */ +unsigned aarch64_get_sve_vlen(CPUARMState *env) +{ +return ((env->vfp.zcr_el[1] & 0xf) + 1) * 16; +} + +/* Set the cumulative ZCR.EL to VLEN, or the nearest supported value. + Return the new value. */ +unsigned aarch64_set_sve_vlen(CPUARMState *env, unsigned vl) +{ +unsigned vq = vl / 16; +unsigned old_vq = (env->vfp.zcr_el[1] & 0xf) + 1; + +if (vq < 1) { +vq = 1; +} else if (vq > ARM_MAX_VQ) { +vq = ARM_MAX_VQ; +} +env->vfp.zcr_el[1] = vq - 1; + +/* The manual sez that when SVE is enabled and VL is widened the + * implementation is allowed to zero the previously inaccessible + * portion of the registers. The corollary to that is that when + * SVE is enabled and VL is narrowed we are also allowed to zero + * the now inaccessible portion of the registers. + * + * The intent of this is that no predicate bit beyond VL is ever set. + * Which means that some operations on predicate registers themselves + * may operate on full uint64_t or even unrolled across the maximum + * uint64_t[4]. Performing 4 bits of host arithmetic unconditionally + * may well be cheaper than conditionals to restrict to the operation + * to the relevant portion of a uint16_t[16]. + * + * ??? Need to move this somewhere else, so that it applies to + * changes to the real system registers and EL state changes. + */ +if (vq < old_vq) { +unsigned i, j; +uint64_t pmask; + +/* Zap the high bits of the zregs. */ +for (i = 0; i < 32; i++) { +memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq)); +} + +/* Zap the high bits of the pregs and ffr. */ +pmask = 0; +if (vq & 3) { +pmask = ~(-1ULL << (16 * (vq & 3))); +} +for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) { +for (i = 0; i < 17; ++i) { +env->vfp.pregs[i].p[j] &= pmask; +} +pmask = 0; +} +} + +return vq * 16; +} -- 2.14.3
[Qemu-devel] [PATCH v2 6/7] linux-user: Support SVE in aarch64 signal frames
Signed-off-by: Richard Henderson --- linux-user/signal.c | 348 ++-- 1 file changed, 283 insertions(+), 65 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 9a380b9e31..af953175db 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -1443,35 +1443,61 @@ struct target_fpsimd_context { uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */ }; -/* - * Auxiliary context saved in the sigcontext.__reserved array. Not exported to - * user space as it will change with the addition of new context. User space - * should check the magic/size information. - */ -struct target_aux_context { -struct target_fpsimd_context fpsimd; -/* additional context to be added before "end" */ -struct target_aarch64_ctx end; +#define TARGET_EXTRA_MAGIC 0x45585401 + +struct target_extra_context { +struct target_aarch64_ctx head; +uint64_t datap; /* 16-byte aligned pointer to extra space cast to __u64 */ +uint32_t size; /* size in bytes of the extra space */ +uint32_t reserved[3]; +}; + +#define TARGET_SVE_MAGIC0x53564501 + +struct target_sve_context { +struct target_aarch64_ctx head; +uint16_t vl; +uint16_t reserved[3]; }; +#define TARGET_SVE_VQ_BYTES 16 + +#define TARGET_SVE_SIG_ZREG_SIZE(VQ) ((VQ) * TARGET_SVE_VQ_BYTES) +#define TARGET_SVE_SIG_PREG_SIZE(VQ) ((VQ) * (TARGET_SVE_VQ_BYTES / 8)) + +#define TARGET_SVE_SIG_REGS_OFFSET \ +QEMU_ALIGN_UP(sizeof(struct target_sve_context), TARGET_SVE_VQ_BYTES) +#define TARGET_SVE_SIG_ZREG_OFFSET(VQ, N) \ +(TARGET_SVE_SIG_REGS_OFFSET + TARGET_SVE_SIG_ZREG_SIZE(VQ) * (N)) +#define TARGET_SVE_SIG_PREG_OFFSET(VQ, N) \ +(TARGET_SVE_SIG_ZREG_OFFSET(VQ, 32) + TARGET_SVE_SIG_PREG_SIZE(VQ) * (N)) +#define TARGET_SVE_SIG_FFR_OFFSET(VQ) \ +(TARGET_SVE_SIG_PREG_OFFSET(VQ, 16)) +#define TARGET_SVE_SIG_CONTEXT_SIZE(VQ) \ +(TARGET_SVE_SIG_PREG_OFFSET(VQ, 17)) + struct target_rt_sigframe { struct target_siginfo info; struct target_ucontext uc; +}; + +struct target_rt_frame_record { uint64_t fp; uint64_t lr; uint32_t tramp[2]; }; -static int target_setup_sigframe(struct target_rt_sigframe *sf, - CPUARMState *env, target_sigset_t *set) +static void target_setup_general_frame(struct target_rt_sigframe *sf, + CPUARMState *env, target_sigset_t *set) { int i; -struct target_aux_context *aux = -(struct target_aux_context *)sf->uc.tuc_mcontext.__reserved; -/* set up the stack frame for unwinding */ -__put_user(env->xregs[29], &sf->fp); -__put_user(env->xregs[30], &sf->lr); +__put_user(0, &sf->uc.tuc_flags); +__put_user(0, &sf->uc.tuc_link); + +__put_user(target_sigaltstack_used.ss_sp, &sf->uc.tuc_stack.ss_sp); +__put_user(sas_ss_flags(env->xregs[31]), &sf->uc.tuc_stack.ss_flags); +__put_user(target_sigaltstack_used.ss_size, &sf->uc.tuc_stack.ss_size); for (i = 0; i < 31; i++) { __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]); @@ -1485,39 +1511,79 @@ static int target_setup_sigframe(struct target_rt_sigframe *sf, for (i = 0; i < TARGET_NSIG_WORDS; i++) { __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]); } +} + +static void target_setup_end_record(struct target_aarch64_ctx *end) +{ +__put_user(0, &end->magic); +__put_user(0, &end->size); +} + +static void target_setup_fpsimd_record(struct target_fpsimd_context *fpsimd, + CPUARMState *env) +{ +int i; + +__put_user(TARGET_FPSIMD_MAGIC, &fpsimd->head.magic); +__put_user(sizeof(struct target_fpsimd_context), &fpsimd->head.size); +__put_user(vfp_get_fpsr(env), &fpsimd->fpsr); +__put_user(vfp_get_fpcr(env), &fpsimd->fpcr); for (i = 0; i < 32; i++) { uint64_t *q = aa64_vfp_qreg(env, i); #ifdef TARGET_WORDS_BIGENDIAN -__put_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]); -__put_user(q[1], &aux->fpsimd.vregs[i * 2]); +__put_user(q[0], &fpsimd->vregs[i * 2 + 1]); +__put_user(q[1], &fpsimd->vregs[i * 2]); #else -__put_user(q[0], &aux->fpsimd.vregs[i * 2]); -__put_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]); +__put_user(q[0], &fpsimd->vregs[i * 2]); +__put_user(q[1], &fpsimd->vregs[i * 2 + 1]); #endif } -__put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr); -__put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr); -__put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic); -__put_user(sizeof(struct target_fpsimd_context), -&aux->fpsimd.head.size); +} -/* set the "end" magic */ -__put_user(0, &aux->end.magic); -__put_user(0, &aux->end.size); +static void target_setup_extra_record(struct target_extra_context *extra, + uint64_t datap, uint32_t extra_size) +{ +__put_user(TARGET_EXTRA_MAGIC, &extra->head.magic); +
[Qemu-devel] [PATCH v2] scripts: Add decodetree.py
To be used to decode ARM SVE, but could be used for any fixed-width ISA. Signed-off-by: Richard Henderson --- Changes since v1: * Pass pycodestyle-{2,3}. * Support 16-bit and 32-bit insns (I have a def file for thumb1). * Testsuite (only negative tests so far). * Called translate functions default to static. * Notice duplicate assignments and missing assignments to fields. * Use '-' to indicate a non-decoded bit, as opposed to '.' which must be filled in elsewhere by a format or a field. --- scripts/decodetree.py | 1026 + tests/Makefile.include|9 +- tests/decode/check.sh | 16 + tests/decode/err_argset1.def |1 + tests/decode/err_argset2.def |1 + tests/decode/err_field1.def |1 + tests/decode/err_field2.def |1 + tests/decode/err_field3.def |1 + tests/decode/err_field4.def |2 + tests/decode/err_field5.def |1 + tests/decode/err_init1.def|2 + tests/decode/err_init2.def|2 + tests/decode/err_init3.def|3 + tests/decode/err_init4.def|3 + tests/decode/err_overlap1.def |2 + tests/decode/err_overlap2.def |2 + tests/decode/err_overlap3.def |2 + tests/decode/err_overlap4.def |2 + tests/decode/err_overlap5.def |1 + tests/decode/err_overlap6.def |2 + tests/decode/err_overlap7.def |2 + 21 files changed, 1081 insertions(+), 1 deletion(-) create mode 100755 scripts/decodetree.py create mode 100755 tests/decode/check.sh create mode 100644 tests/decode/err_argset1.def create mode 100644 tests/decode/err_argset2.def create mode 100644 tests/decode/err_field1.def create mode 100644 tests/decode/err_field2.def create mode 100644 tests/decode/err_field3.def create mode 100644 tests/decode/err_field4.def create mode 100644 tests/decode/err_field5.def create mode 100644 tests/decode/err_init1.def create mode 100644 tests/decode/err_init2.def create mode 100644 tests/decode/err_init3.def create mode 100644 tests/decode/err_init4.def create mode 100644 tests/decode/err_overlap1.def create mode 100644 tests/decode/err_overlap2.def create mode 100644 tests/decode/err_overlap3.def create mode 100644 tests/decode/err_overlap4.def create mode 100644 tests/decode/err_overlap5.def create mode 100644 tests/decode/err_overlap6.def create mode 100644 tests/decode/err_overlap7.def diff --git a/scripts/decodetree.py b/scripts/decodetree.py new file mode 100755 index 00..3c20acf700 --- /dev/null +++ b/scripts/decodetree.py @@ -0,0 +1,1026 @@ +#!/usr/bin/env python +# +# Generate a decoding tree from a specification file. +# +# The tree is built from instruction "patterns". A pattern may represent +# a single architectural instruction or a group of same, depending on what +# is convenient for further processing. +# +# Each pattern has "fixedbits" & "fixedmask", the combination of which +# describes the condition under which the pattern is matched: +# +# (insn & fixedmask) == fixedbits +# +# Each pattern may have "fields", which are extracted from the insn and +# passed along to the translator. Examples of such are registers, +# immediates, and sub-opcodes. +# +# In support of patterns, one may declare fields, argument sets, and +# formats, each of which may be re-used to simplify further definitions. +# +# *** Field syntax: +# +# field_def := '%' identifier ( unnamed_field )+ ( !function=identifier )? +# unnamed_field := number ':' ( 's' ) number +# +# For unnamed_field, the first number is the least-significant bit position of +# the field and the second number is the length of the field. If the 's' is +# present, the field is considered signed. If multiple unnamed_fields are +# present, they are concatenated. In this way one can define disjoint fields. +# +# If !function is specified, the concatenated result is passed through the +# named function, taking and returning an integral value. +# +# FIXME: the fields of the structure into which this result will be stored +# is restricted to "int". Which means that we cannot expand 64-bit items. +# +# Field examples: +# +# %disp 0:s16 -- sextract(i, 0, 16) +# %imm9 16:6 10:3 -- extract(i, 16, 6) << 3 | extract(i, 10, 3) +# %disp12 0:s1 1:1 2:10 -- sextract(i, 0, 1) << 11 +# | extract(i, 1, 1) << 10 +# | extract(i, 2, 10) +# %shimm8 5:s8 13:1 !function=expand_shimm8 +# -- expand_shimm8(sextract(i, 5, 8) << 1 +# | extract(i, 13, 1)) +# +# *** Argument set syntax: +# +# args_def:= '&' identifier ( args_elt )+ +# args_elt:= identifier +# +# Each args_elt defines an argument within the argument set. +# Each argument set will be rendered as a C structure "arg_$name" +# with each of the fields being one of the member arguments. +# +# Argument set examples: +# +# ®3 ra rb rc +# &loadstore reg base
Re: [Qemu-devel] [PATCH v2 02/19] spapr: introduce a skeleton for the XIVE interrupt controller
On Sun, 2018-02-11 at 19:08 +1100, David Gibson wrote: > On Thu, Jan 18, 2018 at 08:27:52AM +1100, Benjamin Herrenschmidt wrote: > > On Wed, 2018-01-17 at 15:39 +0100, Cédric Le Goater wrote: > > > Migration is a problem. We will need both backend QEMU objects to be > > > available anyhow if we want to migrate. So we are back to the current > > > solution creating both QEMU objects but we can try to defer some of the > > > KVM inits and create the KVM device on demand at CAS time. > > > > Do we have a way to migrate a piece of info from the machine *first* > > that indicate what type of XICS/XIVE to instanciate ? > > Nope. qemu migration doesn't work like that. Yes, it should, and > everyone knows it, but changing it is a really long term project. Well, we have a problem then. It looks like Qemu broken migration is fundamentally incompatible with PAPR and CAS design... I know we don't migrate the configuration, that's not exactly what I had in mind tho... Can we have some piece of *data* from the machine be migrated first, and use it on the target to reconfigure the interrupt controller before the stream arrives ? Otherwise, we have indeed no much choice but the horrible wart of creating both interrupt controllers with only one "active". > > > > > The next problem is the ICP object that currently needs the KVM device > > > fd to connect the vcpus ... So, we will need to change that also. > > > That is probably the biggest problem today. We need a way to disconnect > > > the vpcu from the KVM device and see how we can defer the connection. > > > I need to make sure this is possible, I can check that without XIVE > > > > Ben. > > > >
Re: [Qemu-devel] [PATCH v2] scripts: Add decodetree.py
> Changes since v1: > * Pass pycodestyle-{2,3}. > * Support 16-bit and 32-bit insns (I have a def file for thumb1). For the record, here's the thumb1 definition. ./scripts/decodetree.py -w16 thumb1.def r~ %reg_0_77:1 0:3 @rd_rs .. rs:3 rd:3 @rt_rn_rm ... rm:3 rn:3 rt:3 @rd_rn_rm ... rm:3 rn:3 rd:3 @rd_rn_i3 ... imm:3 rn:3 rd:3 @rt_rn_i5 . imm:5 rn:3 rt:3 @rd_i8 . rd:3 imm:8 @rn_reglist . rn:3 reglist:8 Data Processing (two low registers) AND 01 ... ... @rd_rs EOR 01 0001 ... ... @rd_rs MOV_lsl 01 0010 ... ... @rd_rs MOV_lsr 01 0011 ... ... @rd_rs MOV_asr 01 0100 ... ... @rd_rs ADC 01 0101 ... ... @rd_rs SBC 01 0110 ... ... @rd_rs MOV_ror 01 0111 ... ... @rd_rs TST 01 1000 ... ... @rd_rs RSB 01 1001 ... ... @rd_rs CMP_rr 01 1010 ... ... @rd_rs CMN 01 1011 ... ... @rd_rs ORR 01 1100 ... ... @rd_rs MUL 01 1101 ... ... @rd_rs BIC 01 1110 ... ... @rd_rs MVN 01 ... ... @rd_rs Load/store (register offset) STR_rr 0101 000 ... ... ...@rt_rn_rm STRH_rr 0101 001 ... ... ...@rt_rn_rm STRB_rr 0101 010 ... ... ...@rt_rn_rm LDRSB_rr0101 011 ... ... ...@rt_rn_rm LDR_rr 0101 100 ... ... ...@rt_rn_rm LDRH_rr 0101 101 ... ... ...@rt_rn_rm LDRB_rr 0101 110 ... ... ...@rt_rn_rm LDRSH_rr0101 111 ... ... ...@rt_rn_rm Load/store word/byte (immediate offset) STR_ri 01100 . ... ... @rt_rn_i5 LDR_ri 01101 . ... ... @rt_rn_i5 STRB_ri 01110 . ... ... @rt_rn_i5 LDRB_ri 0 . ... ... @rt_rn_i5 Load/store halfword (immediate offset) STRH_ri 1 . ... ... @rt_rn_i5 LDRH_ri 10001 . ... ... @rt_rn_i5 Add PC/SP (immediate) ADR 10100 ... @rd_i8 ADD_sp 10101 ... @rd_i8 Load/store multiple STM 11000 ... @rn_reglist LDM 11001 ... @rn_reglist Add/subtract (three low registers) ADD_rrr 0001100 ... ... ... @rd_rn_rm SUB_rrr 0001101 ... ... ... @rd_rn_rm Add/subtract (two low registers and immediate) ADD_rri 0001 110 ... ... ...@rd_rn_i3 SUB_rri 0001 111 ... ... ...@rd_rn_i3 Add, subtract, compare, move (one low register and immediate) MOV_ri 00100 ... @rd_i8 CMP_ri 00101 ... @rd_i8 ADD_ri 00110 ... @rd_i8 SUB_ri 00111 ... @rd_i8 Branch and exchange BX 0100 0111 0 rm:4 000 BLX 0100 0111 1 rm:4 000 Add, subtract, compare, move (two high registers) ADD_rrr 0100 0100 . rm:4 ...rd=%reg_0_7 rn=%reg_0_7 CMP_rr 0100 0101 . rs:4 ...rd=%reg_0_7 MOV_rr 0100 0110 . rs:4 ...rd=%reg_0_7 Adjust SP (immediate) ADD_rri 1011 0 imm:7 rd=13 rn=13 SUB_rri 1011 1 imm:7 rd=13 rn=13 Extend SXTH1011 0010 00 ... ...@rd_rs SXTB1011 0010 01 ... ...@rd_rs UXTH1011 0010 10 ... ...@rd_rs UXTB1011 0010 11 ... ...@rd_rs Change processor state SETEND 1011 0110 010 flags:5 CPS 1011 0110 011 flags:5 Reverse bytes REV 1011 1010 00 ... ...@rd_rs REV16 1011 1010 01 ... ...@rd_rs REVSH 1011 1010 11 ... ...@rd_rs Hints NOP 1011 YIELD 1011 0001 WFE 1011 0010 WFI 1011 0011 SEV 1011 0100 SEVL1011 0101 NOP 1011 011- # Reserved hint NOP 1011 1--- # Reserved hint Push and Pop PUSH1011 010 reglist:9 POP 1011 110 reglist:9 Conditional branches Bcond 1101 0 cond:3 imm:8 Bcond 1101 1000 imm:8 cond=8 Bcond 1101 1001 imm:8 cond=9 Bcond 1101 1010 imm:8 cond=10 Bcond 1101 1011 imm:8 cond=11 Bcond 1101 1100 imm:8 cond=12 Bcond 1101 1101 imm:8 cond=13 Exception generation UDF 1101 1110 imm:8 SVC 1101 imm:8
Re: [Qemu-devel] [PATCH v2] scripts: Add decodetree.py
Hi, This series failed docker-quick@centos6 build test. Please find the testing commands and their output below. If you have Docker installed, you can probably reproduce it locally. Type: series Message-id: 20180211224656.12767-1-richard.hender...@linaro.org Subject: [Qemu-devel] [PATCH v2] scripts: Add decodetree.py === TEST SCRIPT BEGIN === #!/bin/bash set -e git submodule update --init dtc # Let docker tests dump environment info export SHOW_ENV=1 export J=8 time make docker-test-quick@centos6 === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Switched to a new branch 'test' 1d531c8d23 scripts: Add decodetree.py === OUTPUT BEGIN === Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc' Cloning into '/var/tmp/patchew-tester-tmp-_dti_j7r/src/dtc'... Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42' BUILD centos6 GEN /var/tmp/patchew-tester-tmp-_dti_j7r/src/docker-src.2018-02-11-17.56.03.1101/qemu.tar Cloning into '/var/tmp/patchew-tester-tmp-_dti_j7r/src/docker-src.2018-02-11-17.56.03.1101/qemu.tar.vroot'... done. Checking out files: 50% (2923/5827) Checking out files: 51% (2972/5827) Checking out files: 52% (3031/5827) Checking out files: 53% (3089/5827) Checking out files: 54% (3147/5827) Checking out files: 55% (3205/5827) Checking out files: 56% (3264/5827) Checking out files: 57% (3322/5827) Checking out files: 58% (3380/5827) Checking out files: 59% (3438/5827) Checking out files: 60% (3497/5827) Checking out files: 61% (3555/5827) Checking out files: 62% (3613/5827) Checking out files: 63% (3672/5827) Checking out files: 64% (3730/5827) Checking out files: 65% (3788/5827) Checking out files: 66% (3846/5827) Checking out files: 67% (3905/5827) Checking out files: 68% (3963/5827) Checking out files: 69% (4021/5827) Checking out files: 70% (4079/5827) Checking out files: 71% (4138/5827) Checking out files: 72% (4196/5827) Checking out files: 73% (4254/5827) Checking out files: 74% (4312/5827) Checking out files: 75% (4371/5827) Checking out files: 76% (4429/5827) Checking out files: 77% (4487/5827) Checking out files: 78% (4546/5827) Checking out files: 79% (4604/5827) Checking out files: 80% (4662/5827) Checking out files: 81% (4720/5827) Checking out files: 82% (4779/5827) Checking out files: 83% (4837/5827) Checking out files: 84% (4895/5827) Checking out files: 85% (4953/5827) Checking out files: 86% (5012/5827) Checking out files: 87% (5070/5827) Checking out files: 88% (5128/5827) Checking out files: 89% (5187/5827) Checking out files: 90% (5245/5827) Checking out files: 91% (5303/5827) Checking out files: 92% (5361/5827) Checking out files: 93% (5420/5827) Checking out files: 94% (5478/5827) Checking out files: 95% (5536/5827) Checking out files: 96% (5594/5827) Checking out files: 97% (5653/5827) Checking out files: 97% (5659/5827) Checking out files: 98% (5711/5827) Checking out files: 99% (5769/5827) Checking out files: 100% (5827/5827) Checking out files: 100% (5827/5827), done. Your branch is up-to-date with 'origin/test'. Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc' Cloning into '/var/tmp/patchew-tester-tmp-_dti_j7r/src/docker-src.2018-02-11-17.56.03.1101/qemu.tar.vroot/dtc'... Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42' Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered for path 'ui/keycodemapdb' Cloning into '/var/tmp/patchew-tester-tmp-_dti_j7r/src/docker-src.2018-02-11-17.56.03.1101/qemu.tar.vroot/ui/keycodemapdb'... Submodule path 'ui/keycodemapdb': checked out '6b3d716e2b6472eb7189d3220552280ef3d832ce' COPYRUNNER RUN test-quick in qemu:centos6 Packages installed: SDL-devel-1.2.14-7.el6_7.1.x86_64 bison-2.4.1-5.el6.x86_64 bzip2-devel-1.0.5-7.el6_0.x86_64 ccache-3.1.6-2.el6.x86_64 csnappy-devel-0-6.20150729gitd7bc683.el6.x86_64 flex-2.5.35-9.el6.x86_64 gcc-4.4.7-18.el6.x86_64 gettext-0.17-18.el6.x86_64 git-1.7.1-9.el6_9.x86_64 glib2-devel-2.28.8-9.el6.x86_64 libepoxy-devel-1.2-3.el6.x86_64 libfdt-devel-1.4.0-1.el6.x86_64 librdmacm-devel-1.0.21-0.el6.x86_64 lzo-devel-2.03-3.1.el6_5.1.x86_64 make-3.81-23.el6.x86_64 mesa-libEGL-devel-11.0.7-4.el6.x86_64 mesa-libgbm-devel-11.0.7-4.el6.x86_64 package g++ is not installed pixman-devel-0.32.8-1.el6.x86_64 spice-glib-devel-0.26-8.el6.x86_64 spice-server-devel-0.12.4-16.el6.x86_64 tar-1.23-15.el6_8.x86_64 vte-devel-0.25.1-9.el6.x86_64 xen-devel-4.6.6-2.el6.x86_64 zlib-devel-1.2.3-29.el6.x86_64 Environment variables: PACKAGES=bison bzip2-devel ccache csnappy-devel flex g++ gcc gettext git glib2-devel libepoxy-devel libfdt-devel librdmacm-devel lzo-devel make mesa-libEGL-devel m
Re: [Qemu-devel] [PATCH v2 1/2] hw/arm/aspeed: directly map the serial device to the system address space
On Fri, 2018-02-09 at 05:57 -0300, Philippe Mathieu-Daudé wrote: > (qemu) info mtree > address-space: cpu-memory-0 >- (prio 0, i/o): system > -07ff (prio 0, rom): aspeed.boot_rom > 1e60-1e7f (prio -1, i/o): aspeed_soc.io > - 1e784000-1e78401f (prio 0, i/o): serial > 1e62-1e6200ff (prio 0, i/o): > aspeed.smc.ast2500-fmc > 1e63-1e6300ff (prio 0, i/o): > aspeed.smc.ast2500-spi1 > [...] > 1e72-1e728fff (prio 0, ram): aspeed.sram > 1e782000-1e782fff (prio 0, i/o): aspeed.timer > +1e784000-1e78401f (prio 0, i/o): serial > 1e785000-1e78501f (prio 0, i/o): aspeed.wdt > 1e785020-1e78503f (prio 0, i/o): aspeed.wdt > > Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Andrew Jeffery > --- > hw/arm/aspeed_soc.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c > index c83b7e207b..2a5d041b3b 100644 > --- a/hw/arm/aspeed_soc.c > +++ b/hw/arm/aspeed_soc.c > @@ -257,7 +257,8 @@ static void aspeed_soc_realize(DeviceState *dev, > Error **errp) > /* UART - attach an 8250 to the IO space as our UART5 */ > if (serial_hds[0]) { > qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), > uart_irqs[4]); > -serial_mm_init(&s->iomem, ASPEED_SOC_UART_5_BASE, 2, > +serial_mm_init(get_system_memory(), > + ASPEED_SOC_IOMEM_BASE + > ASPEED_SOC_UART_5_BASE, 2, > uart5, 38400, serial_hds[0], > DEVICE_LITTLE_ENDIAN); > } > signature.asc Description: This is a digitally signed message part
Re: [Qemu-devel] [PATCH v2 2/2] hw/arm/aspeed: simplify using the 'unimplemented device' for aspeed_soc.io
On Fri, 2018-02-09 at 05:57 -0300, Philippe Mathieu-Daudé wrote: > (qemu) info mtree > address-space: cpu-memory-0 >- (prio 0, i/o): system > -07ff (prio 0, rom): aspeed.boot_rom > -1e60-1e7f (prio -1, i/o): aspeed_soc.io > +1e60-1e7f (prio -1000, i/o): aspeed_soc.io > 1e62-1e6200ff (prio 0, i/o): aspeed.smc.ast2500-fmc > 1e63-1e6300ff (prio 0, i/o): aspeed.smc.ast2500-spi1 > 1e631000-1e6310ff (prio 0, i/o): aspeed.smc.ast2500-spi2 > > Signed-off-by: Philippe Mathieu-Daudé > Reviewed-by: Cédric Le Goater Reviewed-by: Andrew Jeffery > --- > include/hw/arm/aspeed_soc.h | 1 - > hw/arm/aspeed_soc.c | 32 +++- > 2 files changed, 3 insertions(+), 30 deletions(-) > > diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h > index f26914a2b9..11ec0179db 100644 > --- a/include/hw/arm/aspeed_soc.h > +++ b/include/hw/arm/aspeed_soc.h > @@ -31,7 +31,6 @@ typedef struct AspeedSoCState { > > /*< public >*/ > ARMCPU cpu; > -MemoryRegion iomem; > MemoryRegion sram; > AspeedVICState vic; > AspeedTimerCtrlState timerctrl; > diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c > index 2a5d041b3b..30d25f8b06 100644 > --- a/hw/arm/aspeed_soc.c > +++ b/hw/arm/aspeed_soc.c > @@ -15,6 +15,7 @@ > #include "qemu-common.h" > #include "cpu.h" > #include "exec/address-spaces.h" > +#include "hw/misc/unimp.h" > #include "hw/arm/aspeed_soc.h" > #include "hw/char/serial.h" > #include "qemu/log.h" > @@ -99,31 +100,6 @@ static const AspeedSoCInfo aspeed_socs[] = { > }, > }; > > -/* > - * IO handlers: simply catch any reads/writes to IO addresses that aren't > - * handled by a device mapping. > - */ > - > -static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size) > -{ > -qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n", > - __func__, offset, size); > -return 0; > -} > - > -static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value, > -unsigned size) > -{ > -qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " > [%u]\n", > - __func__, offset, value, size); > -} > - > -static const MemoryRegionOps aspeed_soc_io_ops = { > -.read = aspeed_soc_io_read, > -.write = aspeed_soc_io_write, > -.endianness = DEVICE_LITTLE_ENDIAN, > -}; > - > static void aspeed_soc_init(Object *obj) > { > AspeedSoCState *s = ASPEED_SOC(obj); > @@ -199,10 +175,8 @@ static void aspeed_soc_realize(DeviceState *dev, Error > **errp) > Error *err = NULL, *local_err = NULL; > > /* IO space */ > -memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL, > -"aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE); > -memory_region_add_subregion_overlap(get_system_memory(), > -ASPEED_SOC_IOMEM_BASE, &s->iomem, > -1); > +create_unimplemented_device("aspeed_soc.io", > +ASPEED_SOC_IOMEM_BASE, > ASPEED_SOC_IOMEM_SIZE); > > /* CPU */ > object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err); signature.asc Description: This is a digitally signed message part
Re: [Qemu-devel] [PATCH v6 00/28] Migration: postcopy failure recovery
Hi, This series failed build test on ppc host. Please find the details below. Type: series Message-id: 20180208103132.28452-1-pet...@redhat.com Subject: [Qemu-devel] [PATCH v6 00/28] Migration: postcopy failure recovery === TEST SCRIPT BEGIN === #!/bin/bash # Testing script will be invoked under the git checkout with # HEAD pointing to a commit that has the patches applied on top of "base" # branch set -e echo "=== ENV ===" env echo "=== PACKAGES ===" rpm -qa echo "=== TEST BEGIN ===" INSTALL=$PWD/install BUILD=$PWD/build mkdir -p $BUILD $INSTALL SRC=$PWD cd $BUILD $SRC/configure --prefix=$INSTALL make -j100 # XXX: we need reliable clean up # make check -j100 V=1 make install === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 Submodule 'capstone' (git://git.qemu.org/capstone.git) registered for path 'capstone' Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc' Submodule 'roms/QemuMacDrivers' (git://git.qemu.org/QemuMacDrivers.git) registered for path 'roms/QemuMacDrivers' Submodule 'roms/SLOF' (git://git.qemu-project.org/SLOF.git) registered for path 'roms/SLOF' Submodule 'roms/ipxe' (git://git.qemu-project.org/ipxe.git) registered for path 'roms/ipxe' Submodule 'roms/openbios' (git://git.qemu-project.org/openbios.git) registered for path 'roms/openbios' Submodule 'roms/openhackware' (git://git.qemu-project.org/openhackware.git) registered for path 'roms/openhackware' Submodule 'roms/qemu-palcode' (git://github.com/rth7680/qemu-palcode.git) registered for path 'roms/qemu-palcode' Submodule 'roms/seabios' (git://git.qemu-project.org/seabios.git/) registered for path 'roms/seabios' Submodule 'roms/seabios-hppa' (git://github.com/hdeller/seabios-hppa.git) registered for path 'roms/seabios-hppa' Submodule 'roms/sgabios' (git://git.qemu-project.org/sgabios.git) registered for path 'roms/sgabios' Submodule 'roms/skiboot' (git://git.qemu.org/skiboot.git) registered for path 'roms/skiboot' Submodule 'roms/u-boot' (git://git.qemu-project.org/u-boot.git) registered for path 'roms/u-boot' Submodule 'roms/vgabios' (git://git.qemu-project.org/vgabios.git/) registered for path 'roms/vgabios' Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered for path 'ui/keycodemapdb' Cloning into 'capstone'... Submodule path 'capstone': checked out '22ead3e0bfdb87516656453336160e0a37b066bf' Cloning into 'dtc'... Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42' Cloning into 'roms/QemuMacDrivers'... Submodule path 'roms/QemuMacDrivers': checked out 'd4e7d7ac663fcb55f1b93575445fcbca372f17a7' Cloning into 'roms/SLOF'... Submodule path 'roms/SLOF': checked out 'fa981320a1e0968d6fc1b8de319723ff8212b337' Cloning into 'roms/ipxe'... Submodule path 'roms/ipxe': checked out '0600d3ae94f93efd10fc6b3c7420a9557a3a1670' Cloning into 'roms/openbios'... Submodule path 'roms/openbios': checked out 'b5c93acd14b7b3886c2c81d84cd18e666984a4c8' Cloning into 'roms/openhackware'... Submodule path 'roms/openhackware': checked out 'c559da7c8eec5e45ef1f67978827af6f0b9546f5' Cloning into 'roms/qemu-palcode'... Submodule path 'roms/qemu-palcode': checked out 'f3c7e44c70254975df2a00af39701eafbac4d471' Cloning into 'roms/seabios'... Submodule path 'roms/seabios': checked out '63451fca13c75870e1703eb3e20584d91179aebc' Cloning into 'roms/seabios-hppa'... Submodule path 'roms/seabios-hppa': checked out '649e6202b8d65d46c69f542b1380f840fbe8ab13' Cloning into 'roms/sgabios'... Submodule path 'roms/sgabios': checked out 'cbaee52287e5f32373181cff50a00b6c4ac9015a' Cloning into 'roms/skiboot'... Submodule path 'roms/skiboot': checked out 'e0ee24c27a172bcf482f6f2bc905e6211c134bcc' Cloning into 'roms/u-boot'... Submodule path 'roms/u-boot': checked out 'd85ca029f257b53a96da6c2fb421e78a003a9943' Cloning into 'roms/vgabios'... Submodule path 'roms/vgabios': checked out '19ea12c230ded95928ecaef0db47a82231c2e485' Cloning into 'ui/keycodemapdb'... Submodule path 'ui/keycodemapdb': checked out '6b3d716e2b6472eb7189d3220552280ef3d832ce' Switched to a new branch 'test' 9fef7a4 migration/hmp: add migrate_pause command e5bc884 migration/qmp: add command migrate-pause ae62f07 hmp/migration: add migrate_recover command b6a9d72 qmp/migration: new command migrate-recover 9903aa7 io: let watcher of the channel run in same ctx ef37cc9 migration: init dst in migration_object_init too b9a7a63 migration: final handshake for the resume 40d1c0e migration: setup ramstate for resume 4faada9 migration: synchronize dirty bitmap for resume 1c86b22 migration: introduce SaveVMHandlers.resume_prepare 99d5d3e migration: new message MIG_RP_MSG_RESUME_ACK 011a3e5 migration: new cmd MIG_CMD_POSTCOPY_RESUME e8ea13a migration: new message MIG_RP_MSG_RECV_BITMAP 0527218 migration: new cmd MIG_CMD_RECV_BITMAP 060b476 migration: wakeup dst ram-load-thread for recover 5c512af migration: new state "postcopy-recover" 3c817a2 migration: rebuild channel on source 498feb3 migration: pa
Re: [Qemu-devel] [PATCH v2 02/19] spapr: introduce a skeleton for the XIVE interrupt controller
On 12/02/18 09:55, Benjamin Herrenschmidt wrote: > On Sun, 2018-02-11 at 19:08 +1100, David Gibson wrote: >> On Thu, Jan 18, 2018 at 08:27:52AM +1100, Benjamin Herrenschmidt wrote: >>> On Wed, 2018-01-17 at 15:39 +0100, Cédric Le Goater wrote: Migration is a problem. We will need both backend QEMU objects to be available anyhow if we want to migrate. So we are back to the current solution creating both QEMU objects but we can try to defer some of the KVM inits and create the KVM device on demand at CAS time. >>> >>> Do we have a way to migrate a piece of info from the machine *first* >>> that indicate what type of XICS/XIVE to instanciate ? >> >> Nope. qemu migration doesn't work like that. Yes, it should, and >> everyone knows it, but changing it is a really long term project. > > Well, we have a problem then. It looks like Qemu broken migration is > fundamentally incompatible with PAPR and CAS design... > > I know we don't migrate the configuration, that's not exactly what I > had in mind tho... Can we have some piece of *data* from the machine be > migrated first, and use it on the target to reconfigure the interrupt > controller before the stream arrives ? These days this is done via libvirt - it reads properties it needs via QMP, then sends an XML with everything (the interrupt controller type may be one of such properties), and starts the destination QEMU with the explicit interrupt controller (like -machine pseries,intrc=xive). Hacking QEMU to do all of this is still in a distant TODO... > Otherwise, we have indeed no much choice but the horrible wart of > creating both interrupt controllers with only one "active". > >>> The next problem is the ICP object that currently needs the KVM device fd to connect the vcpus ... So, we will need to change that also. That is probably the biggest problem today. We need a way to disconnect the vpcu from the KVM device and see how we can defer the connection. I need to make sure this is possible, I can check that without XIVE -- Alexey
Re: [Qemu-devel] [PATCH RFC/D] docs: document our stable process
Quoting Cornelia Huck (2018-02-09 07:11:12) > Some pointers on how to get a patch into stable. Thanks for putting this together. I made some minor suggestions below that might help clarify some points. > > Signed-off-by: Cornelia Huck > --- > > This probably needs more love, but I'd like to have at least _some_ > kind of documentation. > > Maybe this should also go into the wiki? We can probably add a reference to it in: https://wiki.qemu.org/Contribute/SubmitAPatch I should probably add a MAINTAINERS entry for stable that references it too. > > --- > docs/stable-process.rst | 57 > + > 1 file changed, 57 insertions(+) > create mode 100644 docs/stable-process.rst > > diff --git a/docs/stable-process.rst b/docs/stable-process.rst > new file mode 100644 > index 00..2502823dc5 > --- /dev/null > +++ b/docs/stable-process.rst > @@ -0,0 +1,57 @@ > +QEMU and the stable process > +=== > + > +QEMU stable releases > + > + > +QEMU stable releases are based upon the last released QEMU version > +and marked by an additional version number, e.g. 2.10.1. Occasionally, > +a four-number version is released, if a single urgent fix needs to go > +on top. > + > +Usually, a stable release is only done for the last released version. Maybe: "Usually, stable releases are only provided for the last major QEMU release. For example, when QEMU 2.11.0 is released, 2.11.x or 2.11.x.y stable releases are only produced until QEMU 2.12.0 is released, at which the stable process moves to producing 2.12.x/2.12.x.y releases." > + > +What should go into a stable release? > +- > + > +Generally, the following patches are considered stable material: > +- Patches that fix severe issues, like fixes for CVEs > +- Patches that fix regressions > + > +If you think the patch would be important for users of the current release > +(or for a distribution picking fixes), it is usually a good candidate > +for stable. > + > + > +How to get a patch into QEMU stable > +--- > + > +There are various ways to get a patch into stable: > + > +* Preferred: Make sure that the stable maintainers are on copy when you send > + the patch by adding > + > + .. code:: > + > + Cc: qemu-sta...@nongnu.org > + > + to the patch description. This will make git add the stable maintainers > + on copy when your patch is sent out. "By default, this will send the patch to qemu-sta...@nongnu.org if you use git send-email, which is where patches that are stable candidates are tracked by the maintainers." "You can also reply to a patch and Cc: qemu-sta...@nongnu.org directly with your mail client if you think a previously submitted patch should be considered for a stable release." > + > +* If a maintainer judges the patch appropriate for stable later on (or you > + notify them), they will add the same line to your patch, meaning that "to the patch" (in case the Cc'er isn't the author) > + the stable maintainers will be on copy on the maintainer's pull request. > + > +* If you judge an already merged patch suitable for stable, send a mail (preferably as a reply to the most recent patch submission) > + to ``qemu-sta...@nongnu.org`` with ``qemu-devel@nongnu.org`` and > appropriate "along with" > + other people (like the patch author or the relevant maintainer) on copy. > + > +Stable release process > +-- > + > +When the stable maintainers prepare a new stable release, they will prepare > +a git branch with a release candidate and send the patches out to > +``qemu-devel@nongnu.org`` for review. If any of your patches are included, "qemu-devel@nongnu.org and qemu-sta...@nongnu.org" > +please verify that they look fine. You may also nominate other patches that > +you think are suitable for inclusion. After review is complete (may involve > +more release candidates), a new stable release is made available. > -- > 2.13.6 >
[Qemu-devel] [PULL 00/12] ppc-for-2.12 queue 20180212
The following changes since commit c7b02d7d032d6022060e4b393827c963c93ce63f: Merge remote-tracking branch 'remotes/stsquad/tags/pull-travis-speedup-090218-1' into staging (2018-02-09 16:12:34 +) are available in the Git repository at: git://github.com/dgibson/qemu.git tags/ppc-for-2.12-20180212 for you to fetch changes up to 51f233ec92cdab7030cb7407dd7f009911c805b0: misc: introduce new mos6522 VIA device and enable it for ppc builds (2018-02-11 10:18:52 +1100) ppc patch queue 2018-02-12 Here's the accumulatead ppc and pseries related patches for the last while. Highlights are: * A number of Macintosh / CUDA cleanups from Mark Cave-Ayland * An important bug fix (missing "break;") for H_GET_CPU_CHARACTERISTICS * Yet another fix for SMT mode handling * Assorted other cleanups and fixes Daniel Henrique Barboza (1): hw/ppc: rename functions in comments Greg Kurz (1): spapr: add missing break in h_get_cpu_characteristics() Laurent Vivier (1): spapr: set vsmt to MAX(8, smp_threads) Mark Cave-Ayland (9): cuda: do not use old_mmio accesses cuda: don't allow writes to port output pins cuda: introduce CUDAState parameter to get_counter() cuda: rename frequency property to tb_frequency cuda: minor cosmetic tidy-ups to get_next_irq_time() cuda: don't call cuda_update() when writing to ACR register cuda: set timer 1 frequency property to CUDA_TIMER_FREQ cuda: factor out timebase-derived counter value and load time misc: introduce new mos6522 VIA device and enable it for ppc builds default-configs/ppc-softmmu.mak | 1 + hw/misc/Makefile.objs | 3 + hw/misc/macio/cuda.c| 111 - hw/misc/macio/macio.c | 2 +- hw/misc/mos6522.c | 505 hw/misc/trace-events| 7 + hw/ppc/mac.h| 2 +- hw/ppc/spapr.c | 5 +- hw/ppc/spapr_hcall.c| 3 +- include/hw/misc/mos6522.h | 152 10 files changed, 722 insertions(+), 69 deletions(-) create mode 100644 hw/misc/mos6522.c create mode 100644 include/hw/misc/mos6522.h
[Qemu-devel] [PULL 04/12] cuda: don't allow writes to port output pins
From: Mark Cave-Ayland Use the direction registers as a mask to ensure that only input pins are updated upon write. Signed-off-by: Mark Cave-Ayland Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/misc/macio/cuda.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index 6631017ca2..eaa8924f49 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -359,11 +359,11 @@ static void cuda_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) switch(addr) { case CUDA_REG_B: -s->b = val; +s->b = (s->b & ~s->dirb) | (val & s->dirb); cuda_update(s); break; case CUDA_REG_A: -s->a = val; +s->a = (s->a & ~s->dira) | (val & s->dira); break; case CUDA_REG_DIRB: s->dirb = val; -- 2.14.3
[Qemu-devel] [PULL 05/12] spapr: set vsmt to MAX(8, smp_threads)
From: Laurent Vivier We ignore silently the value of smp_threads when we set the default VSMT value, and if smp_threads is greater than VSMT kernel is going into trouble later. Fixes: 8904e5a750 ("spapr: Adjust default VSMT value for better migration compatibility") Signed-off-by: Laurent Vivier Reviewed-by: Greg Kurz Signed-off-by: David Gibson --- hw/ppc/spapr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 96515036e6..9f29434819 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2310,7 +2310,7 @@ static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp) * the value that we'd get with KVM on POWER8, the * overwhelmingly common case in production systems. */ -spapr->vsmt = 8; +spapr->vsmt = MAX(8, smp_threads); } /* KVM: If necessary, set the SMT mode: */ -- 2.14.3
[Qemu-devel] [PULL 02/12] hw/ppc: rename functions in comments
From: Daniel Henrique Barboza Commit bcb5ce08cf ("spapr: Rename machine init functions for clarity") renamed ppc_spapr_reset to spapr_machine_reset and ppc_spapr_init to spapr_machine_init. Let's also rename the references in comments. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/ppc/spapr.c | 3 ++- hw/ppc/spapr_hcall.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 659be6b746..96515036e6 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -464,7 +464,8 @@ static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) } } if (!mem_start) { -/* ppc_spapr_init() checks for rma_size <= node0_size already */ +/* spapr_machine_init() checks for rma_size <= node0_size + * already */ spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); mem_start += spapr->rma_size; node_size -= spapr->rma_size; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 596f58378a..76422cfac1 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1635,7 +1635,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, spapr->cas_legacy_guest_workaround = !spapr_ovec_test(ov1_guest, OV1_PPC_3_00); if (!spapr->cas_reboot) { -/* If ppc_spapr_reset() did not set up a HPT but one is necessary +/* If spapr_machine_reset() did not set up a HPT but one is necessary * (because the guest isn't going to use radix) then set it up here. */ if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) { /* legacy hash or new hash: */ -- 2.14.3
[Qemu-devel] [PULL 01/12] spapr: add missing break in h_get_cpu_characteristics()
From: Greg Kurz Detected by Coverity (CID 1385702). This fixes the recently added hypercall to let guests properly apply Spectre and Meltdown workarounds. Fixes: c59704b25473 "target/ppc/spapr: Add H-Call H_GET_CPU_CHARACTERISTICS" Reported-by: Paolo Bonzini Signed-off-by: Greg Kurz Reviewed-by: Suraj Jitindar Singh Signed-off-by: David Gibson --- hw/ppc/spapr_hcall.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 4d0e6eb0cf..596f58378a 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1697,6 +1697,7 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, switch (safe_indirect_branch) { case SPAPR_CAP_FIXED: characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED; +break; default: /* broken */ assert(safe_indirect_branch == SPAPR_CAP_BROKEN); break; -- 2.14.3
[Qemu-devel] [PULL 07/12] cuda: rename frequency property to tb_frequency
From: Mark Cave-Ayland This allows us to more easily differentiate between the timebase frequency used to calibrate the MacOS timers and the actual frequency of the hardware clock as indicated by CUDA_TIMER_FREQ. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé [dwg: Revert some extraneous changes which break compile] Signed-off-by: David Gibson --- hw/misc/macio/cuda.c | 6 +++--- hw/misc/macio/macio.c | 2 +- hw/ppc/mac.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index fa10b6d0c1..d4a52fbddb 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -179,7 +179,7 @@ static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) { CUDA_DPRINTF("T%d.counter=%d\n", 1 + ti->index, val); ti->load_time = get_tb(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - s->frequency); + s->tb_frequency); ti->counter_value = val; cuda_timer_update(s, ti, ti->load_time); } @@ -879,7 +879,7 @@ static void cuda_realizefn(DeviceState *dev, Error **errp) struct tm tm; s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s); -s->timers[0].frequency = s->frequency; +s->timers[0].frequency = s->tb_frequency; s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer2, s); s->timers[1].frequency = (SCALE_US * 6000) / 4700; @@ -910,7 +910,7 @@ static void cuda_initfn(Object *obj) } static Property cuda_properties[] = { -DEFINE_PROP_UINT64("frequency", CUDAState, frequency, 0), +DEFINE_PROP_UINT64("timebase-frequency", CUDAState, tb_frequency, 0), DEFINE_PROP_END_OF_LIST() }; diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index 44f91d1e7f..a639b09e00 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -451,7 +451,7 @@ void macio_init(PCIDevice *d, macio_state->escc_mem = escc_mem; /* Note: this code is strongly inspirated from the corresponding code in PearPC */ -qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency", +qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency", macio_state->frequency); qdev_init_nofail(DEVICE(d)); diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index b501af1653..fa78115c95 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -99,7 +99,7 @@ typedef struct CUDAState { CUDATimer timers[2]; uint32_t tick_offset; -uint64_t frequency; +uint64_t tb_frequency; uint8_t last_b; uint8_t last_acr; -- 2.14.3
[Qemu-devel] [PULL 09/12] cuda: don't call cuda_update() when writing to ACR register
From: Mark Cave-Ayland The wire protocol for reading data to/from the VIA is triggered by changing inputs on port B rather than changing the timer configuration via the ACR. Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/misc/macio/cuda.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index 729905236c..355a2f2262 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -407,7 +407,6 @@ static void cuda_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) case CUDA_REG_ACR: s->acr = val; cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); -cuda_update(s); break; case CUDA_REG_PCR: s->pcr = val; -- 2.14.3
[Qemu-devel] [PULL 08/12] cuda: minor cosmetic tidy-ups to get_next_irq_time()
From: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/misc/macio/cuda.c | 23 --- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index d4a52fbddb..729905236c 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -184,36 +184,37 @@ static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) cuda_timer_update(s, ti, ti->load_time); } -static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) +static int64_t get_next_irq_time(CUDATimer *ti, int64_t current_time) { int64_t d, next_time; unsigned int counter; /* current counter value */ -d = muldiv64(current_time - s->load_time, +d = muldiv64(current_time - ti->load_time, CUDA_TIMER_FREQ, NANOSECONDS_PER_SECOND); /* the timer goes down from latch to -1 (period of latch + 2) */ -if (d <= (s->counter_value + 1)) { -counter = (s->counter_value - d) & 0x; +if (d <= (ti->counter_value + 1)) { +counter = (ti->counter_value - d) & 0x; } else { -counter = (d - (s->counter_value + 1)) % (s->latch + 2); -counter = (s->latch - counter) & 0x; +counter = (d - (ti->counter_value + 1)) % (ti->latch + 2); +counter = (ti->latch - counter) & 0x; } /* Note: we consider the irq is raised on 0 */ if (counter == 0x) { -next_time = d + s->latch + 1; +next_time = d + ti->latch + 1; } else if (counter == 0) { -next_time = d + s->latch + 2; +next_time = d + ti->latch + 2; } else { next_time = d + counter; } CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n", - s->latch, d, next_time - d); + ti->latch, d, next_time - d); next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, CUDA_TIMER_FREQ) + -s->load_time; -if (next_time <= current_time) + ti->load_time; +if (next_time <= current_time) { next_time = current_time + 1; +} return next_time; } -- 2.14.3
[Qemu-devel] [PULL 11/12] cuda: factor out timebase-derived counter value and load time
From: Mark Cave-Ayland Commit b981289c49 "PPC: Cuda: Use cuda timer to expose tbfreq to guest" altered the timer calculations from those based upon the hardware CUDA clock frequency to those based upon the CPU timebase frequency. In fact we can isolate the differences to 2 simple changes: one to the counter read value and another to the counter load time. Move these changes into separate functions so the implementation can be swapped later. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/misc/macio/cuda.c | 25 - 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index e00df4a21a..a185252144 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -145,21 +145,29 @@ static void cuda_update_irq(CUDAState *s) } } -static uint64_t get_tb(uint64_t time, uint64_t freq) +static uint64_t get_counter_value(CUDAState *s, CUDATimer *ti) { -return muldiv64(time, freq, NANOSECONDS_PER_SECOND); +/* Reverse of the tb calculation algorithm that Mac OS X uses on bootup */ +uint64_t tb_diff = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), +s->tb_frequency, NANOSECONDS_PER_SECOND) - + ti->load_time; + +return (tb_diff * 0xBF401675E5DULL) / (s->tb_frequency << 24); +} + +static uint64_t get_counter_load_time(CUDAState *s, CUDATimer *ti) +{ +uint64_t load_time = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + s->tb_frequency, NANOSECONDS_PER_SECOND); +return load_time; } static unsigned int get_counter(CUDAState *s, CUDATimer *ti) { int64_t d; unsigned int counter; -uint64_t tb_diff; -uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -/* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */ -tb_diff = get_tb(current_time, s->tb_frequency) - ti->load_time; -d = (tb_diff * 0xBF401675E5DULL) / (s->tb_frequency << 24); +d = get_counter_value(s, ti); if (ti->index == 0) { /* the timer goes down from latch to -1 (period of latch + 2) */ @@ -178,8 +186,7 @@ static unsigned int get_counter(CUDAState *s, CUDATimer *ti) static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) { CUDA_DPRINTF("T%d.counter=%d\n", 1 + ti->index, val); -ti->load_time = get_tb(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - s->tb_frequency); +ti->load_time = get_counter_load_time(s, ti); ti->counter_value = val; cuda_timer_update(s, ti, ti->load_time); } -- 2.14.3
[Qemu-devel] [PULL 03/12] cuda: do not use old_mmio accesses
From: Mark Cave-Ayland Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- hw/misc/macio/cuda.c | 40 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index 008d8bd4d5..6631017ca2 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -275,7 +275,7 @@ static void cuda_delay_set_sr_int(CUDAState *s) timer_mod(s->sr_delay_timer, expire); } -static uint32_t cuda_readb(void *opaque, hwaddr addr) +static uint64_t cuda_read(void *opaque, hwaddr addr, unsigned size) { CUDAState *s = opaque; uint32_t val; @@ -350,7 +350,7 @@ static uint32_t cuda_readb(void *opaque, hwaddr addr) return val; } -static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val) +static void cuda_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { CUDAState *s = opaque; @@ -780,38 +780,14 @@ static void cuda_receive_packet_from_host(CUDAState *s, } } -static void cuda_writew (void *opaque, hwaddr addr, uint32_t value) -{ -} - -static void cuda_writel (void *opaque, hwaddr addr, uint32_t value) -{ -} - -static uint32_t cuda_readw (void *opaque, hwaddr addr) -{ -return 0; -} - -static uint32_t cuda_readl (void *opaque, hwaddr addr) -{ -return 0; -} - static const MemoryRegionOps cuda_ops = { -.old_mmio = { -.write = { -cuda_writeb, -cuda_writew, -cuda_writel, -}, -.read = { -cuda_readb, -cuda_readw, -cuda_readl, -}, +.read = cuda_read, +.write = cuda_write, +.endianness = DEVICE_BIG_ENDIAN, +.valid = { +.min_access_size = 1, +.max_access_size = 1, }, -.endianness = DEVICE_NATIVE_ENDIAN, }; static bool cuda_timer_exist(void *opaque, int version_id) -- 2.14.3
[Qemu-devel] [PULL 10/12] cuda: set timer 1 frequency property to CUDA_TIMER_FREQ
From: Mark Cave-Ayland Now that we have successfully decoupled the timebase frequency and the hardware timer frequency, set the timer 1 frequency property to CUDA_TIMER_FREQ and alter get_next_irq_time() to use it rather than the hard-coded constant. In addition to this we must now switch the tb_diff calculation over to use the timebase frequency now that the hardware clock frequency and the timebase frequency are different. Signed-off-by: Mark Cave-Ayland [dwg: Correct a conflict due to a bug in an earlier patch] Signed-off-by: David Gibson --- hw/misc/macio/cuda.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index 355a2f2262..e00df4a21a 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -158,8 +158,8 @@ static unsigned int get_counter(CUDAState *s, CUDATimer *ti) uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */ -tb_diff = get_tb(current_time, ti->frequency) - ti->load_time; -d = (tb_diff * 0xBF401675E5DULL) / (ti->frequency << 24); +tb_diff = get_tb(current_time, s->tb_frequency) - ti->load_time; +d = (tb_diff * 0xBF401675E5DULL) / (s->tb_frequency << 24); if (ti->index == 0) { /* the timer goes down from latch to -1 (period of latch + 2) */ @@ -191,7 +191,7 @@ static int64_t get_next_irq_time(CUDATimer *ti, int64_t current_time) /* current counter value */ d = muldiv64(current_time - ti->load_time, - CUDA_TIMER_FREQ, NANOSECONDS_PER_SECOND); + ti->frequency, NANOSECONDS_PER_SECOND); /* the timer goes down from latch to -1 (period of latch + 2) */ if (d <= (ti->counter_value + 1)) { counter = (ti->counter_value - d) & 0x; @@ -210,7 +210,7 @@ static int64_t get_next_irq_time(CUDATimer *ti, int64_t current_time) } CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n", ti->latch, d, next_time - d); -next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, CUDA_TIMER_FREQ) + +next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, ti->frequency) + ti->load_time; if (next_time <= current_time) { next_time = current_time + 1; @@ -879,7 +879,7 @@ static void cuda_realizefn(DeviceState *dev, Error **errp) struct tm tm; s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s); -s->timers[0].frequency = s->tb_frequency; +s->timers[0].frequency = CUDA_TIMER_FREQ; s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer2, s); s->timers[1].frequency = (SCALE_US * 6000) / 4700; -- 2.14.3
[Qemu-devel] [PULL 06/12] cuda: introduce CUDAState parameter to get_counter()
From: Mark Cave-Ayland This will be required shortly and also happens to match nicely with the corresponding signature for set_counter(). Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: David Gibson --- hw/misc/macio/cuda.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index eaa8924f49..fa10b6d0c1 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -150,7 +150,7 @@ static uint64_t get_tb(uint64_t time, uint64_t freq) return muldiv64(time, freq, NANOSECONDS_PER_SECOND); } -static unsigned int get_counter(CUDATimer *ti) +static unsigned int get_counter(CUDAState *s, CUDATimer *ti) { int64_t d; unsigned int counter; @@ -295,12 +295,12 @@ static uint64_t cuda_read(void *opaque, hwaddr addr, unsigned size) val = s->dira; break; case CUDA_REG_T1CL: -val = get_counter(&s->timers[0]) & 0xff; +val = get_counter(s, &s->timers[0]) & 0xff; s->ifr &= ~T1_INT; cuda_update_irq(s); break; case CUDA_REG_T1CH: -val = get_counter(&s->timers[0]) >> 8; +val = get_counter(s, &s->timers[0]) >> 8; cuda_update_irq(s); break; case CUDA_REG_T1LL: @@ -311,12 +311,12 @@ static uint64_t cuda_read(void *opaque, hwaddr addr, unsigned size) val = (s->timers[0].latch >> 8) & 0xff; break; case CUDA_REG_T2CL: -val = get_counter(&s->timers[1]) & 0xff; +val = get_counter(s, &s->timers[1]) & 0xff; s->ifr &= ~T2_INT; cuda_update_irq(s); break; case CUDA_REG_T2CH: -val = get_counter(&s->timers[1]) >> 8; +val = get_counter(s, &s->timers[1]) >> 8; break; case CUDA_REG_SR: val = s->sr; -- 2.14.3
[Qemu-devel] [PULL 12/12] misc: introduce new mos6522 VIA device and enable it for ppc builds
From: Mark Cave-Ayland The MOS6522 VIA forms the bridge part of several Mac devices, including the Mac via-cuda and via-pmu devices. Introduce a standard mos6522 device that can be shared amongst multiple implementations. This is effectively taking the 6522 parts out of cuda.c and turning them into a separate device whilst also applying some style tidy-ups and including a conversion to trace-events. Signed-off-by: Mark Cave-Ayland Signed-off-by: David Gibson --- default-configs/ppc-softmmu.mak | 1 + hw/misc/Makefile.objs | 3 + hw/misc/mos6522.c | 505 hw/misc/trace-events| 7 + include/hw/misc/mos6522.h | 152 5 files changed, 668 insertions(+) create mode 100644 hw/misc/mos6522.c create mode 100644 include/hw/misc/mos6522.h diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak index 65680d85bc..76e29cfa14 100644 --- a/default-configs/ppc-softmmu.mak +++ b/default-configs/ppc-softmmu.mak @@ -30,6 +30,7 @@ CONFIG_MAC=y CONFIG_ESCC=y CONFIG_MACIO=y CONFIG_SUNGEM=y +CONFIG_MOS6522=y CONFIG_CUDA=y CONFIG_ADB=y CONFIG_MAC_NVRAM=y diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index fce426eb75..f33b37a8e5 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -17,6 +17,9 @@ common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o common-obj-$(CONFIG_A9SCU) += a9scu.o common-obj-$(CONFIG_ARM11SCU) += arm11scu.o +# Mac devices +common-obj-$(CONFIG_MOS6522) += mos6522.o + # PKUnity SoC devices common-obj-$(CONFIG_PUV3) += puv3_pm.o diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c new file mode 100644 index 00..8ad9fc831e --- /dev/null +++ b/hw/misc/mos6522.c @@ -0,0 +1,505 @@ +/* + * QEMU MOS6522 VIA emulation + * + * Copyright (c) 2004-2007 Fabrice Bellard + * Copyright (c) 2007 Jocelyn Mayer + * Copyright (c) 2018 Mark Cave-Ayland + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "hw/hw.h" +#include "hw/input/adb.h" +#include "hw/misc/mos6522.h" +#include "qemu/timer.h" +#include "sysemu/sysemu.h" +#include "qemu/cutils.h" +#include "qemu/log.h" +#include "trace.h" + +/* XXX: implement all timer modes */ + +static void mos6522_timer_update(MOS6522State *s, MOS6522Timer *ti, + int64_t current_time); + +static void mos6522_update_irq(MOS6522State *s) +{ +if (s->ifr & s->ier & (SR_INT | T1_INT | T2_INT)) { +qemu_irq_raise(s->irq); +} else { +qemu_irq_lower(s->irq); +} +} + +static uint64_t get_counter_value(MOS6522State *s, MOS6522Timer *ti) +{ +MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + +if (ti->index == 0) { +return mdc->get_timer1_counter_value(s, ti); +} else { +return mdc->get_timer2_counter_value(s, ti); +} +} + +static uint64_t get_load_time(MOS6522State *s, MOS6522Timer *ti) +{ +MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s); + +if (ti->index == 0) { +return mdc->get_timer1_load_time(s, ti); +} else { +return mdc->get_timer2_load_time(s, ti); +} +} + +static unsigned int get_counter(MOS6522State *s, MOS6522Timer *ti) +{ +int64_t d; +unsigned int counter; + +d = get_counter_value(s, ti); + +if (ti->index == 0) { +/* the timer goes down from latch to -1 (period of latch + 2) */ +if (d <= (ti->counter_value + 1)) { +counter = (ti->counter_value - d) & 0x; +} else { +counter = (d - (ti->counter_value + 1)) % (ti->latch + 2); +counter = (ti->latch - counter) & 0x; +} +} else { +counter = (ti->counter_value - d) & 0x; +} +return counter; +} + +static void set_counter(MOS6522State *s, MOS6522Timer *ti, unsigned int val) +{ +trace_mos6522_set_counter(1 + ti->index, val); +ti->load_time = get_load_t
Re: [Qemu-devel] [PATCH qemu v7 2/4] vfio/pci: Relax DMA map errors for MMIO regions
On Fri, Feb 09, 2018 at 06:55:01PM +1100, Alexey Kardashevskiy wrote: > At the moment if vfio_memory_listener is registered in the system memory > address space, it maps/unmaps every RAM memory region for DMA. > It expects system page size aligned memory sections so vfio_dma_map > would not fail and so far this has been the case. A mapping failure > would be fatal. A side effect of such behavior is that some MMIO pages > would not be mapped silently. > > However we are going to change MSIX BAR handling so we will end having > non-aligned sections in vfio_memory_listener (more details is in > the next patch) and vfio_dma_map will exit QEMU. > > In order to avoid fatal failures on what previously was not a failure and > was just silently ignored, this checks the section alignment to > the smallest supported IOMMU page size and prints an error if not aligned; > it also prints an error if vfio_dma_map failed despite the page size check. > Both errors are not fatal; only MMIO RAM regions are checked > (aka "RAM device" regions). > > If the amount of errors printed is overwhelming, the MSIX relocation > could be used to avoid excessive error output. > > This is unlikely to cause any behavioral change. > > Signed-off-by: Alexey Kardashevskiy There are some relatively superficial problems noted below. But more fundamentally, this feels like it's extending an existing hack past the point of usefulness. The explicit check for is_ram_device() here has always bothered me - it's not like a real bus bridge magically knows whether a target address maps to RAM or not. What I think is really going on is that even for systems without an IOMMU, it's not really true to say that the PCI address space maps directly onto address_space_memory. Instead, there's a large, but much less than 2^64 sized, "upstream window" at address 0 on the PCI bus, which is identity mapped to the system bus. Details will vary with the system, but in practice we expect nothing but RAM to be in that window. Addresses not within that window won't be mapped to the system bus but will just be broadcast on the PCI bus and might be picked up as a p2p transaction. Actually on classic PC, I suspect there may be two windows, below and above the "ISA IO hole". With PCIe it gets more complicated, of course. I still suspect there's some sort of upstream window to the host, but whether things outside the window get reflected back down the PCIe heirarchy will depend on those p2p relevant configuration parameters. Maybe it's time we had a detailed look at what really happens in physical bridges, rather than faking it with the is_ram_device() check? Anyway, that said, the patch below might still be a reasonable interim hack, once the smaller problems are fixed. > --- > hw/vfio/common.c | 55 +-- > 1 file changed, 49 insertions(+), 6 deletions(-) > > diff --git a/hw/vfio/common.c b/hw/vfio/common.c > index f895e3c..736f271 100644 > --- a/hw/vfio/common.c > +++ b/hw/vfio/common.c > @@ -544,18 +544,40 @@ static void vfio_listener_region_add(MemoryListener > *listener, > > llsize = int128_sub(llend, int128_make64(iova)); > > +if (memory_region_is_ram_device(section->mr)) { > +hwaddr pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1; > + > +if ((iova & pgmask) || (llsize & pgmask)) { > +error_report("Region 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx > + " is not aligned to 0x%"HWADDR_PRIx > + " and cannot be mapped for DMA", > + section->offset_within_region, > + int128_getlo(section->size), > + pgmask + 1); > +return; > +} > +} > + > ret = vfio_dma_map(container, iova, int128_get64(llsize), > vaddr, section->readonly); > if (ret) { > error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", " > "0x%"HWADDR_PRIx", %p) = %d (%m)", > container, iova, int128_get64(llsize), vaddr, ret); > +if (memory_region_is_ram_device(section->mr)) { > +/* Allow unexpected mappings not to be fatal for RAM devices */ > +return; > +} > goto fail; > } > > return; > > fail: > +if (memory_region_is_ram_device(section->mr)) { > +error_report("failed to vfio_dma_map. pci p2p may not work"); Isn't this logic exactly backwards? p2p will be affected when a *non RAM* device (itself probably a PCI MMIO window) can't be mapped in. > +return; > +} > /* > * On the initfn path, store the first error in the container so we > * can gracefully fail. Runtime, there's not much we can do other > @@ -577,6 +599,7 @@ static void vfio_listener_region_del(MemoryListener > *listener, > hwaddr iova, end; > Int128 llend, llsize; > int ret; > +bool try_unmap = true; >
Re: [Qemu-devel] [RFC PATCH v6 00/20] replay additions
I tested ARM only with –kernel and –initrd. Can you provide the full command line and the disk image? Pavel Dovgalyuk From: Ciro Santilli [mailto:ciro.santi...@gmail.com] Sent: Saturday, February 10, 2018 3:09 AM To: Pavel Dovgalyuk Cc: Pavel Dovgalyuk; qemu-devel@nongnu.org; kw...@redhat.com; Peter Maydell; war2jor...@live.com; Igor R; quint...@redhat.com; jasow...@redhat.com; m...@redhat.com; Aleksandr Bezzubikov; maria.klimushenk...@ispras.ru; kra...@redhat.com; Thomas Dullien; pbonz...@redhat.com; Alex Bennée Subject: Re: [RFC PATCH v6 00/20] replay additions Also, what command do you use to test on ARM? I'm a bit stuck to get the drive part right, e.g.: -drive file=./buildroot/output.arm~/images/rootfs.ext2,if=scsi,id=img-direct,format=raw \ -drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay \ -device scsi-hd,drive=img-blkreplay \ fails with: qemu-system-arm: -device scsi-hd,drive=img-blkreplay: Conflicts with use by img-direct as 'root', which does not allow 'write' on #block968
[Qemu-devel] [Bug 1748756] Re: [Feature request] Support of TI AM1808 for Lego EV3
** Changed in: qemu Importance: Undecided => Wishlist -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1748756 Title: [Feature request] Support of TI AM1808 for Lego EV3 Status in QEMU: New Bug description: It would be great if emulating TI AM1808 would be possible. It will be a big step towards Lego Mindstorms EV3 emulation. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1748756/+subscriptions
Re: [Qemu-devel] [RFC PATCH v6 00/20] replay additions
> From: Ciro Santilli [mailto:ciro.santi...@gmail.com] > Awesome! This worked with my test procedure described at: > https://stackoverflow.com/questions/46970215/how-to-use-qemus-deterministic-record-and-replay-feature-for-a-linux-kernel-boo > While we are a it, can we clarify the following points the docs? > 1) Usage of the record/replay: mentions that `-net none` is required, unless > a network patch is applied. > But the network section that follows explains how to record network requests, > and I've tested it, so I think the `-net none` / patch requirement is just > outdated and should be removed. > 2) There are mentions of "reverse execution" and "reverse debugging" on the > "Record/replay" section. > Are those supported? If yes, explain there how to use them. Otherwise, remove > the mentions. > I would love to see that feature! Not yet, but they are the next to apply after this series. I'll update the docs. > 3) Is the snapshot feature mentioned in the "Snapshotting" section something > specific to record and replay? > If yes, can we detail further how to use it besides passing > `rrsnapshot=snapshot_name`? How to create and restore the snapshots? > If not, why does the `rrsnapshot=snapshot_name` option exist? > 4) Maybe give the required disk and network commands under "Usage of the > record/replay:" > -drive file=disk.qcow,if=none,id=img-direct > -drive driver=blkreplay,if=none,image=img-direct,id=img-blkreplay > -device ide-hd,drive=img-blkreplay > -netdev user,id=net1 -device rtl8139,netdev=net1 > -object filter-replay,id=replay,netdev=net1 > People likely always want those, but it currently requires reading through > the whole doc file to put everything together. Thanks for reviewing, I'll add the documentation update to the series. Pavel Dovgalyuk
Re: [Qemu-devel] [PATCH qemu v7 2/4] vfio/pci: Relax DMA map errors for MMIO regions
On 12/02/18 16:19, David Gibson wrote: > On Fri, Feb 09, 2018 at 06:55:01PM +1100, Alexey Kardashevskiy wrote: >> At the moment if vfio_memory_listener is registered in the system memory >> address space, it maps/unmaps every RAM memory region for DMA. >> It expects system page size aligned memory sections so vfio_dma_map >> would not fail and so far this has been the case. A mapping failure >> would be fatal. A side effect of such behavior is that some MMIO pages >> would not be mapped silently. >> >> However we are going to change MSIX BAR handling so we will end having >> non-aligned sections in vfio_memory_listener (more details is in >> the next patch) and vfio_dma_map will exit QEMU. >> >> In order to avoid fatal failures on what previously was not a failure and >> was just silently ignored, this checks the section alignment to >> the smallest supported IOMMU page size and prints an error if not aligned; >> it also prints an error if vfio_dma_map failed despite the page size check. >> Both errors are not fatal; only MMIO RAM regions are checked >> (aka "RAM device" regions). >> >> If the amount of errors printed is overwhelming, the MSIX relocation >> could be used to avoid excessive error output. >> >> This is unlikely to cause any behavioral change. >> >> Signed-off-by: Alexey Kardashevskiy > > There are some relatively superficial problems noted below. > > But more fundamentally, this feels like it's extending an existing > hack past the point of usefulness. > > The explicit check for is_ram_device() here has always bothered me - > it's not like a real bus bridge magically knows whether a target > address maps to RAM or not. > > What I think is really going on is that even for systems without an > IOMMU, it's not really true to say that the PCI address space maps > directly onto address_space_memory. Instead, there's a large, but > much less than 2^64 sized, "upstream window" at address 0 on the PCI > bus, which is identity mapped to the system bus. Details will vary > with the system, but in practice we expect nothing but RAM to be in > that window. Addresses not within that window won't be mapped to the > system bus but will just be broadcast on the PCI bus and might be > picked up as a p2p transaction. Currently this p2p works only via the IOMMU, direct p2p is not possible as the guest needs to know physical MMIO addresses to make p2p work and it does not. > Actually on classic PC, I suspect > there may be two windows, below and above the "ISA IO hole". > > With PCIe it gets more complicated, of course. I still suspect > there's some sort of upstream window to the host, but whether things > outside the window get reflected back down the PCIe heirarchy will > depend on those p2p relevant configuration parameters. > > Maybe it's time we had a detailed look at what really happens in > physical bridges, rather than faking it with the is_ram_device() > check? > > Anyway, that said, the patch below might still be a reasonable interim > hack, once the smaller problems are fixed. > >> --- >> hw/vfio/common.c | 55 >> +-- >> 1 file changed, 49 insertions(+), 6 deletions(-) >> >> diff --git a/hw/vfio/common.c b/hw/vfio/common.c >> index f895e3c..736f271 100644 >> --- a/hw/vfio/common.c >> +++ b/hw/vfio/common.c >> @@ -544,18 +544,40 @@ static void vfio_listener_region_add(MemoryListener >> *listener, >> >> llsize = int128_sub(llend, int128_make64(iova)); >> >> +if (memory_region_is_ram_device(section->mr)) { >> +hwaddr pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1; >> + >> +if ((iova & pgmask) || (llsize & pgmask)) { >> +error_report("Region 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx >> + " is not aligned to 0x%"HWADDR_PRIx >> + " and cannot be mapped for DMA", >> + section->offset_within_region, >> + int128_getlo(section->size), >> + pgmask + 1); >> +return; >> +} >> +} >> + >> ret = vfio_dma_map(container, iova, int128_get64(llsize), >> vaddr, section->readonly); >> if (ret) { >> error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", " >> "0x%"HWADDR_PRIx", %p) = %d (%m)", >> container, iova, int128_get64(llsize), vaddr, ret); >> +if (memory_region_is_ram_device(section->mr)) { >> +/* Allow unexpected mappings not to be fatal for RAM devices */ >> +return; >> +} >> goto fail; >> } >> >> return; >> >> fail: >> +if (memory_region_is_ram_device(section->mr)) { >> +error_report("failed to vfio_dma_map. pci p2p may not work"); > > Isn't this logic exactly backwards? p2p will be affected when a *non > RAM* device (itself probably a PCI MMIO window) can't be mapped in. "RAM device MR" == "mapped MMIO MR
Re: [Qemu-devel] [PATCH v2 02/19] spapr: introduce a skeleton for the XIVE interrupt controller
On 02/11/2018 11:55 PM, Benjamin Herrenschmidt wrote: > On Sun, 2018-02-11 at 19:08 +1100, David Gibson wrote: >> On Thu, Jan 18, 2018 at 08:27:52AM +1100, Benjamin Herrenschmidt wrote: >>> On Wed, 2018-01-17 at 15:39 +0100, Cédric Le Goater wrote: Migration is a problem. We will need both backend QEMU objects to be available anyhow if we want to migrate. So we are back to the current solution creating both QEMU objects but we can try to defer some of the KVM inits and create the KVM device on demand at CAS time. >>> >>> Do we have a way to migrate a piece of info from the machine *first* >>> that indicate what type of XICS/XIVE to instanciate ? >> >> Nope. qemu migration doesn't work like that. Yes, it should, and >> everyone knows it, but changing it is a really long term project. > > Well, we have a problem then. It looks like Qemu broken migration is > fundamentally incompatible with PAPR and CAS design... > > I know we don't migrate the configuration, that's not exactly what I > had in mind tho... Can we have some piece of *data* from the machine be > migrated first, and use it on the target to reconfigure the interrupt > controller before the stream arrives ? > > Otherwise, we have indeed no much choice but the horrible wart of > creating both interrupt controllers with only one "active". Well, both QEMU model objects would be created, yes, but one only KVM associated device. It's a bit ugly from a QEMU point of view because the KVM initialization is deferred at reset but, in the pratice, it results in a couple of calls to : - disconnect the VCPU from the KVM interrupt device - destroy the previous KVM interrupt device (new ioctl) - create the new KVM interrupt device - reconnect the VCPU to the KVM interrupt device I don't think it will be a major problem. What I am unease with currently, is how to share the same XIVE objects when under KVM and when not. The only difference is in the nature of the MMIO region and the qemu_irq handler. Work in progress. And we have four interrupt modes to support : XICS-KVM, XICS, XIVE-KVM, XIVE. Thanks, C. The next problem is the ICP object that currently needs the KVM device fd to connect the vcpus ... So, we will need to change that also. That is probably the biggest problem today. We need a way to disconnect the vpcu from the KVM device and see how we can defer the connection. I need to make sure this is possible, I can check that without XIVE >>> >>> Ben. >>> >> >>
[Qemu-devel] [PATCH RFC 12/14] qapi-introspect: modify to_qlit() to append ', ' on level > 0
From: Marc-André Lureau The following patch is going to break list entries with #if/#endif, so they should have the trailing ',' as suffix. Signed-off-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- scripts/qapi/introspect.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index e5c491d936..c02df95e72 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -29,7 +29,7 @@ def to_qlit(obj, level=0, suppress_first_indent=False): for elt in obj] elts.append(indent(level + 1) + "{}") ret = 'QLIT_QLIST(((QLitObject[]) {\n' -ret += ',\n'.join(elts) + '\n' +ret += '\n'.join(elts) + '\n' ret += indent(level) + '}))' elif isinstance(obj, dict): elts = [] @@ -42,6 +42,8 @@ def to_qlit(obj, level=0, suppress_first_indent=False): ret += indent(level) + '}))' else: assert False# not implemented +if level > 0: +ret += ',' return ret -- 2.13.6
[Qemu-devel] [PATCH RFC 10/14] qapi: mcgen() shouldn't indent # lines
From: Marc-André Lureau Skip preprocessor lines when adding indentation, since that would likely result in invalid code. Signed-off-by: Marc-André Lureau --- scripts/qapi/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 692a7ec7c2..1b254d5b32 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1940,8 +1940,8 @@ def cgen(code, **kwds): if indent_level: indent = genindent(indent_level) # re.subn() lacks flags support before Python 2.7, use re.compile() -raw = re.subn(re.compile(r'^.', re.MULTILINE), - indent + r'\g<0>', raw) +raw = re.subn(re.compile(r'^(?!(#|$))', re.MULTILINE), + indent, raw) raw = raw[0] return re.sub(re.escape(eatspace) + r' *', '', raw) -- 2.13.6
[Qemu-devel] [PATCH RFC 14/14] qapi: Add #if conditions to commands, events, types, visitors
Example change to generated code: diff -rup test-qapi-events.h.old test-qapi-events.h --- test-qapi-events.h.old 2018-02-12 07:02:45.672737544 +0100 +++ test-qapi-events.h 2018-02-12 07:03:01.128517669 +0100 @@ -30,8 +30,10 @@ void qapi_event_send_event_e(UserDefZero void qapi_event_send_event_f(UserDefAlternate *arg, Error **errp); void qapi_event_send___org_qemu_x_event(__org_qemu_x_Enum __org_qemu_x_member1, const char *__org_qemu_x_member2, bool has_q_wchar_t, int64_t q_wchar_t, Error **errp); +#if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT) void qapi_event_send_testifevent(TestIfStruct *foo, Error **errp); +#endif /* defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT) */ typedef enum test_QAPIEvent { TEST_QAPI_EVENT_EVENT_A = 0, TODO nice blank lines before #if and after #endif FIXME unclean access of protected members in commands.py Signed-off-by: Markus Armbruster --- scripts/qapi/commands.py | 7 ++- scripts/qapi/common.py | 37 + tests/test-qmp-cmds.c| 4 ++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 21a7e0dbe6..439a8714e2 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -276,8 +276,13 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); self._visited_ret_types[self._genc].add(ret_type) self._genc.add(gen_marshal_output(ret_type)) self._genh.add(gen_marshal_decl(name)) -self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) +self._genc.add(gen_marshal(name, arg_type, boxed, ret_type,)) +# FIXME unclean access of protected members +if self._genc._open_ifcond: +self._regy += gen_if(self._genc._open_ifcond) self._regy += gen_register_command(name, success_response) +if self._genc._open_ifcond: +self._regy += gen_endif(self._genc._open_ifcond) def gen_commands(schema, output_dir, prefix): diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 1a78dfaf3f..164d3e2daa 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -2122,6 +2122,9 @@ class QAPIGenC(QAPIGen): self._blurb = blurb.strip('\n') self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc, re.MULTILINE)) +self._open_ifcond = None +self._preamble_needs_ifcond = False +self._body_needs_ifcond = False def _top(self, fname): return mcgen(''' @@ -2139,6 +2142,36 @@ class QAPIGenC(QAPIGen): ''', blurb=self._blurb, copyright=self._copyright) +def ifcond(self, ifcond, begin): +if begin: +assert not self._open_ifcond +self._open_ifcond = ifcond +self._preamble_needs_ifcond = True +self._body_needs_ifcond = True +else: +assert self._open_ifcond == ifcond +if not self._preamble_needs_ifcond: +QAPIGen.preamble_add(self, gen_endif(ifcond)) +# TODO emit blank line +if not self._body_needs_ifcond: +QAPIGen.add(self, gen_endif(ifcond)) +# TODO emit blank line +self._open_ifcond = None + +def preamble_add(self, text): +if self._open_ifcond and self._preamble_needs_ifcond: +# TODO emit blank line +QAPIGen.preamble_add(self, gen_if(self._open_ifcond)) +self._preamble_needs_ifcond = False +QAPIGen.preamble_add(self, text) + +def add(self, text): +if self._open_ifcond and self._body_needs_ifcond: +# TODO emit blank line +QAPIGen.add(self, gen_if(self._open_ifcond)) +self._body_needs_ifcond = False +QAPIGen.add(self, text) + class QAPIGenH(QAPIGenC): @@ -2224,3 +2257,7 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor): #include "%(basename)s.h" ''', basename=basename)) + +def visit_ifcond(self, ifcond, begin): +self._genc.ifcond(ifcond, begin) +self._genh.ifcond(ifcond, begin) diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index c0a3c46439..b709a1fa3a 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -12,11 +12,11 @@ static QmpCommandList qmp_commands; -/* #if defined(TEST_IF_CMD) */ +#if defined(TEST_IF_CMD) void qmp_TestIfCmd(TestIfStruct *foo, Error **errp) { } -/* #endif */ +#endif void qmp_user_def_cmd(Error **errp) { -- 2.13.6
[Qemu-devel] [PATCH RFC 11/14] qapi: add #if/#endif helpers
From: Marc-André Lureau Add helpers to wrap generated code with #if/#endif lines. Signed-off-by: Marc-André Lureau --- scripts/qapi/common.py | 18 ++ 1 file changed, 18 insertions(+) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 1b254d5b32..1a78dfaf3f 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1973,6 +1973,24 @@ def guardend(name): name=guardname(name)) +def gen_if(ifcond): +ret = '' +for ifc in ifcond: +ret += mcgen(''' +#if %(cond)s +''', cond=ifc) +return ret + + +def gen_endif(ifcond): +ret = '' +for ifc in reversed(ifcond): +ret += mcgen(''' +#endif /* %(cond)s */ +''', cond=ifc) +return ret + + def gen_enum_lookup(name, values, prefix=None): ret = mcgen(''' -- 2.13.6
[Qemu-devel] [PATCH RFC 03/14] qapi/introspect: Simplify WIP
--- scripts/qapi/introspect.py | 20 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index f66c397fb0..6c86673a09 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -51,36 +51,32 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor): self._jsons = [] self._used_types = [] self._name_map = {} +var = c_name(self._prefix, protect=False) + 'qmp_schema_json' self._genc.add(mcgen(''' #include "qemu/osdep.h" #include "%(prefix)sqapi-introspect.h" +const char %(var)s[] = ''', + var=var, prefix=prefix)) +self._genh.add(mcgen(''' +extern const char %(var)s[]; ''', - prefix=prefix)) + var=var)) def visit_begin(self, schema): self._schema = schema def visit_end(self): # visit the types that are actually used -jsons = self._jsons -self._jsons = [] for typ in self._used_types: typ.visit(self) # generate C # TODO can generate awfully long lines -jsons.extend(self._jsons) -name = c_name(self._prefix, protect=False) + 'qmp_schema_json' -self._genh.add(mcgen(''' -extern const char %(c_name)s[]; -''', - c_name=c_name(name))) -lines = to_json(jsons).split('\n') +lines = to_json(self._jsons).split('\n') c_string = '\n'.join([to_c_string(line) for line in lines]) self._genc.add(mcgen(''' -const char %(c_name)s[] = %(c_string)s; +%(c_string)s; ''', - c_name=c_name(name), c_string=c_string)) self._schema = None self._jsons = [] -- 2.13.6
[Qemu-devel] [PATCH RFC 05/14] qapi2texi: minor python code simplification
From: Marc-André Lureau Signed-off-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- scripts/qapi/doc.py | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py index 0ea68bf813..79d11bbe9b 100644 --- a/scripts/qapi/doc.py +++ b/scripts/qapi/doc.py @@ -134,10 +134,9 @@ def texi_enum_value(value): def texi_member(member, suffix=''): """Format a table of members item for an object type member""" typ = member.type.doc_type() -return '@item @code{%s%s%s}%s%s\n' % ( -member.name, -': ' if typ else '', -typ if typ else '', +membertype = ': ' + typ if typ else '' +return '@item @code{%s%s}%s%s\n' % ( +member.name, membertype, ' (optional)' if member.optional else '', suffix) -- 2.13.6
[Qemu-devel] [PATCH RFC 08/14] qapi: leave the ifcond attribute undefined until check()
From: Marc-André Lureau We commonly initialize attributes to None in .init(), then set their real value in .check(). Accessing the attribute before .check() yields None. If we're lucky, the code that accesses the attribute prematurely chokes on None. It won't for .ifcond, because None is a legitimate value. Leave the ifcond attribute undefined until check(). Suggested-by: Markus Armbruster Signed-off-by: Marc-André Lureau --- scripts/qapi/common.py | 21 + 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 789c77f11f..78aeec785e 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1028,13 +1028,19 @@ class QAPISchemaEntity(object): # such place). self.info = info self.doc = doc -self.ifcond = listify_cond(ifcond) +self._ifcond = ifcond # self.ifcond is set after check() def c_name(self): return c_name(self.name) def check(self, schema): -pass +if isinstance(self._ifcond, QAPISchemaType): +# inherit the condition from a type +typ = self._ifcond +typ.check(schema) +self.ifcond = typ.ifcond +else: +self.ifcond = listify_cond(self._ifcond) def is_implicit(self): return not self.info @@ -1171,6 +1177,7 @@ class QAPISchemaEnumType(QAPISchemaType): self.prefix = prefix def check(self, schema): +QAPISchemaType.check(self, schema) seen = {} for v in self.values: v.check_clash(self.info, seen) @@ -1203,8 +1210,10 @@ class QAPISchemaArrayType(QAPISchemaType): self.element_type = None def check(self, schema): +QAPISchemaType.check(self, schema) self.element_type = schema.lookup_type(self._element_type_name) assert self.element_type +self.element_type.check(schema) self.ifcond = self.element_type.ifcond def is_implicit(self): @@ -1247,6 +1256,7 @@ class QAPISchemaObjectType(QAPISchemaType): self.members = None def check(self, schema): +QAPISchemaType.check(self, schema) if self.members is False: # check for cycles raise QAPISemError(self.info, "Object %s contains itself" % self.name) @@ -1429,6 +1439,7 @@ class QAPISchemaAlternateType(QAPISchemaType): self.variants = variants def check(self, schema): +QAPISchemaType.check(self, schema) self.variants.tag_member.check(schema) # Not calling self.variants.check_clash(), because there's nothing # to clash with @@ -1471,6 +1482,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.boxed = boxed def check(self, schema): +QAPISchemaEntity.check(self, schema) if self._arg_type_name: self.arg_type = schema.lookup_type(self._arg_type_name) assert (isinstance(self.arg_type, QAPISchemaObjectType) or @@ -1504,6 +1516,7 @@ class QAPISchemaEvent(QAPISchemaEntity): self.boxed = boxed def check(self, schema): +QAPISchemaEntity.check(self, schema) if self._arg_type_name: self.arg_type = schema.lookup_type(self._arg_type_name) assert (isinstance(self.arg_type, QAPISchemaObjectType) or @@ -1632,7 +1645,7 @@ class QAPISchema(object): # But it's not tight: the disjunction need not imply it. We # may end up compiling useless wrapper types. # TODO kill simple unions or implement the disjunction -assert ifcond == typ.ifcond +assert ifcond == typ._ifcond else: self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond, None, members, None)) @@ -1678,7 +1691,7 @@ class QAPISchema(object): assert len(typ) == 1 typ = self._make_array_type(typ[0], info) typ = self._make_implicit_object_type( -typ, info, None, self.lookup_type(typ).ifcond, +typ, info, None, self.lookup_type(typ), 'wrapper', [self._make_member('data', typ, info)]) return QAPISchemaObjectTypeVariant(case, typ) -- 2.13.6
[Qemu-devel] [PATCH RFC 01/14] qlit: use QType instead of int
From: Marc-André Lureau Suggested-by: Markus Armbruster Signed-off-by: Marc-André Lureau --- include/qapi/qmp/qlit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h index 56f9d97bd9..f1ed082df8 100644 --- a/include/qapi/qmp/qlit.h +++ b/include/qapi/qmp/qlit.h @@ -20,7 +20,7 @@ typedef struct QLitDictEntry QLitDictEntry; typedef struct QLitObject QLitObject; struct QLitObject { -int type; +QType type; union { bool qbool; int64_t qnum; -- 2.13.6
[Qemu-devel] [PATCH RFC 02/14] qlit: add qobject_from_qlit()
From: Marc-André Lureau Instantiate a QObject* from a literal QLitObject. LitObject only supports int64_t for now. uint64_t and double aren't implemented. Signed-off-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- include/qapi/qmp/qlit.h | 2 ++ qobject/qlit.c | 37 + tests/check-qlit.c | 28 3 files changed, 67 insertions(+) diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h index f1ed082df8..c0676d5daf 100644 --- a/include/qapi/qmp/qlit.h +++ b/include/qapi/qmp/qlit.h @@ -50,4 +50,6 @@ struct QLitDictEntry { bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs); +QObject *qobject_from_qlit(const QLitObject *qlit); + #endif /* QLIT_H */ diff --git a/qobject/qlit.c b/qobject/qlit.c index 948e0b860c..a921abf84a 100644 --- a/qobject/qlit.c +++ b/qobject/qlit.c @@ -18,6 +18,7 @@ #include "qapi/qmp/qlit.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qlist.h" +#include "qapi/qmp/qnull.h" #include "qapi/qmp/qnum.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" @@ -86,3 +87,39 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs) return false; } + +QObject *qobject_from_qlit(const QLitObject *qlit) +{ +switch (qlit->type) { +case QTYPE_QNULL: +return QOBJECT(qnull()); +case QTYPE_QNUM: +return QOBJECT(qnum_from_int(qlit->value.qnum)); +case QTYPE_QSTRING: +return QOBJECT(qstring_from_str(qlit->value.qstr)); +case QTYPE_QDICT: { +QDict *qdict = qdict_new(); +QLitDictEntry *e; + +for (e = qlit->value.qdict; e->key; e++) { +qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value)); +} +return QOBJECT(qdict); +} +case QTYPE_QLIST: { +QList *qlist = qlist_new(); +QLitObject *e; + +for (e = qlit->value.qlist; e->type != QTYPE_NONE; e++) { +qlist_append_obj(qlist, qobject_from_qlit(e)); +} +return QOBJECT(qlist); +} +case QTYPE_QBOOL: +return QOBJECT(qbool_from_bool(qlit->value.qbool)); +default: +assert(0); +} + +return NULL; +} diff --git a/tests/check-qlit.c b/tests/check-qlit.c index 5d0f65b9c7..836f4a3090 100644 --- a/tests/check-qlit.c +++ b/tests/check-qlit.c @@ -9,9 +9,11 @@ #include "qemu/osdep.h" +#include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" #include "qapi/qmp/qlit.h" +#include "qapi/qmp/qnum.h" #include "qapi/qmp/qstring.h" static QLitObject qlit = QLIT_QDICT(((QLitDictEntry[]) { @@ -63,11 +65,37 @@ static void qlit_equal_qobject_test(void) qobject_decref(qobj); } +static void qobject_from_qlit_test(void) +{ +QObject *obj, *qobj = qobject_from_qlit(&qlit); +QDict *qdict; +QList *bee; + +qdict = qobject_to_qdict(qobj); +g_assert_cmpint(qdict_get_int(qdict, "foo"), ==, 42); +g_assert_cmpstr(qdict_get_str(qdict, "bar"), ==, "hello world"); +g_assert(qobject_type(qdict_get(qdict, "baz")) == QTYPE_QNULL); + +bee = qdict_get_qlist(qdict, "bee"); +obj = qlist_pop(bee); +g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 43); +qobject_decref(obj); +obj = qlist_pop(bee); +g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), ==, 44); +qobject_decref(obj); +obj = qlist_pop(bee); +g_assert(qbool_get_bool(qobject_to_qbool(obj))); +qobject_decref(obj); + +qobject_decref(qobj); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test); +g_test_add_func("/qlit/qobject_from_qlit", qobject_from_qlit_test); return g_test_run(); } -- 2.13.6
Re: [Qemu-devel] [PATCHv2] linux-user: Fix sched_getaffinity mask size
Le 11/02/2018 à 18:47, Samuel Thibault a écrit : > We properly computed the capped mask size to be put to the application > buffer, but didn't actually used it. Also, we need to return the capped mask > size instead of 0 on success. > > Signed-off-by: Samuel Thibault > > --- > Difference from v1: > - simplify fix > --- > linux-user/syscall.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index 82b35a6bdf..bcda3362fc 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -10493,7 +10493,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long > arg1, > ret = arg2; > } > > -ret = host_to_target_cpu_mask(mask, mask_size, arg3, arg2); > +if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) { > +goto efault; > +} > } > } > break; > Reviewed-by: Laurent Vivier
[Qemu-devel] [PATCH RFC 13/14] qapi-introspect: Add #if conditions to introspection value
Generated tests/test-qapi-introspect.c changes as follows: --- test-qapi-introspect.c.old 2018-02-11 17:36:15.039696522 +0100 +++ tests/test-qapi-introspect.c2018-02-11 17:36:34.455419852 +0100 @@ -118,6 +118,9 @@ QLIT_QDICT(((QLitDictEntry[]) { { "ret-type", QLIT_QSTR("14"), }, {} })), +#if defined(TEST_IF_CMD) +#if defined(TEST_IF_STRUCT) + QLIT_QDICT(((QLitDictEntry[]) { { "arg-type", QLIT_QSTR("15"), }, { "meta-type", QLIT_QSTR("command"), }, @@ -125,12 +128,19 @@ QLIT_QDICT(((QLitDictEntry[]) { { "ret-type", QLIT_QSTR("1"), }, {} })), +#endif /* defined(TEST_IF_STRUCT) */ +#endif /* defined(TEST_IF_CMD) */ + +#if defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT) + QLIT_QDICT(((QLitDictEntry[]) { { "arg-type", QLIT_QSTR("16"), }, { "meta-type", QLIT_QSTR("event"), }, { "name", QLIT_QSTR("TestIfEvent"), }, {} })), +#endif /* defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT) */ + QLIT_QDICT(((QLitDictEntry[]) { { "members", QLIT_QLIST(((QLitObject[]) { {} Signed-off-by: Markus Armbruster --- scripts/qapi/introspect.py | 9 + 1 file changed, 9 insertions(+) diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index c02df95e72..342ae09422 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -40,6 +40,12 @@ def to_qlit(obj, level=0, suppress_first_indent=False): ret = 'QLIT_QDICT(((QLitDictEntry[]) {\n' ret += ',\n'.join(elts) + '\n' ret += indent(level) + '}))' +elif isinstance(obj, tuple): +# Use of tuples for conditionals is a bit of a hack +ifcond, begin = obj +if begin: +return gen_if(ifcond) +return gen_endif(ifcond) else: assert False# not implemented if level > 0: @@ -101,6 +107,9 @@ extern const QLitObject %(var)s; # Ignore types on first pass; visit_end() will pick up used types return not isinstance(entity, QAPISchemaType) +def visit_ifcond(self, ifcond, begin): +self._qlits.append((ifcond, begin)) + def _name(self, name): if self._unmask: return name -- 2.13.6
[Qemu-devel] [PATCH RFC 09/14] qapi: Pass ifcond to visitors
Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 15 +++ tests/qapi-schema/qapi-schema-test.out | 9 + tests/qapi-schema/test-qapi.py | 19 +++ 3 files changed, 43 insertions(+) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 78aeec785e..692a7ec7c2 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1066,6 +1066,9 @@ class QAPISchemaVisitor(object): def visit_include(self, fname, info): pass +def visit_ifcond(self, ifcond, begin): +pass + def visit_builtin_type(self, name, info, json_type): pass @@ -1792,12 +1795,24 @@ class QAPISchema(object): def visit(self, visitor): visitor.visit_begin(self) module = None +ifcond = None for entity in self._entity_list: if visitor.visit_needed(entity): if entity.module != module: +if ifcond: +visitor.visit_ifcond(ifcond, False) +ifcond = None module = entity.module visitor.visit_module(module) +if entity.ifcond != ifcond: +if ifcond: +visitor.visit_ifcond(ifcond, False) +ifcond = entity.ifcond +if ifcond: +visitor.visit_ifcond(ifcond, True) entity.visit(visitor) +if ifcond: +visitor.visit_ifcond(ifcond, False) visitor.visit_end() diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index b11682314c..8fe9d7a3a8 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -232,23 +232,32 @@ command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Unio gen=True success_response=True boxed=False object TestIfStruct member foo: int optional=False +if ['defined(TEST_IF_STRUCT)'] enum TestIfEnum ['foo', 'bar'] +if ['defined(TEST_IF_ENUM)'] object q_obj_TestStruct-wrapper member data: TestStruct optional=False enum TestIfUnionKind ['foo'] +if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)'] object TestIfUnion member type: TestIfUnionKind optional=False tag type case foo: q_obj_TestStruct-wrapper +if ['defined(TEST_IF_UNION) && defined(TEST_IF_STRUCT)'] alternate TestIfAlternate tag type case foo: int case bar: TestStruct +if ['defined(TEST_IF_ALT) && defined(TEST_IF_STRUCT)'] object q_obj_TestIfCmd-arg member foo: TestIfStruct optional=False +if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] command TestIfCmd q_obj_TestIfCmd-arg -> None gen=True success_response=True boxed=False +if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)'] object q_obj_TestIfEvent-arg member foo: TestIfStruct optional=False +if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)'] event TestIfEvent q_obj_TestIfEvent-arg boxed=False +if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)'] diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index 67e417e298..fcdbb5b1ea 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -17,16 +17,26 @@ from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor class QAPISchemaTestVisitor(QAPISchemaVisitor): +def __init__(self): +self._ifcond = None + def visit_module(self, name): print('module %s' % name) def visit_include(self, name, info): print('include %s' % name) +def visit_ifcond(self, ifcond, begin): +if begin: +self._ifcond = ifcond +else: +self._ifcond = None + def visit_enum_type(self, name, info, values, prefix): print('enum %s %s' % (name, values)) if prefix: print('prefix %s' % prefix) +self._print_if(self._ifcond) def visit_object_type(self, name, info, base, members, variants): print('object %s' % name) @@ -36,10 +46,12 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): print('member %s: %s optional=%s' % \ (m.name, m.type.name, m.optional)) self._print_variants(variants) +self._print_if(self._ifcond) def visit_alternate_type(self, name, info, variants): print('alternate %s' % name) self._print_variants(variants) +self._print_if(self._ifcond) def visit_command(self, name, info, arg_type, ret_type, gen, success_response, boxed): @@ -47,10 +59,12 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): (name, arg_type and arg_type.name, ret_type and ret_type.name)) print(' gen=%s success_response=%s boxed=%s' % \ (gen, success_response, boxed)) +self._print_if(self._ifco
[Qemu-devel] [PATCH RFC 04/14] qapi: generate a literal qobject for introspection
From: Marc-André Lureau Replace the generated json string with a literal qobject. The later is easier to deal with, at run time as well as compile time: adding #if conditionals will be easier than in a json string. Signed-off-by: Marc-André Lureau FIXME doc diffs Signed-off-by: Markus Armbruster --- docs/devel/qapi-code-gen.txt | 29 +- monitor.c | 2 +- scripts/qapi/introspect.py | 80 ++ tests/test-qobject-input-visitor.c | 11 -- 4 files changed, 73 insertions(+), 49 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 0c4fc342fe..cb6175ba4d 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -1318,18 +1318,27 @@ Example: #ifndef EXAMPLE_QMP_INTROSPECT_H #define EXAMPLE_QMP_INTROSPECT_H -extern const char example_qmp_schema_json[]; +extern const QLitObject qmp_schema_qlit; #endif $ cat qapi-generated/example-qapi-introspect.c [Uninteresting stuff omitted...] -const char example_qmp_schema_json[] = "[" -"{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, " -"{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"2\"}, " -"{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, " -"{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], \"meta-type\": \"object\", \"name\": \"1\"}, " -"{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"default\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, " -"{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": \"[2]\"}, " -"{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, " -"{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}]"; +const QLitObject example_qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) { +QLIT_QDICT(((QLitDictEntry[]) { +{ "arg-type", QLIT_QSTR("0") }, +{ "meta-type", QLIT_QSTR("event") }, +{ "name", QLIT_QSTR("Event") }, +{ } +})), +QLIT_QDICT(((QLitDictEntry[]) { +{ "members", QLIT_QLIST(((QLitObject[]) { +{ } +})) }, +{ "meta-type", QLIT_QSTR("object") }, +{ "name", QLIT_QSTR("0") }, +{ } +})), +... +{ } +})); diff --git a/monitor.c b/monitor.c index d0e8d350fd..877b90f16d 100644 --- a/monitor.c +++ b/monitor.c @@ -956,7 +956,7 @@ EventInfoList *qmp_query_events(Error **errp) static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, Error **errp) { -*ret_data = qobject_from_json(qmp_schema_json, &error_abort); +*ret_data = qobject_from_qlit(&qmp_schema_qlit); } /* diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index 6c86673a09..e5c491d936 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -13,26 +13,35 @@ See the COPYING file in the top-level directory. from qapi.common import * -# Caveman's json.dumps() replacement (we're stuck at Python 2.4) -# TODO try to use json.dumps() once we get unstuck -def to_json(obj, level=0): +def to_qlit(obj, level=0, suppress_first_indent=False): + +def indent(level): +return level * 4 * ' ' + +if not suppress_first_indent: +ret = indent(level) if obj is None: -ret = 'null' +ret = 'QLIT_QNULL' elif isinstance(obj, str): -ret = '"' + obj.replace('"', r'\"') + '"' +ret = 'QLIT_QSTR(' + to_c_string(obj) + ')' elif isinstance(obj, list): -elts = [to_json(elt, level + 1) +elts = [to_qlit(elt, level + 1) for elt in obj] -ret = '[' + ', '.join(elts) + ']' +elts.append(indent(level + 1) + "{}") +ret = 'QLIT_QLIST(((QLitObject[]) {\n' +ret += ',\n'.join(elts) + '\n' +ret += indent(level) + '}))' elif isinstance(obj, dict): -elts = ['"%s": %s' % (key.replace('"', r'\"'), - to_json(obj[key], level + 1)) -for key in sorted(obj.keys())] -ret = '{' + ', '.join(elts) + '}' +elts = [] +for key, value in sorted(obj.iteritems()): +elts.append(indent(level + 1) + '{ %s, %s }' % +(to_c_string(key), to_qlit(value, level + 1, True))) +elts.append(indent(level + 1) + '{}') +ret = 'QLIT_QDICT(((QLitDictEntry[]) {\n' +ret += ',\n'.join(elts) + '\n' +ret += indent(level) + '}))' else: assert False# not implemented -if level == 1: -ret = '\n' + ret return ret @@ -48,38 +57,41 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor): ' * QAPI/QMP s
[Qemu-devel] [PATCH RFC 07/14] qapi: pass 'if' condition into QAPISchemaEntity objects
From: Marc-André Lureau Built-in objects remain unconditional. Explicitly defined objects use the condition specified in the schema. Implicitly defined objects inherit their condition from their users. For most of them, there is exactly one user, so the condition to use is obvious. The exception is the wrapped type's generated for simple union variants, which can be shared by any number of simple unions. The tight condition would be the disjunction of the conditions of these simple unions. For now, use wrapped type's condition instead. Much simpler and good enough for now. Signed-off-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- scripts/qapi/common.py | 98 +- 1 file changed, 66 insertions(+), 32 deletions(-) diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 0254b9e1ef..789c77f11f 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1007,8 +1007,17 @@ def check_exprs(exprs): # Schema compiler frontend # +def listify_cond(ifcond): +if not ifcond: +return [] +elif not isinstance(ifcond, list): +return [ifcond] +else: +return ifcond + + class QAPISchemaEntity(object): -def __init__(self, name, info, doc): +def __init__(self, name, info, doc, ifcond=None): assert name is None or isinstance(name, str) self.name = name self.module = None @@ -1019,6 +1028,7 @@ class QAPISchemaEntity(object): # such place). self.info = info self.doc = doc +self.ifcond = listify_cond(ifcond) def c_name(self): return c_name(self.name) @@ -1151,8 +1161,8 @@ class QAPISchemaBuiltinType(QAPISchemaType): class QAPISchemaEnumType(QAPISchemaType): -def __init__(self, name, info, doc, values, prefix): -QAPISchemaType.__init__(self, name, info, doc) +def __init__(self, name, info, doc, ifcond, values, prefix): +QAPISchemaType.__init__(self, name, info, doc, ifcond) for v in values: assert isinstance(v, QAPISchemaMember) v.set_owner(name) @@ -1187,7 +1197,7 @@ class QAPISchemaEnumType(QAPISchemaType): class QAPISchemaArrayType(QAPISchemaType): def __init__(self, name, info, element_type): -QAPISchemaType.__init__(self, name, info, None) +QAPISchemaType.__init__(self, name, info, None, None) assert isinstance(element_type, str) self._element_type_name = element_type self.element_type = None @@ -1195,6 +1205,7 @@ class QAPISchemaArrayType(QAPISchemaType): def check(self, schema): self.element_type = schema.lookup_type(self._element_type_name) assert self.element_type +self.ifcond = self.element_type.ifcond def is_implicit(self): return True @@ -1216,11 +1227,12 @@ class QAPISchemaArrayType(QAPISchemaType): class QAPISchemaObjectType(QAPISchemaType): -def __init__(self, name, info, doc, base, local_members, variants): +def __init__(self, name, info, doc, ifcond, + base, local_members, variants): # struct has local_members, optional base, and no variants # flat union has base, variants, and no local_members # simple union has local_members, variants, and no base -QAPISchemaType.__init__(self, name, info, doc) +QAPISchemaType.__init__(self, name, info, doc, ifcond) assert base is None or isinstance(base, str) for m in local_members: assert isinstance(m, QAPISchemaObjectTypeMember) @@ -1408,8 +1420,8 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember): class QAPISchemaAlternateType(QAPISchemaType): -def __init__(self, name, info, doc, variants): -QAPISchemaType.__init__(self, name, info, doc) +def __init__(self, name, info, doc, ifcond, variants): +QAPISchemaType.__init__(self, name, info, doc, ifcond) assert isinstance(variants, QAPISchemaObjectTypeVariants) assert variants.tag_member variants.set_owner(name) @@ -1445,9 +1457,9 @@ class QAPISchemaAlternateType(QAPISchemaType): class QAPISchemaCommand(QAPISchemaEntity): -def __init__(self, name, info, doc, arg_type, ret_type, +def __init__(self, name, info, doc, ifcond, arg_type, ret_type, gen, success_response, boxed): -QAPISchemaEntity.__init__(self, name, info, doc) +QAPISchemaEntity.__init__(self, name, info, doc, ifcond) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) self._arg_type_name = arg_type @@ -1484,8 +1496,8 @@ class QAPISchemaCommand(QAPISchemaEntity): class QAPISchemaEvent(QAPISchemaEntity): -def __init__(self, name, info, doc, arg_type, boxed): -QAPISchemaEntity.__init__(self, name, info, doc) +def __init__(self, name, info, doc, ifcond, arg_type, boxed): +QAPISchemaEntity.
[Qemu-devel] [PATCH RFC 06/14] qapi: add 'if' to top-level expressions
From: Marc-André Lureau Accept 'if' key in top-level elements, accepted as string or list of string type. The following patches will modify the test visitor to check the value is correctly saved, and generate #if/#endif code (as a single #if/endif line or a series for a list). Example of 'if' key: { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' }, 'if': 'defined(TEST_IF_STRUCT)' } The generated code is for now *unconditional*. Later patches generate the conditionals. A following patch for qapi-code-gen.txt will provide more complete documentation for 'if' usage. Signed-off-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- scripts/qapi/common.py | 36 ++-- tests/Makefile.include | 4 tests/qapi-schema/bad-if-empty-list.err | 1 + tests/qapi-schema/bad-if-empty-list.exit | 1 + tests/qapi-schema/bad-if-empty-list.json | 3 +++ tests/qapi-schema/bad-if-empty-list.out | 0 tests/qapi-schema/bad-if-empty.err | 1 + tests/qapi-schema/bad-if-empty.exit | 1 + tests/qapi-schema/bad-if-empty.json | 3 +++ tests/qapi-schema/bad-if-empty.out | 0 tests/qapi-schema/bad-if-list.err| 1 + tests/qapi-schema/bad-if-list.exit | 1 + tests/qapi-schema/bad-if-list.json | 3 +++ tests/qapi-schema/bad-if-list.out| 0 tests/qapi-schema/bad-if.err | 1 + tests/qapi-schema/bad-if.exit| 1 + tests/qapi-schema/bad-if.json| 3 +++ tests/qapi-schema/bad-if.out | 0 tests/qapi-schema/qapi-schema-test.json | 20 ++ tests/qapi-schema/qapi-schema-test.out | 22 +++ tests/test-qmp-cmds.c| 6 ++ 21 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 tests/qapi-schema/bad-if-empty-list.err create mode 100644 tests/qapi-schema/bad-if-empty-list.exit create mode 100644 tests/qapi-schema/bad-if-empty-list.json create mode 100644 tests/qapi-schema/bad-if-empty-list.out create mode 100644 tests/qapi-schema/bad-if-empty.err create mode 100644 tests/qapi-schema/bad-if-empty.exit create mode 100644 tests/qapi-schema/bad-if-empty.json create mode 100644 tests/qapi-schema/bad-if-empty.out create mode 100644 tests/qapi-schema/bad-if-list.err create mode 100644 tests/qapi-schema/bad-if-list.exit create mode 100644 tests/qapi-schema/bad-if-list.json create mode 100644 tests/qapi-schema/bad-if-list.out create mode 100644 tests/qapi-schema/bad-if.err create mode 100644 tests/qapi-schema/bad-if.exit create mode 100644 tests/qapi-schema/bad-if.json create mode 100644 tests/qapi-schema/bad-if.out diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index b9a52e820d..0254b9e1ef 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -637,6 +637,27 @@ def add_name(name, info, meta, implicit=False): all_names[name] = meta +def check_if(expr, info): + +def check_if_str(ifcond, info): +if not isinstance(ifcond, str): +raise QAPISemError( +info, "'if' condition must be a string or a list of strings") +if ifcond == '': +raise QAPISemError(info, "'if' condition '' makes no sense") + +ifcond = expr.get('if') +if ifcond is None: +return +elif isinstance(ifcond, list): +if ifcond == []: +raise QAPISemError(info, "'if' condition [] is useless") +for elt in ifcond: +check_if_str(elt, info) +else: +check_if_str(ifcond, info) + + def check_type(info, source, value, allow_array=False, allow_dict=False, allow_optional=False, allow_metas=[]): @@ -876,6 +897,8 @@ def check_keys(expr_elem, meta, required, optional=[]): raise QAPISemError(info, "'%s' of %s '%s' should only use true value" % (key, meta, name)) +if key == 'if': +check_if(expr, info) for key in required: if key not in expr: raise QAPISemError(info, "Key '%s' is missing from %s '%s'" @@ -904,27 +927,28 @@ def check_exprs(exprs): if 'enum' in expr: meta = 'enum' -check_keys(expr_elem, 'enum', ['data'], ['prefix']) +check_keys(expr_elem, 'enum', ['data'], ['if', 'prefix']) enum_types[expr[meta]] = expr elif 'union' in expr: meta = 'union' check_keys(expr_elem, 'union', ['data'], - ['base', 'discriminator']) + ['base', 'discriminator', 'if']) union_types[expr[meta]] = expr elif 'alternate' in expr: meta = 'alternate' -check_keys(expr_elem, 'alternate', ['data']) +check_keys(expr_elem, 'alternate', ['data'], ['if']) elif 'struct' in expr: meta = 'struct' -check_keys(expr_elem, 'struct'
Re: [Qemu-devel] [PATCH 2/2] 9p: fix leak in synth_name_to_path()
On Fri, 9 Feb 2018 19:29:20 +0100 Marc-André Lureau wrote: > Leak found thanks to ASAN: > > Direct leak of 8 byte(s) in 1 object(s) allocated from: > #0 0x55995789ac90 in __interceptor_malloc > (/home/elmarco/src/qemu/build/x86_64-softmmu/qemu-system-x86_64+0x1510c90) > #1 0x7f0a91190f0c in g_malloc > /home/elmarco/src/gnome/glib/builddir/../glib/gmem.c:94 > #2 0x5599580a281c in v9fs_path_copy > /home/elmarco/src/qemu/hw/9pfs/9p.c:196:17 > #3 0x559958f9ec5d in coroutine_trampoline > /home/elmarco/src/qemu/util/coroutine-ucontext.c:116:9 > #4 0x7f0a8766ebbf (/lib64/libc.so.6+0x50bbf) > > Signed-off-by: Marc-André Lureau > --- > hw/9pfs/9p-synth.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c > index 18082dffe8..54239c9bbf 100644 > --- a/hw/9pfs/9p-synth.c > +++ b/hw/9pfs/9p-synth.c > @@ -495,6 +495,7 @@ static int synth_name_to_path(FsContext *ctx, V9fsPath > *dir_path, > } > out: > /* Copy the node pointer to fid */ > +g_free(target->data); > target->data = g_memdup(&node, sizeof(void *)); > target->size = sizeof(void *); > return 0; Applied both patches. Cheers, -- Greg
Re: [Qemu-devel] [PATCHv2 10/12] cuda: convert to use the shared mos6522 device
On Fri, Feb 09, 2018 at 06:51:40PM +, Mark Cave-Ayland wrote: > Add the relevant hooks as required for the MacOS timer calibration and delayed > SR interrupt. > > Signed-off-by: Mark Cave-Ayland Applied, thanks. > --- > hw/misc/macio/cuda.c | 606 > ++- > hw/ppc/mac.h | 87 > 2 files changed, 204 insertions(+), 489 deletions(-) > > diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c > index a185252144..54c02aeffb 100644 > --- a/hw/misc/macio/cuda.c > +++ b/hw/misc/macio/cuda.c > @@ -26,15 +26,14 @@ > #include "hw/hw.h" > #include "hw/ppc/mac.h" > #include "hw/input/adb.h" > +#include "hw/misc/mos6522.h" > #include "qemu/timer.h" > #include "sysemu/sysemu.h" > #include "qemu/cutils.h" > #include "qemu/log.h" > > -/* XXX: implement all timer modes */ > - > -/* debug CUDA */ > -//#define DEBUG_CUDA > +/* debug CUDA packets */ > +//#define DEBUG_CUDA_PACKET > > /* debug CUDA packets */ > //#define DEBUG_CUDA_PACKET > @@ -47,426 +46,114 @@ > #endif > > /* Bits in B data register: all active low */ > -#define TREQ 0x08/* Transfer request (input) */ > -#define TACK 0x10/* Transfer acknowledge (output) */ > -#define TIP 0x20/* Transfer in progress (output) */ > - > -/* Bits in ACR */ > -#define SR_CTRL 0x1c/* Shift register control bits > */ > -#define SR_EXT 0x0c/* Shift on external clock */ > -#define SR_OUT 0x10/* Shift out if 1 */ > - > -/* Bits in IFR and IER */ > -#define IER_SET 0x80/* set bits in IER */ > -#define IER_CLR 0 /* clear bits in IER */ > -#define SR_INT 0x04/* Shift register full/empty */ > -#define SR_DATA_INT 0x08 > -#define SR_CLOCK_INT 0x10 > -#define T1_INT 0x40/* Timer 1 interrupt */ > -#define T2_INT 0x20/* Timer 2 interrupt */ > - > -/* Bits in ACR */ > -#define T1MODE 0xc0/* Timer 1 mode */ > -#define T1MODE_CONT 0x40/* continuous interrupts */ > +#define TREQ0x08/* Transfer request (input) */ > +#define TACK0x10/* Transfer acknowledge (output) */ > +#define TIP 0x20/* Transfer in progress (output) */ > > /* commands (1st byte) */ > -#define ADB_PACKET 0 > -#define CUDA_PACKET 1 > -#define ERROR_PACKET 2 > -#define TIMER_PACKET 3 > -#define POWER_PACKET 4 > -#define MACIIC_PACKET5 > -#define PMU_PACKET 6 > - > - > -/* CUDA commands (2nd byte) */ > -#define CUDA_WARM_START 0x0 > -#define CUDA_AUTOPOLL0x1 > -#define CUDA_GET_6805_ADDR 0x2 > -#define CUDA_GET_TIME0x3 > -#define CUDA_GET_PRAM0x7 > -#define CUDA_SET_6805_ADDR 0x8 > -#define CUDA_SET_TIME0x9 > -#define CUDA_POWERDOWN 0xa > -#define CUDA_POWERUP_TIME0xb > -#define CUDA_SET_PRAM0xc > -#define CUDA_MS_RESET0xd > -#define CUDA_SEND_DFAC 0xe > -#define CUDA_BATTERY_SWAP_SENSE 0x10 > -#define CUDA_RESET_SYSTEM0x11 > -#define CUDA_SET_IPL 0x12 > -#define CUDA_FILE_SERVER_FLAG0x13 > -#define CUDA_SET_AUTO_RATE 0x14 > -#define CUDA_GET_AUTO_RATE 0x16 > -#define CUDA_SET_DEVICE_LIST 0x19 > -#define CUDA_GET_DEVICE_LIST 0x1a > -#define CUDA_SET_ONE_SECOND_MODE 0x1b > -#define CUDA_SET_POWER_MESSAGES 0x21 > -#define CUDA_GET_SET_IIC 0x22 > -#define CUDA_WAKEUP 0x23 > -#define CUDA_TIMER_TICKLE0x24 > -#define CUDA_COMBINED_FORMAT_IIC 0x25 > +#define ADB_PACKET 0 > +#define CUDA_PACKET 1 > +#define ERROR_PACKET2 > +#define TIMER_PACKET3 > +#define POWER_PACKET4 > +#define MACIIC_PACKET 5 > +#define PMU_PACKET 6 > > #define CUDA_TIMER_FREQ (470 / 6) > > /* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */ > #define RTC_OFFSET 2082844800 > > -/* CUDA registers */ > -#define CUDA_REG_B 0x00 > -#define CUDA_REG_A 0x01 > -#define CUDA_REG_DIRB0x02 > -#define CUDA_REG_DIRA0x03 > -#define CUDA_REG_T1CL0x04 > -#define CUDA_REG_T1CH0x05 > -#define CUDA_REG_T1LL0x06 > -#define CUDA_REG_T1LH0x07 > -#define CUDA_REG_T2CL0x08 > -#define CUDA_REG_T2CH0x09 > -#define CUDA_REG_SR 0x0a > -#define CUDA_REG_ACR 0x0b > -#define CUDA_REG_PCR 0x0c > -#define CUDA_REG_IFR 0x0d > -#define CUDA_REG_IER 0x0e > -#define CUDA_REG_ANH 0x0f > - > -static void cuda_update(CUDAState *s); > static void cuda_receive_packet_from_host(CUDAState *s, >co