[Qemu-devel] [PATCH] block/mirror: fix fail to cancel when VM has heavy BLK IO

2018-01-23 Thread Liang Li
We found that when doing drive mirror to a low speed shared storage,
if there was heavy BLK IO write workload in VM after the 'ready' event,
drive mirror block job can't be canceled immediately, it would keep
running until the heavy BLK IO workload stopped in the VM. This patch
fixed this issue.

Cc: Paolo Bonzini 
Cc: Jeff Cody 
Cc: Kevin Wolf 
Cc: Max Reitz 
Signed-off-by: Huaitong Han 
Signed-off-by: Liang Li 
---
 block/mirror.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index c9badc1..3bc49a5 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -869,11 +869,9 @@ static void coroutine_fn mirror_run(void *opaque)
 
 ret = 0;
 trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
-if (!s->synced) {
-block_job_sleep_ns(>common, delay_ns);
-if (block_job_is_cancelled(>common)) {
-break;
-}
+
+if (block_job_is_cancelled(>common)) {
+break;
 } else if (!should_complete) {
 delay_ns = (s->in_flight == 0 && cnt == 0 ? SLICE_TIME : 0);
 block_job_sleep_ns(>common, delay_ns);
@@ -887,7 +885,7 @@ immediate_exit:
  * or it was cancelled prematurely so that we do not guarantee that
  * the target is a copy of the source.
  */
-assert(ret < 0 || (!s->synced && block_job_is_cancelled(>common)));
+assert(ret < 0 || block_job_is_cancelled(>common));
 assert(need_drain);
 mirror_wait_for_all_io(s);
 }
-- 
1.8.3.1




Re: [Qemu-devel] [PATCH v5 00/28] Migration: postcopy failure recovery

2018-01-23 Thread Peter Xu
On Fri, Jan 12, 2018 at 12:27:42PM +, Dr. David Alan Gilbert wrote:
> * Peter Xu (pet...@redhat.com) wrote:
> > On Thu, Jan 11, 2018 at 04:59:32PM +, Dr. David Alan Gilbert wrote:
> > > * Peter Xu (pet...@redhat.com) wrote:
> > > > Tree is pushed here for better reference and testing (online tree
> > > > includes monitor OOB series):
> > > > 
> > > >   https://github.com/xzpeter/qemu/tree/postcopy-recover-all
> > > > 
> > > > This version removed quite a few patches related to migrate-incoming,
> > > > instead I introduced a new command "migrate-recover" to trigger the
> > > > recovery channel on destination side to simplify the code.
> > > 
> > > I've got this setup on a couple of my test hosts, and I'm using
> > > iptables to try breaking the connection.
> > > 
> > > See below for where I got stuck.
> > > 
> > > > To test this two series altogether, please checkout above tree and
> > > > build.  Note: to test on small and single host, one need to disable
> > > > full bandwidth postcopy migration otherwise it'll complete very fast.
> > > > Basically a simple patch like this would help:
> > > > 
> > > > diff --git a/migration/migration.c b/migration/migration.c
> > > > index 4de3b551fe..c0206023d7 100644
> > > > --- a/migration/migration.c
> > > > +++ b/migration/migration.c
> > > > @@ -1904,7 +1904,7 @@ static int postcopy_start(MigrationState *ms, 
> > > > bool *old_vm_running)
> > > >   * will notice we're in POSTCOPY_ACTIVE and not actually
> > > >   * wrap their state up here
> > > >   */
> > > > -qemu_file_set_rate_limit(ms->to_dst_file, INT64_MAX);
> > > > +// qemu_file_set_rate_limit(ms->to_dst_file, INT64_MAX);
> > > >  if (migrate_postcopy_ram()) {
> > > >  /* Ping just for debugging, helps line traces up */
> > > >  qemu_savevm_send_ping(ms->to_dst_file, 2);
> > > > 
> > > > This patch is included already in above github tree.  Please feel free
> > > > to drop this patch when want to test on big machines and between real
> > > > hosts.
> > > > 
> > > > Detailed Test Procedures (QMP only)
> > > > ===
> > > > 
> > > > 1. start source QEMU.
> > > > 
> > > > $qemu -M q35,kernel-irqchip=split -enable-kvm -snapshot \
> > > >  -smp 4 -m 1G -qmp stdio \
> > > >  -name peter-vm,debug-threads=on \
> > > >  -netdev user,id=net0 \
> > > >  -device e1000,netdev=net0 \
> > > >  -global migration.x-max-bandwidth=4096 \
> > > >  -global migration.x-postcopy-ram=on \
> > > >  /images/fedora-25.qcow2
> > > >
> > > > 2. start destination QEMU.
> > > > 
> > > > $qemu -M q35,kernel-irqchip=split -enable-kvm -snapshot \
> > > >  -smp 4 -m 1G -qmp stdio \
> > > >  -name peter-vm,debug-threads=on \
> > > >  -netdev user,id=net0 \
> > > >  -device e1000,netdev=net0 \
> > > >  -global migration.x-max-bandwidth=4096 \
> > > >  -global migration.x-postcopy-ram=on \
> > > >  -incoming tcp:0.0.0.0: \
> > > >  /images/fedora-25.qcow2
> > > 
> > > I'm using:
> > > ./x86_64-softmmu/qemu-system-x86_64 -nographic -M pc,accel=kvm -smp 4 -m 
> > > 16G -drive file=/home/vms/rhel71.qcow2,id=d,cache=none,if=none -device 
> > > virtio-blk,drive=d -vnc 0:0 -incoming tcp:0: -chardev 
> > > socket,port=4000,host=0,id=mon,server,nowait,telnet -mon 
> > > chardev=mon,id=mon,mode=control -nographic -chardev stdio,mux=on,id=monh 
> > > -mon chardev=monh,mode=readline --device isa-serial,chardev=monh
> > > and I've got both the HMP on the stdio, and the QMP via a telnet
> > > 
> > > > 
> > > > 3. On source, do QMP handshake as normal:
> > > > 
> > > >   {"execute": "qmp_capabilities"}
> > > >   {"return": {}}
> > > > 
> > > > 4. On destination, do QMP handshake to enable OOB:
> > > > 
> > > >   {"execute": "qmp_capabilities", "arguments": { "enable": [ "oob" ] } }
> > > >   {"return": {}}
> > > > 
> > > > 5. On source, trigger initial migrate command, switch to postcopy:
> > > > 
> > > >   {"execute": "migrate", "arguments": { "uri": "tcp:localhost:" } }
> > > >   {"return": {}}
> > > >   {"execute": "query-migrate"}
> > > >   {"return": {"expected-downtime": 300, "status": "active", ...}}
> > > >   {"execute": "migrate-start-postcopy"}
> > > >   {"return": {}}
> > > >   {"timestamp": {"seconds": 1512454728, "microseconds": 768096}, 
> > > > "event": "STOP"}
> > > >   {"execute": "query-migrate"}
> > > >   {"return": {"expected-downtime": 44472, "status": "postcopy-active", 
> > > > ...}}
> > > > 
> > > > 6. On source, manually trigger a "fake network down" using
> > > >"migrate-cancel" command:
> > > > 
> > > >   {"execute": "migrate_cancel"}
> > > >   {"return": {}}
> > > 
> > > Before I do that, I'm breaking the network connection by running on the
> > > source:
> > > iptables -A INPUT -p tcp --source-port  -j DROP
> > > iptables -A INPUT -p tcp --destination-port  -j DROP
> > 
> > This is tricky... I think tcp keepalive may help, but for sure I
> > think we do need a way to 

[Qemu-devel] [PATCH v7 23/23] tests: qmp-test: add oob test

2018-01-23 Thread Peter Xu
Test the new OOB capability.  Here we used the new "x-oob-test" command.
Firstly, we send a lock=true and oob=false command to hang the main
thread.  Then send another lock=false and oob=true command (which will
be run inside parser this time) to free that hanged command.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Peter Xu 
---
 tests/qmp-test.c | 65 
 1 file changed, 65 insertions(+)

diff --git a/tests/qmp-test.c b/tests/qmp-test.c
index 19fa774486..c41e8305b6 100644
--- a/tests/qmp-test.c
+++ b/tests/qmp-test.c
@@ -160,6 +160,70 @@ static void test_qmp_protocol(void)
 qtest_end();
 }
 
+/* Tests for Out-Of-Band support. */
+static void test_qmp_oob(void)
+{
+QDict *resp;
+int acks = 0;
+const char *cmd_id;
+
+global_qtest = qtest_init_without_qmp_handshake(common_args);
+
+/* Ignore the greeting message. */
+resp = qmp_receive();
+g_assert(qdict_get_qdict(resp, "QMP"));
+QDECREF(resp);
+
+/* Try a fake capability, it should fail. */
+resp = qmp("{ 'execute': 'qmp_capabilities', "
+   "  'arguments': { 'enable': [ 'cap-does-not-exist' ] } }");
+g_assert(qdict_haskey(resp, "error"));
+QDECREF(resp);
+
+/* Now, enable OOB in current QMP session, it should success. */
+resp = qmp("{ 'execute': 'qmp_capabilities', "
+   "  'arguments': { 'enable': [ 'oob' ] } }");
+g_assert(qdict_haskey(resp, "return"));
+QDECREF(resp);
+
+/*
+ * Try any command that does not support OOB but with OOB flag. We
+ * should get failure.
+ */
+resp = qmp("{ 'execute': 'query-cpus',"
+   "  'control': { 'run-oob': true } }");
+g_assert(qdict_haskey(resp, "error"));
+QDECREF(resp);
+
+/*
+ * Firstly send the "x-oob-test" command with lock=true and
+ * oob=false, it should hang the dispatcher and main thread;
+ * later, we send another lock=false with oob=true to continue
+ * that thread processing.  Finally we should receive replies from
+ * both commands.
+ */
+qmp_async("{ 'execute': 'x-oob-test',"
+  "  'arguments': { 'lock': true }, "
+  "  'id': 'lock-cmd'}");
+qmp_async("{ 'execute': 'x-oob-test', "
+  "  'arguments': { 'lock': false }, "
+  "  'control': { 'run-oob': true }, "
+  "  'id': 'unlock-cmd' }");
+
+/* Ignore all events.  Wait for 2 acks */
+while (acks < 2) {
+resp = qmp_receive();
+cmd_id = qdict_get_str(resp, "id");
+if (!g_strcmp0(cmd_id, "lock-cmd") ||
+!g_strcmp0(cmd_id, "unlock-cmd")) {
+acks++;
+}
+QDECREF(resp);
+}
+
+qtest_end();
+}
+
 static int query_error_class(const char *cmd)
 {
 static struct {
@@ -339,6 +403,7 @@ int main(int argc, char *argv[])
 g_test_init(, , NULL);
 
 qtest_add_func("qmp/protocol", test_qmp_protocol);
+qtest_add_func("qmp/oob", test_qmp_oob);
 qmp_schema_init();
 add_query_tests();
 
-- 
2.14.3




[Qemu-devel] [PATCH v7 22/23] tests: qmp-test: verify command batching

2018-01-23 Thread Peter Xu
OOB introduced DROP event for flow control.  This should not affect old
QMP clients.  Add a command batching check to make sure of it.

Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Peter Xu 
---
 tests/qmp-test.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/tests/qmp-test.c b/tests/qmp-test.c
index 11b384c829..19fa774486 100644
--- a/tests/qmp-test.c
+++ b/tests/qmp-test.c
@@ -78,6 +78,7 @@ static void test_qmp_protocol(void)
 QList *capabilities;
 const QListEntry *entry;
 QString *qstr;
+int i;
 
 global_qtest = qtest_init_without_qmp_handshake(common_args);
 
@@ -135,6 +136,27 @@ static void test_qmp_protocol(void)
 g_assert_cmpint(qdict_get_int(resp, "id"), ==, 2);
 QDECREF(resp);
 
+/*
+ * Test command batching.  In current test OOB is not enabled, we
+ * should be able to run as many commands in batch as we like.
+ * Using 16 (>8, which is OOB queue length) to make sure OOB won't
+ * break existing clients.  Note: this test does not control the
+ * scheduling of QEMU's QMP command processing threads so it may
+ * not really trigger batching inside QEMU.  This is just a
+ * best-effort test.
+ */
+for (i = 0; i < 16; i++) {
+qmp_async("{ 'execute': 'query-version' }");
+}
+/* Verify the replies to make sure no command is dropped. */
+for (i = 0; i < 16; i++) {
+resp = qmp_receive();
+/* It should never be dropped.  Each of them should be a reply. */
+g_assert(qdict_haskey(resp, "return"));
+g_assert(!qdict_haskey(resp, "event"));
+QDECREF(resp);
+}
+
 qtest_end();
 }
 
-- 
2.14.3




[Qemu-devel] [PATCH v7 17/23] qapi: introduce new cmd option "allow-oob"

2018-01-23 Thread Peter Xu
Here "oob" stands for "Out-Of-Band".  When "allow-oob" is set, it means
the command allows out-of-band execution.

The "oob" idea is proposed by Markus Armbruster in following thread:

  https://lists.gnu.org/archive/html/qemu-devel/2017-09/msg02057.html

This new "allow-oob" boolean will be exposed by "query-qmp-schema" as
well for command entries, so that QMP clients can know which command can
be used as out-of-band calls. For example the command "migrate"
originally looks like:

  {"name": "migrate", "ret-type": "17", "meta-type": "command",
   "arg-type": "86"}

And it'll be changed into:

  {"name": "migrate", "ret-type": "17", "allow-oob": false,
   "meta-type": "command", "arg-type": "86"}

This patch only provides the QMP interface level changes.  It does not
contains the real out-of-band execution implementation yet.

Suggested-by: Markus Armbruster 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Fam Zheng 
Signed-off-by: Peter Xu 
---
 include/qapi/qmp/dispatch.h|  1 +
 qapi/introspect.json   |  6 +-
 scripts/qapi-commands.py   | 19 ++-
 scripts/qapi-introspect.py | 10 --
 scripts/qapi.py| 15 ++-
 scripts/qapi2texi.py   |  2 +-
 tests/qapi-schema/test-qapi.py |  2 +-
 7 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index 20578dcd48..b76798800c 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -23,6 +23,7 @@ typedef enum QmpCommandOptions
 {
 QCO_NO_OPTIONS = 0x0,
 QCO_NO_SUCCESS_RESP = 0x1,
+QCO_ALLOW_OOB = 0x2,
 } QmpCommandOptions;
 
 typedef struct QmpCommand
diff --git a/qapi/introspect.json b/qapi/introspect.json
index 5b3e6e9d78..c7f67b7d78 100644
--- a/qapi/introspect.json
+++ b/qapi/introspect.json
@@ -259,12 +259,16 @@
 #
 # @ret-type: the name of the command's result type.
 #
+# @allow-oob: whether the command allows out-of-band execution.
+# (Since: 2.12)
+#
 # TODO: @success-response (currently irrelevant, because it's QGA, not QMP)
 #
 # Since: 2.5
 ##
 { 'struct': 'SchemaInfoCommand',
-  'data': { 'arg-type': 'str', 'ret-type': 'str' } }
+  'data': { 'arg-type': 'str', 'ret-type': 'str',
+'allow-oob': 'bool' } }
 
 ##
 # @SchemaInfoEvent:
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 974d0a4a80..b2b0bc0510 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -192,10 +192,18 @@ out:
 return ret
 
 
-def gen_register_command(name, success_response):
-options = 'QCO_NO_OPTIONS'
+def gen_register_command(name, success_response, allow_oob):
+options = []
+
 if not success_response:
-options = 'QCO_NO_SUCCESS_RESP'
+options += ['QCO_NO_SUCCESS_RESP']
+if allow_oob:
+options += ['QCO_ALLOW_OOB']
+
+if not options:
+options = ['QCO_NO_OPTIONS']
+
+options = " | ".join(options)
 
 ret = mcgen('''
 qmp_register_command(cmds, "%(name)s",
@@ -241,7 +249,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
 self._visited_ret_types = None
 
 def visit_command(self, name, info, arg_type, ret_type,
-  gen, success_response, boxed):
+  gen, success_response, boxed, allow_oob):
 if not gen:
 return
 self.decl += gen_command_decl(name, arg_type, boxed, ret_type)
@@ -250,7 +258,8 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
 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)
+self._regy += gen_register_command(name, success_response,
+   allow_oob)
 
 
 (input_file, output_dir, do_c, do_h, prefix, opts) = parse_command_line()
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index 032bcea491..9fbf88b644 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -28,6 +28,11 @@ def to_json(obj, level=0):
   to_json(obj[key], level + 1))
 for key in sorted(obj.keys())]
 ret = '{' + ', '.join(elts) + '}'
+elif isinstance(obj, bool):
+if obj:
+ret = 'true'
+else:
+ret = 'false'
 else:
 assert False# not implemented
 if level == 1:
@@ -154,12 +159,13 @@ const char %(c_name)s[] = %(c_string)s;
 for m in variants.variants]})
 
 def visit_command(self, name, info, arg_type, ret_type,
-  gen, success_response, boxed):
+  gen, success_response, boxed, allow_oob):
 arg_type = arg_type or self._schema.the_empty_object_type
 ret_type = 

[Qemu-devel] [PATCH v7 20/23] monitor: enable IO thread for (qmp & !mux) typed

2018-01-23 Thread Peter Xu
Start to use dedicate IO thread for QMP monitors that are not using
MUXed chardev.

Reviewed-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Peter Xu 
---
 monitor.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/monitor.c b/monitor.c
index eac92c9b86..5b7da2b574 100644
--- a/monitor.c
+++ b/monitor.c
@@ -36,6 +36,7 @@
 #include "net/slirp.h"
 #include "chardev/char-fe.h"
 #include "chardev/char-io.h"
+#include "chardev/char-mux.h"
 #include "ui/qemu-spice.h"
 #include "sysemu/numa.h"
 #include "monitor/monitor.h"
@@ -4579,8 +4580,10 @@ static void monitor_qmp_setup_handlers(void *data)
 void monitor_init(Chardev *chr, int flags)
 {
 Monitor *mon = g_malloc(sizeof(*mon));
+/* Enable IOThread for QMPs that are not using MUX chardev backends. */
+bool use_io_thr = (!CHARDEV_IS_MUX(chr)) && (flags & MONITOR_USE_CONTROL);
 
-monitor_data_init(mon, false, false);
+monitor_data_init(mon, false, use_io_thr);
 
 qemu_chr_fe_init(>chr, chr, _abort);
 mon->flags = flags;
-- 
2.14.3




[Qemu-devel] [PATCH v7 16/23] monitor: send event when command queue full

2018-01-23 Thread Peter Xu
Set maximum QMP command queue length to 8.  If queue full, instead of
queue the command, we directly return a "command-dropped" event, telling
client that specific command is dropped.

Note that this flow control mechanism is only valid if OOB is enabled.
If it's not, the effective queue length will always be 1, which strictly
follows original behavior of QMP command handling (which never drop
messages).

Signed-off-by: Peter Xu 
---
 monitor.c | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/monitor.c b/monitor.c
index 51d12412fa..bf0f3d1662 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4055,6 +4055,8 @@ static void monitor_qmp_bh_dispatcher(void *data)
 }
 }
 
+#define  QMP_REQ_QUEUE_LEN_MAX  (8)
+
 static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
 {
 QObject *req, *id = NULL;
@@ -4088,6 +4090,9 @@ static void handle_qmp_command(JSONMessageParser *parser, 
GQueue *tokens)
 req_obj->req = req;
 req_obj->need_resume = false;
 
+/* Protect qmp_requests and fetching its length. */
+qemu_mutex_lock(>qmp.qmp_queue_lock);
+
 /*
  * If OOB is not enabled on current monitor, we'll emulate the old
  * behavior that we won't process current monitor any more until
@@ -4097,6 +4102,18 @@ static void handle_qmp_command(JSONMessageParser 
*parser, GQueue *tokens)
 if (!qmp_oob_enabled(mon)) {
 monitor_suspend(mon);
 req_obj->need_resume = true;
+} else {
+/* Drop the request if queue is full. */
+if (mon->qmp.qmp_requests->length >= QMP_REQ_QUEUE_LEN_MAX) {
+qemu_mutex_unlock(>qmp.qmp_queue_lock);
+qapi_event_send_command_dropped(id,
+COMMAND_DROP_REASON_QUEUE_FULL,
+NULL);
+qobject_decref(id);
+qobject_decref(req);
+g_free(req_obj);
+return;
+}
 }
 
 /*
@@ -4104,7 +4121,6 @@ static void handle_qmp_command(JSONMessageParser *parser, 
GQueue *tokens)
  * handled in time order.  Ownership for req_obj, req, id,
  * etc. will be delivered to the handler side.
  */
-qemu_mutex_lock(>qmp.qmp_queue_lock);
 g_queue_push_tail(mon->qmp.qmp_requests, req_obj);
 qemu_mutex_unlock(>qmp.qmp_queue_lock);
 
-- 
2.14.3




[Qemu-devel] [PATCH v7 19/23] qmp: isolate responses into io thread

2018-01-23 Thread Peter Xu
For those monitors who have enabled IO thread, we'll offload the
responding procedure into IO thread.  The main reason is that chardev is
not thread safe, and we need to do all the read/write IOs in the same
thread.  For use_io_thr=true monitors, that thread is the IO thread.

We do this isolation in similar pattern as what we have done to the
request queue: we first create one response queue for each monitor, then
instead of replying directly in the main thread, we queue the responses
and kick the IO thread to do the rest of the job for us.

A funny thing after doing this is that, when the QMP clients send "quit"
to QEMU, it's possible that we close the IOThread even earlier than
replying to that "quit".  So another thing we need to do before cleaning
up the monitors is that we need to flush the response queue (we don't
need to do that for command queue; after all we are quitting) to make
sure replies for handled commands are always flushed back to clients.

Reviewed-by: Fam Zheng 
Signed-off-by: Peter Xu 
---
 monitor.c | 96 ++-
 1 file changed, 95 insertions(+), 1 deletion(-)

diff --git a/monitor.c b/monitor.c
index d31da3fd1b..eac92c9b86 100644
--- a/monitor.c
+++ b/monitor.c
@@ -175,6 +175,8 @@ typedef struct {
 QemuMutex qmp_queue_lock;
 /* Input queue that holds all the parsed QMP requests */
 GQueue *qmp_requests;
+/* Output queue contains all the QMP responses in order */
+GQueue *qmp_responses;
 } MonitorQMP;
 
 /*
@@ -201,6 +203,7 @@ struct Monitor {
 bool skip_flush;
 bool use_io_thr;
 
+/* We can't access guest memory when holding the lock */
 QemuMutex out_lock;
 QString *outbuf;
 guint out_watch;
@@ -223,6 +226,8 @@ static struct {
 IOThread *mon_iothread;
 /* Bottom half to dispatch the requests received from IO thread */
 QEMUBH *qmp_dispatcher_bh;
+/* Bottom half to deliver the responses back to clients */
+QEMUBH *qmp_respond_bh;
 } mon_global;
 
 /* QMP checker flags */
@@ -412,7 +417,8 @@ int monitor_fprintf(FILE *stream, const char *fmt, ...)
 return 0;
 }
 
-static void monitor_json_emitter(Monitor *mon, const QObject *data)
+static void monitor_json_emitter_raw(Monitor *mon,
+ QObject *data)
 {
 QString *json;
 
@@ -426,6 +432,71 @@ static void monitor_json_emitter(Monitor *mon, const 
QObject *data)
 QDECREF(json);
 }
 
+static void monitor_json_emitter(Monitor *mon, QObject *data)
+{
+if (mon->use_io_thr) {
+/*
+ * If using IO thread, we need to queue the item so that IO
+ * thread will do the rest for us.  Take refcount so that
+ * caller won't free the data (which will be finally freed in
+ * responder thread).
+ */
+qobject_incref(data);
+qemu_mutex_lock(>qmp.qmp_queue_lock);
+g_queue_push_tail(mon->qmp.qmp_responses, (void *)data);
+qemu_mutex_unlock(>qmp.qmp_queue_lock);
+qemu_bh_schedule(mon_global.qmp_respond_bh);
+} else {
+/*
+ * If not using monitor IO thread, then we are in main thread.
+ * Do the emission right away.
+ */
+monitor_json_emitter_raw(mon, data);
+}
+}
+
+struct QMPResponse {
+Monitor *mon;
+QObject *data;
+};
+typedef struct QMPResponse QMPResponse;
+
+/*
+ * Return one QMPResponse.  The response is only valid if
+ * response.data is not NULL.
+ */
+static QMPResponse monitor_qmp_response_pop_one(void)
+{
+Monitor *mon;
+QObject *data = NULL;
+
+qemu_mutex_lock(_lock);
+QTAILQ_FOREACH(mon, _list, entry) {
+qemu_mutex_lock(>qmp.qmp_queue_lock);
+data = g_queue_pop_head(mon->qmp.qmp_responses);
+qemu_mutex_unlock(>qmp.qmp_queue_lock);
+if (data) {
+break;
+}
+}
+qemu_mutex_unlock(_lock);
+return (QMPResponse) { .mon = mon, .data = data };
+}
+
+static void monitor_qmp_bh_responder(void *opaque)
+{
+QMPResponse response;
+
+while (true) {
+response = monitor_qmp_response_pop_one();
+if (!response.data) {
+break;
+}
+monitor_json_emitter_raw(response.mon, response.data);
+qobject_decref(response.data);
+}
+}
+
 static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = {
 /* Limit guest-triggerable events to 1 per second */
 [QAPI_EVENT_RTC_CHANGE]= { 1000 * SCALE_MS },
@@ -612,6 +683,7 @@ static void monitor_data_init(Monitor *mon, bool skip_flush,
 mon->skip_flush = skip_flush;
 mon->use_io_thr = use_io_thr;
 mon->qmp.qmp_requests = g_queue_new();
+mon->qmp.qmp_responses = g_queue_new();
 }
 
 static void monitor_data_destroy(Monitor *mon)
@@ -626,6 +698,7 @@ static void monitor_data_destroy(Monitor *mon)
 qemu_mutex_destroy(>out_lock);
 qemu_mutex_destroy(>qmp.qmp_queue_lock);
 

[Qemu-devel] [PATCH v7 15/23] qmp: add new event "command-dropped"

2018-01-23 Thread Peter Xu
This event will be emitted if one QMP command is dropped.  Along,
declare an enum for the reasons.

Reviewed-by: Fam Zheng 
Signed-off-by: Peter Xu 
---
 qapi-schema.json | 37 +
 1 file changed, 37 insertions(+)

diff --git a/qapi-schema.json b/qapi-schema.json
index 2490d5188e..d6c89efc0d 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3215,3 +3215,40 @@
 # Since: 2.11
 ##
 { 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
+##
+# @CommandDropReason:
+#
+# Reasons that caused one command to be dropped.
+#
+# @queue-full: the command queue is full. This can only occur when
+#  the client sends a new non-oob command before the
+#  response to the previous non-oob command has been
+#  received.
+#
+# Since: 2.12
+##
+{ 'enum': 'CommandDropReason',
+  'data': [ 'queue-full' ] }
+
+##
+# @COMMAND_DROPPED:
+#
+# Emitted when a command is dropped due to some reason.  Commands can
+# only be dropped when the oob capability is enabled.
+#
+# @id: The dropped command's "id" field.
+#
+# @reason: The reason why the command is dropped.
+#
+# Since: 2.12
+#
+# Example:
+#
+# { "event": "COMMAND_DROPPED",
+#   "data": {"result": {"id": "libvirt-102",
+#   "reason": "queue-full" } } }
+#
+##
+{ 'event': 'COMMAND_DROPPED' ,
+  'data': { 'id': 'any', 'reason': 'CommandDropReason' } }
-- 
2.14.3




[Qemu-devel] [PATCH v7 18/23] qmp: support out-of-band (oob) execution

2018-01-23 Thread Peter Xu
Having "allow-oob" to true for a command does not mean that this command
will always be run in out-of-band mode.  The out-of-band quick path will
only be executed if we specify the extra "run-oob" flag when sending the
QMP request:

{ "execute":   "command-that-allows-oob",
  "arguments": { ... },
  "control":   { "run-oob": true } }

The "control" key is introduced to store this extra flag.  "control"
field is used to store arguments that are shared by all the commands,
rather than command specific arguments.  Let "run-oob" be the first.

Note that in the patch I exported qmp_dispatch_check_obj() to be used to
check the request earlier, and at the same time allowed "id" field to be
there since actually we always allow that.

Signed-off-by: Peter Xu 
---
 include/qapi/qmp/dispatch.h |  2 ++
 monitor.c   | 84 -
 qapi/qmp-dispatch.c | 32 -
 trace-events|  2 ++
 4 files changed, 110 insertions(+), 10 deletions(-)

diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index b76798800c..d8d913b338 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -49,6 +49,8 @@ bool qmp_command_is_enabled(const QmpCommand *cmd);
 const char *qmp_command_name(const QmpCommand *cmd);
 bool qmp_has_success_response(const QmpCommand *cmd);
 QObject *qmp_build_error_object(Error *err);
+QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp);
+bool qmp_is_oob(QDict *dict);
 
 typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque);
 
diff --git a/monitor.c b/monitor.c
index bf0f3d1662..d31da3fd1b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1106,6 +1106,44 @@ static void qmp_caps_apply(Monitor *mon, 
QMPCapabilityList *list)
 }
 }
 
+/*
+ * Return true if check successful, or false otherwise.  When false is
+ * returned, detailed error will be in errp if provided.
+ */
+static bool qmp_cmd_oob_check(Monitor *mon, QDict *req, Error **errp)
+{
+const char *command;
+QmpCommand *cmd;
+
+command = qdict_get_try_str(req, "execute");
+if (!command) {
+error_setg(errp, "Command field 'execute' missing");
+return false;
+}
+
+cmd = qmp_find_command(mon->qmp.commands, command);
+if (!cmd) {
+error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
+  "The command %s has not been found", command);
+return false;
+}
+
+if (qmp_is_oob(req)) {
+if (!qmp_oob_enabled(mon)) {
+error_setg(errp, "Please enable Out-Of-Band first "
+   "for the session during capabilities negociation");
+return false;
+}
+if (!(cmd->options & QCO_ALLOW_OOB)) {
+error_setg(errp, "The command %s does not support OOB",
+   command);
+return false;
+}
+}
+
+return true;
+}
+
 void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable,
   Error **errp)
 {
@@ -4049,6 +4087,7 @@ static void monitor_qmp_bh_dispatcher(void *data)
 QMPRequest *req_obj = monitor_qmp_requests_pop_one();
 
 if (req_obj) {
+trace_monitor_qmp_cmd_in_band(qobject_get_try_str(req_obj->id) ?: "");
 monitor_qmp_dispatch_one(req_obj);
 /* Reschedule instead of looping so the main loop stays responsive */
 qemu_bh_schedule(mon_global.qmp_dispatcher_bh);
@@ -4072,17 +4111,31 @@ static void handle_qmp_command(JSONMessageParser 
*parser, GQueue *tokens)
 error_setg(, QERR_JSON_PARSING);
 }
 if (err) {
-monitor_qmp_respond(mon, NULL, err, NULL);
-qobject_decref(req);
-return;
+goto err;
+}
+
+/* Check against the request in general layout */
+qdict = qmp_dispatch_check_obj(req, );
+if (!qdict) {
+goto err;
 }
 
-qdict = qobject_to_qdict(req);
-if (qdict) {
-id = qdict_get(qdict, "id");
-qobject_incref(id);
-qdict_del(qdict, "id");
-} /* else will fail qmp_dispatch() */
+/* Check against OOB specific */
+if (!qmp_cmd_oob_check(mon, qdict, )) {
+goto err;
+}
+
+id = qdict_get(qdict, "id");
+
+/* When OOB is enabled, the "id" field is mandatory. */
+if (qmp_oob_enabled(mon) && !id) {
+error_setg(, "Out-Of-Band capability requires that "
+   "every command contains an 'id' field");
+goto err;
+}
+
+qobject_incref(id);
+qdict_del(qdict, "id");
 
 req_obj = g_new0(QMPRequest, 1);
 req_obj->mon = mon;
@@ -4090,6 +4143,14 @@ static void handle_qmp_command(JSONMessageParser 
*parser, GQueue *tokens)
 req_obj->req = req;
 req_obj->need_resume = false;
 
+if (qmp_is_oob(qdict)) {
+/* Out-Of-Band (OOB) requests are executed directly in parser. */
+trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(req_obj->id)
+

[Qemu-devel] [PATCH v7 11/23] monitor: introduce monitor_qmp_respond()

2018-01-23 Thread Peter Xu
A tiny refactoring, preparing to split the QMP dispatcher away.

Reviewed-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Peter Xu 
---
 monitor.c | 50 +-
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/monitor.c b/monitor.c
index 3e07798442..92114aaa80 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3867,6 +3867,38 @@ static int monitor_can_read(void *opaque)
 return (mon->suspend_cnt == 0) ? 1 : 0;
 }
 
+/*
+ * 1. This function takes ownership of rsp, err, and id.
+ * 2. rsp, err, and id may be NULL.
+ * 3. If err != NULL then rsp must be NULL.
+ */
+static void monitor_qmp_respond(Monitor *mon, QObject *rsp,
+Error *err, QObject *id)
+{
+QDict *qdict = NULL;
+
+if (err) {
+assert(!rsp);
+qdict = qdict_new();
+qdict_put_obj(qdict, "error", qmp_build_error_object(err));
+error_free(err);
+rsp = QOBJECT(qdict);
+}
+
+if (rsp) {
+if (id) {
+/* This is for the qdict below. */
+qobject_incref(id);
+qdict_put_obj(qobject_to_qdict(rsp), "id", id);
+}
+
+monitor_json_emitter(mon, rsp);
+}
+
+qobject_decref(id);
+qobject_decref(rsp);
+}
+
 static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
 {
 QObject *req, *rsp = NULL, *id = NULL;
@@ -3918,24 +3950,8 @@ static void handle_qmp_command(JSONMessageParser 
*parser, GQueue *tokens)
 }
 
 err_out:
-if (err) {
-qdict = qdict_new();
-qdict_put_obj(qdict, "error", qmp_build_error_object(err));
-error_free(err);
-rsp = QOBJECT(qdict);
-}
+monitor_qmp_respond(mon, rsp, err, id);
 
-if (rsp) {
-if (id) {
-qdict_put_obj(qobject_to_qdict(rsp), "id", id);
-id = NULL;
-}
-
-monitor_json_emitter(mon, rsp);
-}
-
-qobject_decref(id);
-qobject_decref(rsp);
 qobject_decref(req);
 }
 
-- 
2.14.3




[Qemu-devel] [PATCH v7 13/23] monitor: let suspend/resume work even with QMPs

2018-01-23 Thread Peter Xu
This patches allows QMP monitors to be suspended/resumed.

One thing to mention is that for QMPs that are using IOThreads, we need
an explicit kick for the IOThread in case it is sleeping.

Meanwhile, we need to take special care on non-interactive HMPs.
Currently only gdbserver is using that.  For these monitors, we still
don't allow suspend/resume operations.

Since at it, add traces for the operations.

Signed-off-by: Peter Xu 
---
 monitor.c| 45 ++---
 trace-events |  1 +
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/monitor.c b/monitor.c
index 60bcf67b3a..76137ba2a4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -246,6 +246,21 @@ static inline bool monitor_is_qmp(const Monitor *mon)
 return (mon->flags & MONITOR_USE_CONTROL);
 }
 
+/**
+ * Whether @mon is using readline?  Note: not all HMP monitors can are
+ * using readline, e.g., gdbserver has non-interactive HMP monitor, so
+ * readline is not used there.
+ */
+static inline bool monitor_uses_readline(const Monitor *mon)
+{
+return mon->flags & MONITOR_USE_READLINE;
+}
+
+static inline bool monitor_is_hmp_non_interactive(const Monitor *mon)
+{
+return !monitor_is_qmp(mon) && !monitor_uses_readline(mon);
+}
+
 /**
  * Is the current monitor, if any, a QMP monitor?
  */
@@ -3994,19 +4009,43 @@ static void monitor_command_cb(void *opaque, const char 
*cmdline,
 
 int monitor_suspend(Monitor *mon)
 {
-if (!mon->rs)
+if (monitor_is_hmp_non_interactive(mon)) {
 return -ENOTTY;
+}
+
+if (monitor_is_qmp(mon)) {
+/*
+ * Kick iothread to make sure this takes effect.  It'll be
+ * evaluated again in prepare() of the watch object.
+ */
+aio_notify(iothread_get_aio_context(mon_global.mon_iothread));
+}
 atomic_inc(>suspend_cnt);
+trace_monitor_suspend(mon, 1);
 return 0;
 }
 
 void monitor_resume(Monitor *mon)
 {
-if (!mon->rs)
+if (monitor_is_hmp_non_interactive(mon)) {
 return;
+}
+
 if (atomic_dec_fetch(>suspend_cnt) == 0) {
-readline_show_prompt(mon->rs);
+if (monitor_is_qmp(mon)) {
+/*
+ * For QMP monitors that are running in IOThread, let's
+ * kick the thread in case it's sleeping.
+ */
+if (mon->use_io_thr) {
+aio_notify(iothread_get_aio_context(mon_global.mon_iothread));
+}
+} else {
+assert(mon->rs);
+readline_show_prompt(mon->rs);
+}
 }
+trace_monitor_suspend(mon, -1);
 }
 
 static QObject *get_qmp_greeting(Monitor *mon)
diff --git a/trace-events b/trace-events
index ec95e67089..eecb68b1d5 100644
--- a/trace-events
+++ b/trace-events
@@ -47,6 +47,7 @@ monitor_protocol_event_emit(uint32_t event, void *data) 
"event=%d data=%p"
 monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) 
"event=%d data=%p rate=%" PRId64
 handle_hmp_command(void *mon, const char *cmdline) "mon %p cmdline: %s"
 handle_qmp_command(void *mon, const char *req) "mon %p req: %s"
+monitor_suspend(void *ptr, int cnt) "mon %p: %d"
 
 # dma-helpers.c
 dma_blk_io(void *dbs, void *bs, int64_t offset, bool to_dev) "dbs=%p bs=%p 
offset=%" PRId64 " to_dev=%d"
-- 
2.14.3




[Qemu-devel] [PATCH v7 14/23] monitor: separate QMP parser and dispatcher

2018-01-23 Thread Peter Xu
Originally QMP goes through these steps:

  JSON Parser --> QMP Dispatcher --> Respond
  /|\(2)(3) |
   (1) |   \|/ (4)
   +-  main thread  +

This patch does this:

  JSON Parser QMP Dispatcher --> Respond
  /|\ |   /|\   (4) |
   |  | (2)| (3)|  (5)
   (1) |  +->  |   \|/
   +-  main thread  <---+

So the parsing job and the dispatching job is isolated now.  It gives us
a chance in following up patches to totally move the parser outside.

The isolation is done using one QEMUBH. Only one dispatcher QEMUBH is
used for all the monitors.

Signed-off-by: Peter Xu 
---
 monitor.c | 201 +++---
 1 file changed, 178 insertions(+), 23 deletions(-)

diff --git a/monitor.c b/monitor.c
index 76137ba2a4..51d12412fa 100644
--- a/monitor.c
+++ b/monitor.c
@@ -168,6 +168,13 @@ typedef struct {
  */
 QmpCommandList *commands;
 bool qmp_caps[QMP_CAPABILITY__MAX];
+/*
+ * Protects qmp request/response queue.  Please take monitor_lock
+ * first when used together.
+ */
+QemuMutex qmp_queue_lock;
+/* Input queue that holds all the parsed QMP requests */
+GQueue *qmp_requests;
 } MonitorQMP;
 
 /*
@@ -214,6 +221,8 @@ struct Monitor {
 /* Let's add monitor global variables to this struct. */
 static struct {
 IOThread *mon_iothread;
+/* Bottom half to dispatch the requests received from IO thread */
+QEMUBH *qmp_dispatcher_bh;
 } mon_global;
 
 /* QMP checker flags */
@@ -596,11 +605,13 @@ static void monitor_data_init(Monitor *mon, bool 
skip_flush,
 {
 memset(mon, 0, sizeof(Monitor));
 qemu_mutex_init(>out_lock);
+qemu_mutex_init(>qmp.qmp_queue_lock);
 mon->outbuf = qstring_new();
 /* Use *mon_cmds by default. */
 mon->cmd_table = mon_cmds;
 mon->skip_flush = skip_flush;
 mon->use_io_thr = use_io_thr;
+mon->qmp.qmp_requests = g_queue_new();
 }
 
 static void monitor_data_destroy(Monitor *mon)
@@ -613,6 +624,8 @@ static void monitor_data_destroy(Monitor *mon)
 readline_free(mon->rs);
 QDECREF(mon->outbuf);
 qemu_mutex_destroy(>out_lock);
+qemu_mutex_destroy(>qmp.qmp_queue_lock);
+g_queue_free(mon->qmp.qmp_requests);
 }
 
 char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
@@ -1052,6 +1065,16 @@ static void monitor_init_qmp_commands(void)
  qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS);
 }
 
+static bool qmp_cap_enabled(Monitor *mon, QMPCapability cap)
+{
+return mon->qmp.qmp_caps[cap];
+}
+
+static bool qmp_oob_enabled(Monitor *mon)
+{
+return qmp_cap_enabled(mon, QMP_CAPABILITY_OOB);
+}
+
 static void qmp_caps_check(Monitor *mon, QMPCapabilityList *list,
Error **errp)
 {
@@ -3914,30 +3937,39 @@ static void monitor_qmp_respond(Monitor *mon, QObject 
*rsp,
 qobject_decref(rsp);
 }
 
-static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
+struct QMPRequest {
+/* Owner of the request */
+Monitor *mon;
+/* "id" field of the request */
+QObject *id;
+/* Request object to be handled */
+QObject *req;
+/*
+ * Whether we need to resume the monitor afterward.  This flag is
+ * used to emulate the old QMP server behavior that the current
+ * command must be completed before execution of the next one.
+ */
+bool need_resume;
+};
+typedef struct QMPRequest QMPRequest;
+
+/*
+ * Dispatch one single QMP request. The function will free the req_obj
+ * and objects inside it before return.
+ */
+static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
 {
-QObject *req, *rsp = NULL, *id = NULL;
+Monitor *mon, *old_mon;
+QObject *req, *rsp = NULL, *id;
 QDict *qdict = NULL;
-MonitorQMP *mon_qmp = container_of(parser, MonitorQMP, parser);
-Monitor *old_mon, *mon = container_of(mon_qmp, Monitor, qmp);
-
-Error *err = NULL;
+bool need_resume;
 
-req = json_parser_parse_err(tokens, NULL, );
-if (!req && !err) {
-/* json_parser_parse_err() sucks: can fail without setting @err */
-error_setg(, QERR_JSON_PARSING);
-}
-if (err) {
-goto err_out;
-}
+req = req_obj->req;
+mon = req_obj->mon;
+id = req_obj->id;
+need_resume = req_obj->need_resume;
 
-qdict = qobject_to_qdict(req);
-if (qdict) {
-id = qdict_get(qdict, "id");
-qobject_incref(id);
-qdict_del(qdict, "id");
-} /* else will fail qmp_dispatch() */
+g_free(req_obj);
 
 if (trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) {
 QString *req_json = qobject_to_json(req);
@@ -3948,7 +3980,7 @@ static void handle_qmp_command(JSONMessageParser *parser, 
GQueue *tokens)
 old_mon = cur_mon;
 cur_mon = mon;
 
-rsp = qmp_dispatch(cur_mon->qmp.commands, 

[Qemu-devel] [PATCH v7 09/23] monitor: allow using IO thread for parsing

2018-01-23 Thread Peter Xu
For each Monitor, add one field "use_io_thr" to show whether it will be
using the dedicated monitor IO thread to handle input/output.  When set,
monitor IO parsing work will be offloaded to the dedicated monitor IO
thread, rather than the original main loop thread.

This only works for QMP.  HMP will always be run on the main loop
thread.

Currently we're still keeping use_io_thr off always.  Will turn it on
later at some point.

One thing to mention is that we cannot set use_io_thr for every QMP
monitor.  The problem is that MUXed typed chardevs may not work well
with it now. When MUX is used, frontend of chardev can be the monitor
plus something else.  The only thing we know would be safe to be run
outside main thread so far is the monitor frontend. All the rest of the
frontends should still be run in main thread only.

Signed-off-by: Peter Xu 
---
 monitor.c | 107 +-
 1 file changed, 99 insertions(+), 8 deletions(-)

diff --git a/monitor.c b/monitor.c
index cef71d5c45..fd6e9a6d28 100644
--- a/monitor.c
+++ b/monitor.c
@@ -35,6 +35,7 @@
 #include "net/net.h"
 #include "net/slirp.h"
 #include "chardev/char-fe.h"
+#include "chardev/char-io.h"
 #include "ui/qemu-spice.h"
 #include "sysemu/numa.h"
 #include "monitor/monitor.h"
@@ -75,6 +76,7 @@
 #include "qmp-introspect.h"
 #include "sysemu/qtest.h"
 #include "sysemu/cpus.h"
+#include "sysemu/iothread.h"
 #include "qemu/cutils.h"
 #include "qapi/qmp/dispatch.h"
 
@@ -189,6 +191,7 @@ struct Monitor {
 int flags;
 int suspend_cnt;
 bool skip_flush;
+bool use_io_thr;
 
 QemuMutex out_lock;
 QString *outbuf;
@@ -207,6 +210,11 @@ struct Monitor {
 QTAILQ_ENTRY(Monitor) entry;
 };
 
+/* Let's add monitor global variables to this struct. */
+static struct {
+IOThread *mon_iothread;
+} mon_global;
+
 /* QMP checker flags */
 #define QMP_ACCEPT_UNKNOWNS 1
 
@@ -567,7 +575,8 @@ static void monitor_qapi_event_init(void)
 
 static void handle_hmp_command(Monitor *mon, const char *cmdline);
 
-static void monitor_data_init(Monitor *mon, bool skip_flush)
+static void monitor_data_init(Monitor *mon, bool skip_flush,
+  bool use_io_thr)
 {
 memset(mon, 0, sizeof(Monitor));
 qemu_mutex_init(>out_lock);
@@ -575,6 +584,7 @@ static void monitor_data_init(Monitor *mon, bool skip_flush)
 /* Use *mon_cmds by default. */
 mon->cmd_table = mon_cmds;
 mon->skip_flush = skip_flush;
+mon->use_io_thr = use_io_thr;
 }
 
 static void monitor_data_destroy(Monitor *mon)
@@ -595,7 +605,7 @@ char *qmp_human_monitor_command(const char *command_line, 
bool has_cpu_index,
 char *output = NULL;
 Monitor *old_mon, hmp;
 
-monitor_data_init(, true);
+monitor_data_init(, true, false);
 
 old_mon = cur_mon;
 cur_mon = 
@@ -4034,12 +4044,29 @@ static void sortcmdlist(void)
 qsort((void *)info_cmds, array_num, elem_size, compare_mon_cmd);
 }
 
+static GMainContext *monitor_io_context_get(void)
+{
+return iothread_get_g_main_context(mon_global.mon_iothread);
+}
+
+static AioContext *monitor_aio_context_get(void)
+{
+return iothread_get_aio_context(mon_global.mon_iothread);
+}
+
+static void monitor_iothread_init(void)
+{
+mon_global.mon_iothread = iothread_create("mon_iothread",
+  _abort);
+}
+
 void monitor_init_globals(void)
 {
 monitor_init_qmp_commands();
 monitor_qapi_event_init();
 sortcmdlist();
 qemu_mutex_init(_lock);
+monitor_iothread_init();
 }
 
 /* These functions just adapt the readline interface in a typesafe way.  We
@@ -4082,11 +4109,41 @@ void error_vprintf_unless_qmp(const char *fmt, va_list 
ap)
 }
 }
 
+static void monitor_list_append(Monitor *mon)
+{
+qemu_mutex_lock(_lock);
+QTAILQ_INSERT_HEAD(_list, mon, entry);
+qemu_mutex_unlock(_lock);
+}
+
+static void monitor_qmp_setup_handlers(void *data)
+{
+Monitor *mon = data;
+GMainContext *context;
+
+if (mon->use_io_thr) {
+/*
+ * When use_io_thr is set, we use the global shared dedicated
+ * IO thread for this monitor to handle input/output.
+ */
+context = monitor_io_context_get();
+/* We should have inited globals before reaching here. */
+assert(context);
+} else {
+/* The default main loop, which is the main thread */
+context = NULL;
+}
+
+qemu_chr_fe_set_handlers(>chr, monitor_can_read, monitor_qmp_read,
+ monitor_qmp_event, NULL, mon, context, true);
+monitor_list_append(mon);
+}
+
 void monitor_init(Chardev *chr, int flags)
 {
 Monitor *mon = g_malloc(sizeof(*mon));
 
-monitor_data_init(mon, false);
+monitor_data_init(mon, false, false);
 
 qemu_chr_fe_init(>chr, chr, _abort);
 mon->flags = flags;
@@ -4099,24 +4156,55 @@ void monitor_init(Chardev *chr, int flags)
 }
 
 if (monitor_is_qmp(mon)) 

[Qemu-devel] [PATCH v7 12/23] monitor: let suspend_cnt be thread safe

2018-01-23 Thread Peter Xu
Monitor code now can be run in more than one thread.  Let it be thread
safe when accessing suspend_cnt counter.

Reviewed-by: Eric Blake 
Signed-off-by: Peter Xu 
---
 monitor.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/monitor.c b/monitor.c
index 92114aaa80..60bcf67b3a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -190,7 +190,7 @@ struct Monitor {
 CharBackend chr;
 int reset_seen;
 int flags;
-int suspend_cnt;
+int suspend_cnt;/* Needs to be accessed atomically */
 bool skip_flush;
 bool use_io_thr;
 
@@ -3864,7 +3864,7 @@ static int monitor_can_read(void *opaque)
 {
 Monitor *mon = opaque;
 
-return (mon->suspend_cnt == 0) ? 1 : 0;
+return !atomic_mb_read(>suspend_cnt);
 }
 
 /*
@@ -3996,7 +3996,7 @@ int monitor_suspend(Monitor *mon)
 {
 if (!mon->rs)
 return -ENOTTY;
-mon->suspend_cnt++;
+atomic_inc(>suspend_cnt);
 return 0;
 }
 
@@ -4004,8 +4004,9 @@ void monitor_resume(Monitor *mon)
 {
 if (!mon->rs)
 return;
-if (--mon->suspend_cnt == 0)
+if (atomic_dec_fetch(>suspend_cnt) == 0) {
 readline_show_prompt(mon->rs);
+}
 }
 
 static QObject *get_qmp_greeting(Monitor *mon)
@@ -4070,19 +4071,19 @@ static void monitor_event(void *opaque, int event)
 monitor_resume(mon);
 monitor_flush(mon);
 } else {
-mon->suspend_cnt = 0;
+atomic_mb_set(>suspend_cnt, 0);
 }
 break;
 
 case CHR_EVENT_MUX_OUT:
 if (mon->reset_seen) {
-if (mon->suspend_cnt == 0) {
+if (atomic_mb_read(>suspend_cnt) == 0) {
 monitor_printf(mon, "\n");
 }
 monitor_flush(mon);
 monitor_suspend(mon);
 } else {
-mon->suspend_cnt++;
+atomic_inc(>suspend_cnt);
 }
 qemu_mutex_lock(>out_lock);
 mon->mux_out = 1;
-- 
2.14.3




[Qemu-devel] [PATCH v7 21/23] qmp: add command "x-oob-test"

2018-01-23 Thread Peter Xu
This command is only used to test OOB functionality.  It should not be
used for any other purposes.

Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Fam Zheng 
Signed-off-by: Peter Xu 
---
 qapi-schema.json | 18 ++
 qmp.c| 16 
 2 files changed, 34 insertions(+)

diff --git a/qapi-schema.json b/qapi-schema.json
index d6c89efc0d..59ea3e2051 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3252,3 +3252,21 @@
 ##
 { 'event': 'COMMAND_DROPPED' ,
   'data': { 'id': 'any', 'reason': 'CommandDropReason' } }
+
+##
+# @x-oob-test:
+#
+# Test OOB functionality.  When send this command with lock=true,
+# it'll try to hang the dispatcher.  When send it with lock=false,
+# it'll try to notify the locked thread to continue.  Note: it should
+# only be used by QMP test program rather than anything else.
+#
+# Since: 2.12
+#
+# Example:
+#
+# { "execute": "x-oob-test",
+#   "arguments": { "lock": true } }
+##
+{ 'command': 'x-oob-test', 'data' : { 'lock': 'bool' },
+  'allow-oob': true }
diff --git a/qmp.c b/qmp.c
index 52cfd2d81c..c7dcbe72e3 100644
--- a/qmp.c
+++ b/qmp.c
@@ -717,3 +717,19 @@ MemoryInfo *qmp_query_memory_size_summary(Error **errp)
 
 return mem_info;
 }
+
+static QemuSemaphore x_oob_test_sem;
+
+static void __attribute__((constructor)) x_oob_test_init(void)
+{
+qemu_sem_init(_oob_test_sem, 0);
+}
+
+void qmp_x_oob_test(bool lock, Error **errp)
+{
+if (lock) {
+qemu_sem_wait(_oob_test_sem);
+} else {
+qemu_sem_post(_oob_test_sem);
+}
+}
-- 
2.14.3




[Qemu-devel] [PATCH v7 10/23] qmp: introduce QMPCapability

2018-01-23 Thread Peter Xu
There were no QMP capabilities defined.  Define the first "oob" as
capability to allow out-of-band messages.

After this patch, we will allow QMP clients to enable QMP capabilities
when sending the first "qmp_capabilities" command.  Originally we are
starting QMP session with no arguments like:

  { "execute": "qmp_capabilities" }

Now we can enable some QMP capabilities using (take OOB as example,
which is the only one capability that we support):

  { "execute": "qmp_capabilities",
"argument": { "enable": [ "oob" ] } }

When the "argument" key is not provided, no capability is enabled.

For capability "oob", the monitor needs to be run on dedicated IO
thread, otherwise the command will fail.  For example, trying to enable
OOB on a MUXed typed QMP monitor will fail.

One thing to mention is that, QMP capabilities are per-monitor, and also
when the connection is closed due to some reason, the capabilities will
be reset.

Also, touch up qmp-test.c to test the new bits.

Signed-off-by: Peter Xu 
---
 monitor.c| 76 
 qapi-schema.json | 32 +---
 tests/qmp-test.c | 10 +++-
 3 files changed, 109 insertions(+), 9 deletions(-)

diff --git a/monitor.c b/monitor.c
index fd6e9a6d28..3e07798442 100644
--- a/monitor.c
+++ b/monitor.c
@@ -167,6 +167,7 @@ typedef struct {
  * mode.
  */
 QmpCommandList *commands;
+bool qmp_caps[QMP_CAPABILITY__MAX];
 } MonitorQMP;
 
 /*
@@ -1036,8 +1037,42 @@ static void monitor_init_qmp_commands(void)
  qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS);
 }
 
-void qmp_qmp_capabilities(Error **errp)
+static void qmp_caps_check(Monitor *mon, QMPCapabilityList *list,
+   Error **errp)
+{
+for (; list; list = list->next) {
+assert(list->value < QMP_CAPABILITY__MAX);
+switch (list->value) {
+case QMP_CAPABILITY_OOB:
+if (!mon->use_io_thr) {
+/*
+ * Out-Of-Band only works with monitors that are
+ * running on dedicated IOThread.
+ */
+error_setg(errp, "This monitor does not support "
+   "Out-Of-Band (OOB)");
+return;
+}
+break;
+default:
+break;
+}
+}
+}
+
+/* This function should only be called after capabilities are checked. */
+static void qmp_caps_apply(Monitor *mon, QMPCapabilityList *list)
 {
+for (; list; list = list->next) {
+mon->qmp.qmp_caps[list->value] = true;
+}
+}
+
+void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable,
+  Error **errp)
+{
+Error *local_err = NULL;
+
 if (cur_mon->qmp.commands == _commands) {
 error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
   "Capabilities negotiation is already complete, command "
@@ -1045,6 +1080,21 @@ void qmp_qmp_capabilities(Error **errp)
 return;
 }
 
+/* Enable QMP capabilities provided by the client if applicable. */
+if (has_enable) {
+qmp_caps_check(cur_mon, enable, _err);
+if (local_err) {
+/*
+ * Failed check on any of the capabilities will fail the
+ * entire command (and thus not apply any of the other
+ * capabilities that were also requested).
+ */
+error_propagate(errp, local_err);
+return;
+}
+qmp_caps_apply(cur_mon, enable);
+}
+
 cur_mon->qmp.commands = _commands;
 }
 
@@ -3942,14 +3992,29 @@ void monitor_resume(Monitor *mon)
 readline_show_prompt(mon->rs);
 }
 
-static QObject *get_qmp_greeting(void)
+static QObject *get_qmp_greeting(Monitor *mon)
 {
+QList *cap_list = qlist_new();
 QObject *ver = NULL;
+QMPCapability cap;
 
 qmp_marshal_query_version(NULL, , NULL);
 
-return qobject_from_jsonf("{'QMP': {'version': %p, 'capabilities': []}}",
-  ver);
+for (cap = 0; cap < QMP_CAPABILITY__MAX; cap++) {
+if (!mon->use_io_thr && cap == QMP_CAPABILITY_OOB) {
+/* Monitors that are not using IOThread won't support OOB */
+continue;
+}
+qlist_append(cap_list, qstring_from_str(QMPCapability_str(cap)));
+}
+
+return qobject_from_jsonf("{'QMP': {'version': %p, 'capabilities': %p}}",
+  ver, cap_list);
+}
+
+static void monitor_qmp_caps_reset(Monitor *mon)
+{
+memset(mon->qmp.qmp_caps, 0, sizeof(mon->qmp.qmp_caps));
 }
 
 static void monitor_qmp_event(void *opaque, int event)
@@ -3960,7 +4025,8 @@ static void monitor_qmp_event(void *opaque, int event)
 switch (event) {
 case CHR_EVENT_OPENED:
 mon->qmp.commands = _cap_negotiation_commands;
-data = get_qmp_greeting();
+monitor_qmp_caps_reset(mon);
+data = get_qmp_greeting(mon);
 

[Qemu-devel] [PATCH v7 07/23] monitor: unify global init

2018-01-23 Thread Peter Xu
There are many places where the monitor initializes its globals:

- monitor_init_qmp_commands() at the very beginning
- single function to init monitor_lock
- in the first entry of monitor_init() using "is_first_init"

Unify them a bit.

monitor_lock is not used before monitor_init() (as confirmed by code
analysis and gdb watchpoints); so we are safe delaying what was a
constructor-time initialization of the mutex into the later first call
to monitor_init().

Reviewed-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Eric Blake 
Signed-off-by: Peter Xu 
---
 include/monitor/monitor.h |  2 +-
 monitor.c | 25 ++---
 vl.c  |  7 ++-
 3 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 83ea4a1aaf..3a5128ab1b 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -16,7 +16,7 @@ extern Monitor *cur_mon;
 
 bool monitor_cur_is_qmp(void);
 
-void monitor_init_qmp_commands(void);
+void monitor_init_globals(void);
 void monitor_init(Chardev *chr, int flags);
 void monitor_cleanup(void);
 
diff --git a/monitor.c b/monitor.c
index 253be6871a..f32187b991 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1000,7 +1000,7 @@ static void qmp_unregister_commands_hack(void)
 #endif
 }
 
-void monitor_init_qmp_commands(void)
+static void monitor_init_qmp_commands(void)
 {
 /*
  * Two command lists:
@@ -4034,6 +4034,14 @@ static void sortcmdlist(void)
 qsort((void *)info_cmds, array_num, elem_size, compare_mon_cmd);
 }
 
+void monitor_init_globals(void)
+{
+monitor_init_qmp_commands();
+monitor_qapi_event_init();
+sortcmdlist();
+qemu_mutex_init(_lock);
+}
+
 /* These functions just adapt the readline interface in a typesafe way.  We
  * could cast function pointers but that discards compiler checks.
  */
@@ -4074,23 +4082,10 @@ void error_vprintf_unless_qmp(const char *fmt, va_list 
ap)
 }
 }
 
-static void __attribute__((constructor)) monitor_lock_init(void)
-{
-qemu_mutex_init(_lock);
-}
-
 void monitor_init(Chardev *chr, int flags)
 {
-static int is_first_init = 1;
-Monitor *mon;
-
-if (is_first_init) {
-monitor_qapi_event_init();
-sortcmdlist();
-is_first_init = 0;
-}
+Monitor *mon = g_malloc(sizeof(*mon));
 
-mon = g_malloc(sizeof(*mon));
 monitor_data_init(mon, false);
 
 qemu_chr_fe_init(>chr, chr, _abort);
diff --git a/vl.c b/vl.c
index e725ecbc08..095769e6c9 100644
--- a/vl.c
+++ b/vl.c
@@ -3098,7 +3098,6 @@ int main(int argc, char **argv, char **envp)
 qemu_init_exec_dir(argv[0]);
 
 module_call_init(MODULE_INIT_QOM);
-monitor_init_qmp_commands();
 
 qemu_add_opts(_drive_opts);
 qemu_add_drive_opts(_legacy_drive_opts);
@@ -4562,6 +4561,12 @@ int main(int argc, char **argv, char **envp)
 default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS);
 default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS);
 
+/*
+ * Note: qtest_enabled() (which is used in monitor_qapi_event_init())
+ * depends on configure_accelerator() above.
+ */
+monitor_init_globals();
+
 if (qemu_opts_foreach(qemu_find_opts("mon"),
   mon_init_func, NULL, NULL)) {
 exit(1);
-- 
2.14.3




[Qemu-devel] [PATCH v7 08/23] monitor: let mon_list be tail queue

2018-01-23 Thread Peter Xu
It was QLIST.  I want to use this list to do monitor priority job later,
which need tail insertion ability.  So switching to a tail queue.

Reviewed-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Peter Xu 
---
 monitor.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/monitor.c b/monitor.c
index f32187b991..cef71d5c45 100644
--- a/monitor.c
+++ b/monitor.c
@@ -204,7 +204,7 @@ struct Monitor {
 void *password_opaque;
 mon_cmd_t *cmd_table;
 QLIST_HEAD(,mon_fd_t) fds;
-QLIST_ENTRY(Monitor) entry;
+QTAILQ_ENTRY(Monitor) entry;
 };
 
 /* QMP checker flags */
@@ -213,7 +213,7 @@ struct Monitor {
 /* Protects mon_list, monitor_event_state.  */
 static QemuMutex monitor_lock;
 
-static QLIST_HEAD(mon_list, Monitor) mon_list;
+static QTAILQ_HEAD(mon_list, Monitor) mon_list;
 static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
 static int mon_refcount;
 
@@ -414,7 +414,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict 
*qdict)
 Monitor *mon;
 
 trace_monitor_protocol_event_emit(event, qdict);
-QLIST_FOREACH(mon, _list, entry) {
+QTAILQ_FOREACH(mon, _list, entry) {
 if (monitor_is_qmp(mon)
 && mon->qmp.commands != _cap_negotiation_commands) {
 monitor_json_emitter(mon, QOBJECT(qdict));
@@ -4109,7 +4109,7 @@ void monitor_init(Chardev *chr, int flags)
 }
 
 qemu_mutex_lock(_lock);
-QLIST_INSERT_HEAD(_list, mon, entry);
+QTAILQ_INSERT_HEAD(_list, mon, entry);
 qemu_mutex_unlock(_lock);
 }
 
@@ -4118,8 +4118,8 @@ void monitor_cleanup(void)
 Monitor *mon, *next;
 
 qemu_mutex_lock(_lock);
-QLIST_FOREACH_SAFE(mon, _list, entry, next) {
-QLIST_REMOVE(mon, entry);
+QTAILQ_FOREACH_SAFE(mon, _list, entry, next) {
+QTAILQ_REMOVE(_list, mon, entry);
 monitor_data_destroy(mon);
 g_free(mon);
 }
-- 
2.14.3




[Qemu-devel] [PATCH v7 06/23] monitor: move the cur_mon hack deeper for QMP

2018-01-23 Thread Peter Xu
In monitor_qmp_read(), we have the hack to temporarily replace the
cur_mon pointer.  Now we move this hack deeper inside the QMP dispatcher
routine since the Monitor pointer can be actually obtained using
container_of() upon the parser object, just like most of the other JSON
parser users do.

This does not make much sense as a single patch.  However, this will be
a big step for the next patch, when the QMP dispatcher routine will be
split from the QMP parser.

Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Eric Blake 
Signed-off-by: Peter Xu 
---
 monitor.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/monitor.c b/monitor.c
index 3a28a6d935..253be6871a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -3811,7 +3811,9 @@ static void handle_qmp_command(JSONMessageParser *parser, 
GQueue *tokens)
 {
 QObject *req, *rsp = NULL, *id = NULL;
 QDict *qdict = NULL;
-Monitor *mon = cur_mon;
+MonitorQMP *mon_qmp = container_of(parser, MonitorQMP, parser);
+Monitor *old_mon, *mon = container_of(mon_qmp, Monitor, qmp);
+
 Error *err = NULL;
 
 req = json_parser_parse_err(tokens, NULL, );
@@ -3836,8 +3838,13 @@ static void handle_qmp_command(JSONMessageParser 
*parser, GQueue *tokens)
 QDECREF(req_json);
 }
 
+old_mon = cur_mon;
+cur_mon = mon;
+
 rsp = qmp_dispatch(cur_mon->qmp.commands, req);
 
+cur_mon = old_mon;
+
 if (mon->qmp.commands == _cap_negotiation_commands) {
 qdict = qdict_get_qdict(qobject_to_qdict(rsp), "error");
 if (qdict
@@ -3874,13 +3881,9 @@ err_out:
 
 static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)
 {
-Monitor *old_mon = cur_mon;
-
-cur_mon = opaque;
-
-json_message_parser_feed(_mon->qmp.parser, (const char *) buf, size);
+Monitor *mon = opaque;
 
-cur_mon = old_mon;
+json_message_parser_feed(>qmp.parser, (const char *) buf, size);
 }
 
 static void monitor_read(void *opaque, const uint8_t *buf, int size)
-- 
2.14.3




[Qemu-devel] [PATCH v7 03/23] qobject: introduce qobject_get_try_str()

2018-01-23 Thread Peter Xu
A quick way to fetch string from qobject when it's a QString.

Reviewed-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Peter Xu 
---
 include/qapi/qmp/qstring.h |  1 +
 qobject/qstring.c  | 11 +++
 2 files changed, 12 insertions(+)

diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h
index a145c8ca00..6517d8e377 100644
--- a/include/qapi/qmp/qstring.h
+++ b/include/qapi/qmp/qstring.h
@@ -28,6 +28,7 @@ QString *qstring_from_substr(const char *str, int start, int 
end);
 size_t qstring_get_length(const QString *qstring);
 const char *qstring_get_str(const QString *qstring);
 const char *qstring_get_try_str(const QString *qstring);
+const char *qobject_get_try_str(const QObject *qstring);
 void qstring_append_int(QString *qstring, int64_t value);
 void qstring_append(QString *qstring, const char *str);
 void qstring_append_chr(QString *qstring, int c);
diff --git a/qobject/qstring.c b/qobject/qstring.c
index 7638ab990d..e556b1afdf 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -138,6 +138,17 @@ const char *qstring_get_try_str(const QString *qstring)
 return qstring ? qstring_get_str(qstring) : NULL;
 }
 
+/**
+ * qobject_get_try_str(): Return a pointer to the corresponding string
+ *
+ * NOTE: the string will only be returned if the object is valid, and
+ * its type is QString, otherwise NULL is returned.
+ */
+const char *qobject_get_try_str(const QObject *qstring)
+{
+return qstring_get_try_str(qobject_to_qstring(qstring));
+}
+
 /**
  * qstring_is_equal(): Test whether the two QStrings are equal
  */
-- 
2.14.3




[Qemu-devel] [PATCH v7 01/23] docs: update QMP documents for OOB commands

2018-01-23 Thread Peter Xu
Update both the developer and spec for the new QMP OOB (Out-Of-Band)
command.

Signed-off-by: Peter Xu 
---
 docs/devel/qapi-code-gen.txt | 68 
 docs/interop/qmp-spec.txt| 30 ---
 2 files changed, 89 insertions(+), 9 deletions(-)

diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 06ab699066..4d3db0ad39 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -554,9 +554,12 @@ following example objects:
 
 === Commands ===
 
+--- General Command Layout ---
+
 Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
  '*returns': TYPE-NAME, '*boxed': true,
- '*gen': false, '*success-response': false }
+ '*gen': false, '*success-response': false,
+ '*allow-oob': false }
 
 Commands are defined by using a dictionary containing several members,
 where three members are most common.  The 'command' member is a
@@ -636,6 +639,59 @@ possible, the command expression should include the 
optional key
 'success-response' with boolean value false.  So far, only QGA makes
 use of this member.
 
+A command can be declared to support Out-Of-Band (OOB) execution.  By
+default, commands do not support OOB.  To declare a command to support
+it, we need an extra 'allow-oob' field.  For example:
+
+ { 'command': 'migrate_recover',
+   'data': { 'uri': 'str' }, 'allow-oob': true }
+
+To execute a command in Out-Of-Band way, we need to specify the
+"control" field in the request, with "run-oob" set to true. Example:
+
+ => { "execute": "command-support-oob",
+  "arguments": { ... },
+  "control": { "run-oob": true } }
+ <= { "return": { } }
+
+Without it, even the commands that support out-of-band execution will
+still be run In-Band.
+
+Please read the "Out-Of-Band Command Execution" section below for more
+information on how OOB execution works.
+
+--- About Out-Of-Band (OOB) Command Execution ---
+
+Out-Of-Band does not mean a special kind of command. Instead, it's a
+special way to execute the command.  One normal command can be
+declared to support Out-Of-Band execution when 'allow-oob' field is
+set to true when defining the command.  With that, it can be run in an
+Out-Of-Band way if 'run-oob' is specified in 'control' field of
+command request.
+
+When we say normal QMP command executions, it means basically the
+following:
+
+- They are executed in order,
+- They run only in main thread of QEMU,
+- They have the BQL taken during execution.
+
+For OOB command executions, they differ in the following:
+
+- They can be executed before an existing command,
+- They run in a monitor dedicated thread,
+- They do not take the BQL during execution.
+
+OOB command handlers must satisfy the following conditions:
+
+- It executes extremely fast,
+- It does not take any lock, or, it can take very small locks if all
+  critical regions also follow the rules for OOB command handler code,
+- It does not invoke system calls that may block,
+- It does not access guest RAM that may block when userfaultfd is
+  enabled for postcopy live migration.
+
+If in doubt, do not implement OOB execution support.
 
 === Events ===
 
@@ -739,10 +795,12 @@ references by name.
 QAPI schema definitions not reachable that way are omitted.
 
 The SchemaInfo for a command has meta-type "command", and variant
-members "arg-type" and "ret-type".  On the wire, the "arguments"
-member of a client's "execute" command must conform to the object type
-named by "arg-type".  The "return" member that the server passes in a
-success response conforms to the type named by "ret-type".
+members "arg-type", "ret-type" and "allow-oob".  On the wire, the
+"arguments" member of a client's "execute" command must conform to the
+object type named by "arg-type".  The "return" member that the server
+passes in a success response conforms to the type named by
+"ret-type".  When "allow-oob" is set, it means the command supports
+out-of-band execution.
 
 If the command takes no arguments, "arg-type" names an object type
 without members.  Likewise, if the command returns nothing, "ret-type"
diff --git a/docs/interop/qmp-spec.txt b/docs/interop/qmp-spec.txt
index f8b5356015..e20163c138 100644
--- a/docs/interop/qmp-spec.txt
+++ b/docs/interop/qmp-spec.txt
@@ -83,16 +83,27 @@ The greeting message format is:
 2.2.1 Capabilities
 --
 
-As of the date this document was last revised, no server or client
-capability strings have been defined.
+Currently supported capabilities are:
 
+- "oob": it means the QMP server supports "Out-Of-Band" command
+  execution.  For more detail, please see "run-oob" parameter in
+  "Issuing Commands" section below.  Not all commands allow this "oob"
+  execution.  One can know whether one command supports "oob" by
+  "query-qmp-schema" command.
+
+QMP clients can get a list of supported QMP capabilities of the QMP
+server in the greeting message mentioned 

[Qemu-devel] [PATCH v7 05/23] monitor: move skip_flush into monitor_data_init

2018-01-23 Thread Peter Xu
It's part of the data init.  Collect it.

Reviewed-by: Dr. David Alan Gilbert 
Reviewed-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Peter Xu 
---
 monitor.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/monitor.c b/monitor.c
index b9da5e20d1..3a28a6d935 100644
--- a/monitor.c
+++ b/monitor.c
@@ -567,13 +567,14 @@ static void monitor_qapi_event_init(void)
 
 static void handle_hmp_command(Monitor *mon, const char *cmdline);
 
-static void monitor_data_init(Monitor *mon)
+static void monitor_data_init(Monitor *mon, bool skip_flush)
 {
 memset(mon, 0, sizeof(Monitor));
 qemu_mutex_init(>out_lock);
 mon->outbuf = qstring_new();
 /* Use *mon_cmds by default. */
 mon->cmd_table = mon_cmds;
+mon->skip_flush = skip_flush;
 }
 
 static void monitor_data_destroy(Monitor *mon)
@@ -594,8 +595,7 @@ char *qmp_human_monitor_command(const char *command_line, 
bool has_cpu_index,
 char *output = NULL;
 Monitor *old_mon, hmp;
 
-monitor_data_init();
-hmp.skip_flush = true;
+monitor_data_init(, true);
 
 old_mon = cur_mon;
 cur_mon = 
@@ -4088,7 +4088,7 @@ void monitor_init(Chardev *chr, int flags)
 }
 
 mon = g_malloc(sizeof(*mon));
-monitor_data_init(mon);
+monitor_data_init(mon, false);
 
 qemu_chr_fe_init(>chr, chr, _abort);
 mon->flags = flags;
-- 
2.14.3




[Qemu-devel] [PATCH v7 04/23] qobject: let object_property_get_str() use new API

2018-01-23 Thread Peter Xu
We can simplify object_property_get_str() using the new
qobject_get_try_str().

Reviewed-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Eric Blake 
Signed-off-by: Peter Xu 
---
 qom/object.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/qom/object.c b/qom/object.c
index c58c52d518..9cbeb51f0b 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1116,18 +1116,15 @@ char *object_property_get_str(Object *obj, const char 
*name,
   Error **errp)
 {
 QObject *ret = object_property_get_qobject(obj, name, errp);
-QString *qstring;
 char *retval;
 
 if (!ret) {
 return NULL;
 }
-qstring = qobject_to_qstring(ret);
-if (!qstring) {
+
+retval = g_strdup(qobject_get_try_str(ret));
+if (!retval) {
 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
-retval = NULL;
-} else {
-retval = g_strdup(qstring_get_str(qstring));
 }
 
 qobject_decref(ret);
-- 
2.14.3




[Qemu-devel] [PATCH v7 02/23] qobject: introduce qstring_get_try_str()

2018-01-23 Thread Peter Xu
The only difference from qstring_get_str() is that it allows the qstring
to be NULL.  If so, NULL is returned.

CC: Eric Blake 
CC: Markus Armbruster 
Reviewed-by: Fam Zheng 
Reviewed-by: Stefan Hajnoczi 
Reviewed-by: Eric Blake 
Signed-off-by: Peter Xu 
---
 include/qapi/qmp/qstring.h |  1 +
 qobject/qstring.c  | 10 ++
 2 files changed, 11 insertions(+)

diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h
index 65c05a9be5..a145c8ca00 100644
--- a/include/qapi/qmp/qstring.h
+++ b/include/qapi/qmp/qstring.h
@@ -27,6 +27,7 @@ QString *qstring_from_str(const char *str);
 QString *qstring_from_substr(const char *str, int start, int end);
 size_t qstring_get_length(const QString *qstring);
 const char *qstring_get_str(const QString *qstring);
+const char *qstring_get_try_str(const QString *qstring);
 void qstring_append_int(QString *qstring, int64_t value);
 void qstring_append(QString *qstring, const char *str);
 void qstring_append_chr(QString *qstring, int c);
diff --git a/qobject/qstring.c b/qobject/qstring.c
index 74182a1c02..7638ab990d 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -128,6 +128,16 @@ const char *qstring_get_str(const QString *qstring)
 return qstring->string;
 }
 
+/**
+ * qstring_get_try_str(): Return a pointer to the stored string
+ *
+ * NOTE: will return NULL if qstring is not provided.
+ */
+const char *qstring_get_try_str(const QString *qstring)
+{
+return qstring ? qstring_get_str(qstring) : NULL;
+}
+
 /**
  * qstring_is_equal(): Test whether the two QStrings are equal
  */
-- 
2.14.3




[Qemu-devel] [PATCH v7 00/23] QMP: out-of-band (OOB) execution support

2018-01-23 Thread Peter Xu
This version should have addressed all comments in previous one, also
fixed another race condition after I addressed all the comments (a new
race condition introduced by addressing the comments...).  For some
more details of the race condition, please see the last entry of
change log, and please refer to patch 9 for the code change.

I removed RFC tag from this version.  Please review.  Thanks.

v7:
- add some r-bs, and remove some.
- remove the chardev fix since already queued by Paolo
- use local var in qemu_chr_fe_add_watch [Stefan]
- move doc patch to front, mention it in some patches [Eric]
- Quite a few of English fixes [Eric]
- fix unlock missing in handle_qmp_command [Stefan]
- squash some patches according to the review comments
- don't break gdbserver usage on HMP non-interactive mode by fixing up
  the suspend/resume logic [Fam, Stefan]
- move the qemu_chr_fe_set_handlers() call in monitor_init() into a
  bottom half to avoid race between the call itself and
  iothread. [Stefan]
- spent quite a lot of time debugging another assertion failure in
  io_watch_poll_finalize() after above change is made (ouch! I really
  hoped we always have the latest glib): when QEMU inits chardevs in
  chardev_init_func() it's possible that QEMU registers the chardev
  handlers there, even before CharBackend is connected to that chardev
  in monitor_init().  Then, when we reach monitor_init() we must make
  sure we unregister that old one first, or there can have one orphan
  GSource still in default gcontext (note that this can really happen
  when we start to use QEMUBH to setup chardev frontends, which is
  above change).

v6:
- add r-bs
- s/negociate/negotiate/ [Dave]
- let mon_global be anonymous struct [Stefan]
- in monitor_init(): call qemu_chr_fe_set_handlers() later than init
  parser, then it's safe [Stefan]
- drop patch "qjson: add "opaque" field to JSONMessageParser",
  re-write the following one to use container_of(). [Stefan]
- keep get_qmp_greeting() the old way, add cap list [Stefan, Fam]
- fix the iothread_stop() comment since that's not really related to
  the glib bug [Stefan]
- when do qmp greeting, don't expose oob capability if iothread not
  used [Stefan, Fam]
- squash "qmp: introduce some capability helpers" into patch "monitor:
  separate QMP parser and dispatcher" [Fam]
- tune comments for monitor_qmp_respond(). [Stefan]
- use atomic_mb_{read|set}() where proper instead of no-mb ones
  [Stefan]
- add patch to let monitor suspend/resume really support QMP.  Notify
  iothread when needed, in both suspend/resume. [Stefan]
- add comment for qmp_queue_lock on lock taking ordering. [Stefan]
- refactor monitor_qmp_bh_dispatcher() to not loop, instead queue
  itself after each request. [Stefan]
- rename "request" into "command" in the new qmp event [Stefan]
- in handle_qmp_command() protect the queue length fetch with
  qmp_queue_lock [Stefan]
- one more s/2.11/2.12/.  [Fam]
- when isolating response queue, not only flush the queue, but also
  flush the monitor out buffer [Stefan]
- document rewrite [Stefan]
- some other touch-ups that I forgot to mention and some tiny new
  patches... anyway, rbs will be gone if any of the patch is touched
  up.  Please have a look!

v5
- rename "monitor_iothread" to "mon_iothread" [Dave]
- add comment in monitor_cleanup(), note that when the hacks can be
  removed. [Dan]
- add a note section in qmp-spec.txt, mentioning about how to migrate
  existing QMP command to oob-capable command. [Dave]
- drop patch "qmp: let migrate-incoming allow out-of-band".  All
  migration related changes will all be put into postcopy-recovery
  series.

v4:
- drop first patch to fix IOWatchPool [Stefan, Dan]
- add s-o-b where missing, and newly got r-bs
- fix English error in commit msg [Fam]
- some tunes on request-dropped event:  [Stefan]
  - firstly let 'id' be any type, meanwhile make sure "id" is there as
long as OOB is enabled for the monitor.
  - some comments fix
- add new command "x-oob-test" for testing oob commands [Stefan]
- simplify the test codes to use new x-oob-test
- flush response queue before cleanup monitors

This series was born from this one:

  https://lists.gnu.org/archive/html/qemu-devel/2017-08/msg04310.html

The idea comes from Markus Armbruster and the discussion we had in the
thread.  It's not a super ideal solution (I believe Markus had been
thinking hard to keep everything in order meanwhile trying to satisfy
the migration requirement), but AFAIU it's currently the best.

What is OOB?


It's the shortcut of Out-Of-Band execution, its name is given by
Markus.  It's a way to quickly execute a QMP request.  Say, originally
QMP is going throw these steps:

  JSON Parser --> QMP Dispatcher --> Respond
  /|\(2)(3) |
   (1) |   \|/ (4)
   +-  main thread  +

The requests are executed by the so-called QMP-dispatcher after the
JSON is parsed.  If OOB is 

[Qemu-devel] [PATCH] iotests: Fix CID for VMDK afl image

2018-01-23 Thread Fam Zheng
The descriptor block in the image, which includes the CID to verify, has been
invalid since the reference image was added. Since commit 9877860e7bd we report
this error earlier than the "file too large", so 059.out mismatches.

Instead of fixing the output, we fix the image descriptor, because the code
path we want to exercise is actually the invalid image size.

The binary change is generated along the operations of:

  $ bunzip2 afl9.vmdk.bz2
  $ qemu-img create -f qcow2 fix.vmdk 1G
  $ dd if=afl9.vmdk.bz2 of=fix.vmdk bs=512 count=1 conv=notrunc
  $ mv fix.vmdk afl9.vmdk
  $ bzip2 afl9.vmdk

Signed-off-by: Fam Zheng 
---
 tests/qemu-iotests/sample_images/afl9.vmdk.bz2 | Bin 178 -> 618 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)

diff --git a/tests/qemu-iotests/sample_images/afl9.vmdk.bz2 
b/tests/qemu-iotests/sample_images/afl9.vmdk.bz2
index 
03615d36a12425cf4240bab86f4cfe648db14572..9fcd0af45a815431acf4689e0845ecf2d333cd58
 100644
GIT binary patch
literal 618
zcmV-w0+szjT4*^jL0KkKSvgW7ssIN3|NsBH-Q9UpfAhclU70`s-*NE~5QvC~h=_=Y
zh>D2n*q*=vygR634445h35k;?00h9835kMW4$iPepVE{Bqk)uhJ^wfGLr=)3s
zhM5CR88jLh7)B;cA*K)*6GmuECPU3o4NWG5O#pg>Ak#xY8Z^CrMt}oD38Ns$
z02n}M0LdjZ&}cLPqd+nPKmn$j0iXe(02%-d27nnJriN-uE+X@Bj4BBfd|yV!NB
zwqkL}nW3AI5x^jp=t%^F1pxqp)v#n#)j$zcm1xqv(!$2d*5%vF{5RPWnOV8-^tE<(
zU~%&}Y0uNu*9Wt=yS^8PkC%IG;aD{l#sG`m4Ho*fsHXdM

Re: [Qemu-devel] [Qemu-block] [PATCH] block/vmdk: Report failures in vmdk_read_cid()

2018-01-23 Thread Fam Zheng
On Fri, Jan 19, 2018 at 7:35 PM, Paolo Bonzini  wrote:
> On 28/07/2017 14:54, Kevin Wolf wrote:
>> Am 09.07.2017 um 19:06 hat Peter Maydell geschrieben:
>>> The function vmdk_read_cid() can fail if the read on the underlying
>>> block device fails, or if there's a format error in the VMDK file.
>>> However its API doesn't provide a mechanism to report these errors,
>>> and in some cases we were returning a CID of 0 and in some cases a
>>> CID of 0x, either of which might potentially be valid values.
>>>
>>> Change the function to return 0 on success or a negative errno, and
>>> return the CID via a uint32_t* argument. Update the callsites to
>>> handle and propagate the error appropriately.
>>>
>>> This fixes in passing a Coverity-spotted issue (CID 1350038) where
>>> we weren't checking the return value from sscanf().
>>>
>>> Signed-off-by: Peter Maydell 
>>
>> Fam, this is the commit that introduced the qemu-iotests 059 failure for
>> vmdk. I think what's happening is that we use an image produced by a
>> fuzzer, and with the additional checks introduced in this patch, we now
>> fail earlier and don't test the condition any more that we wanted to
>> test.
>>
>> So do we need a new version of sample_images/afl9.vmdk.bz2 that has a
>> valid CID?

I'll send a patch to fix the CID today.

Fam

>
> This has never been fixed, has it?  I still see the failure.
>
> Paolo



Re: [Qemu-devel] [PATCH v5 0/4] cryptodev: add vhost support

2018-01-23 Thread Fam Zheng
On Fri, Jan 19, 2018 at 4:13 PM, Zhoujian (jay)  wrote:
> [...]
>
>> Configure options:
>> --enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --
>> prefix=/tmp/qemu-test/install
> [...]
>
>> KVM support   yes
>> HAX support   no
>> HVF support   no
>> TCG support   yes
>> TCG debug enabled no
>> TCG interpreter   no
>> malloc trim support yes
>> RDMA support  yes
>> fdt support   yes
>> preadv supportyes
>> fdatasync yes
>> madvise   yes
>> posix_madvise yes
>> libcap-ng support no
>> vhost-net support yes
>> vhost-crypto support yes
>> vhost-scsi support yes
>> vhost-vsock support yes
>> vhost-user support yes
> [...]
>
>> make[1]: *** No rule to make target `../backends/cryptodev-vhost-user.o',
>> needed by `qemu-system-x86_64'.  Stop.
>> make[1]: *** Waiting for unfinished jobs
>
> But it's successfully compiled using centos7 and mingw32 locally, and I 
> couldn't
> reproduce this. Is it related to docker? (I don't have docker environment in 
> hand)
>

I don't know, maybe it's related to the -j8 parallelism? If you simply do:

$ sudo yum install docker
$ sudo systemctl start docker

You'll have a docker environment ready. (you should be root or make
sure passwordless sudo works in order to run docker commands). Then:

$ make docker-test-build@min-glib V=1 J=8

If it fails, add DEBUG=1 to the command line and start again. If will
prompt you in a shell before building QEMU. Press ctrl-d to start
building. When error happens, you'll be in the shell again to do usual
things (debug, edit-build-run...).

(We should add a docs/devel/docker-testing.txt describing the steps).

Fam



Re: [Qemu-devel] [PATCH v2 0/4] coroutine-lock: polymorphic CoQueue

2018-01-23 Thread Fam Zheng
On Tue, Jan 16, 2018 at 10:23 PM, Paolo Bonzini  wrote:
> There are cases in which a queued coroutine must be restarted from
> non-coroutine context (with qemu_co_enter_next).  In this cases,
> qemu_co_enter_next also needs to be thread-safe, but it cannot use a
> CoMutex and so cannot qemu_co_queue_wait.  This happens in curl (which
> right now is rolling its own list of Coroutines) and will happen in
> Fam's NVMe driver as well.
>
> This series extracts the idea of a polymorphic lockable object
> from my "scoped lock guard" proposal, and applies it to CoQueue.
> The implementation of QemuLockable is similar to C11 _Generic, but
> redone using the preprocessor and GCC builtins for compatibility.
>
> In general, while a bit on the esoteric side, the functionality used
> to emulate _Generic is fairly old in GCC, and the builtins are already
> used by include/qemu/atomic.h; the series was tested with Fedora 27 (boot
> Damn Small Linux via http) and CentOS 6 (compiled only).
>
> Paolo
>
> v1->v2: fix typos and copyright year

Reviewed-by: Fam Zheng 

Should I include this series in my pull request for the NVMe driver?



Re: [Qemu-devel] [PATCH v10 2/4] fw_cfg: do DMA read operation

2018-01-23 Thread Peter Xu
On Tue, Jan 23, 2018 at 05:40:39PM +0100, Marc-André Lureau wrote:
> Modify fw_cfg_read_blob() to use DMA if the device supports it.
> Return errors, because the operation may fail.
> 
> The DMA operation is expected to run synchronously with today qemu,
> but the specification states that it may become async, so we run
> "control" field check in a loop for eventual changes.
> 
> We may want to switch all the *buf addresses to use only kmalloc'ed
> buffers (instead of using stack/image addresses with dma=false).
> 
> Signed-off-by: Marc-André Lureau 
> ---
>  drivers/firmware/qemu_fw_cfg.c | 131 
> ++---
>  1 file changed, 111 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
> index 740df0df2260..686f0e839858 100644
> --- a/drivers/firmware/qemu_fw_cfg.c
> +++ b/drivers/firmware/qemu_fw_cfg.c
> @@ -33,6 +33,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  MODULE_AUTHOR("Gabriel L. Somlo ");
>  MODULE_DESCRIPTION("QEMU fw_cfg sysfs support");
> @@ -43,12 +44,22 @@ MODULE_LICENSE("GPL");
>  #define FW_CFG_ID 0x01
>  #define FW_CFG_FILE_DIR   0x19
>  
> +#define FW_CFG_VERSION_DMA 0x02
> +#define FW_CFG_DMA_CTL_ERROR   0x01
> +#define FW_CFG_DMA_CTL_READ0x02
> +#define FW_CFG_DMA_CTL_SKIP0x04
> +#define FW_CFG_DMA_CTL_SELECT  0x08
> +#define FW_CFG_DMA_CTL_WRITE   0x10
> +
>  /* size in bytes of fw_cfg signature */
>  #define FW_CFG_SIG_SIZE 4
>  
>  /* fw_cfg "file name" is up to 56 characters (including terminating nul) */
>  #define FW_CFG_MAX_FILE_PATH 56
>  
> +/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */
> +static u32 fw_cfg_rev;
> +
>  /* fw_cfg file directory entry type */
>  struct fw_cfg_file {
>   u32 size;
> @@ -57,6 +68,12 @@ struct fw_cfg_file {
>   char name[FW_CFG_MAX_FILE_PATH];
>  };
>  
> +struct fw_cfg_dma {
> + u32 control;
> + u32 length;
> + u64 address;
> +} __packed;
> +
>  /* fw_cfg device i/o register addresses */
>  static bool fw_cfg_is_mmio;
>  static phys_addr_t fw_cfg_p_base;
> @@ -75,12 +92,68 @@ static inline u16 fw_cfg_sel_endianness(u16 key)
>   return fw_cfg_is_mmio ? cpu_to_be16(key) : cpu_to_le16(key);
>  }
>  
> +static inline bool fw_cfg_dma_enabled(void)
> +{
> + return fw_cfg_rev & FW_CFG_VERSION_DMA && fw_cfg_reg_dma;
> +}
> +
> +/* qemu fw_cfg device is sync today, but spec says it may become async */
> +static void fw_cfg_wait_for_control(struct fw_cfg_dma *d)
> +{
> + do {
> + u32 ctrl = be32_to_cpu(READ_ONCE(d->control));
> +
> + if ((ctrl & ~FW_CFG_DMA_CTL_ERROR) == 0)
> + return;
> +
> + usleep_range(50, 100);
> + } while (true);
> +}
> +
> +static ssize_t fw_cfg_dma_transfer(struct device *dev,
> + void *address, u32 length, u32 control)
> +{
> + phys_addr_t dma;
> + struct fw_cfg_dma *d = NULL;
> + ssize_t ret = length;
> +
> + d = kmalloc(sizeof(*d), GFP_KERNEL);
> + if (!d) {
> + ret = -ENOMEM;
> + goto end;
> + }
> +
> + *d = (struct fw_cfg_dma) {
> + .address = cpu_to_be64(virt_to_phys(address)),
> + .length = cpu_to_be32(length),
> + .control = cpu_to_be32(control)
> + };
> +
> + dma = virt_to_phys(d);
> +
> + iowrite32be((u64)dma >> 32, fw_cfg_reg_dma);
> + iowrite32be(dma, fw_cfg_reg_dma + 4);

We can do it with iowrite64be(virt_to_phys(d)) too?  In all cases I
think it's good enough and no worth for a repost.

For the DMA transfer part:

Acked-by: Peter Xu 

Thanks,

-- 
Peter Xu



Re: [Qemu-devel] [PATCH v1 06/21] RISC-V FPU Support

2018-01-23 Thread Jim Wilson
On Tue, Jan 23, 2018 at 3:35 PM, Michael Clark  wrote:
> We want minimum number (minnum). It's been added to the draft spec and will
> be in riscv-spec-v2.3.pdf

In the preface of the draft, it says
• Defined the signed-zero behavior of FMIN.fmt and FMAX.fmt, and
changed their behavior on
signaling-NaN inputs to conform to the minimumNumber and maximumNumber
operations
in the proposed IEEE 754-201x specification.

But if qemu doesn't have minimumNumber support yet, then yes minNum is correct.

This is discussed a bit here
https://github.com/riscv/riscv-isa-manual/issues/65

Jim



Re: [Qemu-devel] [PATCH v1 06/21] RISC-V FPU Support

2018-01-23 Thread Michael Clark
On Tue, Jan 23, 2018 at 4:01 PM, Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 01/23/2018 01:37 PM, Michael Clark wrote:
> >
> >
> > On Wed, Jan 3, 2018 at 12:10 PM, Richard Henderson
> > >
> wrote:
> >
> > On 01/02/2018 04:44 PM, Michael Clark wrote:
> > > +/* convert RISC-V rounding mode to IEEE library numbers */
> > > +unsigned int ieee_rm[] = {
> >
> > static const.
> >
> >
> > Done.
> >
> > > +/* obtain rm value to use in computation
> > > + * as the last step, convert rm codes to what the softfloat
> library expects
> > > + * Adapted from Spike's decode.h:RM
> > > + */
> > > +#define RM ({ \
> > > +if (rm == 7) {\
> > > +rm = env->frm;   \
> > > +} \
> > > +if (rm > 4) { \
> > > +helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
> > > +} \
> > > +ieee_rm[rm]; })
> >
> > Please use inline functions and not these macros.
> >
> >
> > Done.
> >
> > In fact the previous code would, with normal control flow, dereference
> > ieee_rm[rm] with an out of bounds round mode so assuming
> helper_raise_exception
> > does a longjmp, i've inserted g_assert_not_reached() after the
> exception. An
> > analyser could detect that ieee_rm has an out of bounds access assuming
> normal
> > control flow. e.g.
> >
> > static inline void set_fp_round_mode(CPURISCVState *env, uint64_t rm)
> > {
> > if (rm == 7) {
> > rm = env->frm;
> > } else if (rm > 4) {
> > helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST);
> > g_assert_not_reached();
>
> Yes, raise_exception exits via longjmp.  This is a good change.
>
> > Are translations not implicitly indexed by cpu_mmu_index? i.e. do we
> also need
> > to add cpu_mmu_index to cpu_get_tb_cpu_state flags to prevent code
> translated
> > for one value of mmu_index running in code with another value of
> mmu_index (in
> > the case of riscv, we currently return processor mode / privilege level
> in
> > cpu_mmu_index).
>
> No, there is no implicit indexing.  That's why I've mentioned exactly this
> at
> least twice in review so far.
>
> There are two ways to do this correctly.  One is to add all the bits that
> specify processor state (e.g. Alpha stores pal_code bit and supervisor
> bit).
> Another is to actually encode the mmu_idx into the flags (e.g. ARM).


I reviewed Stefan's patches. Stefan has some code that encoded processor
flags in mmu_index however it removed some well-tested code paths and I was
hesitant to make such a large change to get_physical_address at this point
in time. I read Stefan's code and used some fragments from it but was
relatively cautious with regard to changing relatively well tested code
paths. I tried to make the most minimal change for the sake of correctness.

For the meantime we've greatly simplified cpu_mmu_index to just return the
processor mode as well as adding the processor mode to cpu_get_tb_cpu_state
flags. cpu_mmu_index previously returned a permutation of env->priv
(containing processer mode), mstatus.MPP (previous mode) and mstatus.MPRV.
When MPRV is set, M mode loads and stores operate as per the mode in
mstatus.MPP and the previous cpu_mmu_index function returned the mode the
processor should do loads and stores as, not the current mode. This is
problematic as mstatus.MPRV can be altered from user code via register
values so there was a potential to re-enter a pre-existing trace with a
different mmu_index. I believe we have eliminated that issue.

These two changes should fix the issue and we've performed testing with
these patches:

-
https://github.com/michaeljclark/riscv-qemu/commit/82012aef90e5c4500f926523b3b2ff621b0cd512
-
https://github.com/michaeljclark/riscv-qemu/commit/abdb897a4a607d00cfce577ac37ca6119004658f

There is a possibility to further improve this code and potentially avoid
TLB flushes, by encoding more state in cpu_mmu_index
and cpu_get_tb_cpu_state flags. I would say that mstatus.SUM flag is
altered frequently in Linux's copy_to/from_user and is likely to result in
decent performance improvement if we can eliminate the TLB flush when the
SUM bit is changed (it is in concept similar to SMAP on x86). mstatus.MPRV
is used by the monitor for handling misaligned loads and stores which
should be relatively rare (the occasional use of structs with
__attribute__((packed))). Eliminating the tlb_flush on mstatus.SUM changes
likely will have the most positive performance impact

We have increased performance somewhat already (~2.5X faster on dd
if=/dev/zero of=/dev/null bs=1 count=10). We eliminated a tlb_flush on
privilege level changes as this is included (now 

Re: [Qemu-devel] Call for GSoC & Outreachy 2018 mentors & project ideas

2018-01-23 Thread Alistair Francis
On Thu, Jan 18, 2018 at 8:49 AM, David Hildenbrand  wrote:
> On 12.01.2018 00:25, Alistair Francis wrote:
>> On Wed, Jan 10, 2018 at 4:52 AM, Stefan Hajnoczi  wrote:
>>> On Tue, Jan 9, 2018 at 9:45 PM, Alistair Francis  
>>> wrote:
 Can anyone who has done this before chime in.

 What do you think about getting someone to cleanup and improve the GDB
 support in QEMU? Would that be the right difficulty of task for a GSoC
 project?
>
> Don't understand that sentence. We already support multiple CPUs
> (represented and switchable just like threads in GDB), no?

We support multiple of the same CPU, such as multiple cores. What we
don't support is multiple of different types of CPUs. Something like
ARMs bit.LITTLE or Xilinx's 4xA53s and 2xR5s.

Alistair

>
> An interesting thing to look at could be tracepoint support in GDB.
>
>>>
>>> There is not enough information to give feedback on whether this
>>> project idea is suitable.  What are the specific tasks you'd like the
>>> student to work on?
>>>
>>> In general, I'm sure there are well-defined 12-week project ideas
>>> around the GDB stub.  New features are easy to propose and are usually
>>> well-defined (e.g. implement these commands that are documented in the
>>> GDB protocol documentation).  Cleaning up code is less clear and it
>>> would depend on exactly what needs to be done.  Interns will not have
>>> a background in the QEMU codebase and may not be able to make
>>> judgements about how to structure things, so I would be more careful
>>> about refactoring/cleanup projects.
>>>
>>> Please see my talk about QEMU GSoC for guidelines on project ideas:
>>> https://www.youtube.com/watch?v=xNVCX7YMUL8=19m11s
>>> http://vmsplice.net/~stefan/stefanha-kvm-forum-2016.pdf
>>
>> That helps a lot, thanks for that.
>>
>> So for a more concrete solution, how would adding support for multi
>> CPU support to the GDB server sound?
>>
>> This would allow GDB debugging for the A53 and the R5 on the Xilinx
>> ZynqMP for example. This is something we have in the Xilinx tree, but
>> it is in no state to go upstream and really needs to be re-write to be
>> upstreamable and more generic.
>>
>> Alistair
>>
>>>
>>> Hope this helps,
>>> Stefan
>
>
> --
>
> Thanks,
>
> David / dhildenb



Re: [Qemu-devel] [PATCH v9 16/16] hw/arm/xilinx_zynq: fix the capabilities register to match the datasheet

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 6:08 PM, Philippe Mathieu-Daudé  wrote:
> checking Xilinx datasheet "UG585" (v1.12.1)
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/arm/xilinx_zynq.c | 53 
> 
>  tests/sdhci-test.c   |  5 +
>  2 files changed, 34 insertions(+), 24 deletions(-)
>
> diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
> index 1836a4ed45..0f76333770 100644
> --- a/hw/arm/xilinx_zynq.c
> +++ b/hw/arm/xilinx_zynq.c
> @@ -61,6 +61,8 @@ static const int dma_irqs[8] = {
>  #define SLCR_XILINX_UNLOCK_KEY  0xdf0d
>  #define SLCR_XILINX_LOCK_KEY0x767b
>
> +#define ZYNQ_SDHCI_CAPABILITIES 0x69ec0080  /* Datasheet: UG585 (v1.12.1) */
> +
>  #define ARMV7_IMM16(x) (extract32((x),  0, 12) | \
>  extract32((x), 12,  4) << 16)
>
> @@ -165,10 +167,8 @@ static void zynq_init(MachineState *machine)
>  MemoryRegion *address_space_mem = get_system_memory();
>  MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
>  MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
> -DeviceState *dev, *carddev;
> +DeviceState *dev;
>  SysBusDevice *busdev;
> -DriveInfo *di;
> -BlockBackend *blk;
>  qemu_irq pic[64];
>  int n;
>
> @@ -247,27 +247,32 @@ static void zynq_init(MachineState *machine)
>  gem_init(_table[0], 0xE000B000, pic[54-IRQ_OFFSET]);
>  gem_init(_table[1], 0xE000C000, pic[77-IRQ_OFFSET]);
>
> -dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
> -qdev_init_nofail(dev);
> -sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE010);
> -sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]);
> -
> -di = drive_get_next(IF_SD);
> -blk = di ? blk_by_legacy_dinfo(di) : NULL;
> -carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
> -qdev_prop_set_drive(carddev, "drive", blk, _fatal);
> -object_property_set_bool(OBJECT(carddev), true, "realized", 
> _fatal);
> -
> -dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
> -qdev_init_nofail(dev);
> -sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000);
> -sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]);
> -
> -di = drive_get_next(IF_SD);
> -blk = di ? blk_by_legacy_dinfo(di) : NULL;
> -carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
> -qdev_prop_set_drive(carddev, "drive", blk, _fatal);
> -object_property_set_bool(OBJECT(carddev), true, "realized", 
> _fatal);
> +for (n = 0; n < 2; n++) {
> +int hci_irq = n ? 79 : 56;
> +hwaddr hci_addr = n ? 0xE0101000 : 0xE010;
> +DriveInfo *di;
> +BlockBackend *blk;
> +DeviceState *carddev;
> +
> +/* Compatible with:
> + * - SD Host Controller Specification Version 2.0 Part A2
> + * - SDIO Specification Version 2.0
> + * - MMC Specification Version 3.31
> + */
> +dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
> +qdev_prop_set_uint8(dev, "sd-spec-version", 2);
> +qdev_prop_set_uint64(dev, "capareg", ZYNQ_SDHCI_CAPABILITIES);
> +qdev_init_nofail(dev);
> +sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, hci_addr);
> +sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[hci_irq - 
> IRQ_OFFSET]);
> +
> +di = drive_get_next(IF_SD);
> +blk = di ? blk_by_legacy_dinfo(di) : NULL;
> +carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), 
> TYPE_SD_CARD);
> +qdev_prop_set_drive(carddev, "drive", blk, _fatal);
> +object_property_set_bool(OBJECT(carddev), true, "realized",
> + _fatal);
> +}
>
>  dev = qdev_create(NULL, TYPE_ZYNQ_XADC);
>  qdev_init_nofail(dev);
> diff --git a/tests/sdhci-test.c b/tests/sdhci-test.c
> index 094e0570e1..aae2cfc1b5 100644
> --- a/tests/sdhci-test.c
> +++ b/tests/sdhci-test.c
> @@ -41,6 +41,11 @@ static const struct sdhci_t {
>  /* Exynos4210 */
>  { "arm","smdkc210",
>  {0x1251, 2, 0,  {1, 0x5e80080} } },
> +
> +/* Zynq-7000 */
> +{ "arm","xilinx-zynq-a9",   /* Datasheet: UG585 (v1.12.1) */
> +{0xe010, 2, 0,  {1, 0x69ec0080} } },
> +
>  };
>
>  static struct {
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v9 09/16] sdhci: simplify sdhci_get_fifolen()

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 6:08 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/sd/sdhci-internal.h |  4 +++-
>  hw/sd/sdhci.c  | 20 +---
>  2 files changed, 8 insertions(+), 16 deletions(-)
>
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index b7751c815f..577ca9da54 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -24,6 +24,8 @@
>  #ifndef SDHCI_INTERNAL_H
>  #define SDHCI_INTERNAL_H
>
> +#include "hw/registerfields.h"
> +
>  /* R/W SDMA System Address register 0x0 */
>  #define SDHC_SYSAD 0x00
>
> @@ -179,7 +181,7 @@
>  #define SDHC_CAN_DO_ADMA2  0x0008
>  #define SDHC_CAN_DO_ADMA1  0x0010
>  #define SDHC_64_BIT_BUS_SUPPORT(1 << 28)
> -#define SDHC_CAPAB_BLOCKSIZE(x)(((x) >> 16) & 0x3)
> +FIELD(SDHC_CAPAB, MAXBLOCKLENGTH, 16, 2);
>
>  /* HWInit Maximum Current Capabilities Register 0x0 */
>  #define SDHC_MAXCURR   0x48
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 1c781c4ba5..dce1a49af1 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -59,6 +59,11 @@
>   */
>  #define SDHC_CAPAB_REG_DEFAULT 0x057834b4
>
> +static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
> +{
> +return 1 << (9 + FIELD_EX32(s->capareg, SDHC_CAPAB, MAXBLOCKLENGTH));
> +}
> +
>  static uint8_t sdhci_slotint(SDHCIState *s)
>  {
>  return (s->norintsts & s->norintsigen) || (s->errintsts & 
> s->errintsigen) ||
> @@ -1118,21 +1123,6 @@ static const MemoryRegionOps sdhci_mmio_ops = {
>  .endianness = DEVICE_LITTLE_ENDIAN,
>  };
>
> -static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
> -{
> -switch (SDHC_CAPAB_BLOCKSIZE(s->capareg)) {
> -case 0:
> -return 512;
> -case 1:
> -return 1024;
> -case 2:
> -return 2048;
> -default:
> -hw_error("SDHC: unsupported value for maximum block size\n");
> -return 0;
> -}
> -}
> -
>  static void sdhci_init_readonly_registers(SDHCIState *s, Error **errp)
>  {
>  if (s->sd_spec_version != 2) {
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v9 14/16] hw/arm/exynos4210: access the 64-bit capareg with qdev_prop_set_uint64()

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 6:08 PM, Philippe Mathieu-Daudé  wrote:
> We only set a 32-bit value, but this is a good practice in case this
> code is used as reference.
>
> (missed in 5efc9016e52)
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/arm/exynos4210.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
> index e8e1d81e62..d89322c7ea 100644
> --- a/hw/arm/exynos4210.c
> +++ b/hw/arm/exynos4210.c
> @@ -378,7 +378,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
>  DriveInfo *di;
>
>  dev = qdev_create(NULL, TYPE_SYSBUS_SDHCI);
> -qdev_prop_set_uint32(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
> +qdev_prop_set_uint64(dev, "capareg", EXYNOS4210_SDHCI_CAPABILITIES);
>  qdev_init_nofail(dev);
>
>  busdev = SYS_BUS_DEVICE(dev);
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v3 05/12] sdcard: add more trace events

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:21 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Acked-by: Alistair Francis 

Alistair

> ---
>  hw/sd/sd.c | 32 ++--
>  hw/sd/trace-events | 13 +
>  2 files changed, 39 insertions(+), 6 deletions(-)
>
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index 03263e08ae..dc4b2329e4 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -177,6 +177,8 @@ static bool sd_get_cmd_line(SDState *sd)
>
>  static void sd_set_voltage(SDState *sd, uint16_t millivolts)
>  {
> +trace_sdcard_set_voltage(millivolts);
> +
>  switch (millivolts) {
>  case 3001 ... 3600: /* SD_VOLTAGE_3_3V */
>  case 2001 ... 3000: /* SD_VOLTAGE_3_0V */
> @@ -272,6 +274,7 @@ static void sd_ocr_powerup(void *opaque)
>  {
>  SDState *sd = opaque;
>
> +trace_sdcard_powerup();
>  /* Set powered up bit in OCR */
>  assert(!(sd->ocr & OCR_POWER_UP));
>  sd->ocr |= OCR_POWER_UP;
> @@ -475,6 +478,7 @@ static void sd_reset(DeviceState *dev)
>  uint64_t size;
>  uint64_t sect;
>
> +trace_sdcard_reset();
>  if (sd->blk) {
>  blk_get_geometry(sd->blk, );
>  } else {
> @@ -528,7 +532,10 @@ static void sd_cardchange(void *opaque, bool load, Error 
> **errp)
>  bool readonly = sd_get_readonly(sd);
>
>  if (inserted) {
> +trace_sdcard_inserted(readonly);
>  sd_reset(dev);
> +} else {
> +trace_sdcard_ejected();
>  }
>
>  /* The IRQ notification is for legacy non-QOM SD controller devices;
> @@ -660,6 +667,7 @@ static void sd_erase(SDState *sd)
>  uint64_t erase_start = sd->erase_start;
>  uint64_t erase_end = sd->erase_end;
>
> +trace_sdcard_erase();
>  if (!sd->erase_start || !sd->erase_end) {
>  sd->card_status |= ERASE_SEQ_ERROR;
>  return;
> @@ -749,6 +757,11 @@ static void sd_lock_command(SDState *sd)
>  else
>  pwd_len = 0;
>
> +if (lock) {
> +trace_sdcard_lock();
> +} else {
> +trace_sdcard_unlock();
> +}
>  if (erase) {
>  if (!(sd->card_status & CARD_IS_LOCKED) || sd->blk_len > 1 ||
>  set_pwd || clr_pwd || lock || sd->wp_switch ||
> @@ -1075,10 +1088,12 @@ static sd_rsp_type_t sd_normal_command(SDState *sd,
>  case 16:   /* CMD16:  SET_BLOCKLEN */
>  switch (sd->state) {
>  case sd_transfer_state:
> -if (req.arg > (1 << HWBLOCK_SHIFT))
> +if (req.arg > (1 << HWBLOCK_SHIFT)) {
>  sd->card_status |= BLOCK_LEN_ERROR;
> -else
> +} else {
> +trace_sdcard_set_blocklen(req.arg);
>  sd->blk_len = req.arg;
> +}
>
>  return sd_r1;
>
> @@ -1450,10 +1465,13 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
>  if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) {
>  timer_del(sd->ocr_power_timer);
>  sd_ocr_powerup(sd);
> -} else if (!timer_pending(sd->ocr_power_timer)) {
> -timer_mod_ns(sd->ocr_power_timer,
> - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
> -  + OCR_POWER_DELAY_NS));
> +} else {
> +trace_sdcard_inquiry_cmd41();
> +if (!timer_pending(sd->ocr_power_timer)) {
> +timer_mod_ns(sd->ocr_power_timer,
> + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
> +  + OCR_POWER_DELAY_NS));
> +}
>  }
>  }
>
> @@ -1666,6 +1684,7 @@ void sd_write_data(SDState *sd, uint8_t value)
>  if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
>  return;
>
> +trace_sdcard_write_data(sd->current_cmd, value);
>  switch (sd->current_cmd) {
>  case 24:   /* CMD24:  WRITE_SINGLE_BLOCK */
>  sd->data[sd->data_offset ++] = value;
> @@ -1803,6 +1822,7 @@ uint8_t sd_read_data(SDState *sd)
>
>  io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
>
> +trace_sdcard_read_data(sd->current_cmd, io_len);
>  switch (sd->current_cmd) {
>  case 6:/* CMD6:   SWITCH_FUNCTION */
>  ret = sd->data[sd->data_offset ++];
> diff --git a/hw/sd/trace-events b/hw/sd/trace-events
> index b2aa19ec0d..3040d32560 100644
> --- a/hw/sd/trace-events
> +++ b/hw/sd/trace-events
> @@ -27,8 +27,21 @@ sdhci_capareg(const char *desc, uint16_t val) "%s: %u"
>  sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d 
> arg 0x%08x (state %s)"
>  sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x"
>  sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
> +sdcard_powerup(void) ""
> +sdcard_inquiry_cmd41(void) ""
> +sdcard_set_enable(bool current_state, bool new_state) "%u -> %u"
> 

Re: [Qemu-devel] [PATCH v9 10/16] sdhci: check the Spec v1 capabilities correctness

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 6:08 PM, Philippe Mathieu-Daudé  wrote:
> Incorrect value will throw an error.
>
> Note than Spec v2 is supported by default.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/sd/sdhci-internal.h | 21 ++-
>  hw/sd/sdhci.c  | 97 
> +-
>  hw/sd/trace-events |  1 +
>  3 files changed, 117 insertions(+), 2 deletions(-)
>
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index 577ca9da54..c5e26bf8f3 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -86,6 +86,9 @@
>
>  /* R/W Host control Register 0x0 */
>  #define SDHC_HOSTCTL   0x28
> +FIELD(SDHC_HOSTCTL, LED_CTRL,  0, 1);
> +FIELD(SDHC_HOSTCTL, DATATRANSFERWIDTH, 1, 1); /* SD mode only */
> +FIELD(SDHC_HOSTCTL, HIGH_SPEED,2, 1);
>  #define SDHC_CTRL_DMA_CHECK_MASK   0x18
>  #define SDHC_CTRL_SDMA 0x00
>  #define SDHC_CTRL_ADMA1_32 0x08
> @@ -96,6 +99,7 @@
>  /* R/W Power Control Register 0x0 */
>  #define SDHC_PWRCON0x29
>  #define SDHC_POWER_ON  (1 << 0)
> +FIELD(SDHC_PWRCON, BUS_VOLTAGE,1, 3);
>
>  /* R/W Block Gap Control Register 0x0 */
>  #define SDHC_BLKGAP0x2A
> @@ -118,6 +122,7 @@
>
>  /* R/W Timeout Control Register 0x0 */
>  #define SDHC_TIMEOUTCON0x2E
> +FIELD(SDHC_TIMEOUTCON, COUNTER,0, 4);
>
>  /* R/W Software Reset Register 0x0 */
>  #define SDHC_SWRST 0x2F
> @@ -174,17 +179,31 @@
>
>  /* ROC Auto CMD12 error status register 0x0 */
>  #define SDHC_ACMD12ERRSTS  0x3C
> +FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
> +FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,  2, 1);
> +FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,4, 1);
>
>  /* HWInit Capabilities Register 0x05E80080 */
>  #define SDHC_CAPAB 0x40
> -#define SDHC_CAN_DO_DMA0x0040
>  #define SDHC_CAN_DO_ADMA2  0x0008
>  #define SDHC_CAN_DO_ADMA1  0x0010
>  #define SDHC_64_BIT_BUS_SUPPORT(1 << 28)
> +FIELD(SDHC_CAPAB, TOCLKFREQ,   0, 6);
> +FIELD(SDHC_CAPAB, TOUNIT,  7, 1);
> +FIELD(SDHC_CAPAB, BASECLKFREQ, 8, 8);
>  FIELD(SDHC_CAPAB, MAXBLOCKLENGTH, 16, 2);
> +FIELD(SDHC_CAPAB, HIGHSPEED,  21, 1);
> +FIELD(SDHC_CAPAB, SDMA,   22, 1);
> +FIELD(SDHC_CAPAB, SUSPRESUME, 23, 1);
> +FIELD(SDHC_CAPAB, V33,24, 1);
> +FIELD(SDHC_CAPAB, V30,25, 1);
> +FIELD(SDHC_CAPAB, V18,26, 1);
>
>  /* HWInit Maximum Current Capabilities Register 0x0 */
>  #define SDHC_MAXCURR   0x48
> +FIELD(SDHC_MAXCURR, V33_VDD1,  0, 8);
> +FIELD(SDHC_MAXCURR, V30_VDD1,  8, 8);
> +FIELD(SDHC_MAXCURR, V18_VDD1, 16, 8);
>
>  /* W Force Event Auto CMD12 Error Interrupt Register 0x */
>  #define SDHC_FEAER 0x50
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index dce1a49af1..91dfd684d8 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -23,6 +23,7 @@
>   */
>
>  #include "qemu/osdep.h"
> +#include "qemu/error-report.h"
>  #include "qapi/error.h"
>  #include "hw/hw.h"
>  #include "sysemu/block-backend.h"
> @@ -64,6 +65,92 @@ static inline unsigned int sdhci_get_fifolen(SDHCIState *s)
>  return 1 << (9 + FIELD_EX32(s->capareg, SDHC_CAPAB, MAXBLOCKLENGTH));
>  }
>
> +/* return true on error */
> +static bool sdhci_check_capab_freq_range(SDHCIState *s, const char *desc,
> + uint8_t freq, Error **errp)
> +{
> +switch (freq) {
> +case 0:
> +case 10 ... 63:
> +break;
> +default:
> +error_setg(errp, "SD %s clock frequency can have value"
> +   "in range 0-63 only", desc);
> +return true;
> +}
> +return false;
> +}
> +
> +static void sdhci_check_capareg(SDHCIState *s, Error **errp)
> +{
> +uint64_t msk = s->capareg;
> +uint32_t val;
> +bool y;
> +
> +switch (s->sd_spec_version) {
> +case 2: /* default version */
> +
> +/* fallback */
> +case 1:
> +y = FIELD_EX64(s->capareg, SDHC_CAPAB, TOUNIT);
> +msk = FIELD_DP64(msk, SDHC_CAPAB, TOUNIT, 0);
> +
> +val = FIELD_EX64(s->capareg, SDHC_CAPAB, TOCLKFREQ);
> +trace_sdhci_capareg(y ? "timeout (MHz)" : "Timeout (KHz)", val);
> +if (sdhci_check_capab_freq_range(s, "timeout", val, errp)) {
> +return;
> +}
> +msk = FIELD_DP64(msk, SDHC_CAPAB, TOCLKFREQ, 0);
> +
> +val = FIELD_EX64(s->capareg, SDHC_CAPAB, BASECLKFREQ);
> +trace_sdhci_capareg(y ? "base (MHz)" : "Base (KHz)", val);
> +if (sdhci_check_capab_freq_range(s, "base", val, errp)) {
> +return;
> +}
> +msk = FIELD_DP64(msk, SDHC_CAPAB, 

Re: [Qemu-devel] [PATCH v1 06/21] RISC-V FPU Support

2018-01-23 Thread Richard Henderson
On 01/23/2018 03:15 PM, Michael Clark wrote:
> > +uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t 
> frs2,
> > +                        uint64_t frs3, uint64_t rm)
> > +{
> > +    require_fp;
> > +    set_float_rounding_mode(RM, >fp_status);
> > +    frs1 = float32_muladd(frs1, frs2, frs3 ^ (uint32_t)INT32_MIN, 0,
> > +                          >fp_status);
> 
> Given that RISC-V always returns a default NaN, you obviously do not care 
> about
> the sign of a NaN result.  Therefore you should use float_muladd_negate_c 
> as
> the fourth argument here and not perform the sign flip manually.
> 
> 
> We do care about the sign of NaN results.
> 
> Jim Wilson spotted this bug and removed a call to set_default_nan_mode
> 
> https://github.com/riscv/riscv-qemu/commit/4223d89b0c5c671332d66bcd649db5c6f46559f5

Ok.  Now it depends on what result you care about for madd specifically.

If, like x86 and Power, fmsub returns the (silenced) original input NaN, you
want the float_muladd_* flags.

If, like ARM, fmsub returns the (silenced) negated input NaN, then you do need
to change sign externally.  If this is the case, please use float32_chs instead
of open-coding it with xor.


r~



Re: [Qemu-devel] [PATCH v1 06/21] RISC-V FPU Support

2018-01-23 Thread Richard Henderson
On 01/23/2018 01:37 PM, Michael Clark wrote:
> 
> 
> On Wed, Jan 3, 2018 at 12:10 PM, Richard Henderson
> > wrote:
> 
> On 01/02/2018 04:44 PM, Michael Clark wrote:
> > +/* convert RISC-V rounding mode to IEEE library numbers */
> > +unsigned int ieee_rm[] = {
> 
> static const.
> 
> 
> Done. 
> 
> > +/* obtain rm value to use in computation
> > + * as the last step, convert rm codes to what the softfloat library 
> expects
> > + * Adapted from Spike's decode.h:RM
> > + */
> > +#define RM ({                                             \
> > +if (rm == 7) {                                            \
> > +    rm = env->frm;                               \
> > +}                                                         \
> > +if (rm > 4) {                                             \
> > +    helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
> > +}                                                         \
> > +ieee_rm[rm]; })
> 
> Please use inline functions and not these macros.
> 
> 
> Done.
> 
> In fact the previous code would, with normal control flow, dereference
> ieee_rm[rm] with an out of bounds round mode so assuming 
> helper_raise_exception
> does a longjmp, i've inserted g_assert_not_reached() after the exception. An
> analyser could detect that ieee_rm has an out of bounds access assuming normal
> control flow. e.g.
> 
> static inline void set_fp_round_mode(CPURISCVState *env, uint64_t rm)
> {
>     if (rm == 7) {
>         rm = env->frm;
>     } else if (rm > 4) {
>         helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST);
>         g_assert_not_reached();

Yes, raise_exception exits via longjmp.  This is a good change.

> Are translations not implicitly indexed by cpu_mmu_index? i.e. do we also need
> to add cpu_mmu_index to cpu_get_tb_cpu_state flags to prevent code translated
> for one value of mmu_index running in code with another value of mmu_index (in
> the case of riscv, we currently return processor mode / privilege level in
> cpu_mmu_index).

No, there is no implicit indexing.  That's why I've mentioned exactly this at
least twice in review so far.

There are two ways to do this correctly.  One is to add all the bits that
specify processor state (e.g. Alpha stores pal_code bit and supervisor bit).
Another is to actually encode the mmu_idx into the flags (e.g. ARM).


r~



[Qemu-devel] [PATCH 7/7] tests: virtio-9p: add FLUSH operation test

2018-01-23 Thread Greg Kurz
The idea is to send a victim request that will possibly block in the
server and to send a flush request to cancel the victim request.

This patch adds two test to verifiy that:
- the server does not reply to a victim request that was actually
  cancelled
- the server replies to the flush request after replying to the
  victim request if it could not cancel it

9p request cancellation reference:

http://man.cat-v.org/plan_9/5/flush

Signed-off-by: Greg Kurz 
---
 hw/9pfs/9p-synth.c |   24 ++
 hw/9pfs/9p-synth.h |5 ++
 hw/9pfs/9p.c   |1 
 tests/virtio-9p-test.c |  117 +++-
 4 files changed, 134 insertions(+), 13 deletions(-)

diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index f2d59a90a670..0a9940dfa23c 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -521,6 +521,24 @@ static ssize_t v9fs_synth_qtest_write(void *buf, int len, 
off_t offset,
 return len;
 }
 
+static ssize_t v9fs_synth_qtest_flush_write(void *buf, int len, off_t offset,
+void *arg)
+{
+QtestV9fsSynthFlushData *data = buf;
+
+assert(len == sizeof(*data));
+
+if (data->usec_timeout) {
+usleep(data->usec_timeout);
+
+/* This will cause the server to call us again until we're cancelled */
+errno = EINTR;
+return -1;
+}
+
+return len;
+}
+
 static int synth_init(FsContext *ctx, Error **errp)
 {
 QLIST_INIT(_root.child);
@@ -557,6 +575,12 @@ static int synth_init(FsContext *ctx, Error **errp)
 ret = qemu_v9fs_synth_add_file(NULL, 0, QTEST_V9FS_SYNTH_WRITE_FILE,
NULL, v9fs_synth_qtest_write, ctx);
 assert(!ret);
+
+/* File for FLUSH test */
+ret = qemu_v9fs_synth_add_file(NULL, 0, QTEST_V9FS_SYNTH_FLUSH_FILE,
+   NULL, v9fs_synth_qtest_flush_write,
+   ctx);
+assert(!ret);
 }
 
 return 0;
diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h
index a74032d7bd9a..502ec6309a36 100644
--- a/hw/9pfs/9p-synth.h
+++ b/hw/9pfs/9p-synth.h
@@ -54,5 +54,10 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
 #define QTEST_V9FS_SYNTH_WALK_FILE "WALK%d"
 #define QTEST_V9FS_SYNTH_LOPEN_FILE "LOPEN"
 #define QTEST_V9FS_SYNTH_WRITE_FILE "WRITE"
+#define QTEST_V9FS_SYNTH_FLUSH_FILE "FLUSH"
+
+typedef struct {
+uint32_t usec_timeout;
+} QtestV9fsSynthFlushData;
 
 #endif
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 73dafffe239f..eae82db4ef60 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -24,6 +24,7 @@
 #include "coth.h"
 #include "trace.h"
 #include "migration/blocker.h"
+#include "sysemu/qtest.h"
 
 int open_fd_hw;
 int total_open_fd;
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 57ae3a666c61..b234e09e252d 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -247,14 +247,15 @@ static const char *rmessage_name(uint8_t id)
 id == P9_RWALK ? "RWALK" :
 id == P9_RLOPEN ? "RLOPEN" :
 id == P9_RWRITE ? "RWRITE" :
+id == P9_RFLUSH ? "RFLUSH" :
 "";
 }
 
-static void v9fs_req_wait_for_reply(P9Req *req)
+static void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len)
 {
 QVirtIO9P *v9p = req->v9p;
 
-qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head, NULL,
+qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head, len,
QVIRTIO_9P_TIMEOUT_US);
 }
 
@@ -451,6 +452,24 @@ static void v9fs_rwrite(P9Req *req, uint32_t *count)
 v9fs_req_free(req);
 }
 
+/* size[4] Tflush tag[2] oldtag[2] */
+static P9Req *v9fs_tflush(QVirtIO9P *v9p, uint16_t oldtag, uint16_t tag)
+{
+P9Req *req;
+
+req = v9fs_req_init(v9p,  2, P9_TFLUSH, tag);
+v9fs_uint32_write(req, oldtag);
+v9fs_req_send(req);
+return req;
+}
+
+/* size[4] Rflush tag[2] */
+static void v9fs_rflush(P9Req *req)
+{
+v9fs_req_recv(req, P9_RFLUSH);
+v9fs_req_free(req);
+}
+
 static void fs_version(QVirtIO9P *v9p)
 {
 const char *version = "9P2000.L";
@@ -459,7 +478,7 @@ static void fs_version(QVirtIO9P *v9p)
 P9Req *req;
 
 req = v9fs_tversion(v9p, P9_MAX_SIZE, version, P9_NOTAG);
-v9fs_req_wait_for_reply(req);
+v9fs_req_wait_for_reply(req, NULL);
 v9fs_rversion(req, _len, _version);
 
 g_assert_cmpmem(server_version, server_len, version, strlen(version));
@@ -473,7 +492,7 @@ static void fs_attach(QVirtIO9P *v9p)
 
 fs_version(v9p);
 req = v9fs_tattach(v9p, 0, getuid(), 0);
-v9fs_req_wait_for_reply(req);
+v9fs_req_wait_for_reply(req, NULL);
 v9fs_rattach(req, NULL);
 }
 
@@ -491,7 +510,7 @@ static void fs_walk(QVirtIO9P *v9p)
 
 fs_attach(v9p);
 req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames, 0);
-v9fs_req_wait_for_reply(req);
+v9fs_req_wait_for_reply(req, NULL);
 v9fs_rwalk(req, , );
 
 g_assert_cmpint(nwqid, ==, 

[Qemu-devel] [PATCH 6/7] libqos/virtio: return length written into used descriptor

2018-01-23 Thread Greg Kurz
When a 9p request is flushed (ie, cancelled) by the guest, the device
is expected to simply mark the request as used, without sending a 9p
reply (ie, without writing anything into the used buffer).

To be able to test this, we need access to the length written by the
device into the used descriptor. This patch adds a uint32_t * argument
to qvirtqueue_get_buf() and qvirtio_wait_used_elem() for this purpose.

All existing users are updated accordingly.

Signed-off-by: Greg Kurz 
---
 tests/libqos/virtio.c|   25 +
 tests/libqos/virtio.h|3 ++-
 tests/virtio-9p-test.c   |2 +-
 tests/virtio-blk-test.c  |   24 +---
 tests/virtio-net-test.c  |6 +++---
 tests/virtio-scsi-test.c |3 ++-
 6 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/tests/libqos/virtio.c b/tests/libqos/virtio.c
index 0879a621c8af..0dad5c19acde 100644
--- a/tests/libqos/virtio.c
+++ b/tests/libqos/virtio.c
@@ -119,6 +119,8 @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
 /*
  * qvirtio_wait_used_elem:
  * @desc_idx: The next expected vq->desc[] index in the used ring
+ * @len: A pointer that is filled with the length written into the buffer, may
+ *   be NULL
  * @timeout_us: How many microseconds to wait before failing
  *
  * This function waits for the next completed request on the used ring.
@@ -126,6 +128,7 @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
 void qvirtio_wait_used_elem(QVirtioDevice *d,
 QVirtQueue *vq,
 uint32_t desc_idx,
+uint32_t *len,
 gint64 timeout_us)
 {
 gint64 start_time = g_get_monotonic_time();
@@ -136,7 +139,7 @@ void qvirtio_wait_used_elem(QVirtioDevice *d,
 clock_step(100);
 
 if (d->bus->get_queue_isr_status(d, vq) &&
-qvirtqueue_get_buf(vq, _desc_idx)) {
+qvirtqueue_get_buf(vq, _desc_idx, len)) {
 g_assert_cmpint(got_desc_idx, ==, desc_idx);
 return;
 }
@@ -304,30 +307,36 @@ void qvirtqueue_kick(QVirtioDevice *d, QVirtQueue *vq, 
uint32_t free_head)
 /*
  * qvirtqueue_get_buf:
  * @desc_idx: A pointer that is filled with the vq->desc[] index, may be NULL
+ * @len: A pointer that is filled with the length written into the buffer, may
+ *   be NULL
  *
  * This function gets the next used element if there is one ready.
  *
  * Returns: true if an element was ready, false otherwise
  */
-bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx)
+bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx, uint32_t *len)
 {
 uint16_t idx;
+uint64_t elem_addr;
 
 idx = readw(vq->used + offsetof(struct vring_used, idx));
 if (idx == vq->last_used_idx) {
 return false;
 }
 
-if (desc_idx) {
-uint64_t elem_addr;
+elem_addr = vq->used +
+offsetof(struct vring_used, ring) +
+(vq->last_used_idx % vq->size) *
+sizeof(struct vring_used_elem);
 
-elem_addr = vq->used +
-offsetof(struct vring_used, ring) +
-(vq->last_used_idx % vq->size) *
-sizeof(struct vring_used_elem);
+if (desc_idx) {
 *desc_idx = readl(elem_addr + offsetof(struct vring_used_elem, id));
 }
 
+if (len) {
+*len = readw(elem_addr + offsetof(struct vring_used_elem, len));
+}
+
 vq->last_used_idx++;
 return true;
 }
diff --git a/tests/libqos/virtio.h b/tests/libqos/virtio.h
index 0a04740adfe1..69b5b13840e7 100644
--- a/tests/libqos/virtio.h
+++ b/tests/libqos/virtio.h
@@ -124,6 +124,7 @@ uint8_t qvirtio_wait_status_byte_no_isr(QVirtioDevice *d,
 void qvirtio_wait_used_elem(QVirtioDevice *d,
 QVirtQueue *vq,
 uint32_t desc_idx,
+uint32_t *len,
 gint64 timeout_us);
 void qvirtio_wait_config_isr(QVirtioDevice *d, gint64 timeout_us);
 QVirtQueue *qvirtqueue_setup(QVirtioDevice *d,
@@ -140,7 +141,7 @@ uint32_t qvirtqueue_add(QVirtQueue *vq, uint64_t data, 
uint32_t len, bool write,
 bool next);
 uint32_t qvirtqueue_add_indirect(QVirtQueue *vq, QVRingIndirectDesc *indirect);
 void qvirtqueue_kick(QVirtioDevice *d, QVirtQueue *vq, uint32_t free_head);
-bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx);
+bool qvirtqueue_get_buf(QVirtQueue *vq, uint32_t *desc_idx, uint32_t *len);
 
 void qvirtqueue_set_used_event(QVirtQueue *vq, uint16_t idx);
 
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 5871a16dac73..57ae3a666c61 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -254,7 +254,7 @@ static void v9fs_req_wait_for_reply(P9Req *req)
 {
 QVirtIO9P *v9p = req->v9p;
 
-qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head,
+

[Qemu-devel] [PATCH 4/7] tests: virtio-9p: add LOPEN operation test

2018-01-23 Thread Greg Kurz
Trivial test of a successful open.

Signed-off-by: Greg Kurz 
---
 hw/9pfs/9p-synth.c |5 +
 hw/9pfs/9p-synth.h |1 +
 tests/virtio-9p-test.c |   47 +++
 3 files changed, 53 insertions(+)

diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index dcbd320da17a..f17b74f44461 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -541,6 +541,11 @@ static int synth_init(FsContext *ctx, Error **errp)
 assert(!ret);
 g_free(name);
 }
+
+/* File for LOPEN test */
+ret = qemu_v9fs_synth_add_file(NULL, 0, QTEST_V9FS_SYNTH_LOPEN_FILE,
+   NULL, NULL, ctx);
+assert(!ret);
 }
 
 return 0;
diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h
index 876b4ef58288..2a8d6fd00d69 100644
--- a/hw/9pfs/9p-synth.h
+++ b/hw/9pfs/9p-synth.h
@@ -52,5 +52,6 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
 /* qtest stuff */
 
 #define QTEST_V9FS_SYNTH_WALK_FILE "WALK%d"
+#define QTEST_V9FS_SYNTH_LOPEN_FILE "LOPEN"
 
 #endif
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 652198156731..6ba782e24f3a 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -238,6 +238,7 @@ static const char *rmessage_name(uint8_t id)
 id == P9_RVERSION ? "RVERSION" :
 id == P9_RATTACH ? "RATTACH" :
 id == P9_RWALK ? "RWALK" :
+id == P9_RLOPEN ? "RLOPEN" :
 "";
 }
 
@@ -389,6 +390,34 @@ static void v9fs_rwalk(P9Req *req, uint16_t *nwqid, 
v9fs_qid **wqid)
 v9fs_req_free(req);
 }
 
+/* size[4] Tlopen tag[2] fid[4] flags[4] */
+static P9Req *v9fs_tlopen(QVirtIO9P *v9p, uint32_t fid, uint32_t flags,
+  uint16_t tag)
+{
+P9Req *req;
+
+req = v9fs_req_init(v9p,  4 + 4, P9_TLOPEN, tag);
+v9fs_uint32_write(req, fid);
+v9fs_uint32_write(req, flags);
+v9fs_req_send(req);
+return req;
+}
+
+/* size[4] Rlopen tag[2] qid[13] iounit[4] */
+static void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit)
+{
+v9fs_req_recv(req, P9_RLOPEN);
+if (qid) {
+v9fs_memread(req, qid, 13);
+} else {
+v9fs_memskip(req, 13);
+}
+if (iounit) {
+v9fs_uint32_read(req, iounit);
+}
+v9fs_req_free(req);
+}
+
 static void fs_version(QVirtIO9P *v9p)
 {
 const char *version = "9P2000.L";
@@ -478,6 +507,23 @@ static void fs_walk_dotdot(QVirtIO9P *v9p)
 g_free(wnames[0]);
 }
 
+static void fs_lopen(QVirtIO9P *v9p)
+{
+char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_LOPEN_FILE) };
+P9Req *req;
+
+fs_attach(v9p);
+req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+v9fs_req_wait_for_reply(req);
+v9fs_rwalk(req, NULL, NULL);
+
+req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
+v9fs_req_wait_for_reply(req);
+v9fs_rlopen(req, NULL, NULL);
+
+g_free(wnames[0]);
+}
+
 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
 
 static void v9fs_run_pci_test(gconstpointer data)
@@ -507,6 +553,7 @@ int main(int argc, char **argv)
 v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/no_slash", fs_walk_no_slash);
 v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/dotdot_from_root",
fs_walk_dotdot);
+v9fs_qtest_pci_add("/virtio/9p/pci/fs/lopen/basic", fs_lopen);
 
 return g_test_run();
 }




[Qemu-devel] [PATCH 5/7] tests: virtio-9p: add WRITE operation test

2018-01-23 Thread Greg Kurz
Trivial test of a successful write.

Signed-off-by: Greg Kurz 
---
 hw/9pfs/9p-synth.c |   11 +
 hw/9pfs/9p-synth.h |1 +
 tests/virtio-9p-test.c |   59 
 3 files changed, 71 insertions(+)

diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index f17b74f44461..f2d59a90a670 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -515,6 +515,12 @@ static int synth_unlinkat(FsContext *ctx, V9fsPath *dir,
 return -1;
 }
 
+static ssize_t v9fs_synth_qtest_write(void *buf, int len, off_t offset,
+  void *arg)
+{
+return len;
+}
+
 static int synth_init(FsContext *ctx, Error **errp)
 {
 QLIST_INIT(_root.child);
@@ -546,6 +552,11 @@ static int synth_init(FsContext *ctx, Error **errp)
 ret = qemu_v9fs_synth_add_file(NULL, 0, QTEST_V9FS_SYNTH_LOPEN_FILE,
NULL, NULL, ctx);
 assert(!ret);
+
+/* File for WRITE test */
+ret = qemu_v9fs_synth_add_file(NULL, 0, QTEST_V9FS_SYNTH_WRITE_FILE,
+   NULL, v9fs_synth_qtest_write, ctx);
+assert(!ret);
 }
 
 return 0;
diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h
index 2a8d6fd00d69..a74032d7bd9a 100644
--- a/hw/9pfs/9p-synth.h
+++ b/hw/9pfs/9p-synth.h
@@ -53,5 +53,6 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
 
 #define QTEST_V9FS_SYNTH_WALK_FILE "WALK%d"
 #define QTEST_V9FS_SYNTH_LOPEN_FILE "LOPEN"
+#define QTEST_V9FS_SYNTH_WRITE_FILE "WRITE"
 
 #endif
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 6ba782e24f3a..5871a16dac73 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -150,6 +150,13 @@ static void v9fs_uint32_write(P9Req *req, uint32_t val)
 v9fs_memwrite(req, _val, 4);
 }
 
+static void v9fs_uint64_write(P9Req *req, uint64_t val)
+{
+uint64_t le_val = cpu_to_le64(val);
+
+v9fs_memwrite(req, _val, 8);
+}
+
 static void v9fs_uint32_read(P9Req *req, uint32_t *val)
 {
 v9fs_memread(req, val, 4);
@@ -239,6 +246,7 @@ static const char *rmessage_name(uint8_t id)
 id == P9_RATTACH ? "RATTACH" :
 id == P9_RWALK ? "RWALK" :
 id == P9_RLOPEN ? "RLOPEN" :
+id == P9_RWRITE ? "RWRITE" :
 "";
 }
 
@@ -418,6 +426,31 @@ static void v9fs_rlopen(P9Req *req, v9fs_qid *qid, 
uint32_t *iounit)
 v9fs_req_free(req);
 }
 
+/* size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count] */
+static P9Req *v9fs_twrite(QVirtIO9P *v9p, uint32_t fid, uint64_t offset,
+  uint32_t count, const void *data, uint16_t tag)
+{
+P9Req *req;
+
+req = v9fs_req_init(v9p,  4 + 8 + 4 + count, P9_TWRITE, tag);
+v9fs_uint32_write(req, fid);
+v9fs_uint64_write(req, offset);
+v9fs_uint32_write(req, count);
+v9fs_memwrite(req, data, count);
+v9fs_req_send(req);
+return req;
+}
+
+/* size[4] Rwrite tag[2] count[4] */
+static void v9fs_rwrite(P9Req *req, uint32_t *count)
+{
+v9fs_req_recv(req, P9_RWRITE);
+if (count) {
+v9fs_uint32_read(req, count);
+}
+v9fs_req_free(req);
+}
+
 static void fs_version(QVirtIO9P *v9p)
 {
 const char *version = "9P2000.L";
@@ -524,6 +557,31 @@ static void fs_lopen(QVirtIO9P *v9p)
 g_free(wnames[0]);
 }
 
+static void fs_write(QVirtIO9P *v9p)
+{
+static const uint32_t write_count = P9_MAX_SIZE / 2;
+char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_WRITE_FILE) };
+char *buf = g_malloc(write_count);
+uint32_t count;
+P9Req *req;
+
+fs_attach(v9p);
+req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+v9fs_req_wait_for_reply(req);
+v9fs_rwalk(req, NULL, NULL);
+
+req = v9fs_tlopen(v9p, 1, O_WRONLY, 0);
+v9fs_req_wait_for_reply(req);
+v9fs_rlopen(req, NULL, NULL);
+
+req = v9fs_twrite(v9p, 1, 0, write_count, buf, 0);
+v9fs_req_wait_for_reply(req);
+v9fs_rwrite(req, );
+g_assert_cmpint(count, ==, write_count);
+
+g_free(wnames[0]);
+}
+
 typedef void (*v9fs_test_fn)(QVirtIO9P *v9p);
 
 static void v9fs_run_pci_test(gconstpointer data)
@@ -554,6 +612,7 @@ int main(int argc, char **argv)
 v9fs_qtest_pci_add("/virtio/9p/pci/fs/walk/dotdot_from_root",
fs_walk_dotdot);
 v9fs_qtest_pci_add("/virtio/9p/pci/fs/lopen/basic", fs_lopen);
+v9fs_qtest_pci_add("/virtio/9p/pci/fs/write/basic", fs_write);
 
 return g_test_run();
 }




[Qemu-devel] [PATCH 1/7] tests: virtio-9p: move request tag to the test functions

2018-01-23 Thread Greg Kurz
It doesn't really makes sense to hide the request tag from the test
functions. It prevents to test the 9p server behavior when passed
a wrong tag (ie, still in use or different from P9_NOTAG for a
version request). Also the spec says that a tag is reusable as soon
as the corresponding request was replied or flushed: no need to
always increment tags like we do now. And finaly, an upcoming test
of the flush command will need to manipulate tags explicitely.

This simply changes all request functions to have a tag argument.
Except for the version request which needs P9_NOTAG, all other
tests can pass 0 since they wait for the reply before sending
another request.

Signed-off-by: Greg Kurz 
---
 tests/virtio-9p-test.c |   28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 00f00f7246e9..5ada2839b9ae 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -27,7 +27,6 @@ typedef struct {
 QOSState *qs;
 QVirtQueue *vq;
 char *test_share;
-uint16_t p9_req_tag;
 } QVirtIO9P;
 
 static QVirtIO9P *qvirtio_9p_start(const char *driver)
@@ -294,10 +293,11 @@ static void v9fs_rlerror(P9Req *req, uint32_t *err)
 }
 
 /* size[4] Tversion tag[2] msize[4] version[s] */
-static P9Req *v9fs_tversion(QVirtIO9P *v9p, uint32_t msize, const char 
*version)
+static P9Req *v9fs_tversion(QVirtIO9P *v9p, uint32_t msize, const char 
*version,
+uint16_t tag)
 {
 P9Req *req = v9fs_req_init(v9p, 4 + v9fs_string_size(version), P9_TVERSION,
-   P9_NOTAG);
+   tag);
 
 v9fs_uint32_write(req, msize);
 v9fs_string_write(req, version);
@@ -323,12 +323,12 @@ static void v9fs_rversion(P9Req *req, uint16_t *len, char 
**version)
 }
 
 /* size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s] n_uname[4] */
-static P9Req *v9fs_tattach(QVirtIO9P *v9p, uint32_t fid, uint32_t n_uname)
+static P9Req *v9fs_tattach(QVirtIO9P *v9p, uint32_t fid, uint32_t n_uname,
+   uint16_t tag)
 {
 const char *uname = ""; /* ignored by QEMU */
 const char *aname = ""; /* ignored by QEMU */
-P9Req *req = v9fs_req_init(v9p, 4 + 4 + 2 + 2 + 4, P9_TATTACH,
-   ++(v9p->p9_req_tag));
+P9Req *req = v9fs_req_init(v9p, 4 + 4 + 2 + 2 + 4, P9_TATTACH, tag);
 
 v9fs_uint32_write(req, fid);
 v9fs_uint32_write(req, P9_NOFID);
@@ -353,7 +353,7 @@ static void v9fs_rattach(P9Req *req, v9fs_qid *qid)
 
 /* size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s]) */
 static P9Req *v9fs_twalk(QVirtIO9P *v9p, uint32_t fid, uint32_t newfid,
- uint16_t nwname, char *const wnames[])
+ uint16_t nwname, char *const wnames[], uint16_t tag)
 {
 P9Req *req;
 int i;
@@ -362,7 +362,7 @@ static P9Req *v9fs_twalk(QVirtIO9P *v9p, uint32_t fid, 
uint32_t newfid,
 for (i = 0; i < nwname; i++) {
 size += v9fs_string_size(wnames[i]);
 }
-req = v9fs_req_init(v9p,  size, P9_TWALK, ++(v9p->p9_req_tag));
+req = v9fs_req_init(v9p,  size, P9_TWALK, tag);
 v9fs_uint32_write(req, fid);
 v9fs_uint32_write(req, newfid);
 v9fs_uint16_write(req, nwname);
@@ -397,7 +397,7 @@ static void fs_version(QVirtIO9P *v9p)
 char *server_version;
 P9Req *req;
 
-req = v9fs_tversion(v9p, P9_MAX_SIZE, version);
+req = v9fs_tversion(v9p, P9_MAX_SIZE, version, P9_NOTAG);
 v9fs_rversion(req, _len, _version);
 
 g_assert_cmpmem(server_version, server_len, version, strlen(version));
@@ -410,7 +410,7 @@ static void fs_attach(QVirtIO9P *v9p)
 P9Req *req;
 
 fs_version(v9p);
-req = v9fs_tattach(v9p, 0, getuid());
+req = v9fs_tattach(v9p, 0, getuid(), 0);
 v9fs_rattach(req, NULL);
 }
 
@@ -430,7 +430,7 @@ static void fs_walk(QVirtIO9P *v9p)
 }
 
 fs_attach(v9p);
-req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames);
+req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames, 0);
 v9fs_rwalk(req, , );
 
 g_assert_cmpint(nwqid, ==, P9_MAXWELEM);
@@ -451,7 +451,7 @@ static void fs_walk_no_slash(QVirtIO9P *v9p)
 uint32_t err;
 
 fs_attach(v9p);
-req = v9fs_twalk(v9p, 0, 1, 1, wnames);
+req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
 v9fs_rlerror(req, );
 
 g_assert_cmpint(err, ==, ENOENT);
@@ -466,10 +466,10 @@ static void fs_walk_dotdot(QVirtIO9P *v9p)
 P9Req *req;
 
 fs_version(v9p);
-req = v9fs_tattach(v9p, 0, getuid());
+req = v9fs_tattach(v9p, 0, getuid(), 0);
 v9fs_rattach(req, _qid);
 
-req = v9fs_twalk(v9p, 0, 1, 1, wnames);
+req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
 v9fs_rwalk(req, NULL, ); /* We now we'll get one qid */
 
 g_assert_cmpmem(_qid, 13, wqid[0], 13);




[Qemu-devel] [PATCH 3/7] tests: virtio-9p: use the synth backend

2018-01-23 Thread Greg Kurz
The purpose of virtio-9p-test is to test the virtio-9p device, especially
the 9p server state machine. We don't really care what fsdev backend we're
using. Moreover, if we want to be able to test the flush request or a
device reset with in-flights I/O, it is close to impossible to achieve
with a physical backend because we cannot ask it reliably to put an I/O
on hold at a specific point in time.

Fortunately, we can do that with the synthetic backend, which allows to
register callbacks on read/write accesses to a specific file. This will
be used by a later patch to test the 9P flush request.

The walk request test is converted to using the synth backend.

Signed-off-by: Greg Kurz 
---
 hw/9pfs/9p-synth.c |   16 
 hw/9pfs/9p-synth.h |4 
 tests/virtio-9p-test.c |   22 ++
 3 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 8f255e91c00f..dcbd320da17a 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -19,6 +19,7 @@
 #include "qemu/rcu.h"
 #include "qemu/rcu_queue.h"
 #include "qemu/cutils.h"
+#include "sysemu/qtest.h"
 
 /* Root node for synth file system */
 static V9fsSynthNode synth_root = {
@@ -527,6 +528,21 @@ static int synth_init(FsContext *ctx, Error **errp)
 
 /* Mark the subsystem is ready for use */
 synth_fs = 1;
+
+if (qtest_enabled()) {
+V9fsSynthNode *node = NULL;
+int i, ret;
+
+/* Directory hierarchy for WALK test */
+for (i = 0; i < P9_MAXWELEM; i++) {
+char *name = g_strdup_printf(QTEST_V9FS_SYNTH_WALK_FILE, i);
+
+ret = qemu_v9fs_synth_mkdir(node, 0700, name, );
+assert(!ret);
+g_free(name);
+}
+}
+
 return 0;
 }
 
diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h
index 49c2fc7b274e..876b4ef58288 100644
--- a/hw/9pfs/9p-synth.h
+++ b/hw/9pfs/9p-synth.h
@@ -49,4 +49,8 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
  const char *name, v9fs_synth_read read,
  v9fs_synth_write write, void *arg);
 
+/* qtest stuff */
+
+#define QTEST_V9FS_SYNTH_WALK_FILE "WALK%d"
+
 #endif
diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index cb086315a36e..652198156731 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -17,6 +17,7 @@
 #include "standard-headers/linux/virtio_ids.h"
 #include "standard-headers/linux/virtio_pci.h"
 #include "hw/9pfs/9p.h"
+#include "hw/9pfs/9p-synth.h"
 
 #define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000)
 
@@ -26,23 +27,19 @@ typedef struct {
 QVirtioDevice *dev;
 QOSState *qs;
 QVirtQueue *vq;
-char *test_share;
 } QVirtIO9P;
 
 static QVirtIO9P *qvirtio_9p_start(const char *driver)
 {
 const char *arch = qtest_get_arch();
-const char *cmd = "-fsdev local,id=fsdev0,security_model=none,path=%s "
+const char *cmd = "-fsdev synth,id=fsdev0 "
   "-device %s,fsdev=fsdev0,mount_tag=%s";
 QVirtIO9P *v9p = g_new0(QVirtIO9P, 1);
 
-v9p->test_share = g_strdup("/tmp/qtest.XX");
-g_assert_nonnull(mkdtemp(v9p->test_share));
-
 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
-v9p->qs = qtest_pc_boot(cmd, v9p->test_share, driver, mount_tag);
+v9p->qs = qtest_pc_boot(cmd, driver, mount_tag);
 } else if (strcmp(arch, "ppc64") == 0) {
-v9p->qs = qtest_spapr_boot(cmd, v9p->test_share, driver, mount_tag);
+v9p->qs = qtest_spapr_boot(cmd, driver, mount_tag);
 } else {
 g_printerr("virtio-9p tests are only available on x86 or ppc64\n");
 exit(EXIT_FAILURE);
@@ -54,8 +51,6 @@ static QVirtIO9P *qvirtio_9p_start(const char *driver)
 static void qvirtio_9p_stop(QVirtIO9P *v9p)
 {
 qtest_shutdown(v9p->qs);
-rmdir(v9p->test_share);
-g_free(v9p->test_share);
 g_free(v9p);
 }
 
@@ -422,17 +417,14 @@ static void fs_attach(QVirtIO9P *v9p)
 
 static void fs_walk(QVirtIO9P *v9p)
 {
-char *wnames[P9_MAXWELEM], *paths[P9_MAXWELEM];
-char *last_path = v9p->test_share;
+char *wnames[P9_MAXWELEM];
 uint16_t nwqid;
 v9fs_qid *wqid;
 int i;
 P9Req *req;
 
 for (i = 0; i < P9_MAXWELEM; i++) {
-wnames[i] = g_strdup_printf("%s%d", __func__, i);
-last_path = paths[i] = g_strdup_printf("%s/%s", last_path, wnames[i]);
-g_assert(!mkdir(paths[i], 0700));
+wnames[i] = g_strdup_printf(QTEST_V9FS_SYNTH_WALK_FILE, i);
 }
 
 fs_attach(v9p);
@@ -443,8 +435,6 @@ static void fs_walk(QVirtIO9P *v9p)
 g_assert_cmpint(nwqid, ==, P9_MAXWELEM);
 
 for (i = 0; i < P9_MAXWELEM; i++) {
-rmdir(paths[P9_MAXWELEM - i - 1]);
-g_free(paths[P9_MAXWELEM - i - 1]);
 g_free(wnames[i]);
 }
 




[Qemu-devel] [PATCH 2/7] tests: virtio-9p: wait for completion in the test code

2018-01-23 Thread Greg Kurz
In order to test request cancellation, we will need to send multiple
requests and wait for the associated replies. Since we poll the ISR
to know if a request completed, we may have several replies to parse
when we detect ISR was set to 1.

This patch moves the waiting out of the reply parsing path, up into
the functional tests.

Signed-off-by: Greg Kurz 
---
 tests/virtio-9p-test.c |   14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c
index 5ada2839b9ae..cb086315a36e 100644
--- a/tests/virtio-9p-test.c
+++ b/tests/virtio-9p-test.c
@@ -246,13 +246,17 @@ static const char *rmessage_name(uint8_t id)
 "";
 }
 
-static void v9fs_req_recv(P9Req *req, uint8_t id)
+static void v9fs_req_wait_for_reply(P9Req *req)
 {
 QVirtIO9P *v9p = req->v9p;
-P9Hdr hdr;
 
 qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head,
QVIRTIO_9P_TIMEOUT_US);
+}
+
+static void v9fs_req_recv(P9Req *req, uint8_t id)
+{
+P9Hdr hdr;
 
 v9fs_memread(req, , 7);
 hdr.size = ldl_le_p();
@@ -398,6 +402,7 @@ static void fs_version(QVirtIO9P *v9p)
 P9Req *req;
 
 req = v9fs_tversion(v9p, P9_MAX_SIZE, version, P9_NOTAG);
+v9fs_req_wait_for_reply(req);
 v9fs_rversion(req, _len, _version);
 
 g_assert_cmpmem(server_version, server_len, version, strlen(version));
@@ -411,6 +416,7 @@ static void fs_attach(QVirtIO9P *v9p)
 
 fs_version(v9p);
 req = v9fs_tattach(v9p, 0, getuid(), 0);
+v9fs_req_wait_for_reply(req);
 v9fs_rattach(req, NULL);
 }
 
@@ -431,6 +437,7 @@ static void fs_walk(QVirtIO9P *v9p)
 
 fs_attach(v9p);
 req = v9fs_twalk(v9p, 0, 1, P9_MAXWELEM, wnames, 0);
+v9fs_req_wait_for_reply(req);
 v9fs_rwalk(req, , );
 
 g_assert_cmpint(nwqid, ==, P9_MAXWELEM);
@@ -452,6 +459,7 @@ static void fs_walk_no_slash(QVirtIO9P *v9p)
 
 fs_attach(v9p);
 req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+v9fs_req_wait_for_reply(req);
 v9fs_rlerror(req, );
 
 g_assert_cmpint(err, ==, ENOENT);
@@ -467,9 +475,11 @@ static void fs_walk_dotdot(QVirtIO9P *v9p)
 
 fs_version(v9p);
 req = v9fs_tattach(v9p, 0, getuid(), 0);
+v9fs_req_wait_for_reply(req);
 v9fs_rattach(req, _qid);
 
 req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0);
+v9fs_req_wait_for_reply(req);
 v9fs_rwalk(req, NULL, ); /* We now we'll get one qid */
 
 g_assert_cmpmem(_qid, 13, wqid[0], 13);




[Qemu-devel] [PATCH 0/7] tests: virtio-9p: test request cancellation

2018-01-23 Thread Greg Kurz
This series does several changes to virtio-9p-test in order to be able
to test request cancellation (flush in 9p wording):

patches 1-2: preparatory work, basically doing things in the test code,
 rather that in the common code for flexibility and clarity

patch 3: the cornerstone of the series, switch to using the synth fsdev
 backend, which allows to associate specific write/read ops to
 a given file. Since this backend never got used since it was
 merged, it looks like an ideal vehicle to add QTEST aware code
 in QEMU

patches 4-5: trivial open & write tests, since the flush test will need
 to open a file and write to it

patch 6: another important patch that allows to know the length written
 by the guest into a used buffer 

patch 7: the goal of this series, two request cancellation tests

This series depends on the following patch:

https://lists.nongnu.org/archive/html/qemu-devel/2018-01/msg05604.html

Please comment.

Cheers,

--
Greg

---

Greg Kurz (7):
  tests: virtio-9p: move request tag to the test functions
  tests: virtio-9p: wait for completion in the test code
  tests: virtio-9p: use the synth backend
  tests: virtio-9p: add LOPEN operation test
  tests: virtio-9p: add WRITE operation test
  libqos/virtio: return length written into used descriptor
  tests: virtio-9p: add FLUSH operation test


 hw/9pfs/9p-synth.c   |   56 ++
 hw/9pfs/9p-synth.h   |   11 ++
 hw/9pfs/9p.c |1 
 tests/libqos/virtio.c|   25 +++-
 tests/libqos/virtio.h|3 -
 tests/virtio-9p-test.c   |  263 --
 tests/virtio-blk-test.c  |   24 ++--
 tests/virtio-net-test.c  |6 +
 tests/virtio-scsi-test.c |3 -
 9 files changed, 335 insertions(+), 57 deletions(-)




Re: [Qemu-devel] [PATCH v1 06/21] RISC-V FPU Support

2018-01-23 Thread Michael Clark
On Tue, Jan 23, 2018 at 3:15 PM, Michael Clark  wrote:

>
>
> On Wed, Jan 3, 2018 at 12:10 PM, Richard Henderson <
> richard.hender...@linaro.org> wrote:
>
>> On 01/02/2018 04:44 PM, Michael Clark wrote:
>> > +/* convert RISC-V rounding mode to IEEE library numbers */
>> > +unsigned int ieee_rm[] = {
>>
>> static const.
>>
>> > +/* obtain rm value to use in computation
>> > + * as the last step, convert rm codes to what the softfloat library
>> expects
>> > + * Adapted from Spike's decode.h:RM
>> > + */
>> > +#define RM ({ \
>> > +if (rm == 7) {\
>> > +rm = env->frm;   \
>> > +} \
>> > +if (rm > 4) { \
>> > +helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
>> > +} \
>> > +ieee_rm[rm]; })
>>
>> Please use inline functions and not these macros.
>>
>> Probably this applies to some of the helpers that I've already reviewed,
>> but
>> you're going to need to use an exception raising function that also
>> performs an
>> unwind (usually via cpu_loop_exit_restore).  The GETPC() that feeds the
>> unwind
>> must be placed in the outer-most helper (including inlines).
>>
>> > +#ifndef CONFIG_USER_ONLY
>> > +#define require_fp if (!(env->mstatus & MSTATUS_FS)) { \
>> > +helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
>> > +}
>>
>> If you included MSTATUS_FS in cpu_get_tb_cpu_state flags, then you could
>> be
>> checking for this at translation time instead of at run time.
>>
>> > +/* convert softfloat library flag numbers to RISC-V */
>> > +unsigned int softfloat_flags_to_riscv(unsigned int flags)
>> > +{
>> > +int rv_flags = 0;
>> > +rv_flags |= (flags & float_flag_inexact) ? 1 : 0;
>> > +rv_flags |= (flags & float_flag_underflow) ? 2 : 0;
>> > +rv_flags |= (flags & float_flag_overflow) ? 4 : 0;
>> > +rv_flags |= (flags & float_flag_divbyzero) ? 8 : 0;
>> > +rv_flags |= (flags & float_flag_invalid) ? 16 : 0;
>>
>> FPEXC_NX et al.
>>
>> > +/* adapted from Spike's decode.h:set_fp_exceptions */
>> > +#define set_fp_exceptions() do { \
>> > +env->fflags |= softfloat_flags_to_riscv(get_f
>> loat_exception_flags(\
>> > +>fp_status)); \
>> > +set_float_exception_flags(0, >fp_status); \
>> > +} while (0)
>>
>> inline function.  Usually written as
>>
>>   int flags = get_float_exception_flags(>fp_status);
>>   if (flags) {
>> set_float_exception_flags(0, >fp_status);
>> env->fflags |= softfloat_flags_to_riscv(flags);
>>   }
>>
>> since we really do expect exceptions to be exceptional.
>>
>> > +uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t
>> frs2,
>> > +uint64_t frs3, uint64_t rm)
>> > +{
>> > +require_fp;
>> > +set_float_rounding_mode(RM, >fp_status);
>> > +frs1 = float32_muladd(frs1, frs2, frs3 ^ (uint32_t)INT32_MIN, 0,
>> > +  >fp_status);
>>
>> Given that RISC-V always returns a default NaN, you obviously do not care
>> about
>> the sign of a NaN result.  Therefore you should use float_muladd_negate_c
>> as
>> the fourth argument here and not perform the sign flip manually.
>
>
> We do care about the sign of NaN results.
>
> Jim Wilson spotted this bug and removed a call to set_default_nan_mode
>
> https://github.com/riscv/riscv-qemu/commit/4223d89b0c5c671332d66bcd649db5
> c6f46559f5
>
>
>> > +uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t
>> frs2,
>> > + uint64_t frs3, uint64_t rm)
>> > +{
>> > +require_fp;
>> > +set_float_rounding_mode(RM, >fp_status);
>> > +frs1 = float32_muladd(frs1 ^ (uint32_t)INT32_MIN, frs2, frs3, 0,
>> > +  >fp_status);
>>
>> float_muladd_negate_product.
>>
>> > +uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t
>> frs2,
>> > + uint64_t frs3, uint64_t rm)
>> > +{
>> > +require_fp;
>> > +set_float_rounding_mode(RM, >fp_status);
>> > +frs1 = float32_muladd(frs1 ^ (uint32_t)INT32_MIN, frs2,
>> > +  frs3 ^ (uint32_t)INT32_MIN, 0,
>> >fp_status);
>>
>> float_muladd_negate_c | float_muladd_negate_product
>>
>> > +uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t
>> frs2)
>> > +{
>> > +require_fp;
>> > +frs1 = float32_minnum(frs1, frs2, >fp_status);
>>
>> If you want minnum and not min, riscv-spec-v2.2.pdf could use some more
>> verbage
>> to specify that.
>
>
> We'll look at Spike (riscv-isa-sim)... Spike has the correct behavior.
>

We want minimum number (minnum). It's been added to the draft spec and will
be in riscv-spec-v2.3.pdf

Section 8.6 in the draft spec says:

"
Floating-point minimum-number and maximum-number instructions FMIN.S and
FMAX.S write, 

Re: [Qemu-devel] [PATCH v1 06/21] RISC-V FPU Support

2018-01-23 Thread Michael Clark
On Wed, Jan 3, 2018 at 12:10 PM, Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 01/02/2018 04:44 PM, Michael Clark wrote:
> > +/* convert RISC-V rounding mode to IEEE library numbers */
> > +unsigned int ieee_rm[] = {
>
> static const.
>
> > +/* obtain rm value to use in computation
> > + * as the last step, convert rm codes to what the softfloat library
> expects
> > + * Adapted from Spike's decode.h:RM
> > + */
> > +#define RM ({ \
> > +if (rm == 7) {\
> > +rm = env->frm;   \
> > +} \
> > +if (rm > 4) { \
> > +helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
> > +} \
> > +ieee_rm[rm]; })
>
> Please use inline functions and not these macros.
>
> Probably this applies to some of the helpers that I've already reviewed,
> but
> you're going to need to use an exception raising function that also
> performs an
> unwind (usually via cpu_loop_exit_restore).  The GETPC() that feeds the
> unwind
> must be placed in the outer-most helper (including inlines).
>
> > +#ifndef CONFIG_USER_ONLY
> > +#define require_fp if (!(env->mstatus & MSTATUS_FS)) { \
> > +helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
> > +}
>
> If you included MSTATUS_FS in cpu_get_tb_cpu_state flags, then you could be
> checking for this at translation time instead of at run time.
>
> > +/* convert softfloat library flag numbers to RISC-V */
> > +unsigned int softfloat_flags_to_riscv(unsigned int flags)
> > +{
> > +int rv_flags = 0;
> > +rv_flags |= (flags & float_flag_inexact) ? 1 : 0;
> > +rv_flags |= (flags & float_flag_underflow) ? 2 : 0;
> > +rv_flags |= (flags & float_flag_overflow) ? 4 : 0;
> > +rv_flags |= (flags & float_flag_divbyzero) ? 8 : 0;
> > +rv_flags |= (flags & float_flag_invalid) ? 16 : 0;
>
> FPEXC_NX et al.
>
> > +/* adapted from Spike's decode.h:set_fp_exceptions */
> > +#define set_fp_exceptions() do { \
> > +env->fflags |= softfloat_flags_to_riscv(get_float_exception_flags(\
> > +>fp_status)); \
> > +set_float_exception_flags(0, >fp_status); \
> > +} while (0)
>
> inline function.  Usually written as
>
>   int flags = get_float_exception_flags(>fp_status);
>   if (flags) {
> set_float_exception_flags(0, >fp_status);
> env->fflags |= softfloat_flags_to_riscv(flags);
>   }
>
> since we really do expect exceptions to be exceptional.
>
> > +uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t
> frs2,
> > +uint64_t frs3, uint64_t rm)
> > +{
> > +require_fp;
> > +set_float_rounding_mode(RM, >fp_status);
> > +frs1 = float32_muladd(frs1, frs2, frs3 ^ (uint32_t)INT32_MIN, 0,
> > +  >fp_status);
>
> Given that RISC-V always returns a default NaN, you obviously do not care
> about
> the sign of a NaN result.  Therefore you should use float_muladd_negate_c
> as
> the fourth argument here and not perform the sign flip manually.


We do care about the sign of NaN results.

Jim Wilson spotted this bug and removed a call to set_default_nan_mode

https://github.com/riscv/riscv-qemu/commit/4223d89b0c5c671332d66bcd649db5c6f46559f5


> > +uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t
> frs2,
> > + uint64_t frs3, uint64_t rm)
> > +{
> > +require_fp;
> > +set_float_rounding_mode(RM, >fp_status);
> > +frs1 = float32_muladd(frs1 ^ (uint32_t)INT32_MIN, frs2, frs3, 0,
> > +  >fp_status);
>
> float_muladd_negate_product.
>
> > +uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t
> frs2,
> > + uint64_t frs3, uint64_t rm)
> > +{
> > +require_fp;
> > +set_float_rounding_mode(RM, >fp_status);
> > +frs1 = float32_muladd(frs1 ^ (uint32_t)INT32_MIN, frs2,
> > +  frs3 ^ (uint32_t)INT32_MIN, 0,
> >fp_status);
>
> float_muladd_negate_c | float_muladd_negate_product
>
> > +uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
> > +{
> > +require_fp;
> > +frs1 = float32_minnum(frs1, frs2, >fp_status);
>
> If you want minnum and not min, riscv-spec-v2.2.pdf could use some more
> verbage
> to specify that.


We'll look at Spike (riscv-isa-sim)... Spike has the correct behavior.


> > +/* adapted from spike */
> > +#define isNaNF32UI(ui) (0xFF00 < (uint32_t)((uint_fast32_t)ui << 1))
>
> float32_is_any_nan
>
> > +#define signF32UI(a) ((bool)((uint32_t)a >> 31))
>
> float32_is_neg
>
> > +#define expF32UI(a) ((int_fast16_t)(a >> 23) & 0xFF)
> > +#define fracF32UI(a) (a & 0x007F)
>
> Either float32_is_infinity or float32_is_zero_or_denormal.
>
> > +union ui32_f32 { uint32_t ui; uint32_t f; };
>
> This is just silly.
>
> > 

Re: [Qemu-devel] [PATCH] pl110: Implement vertical compare/next base interrupts

2018-01-23 Thread no-reply
Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20180123225654.5764-1-linus.wall...@linaro.org
Subject: [Qemu-devel] [PATCH] pl110: Implement vertical compare/next base 
interrupts

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]   
patchew/20180123225654.5764-1-linus.wall...@linaro.org -> 
patchew/20180123225654.5764-1-linus.wall...@linaro.org
Switched to a new branch 'test'
2512b151b6 pl110: Implement vertical compare/next base interrupts

=== OUTPUT BEGIN ===
Checking PATCH 1/1: pl110: Implement vertical compare/next base interrupts...
WARNING: line over 80 characters
#76: FILE: hw/display/pl110.c:342:
+  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / 
60);

ERROR: line over 90 characters
#86: FILE: hw/display/pl110.c:453:
+  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 
NANOSECONDS_PER_SECOND / 60);

WARNING: line over 80 characters
#96: FILE: hw/display/pl110.c:501:
+s->vblank_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pl110_vblank_interrupt, 
s);

total: 1 errors, 2 warnings, 63 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-de...@freelists.org

[Qemu-devel] [PATCH] pl110: Implement vertical compare/next base interrupts

2018-01-23 Thread Linus Walleij
This implements rudimentary support for interrupt generation on the
PL110. I am working on a new DRI/KMS driver for Linux and since that
uses the blanking interrupt, we need something to fire here. Without
any interrupt support Linux waits for a while and then gives ugly
messages about the vblank not working in the console (it does not
hang perpetually or anything though, DRI is pretty forgiving).

I solved it for now by setting up a timer to fire at 60Hz and pull
the interrupts for "vertical compare" and "next memory base"
at this interval. This works fine and fires roughly the same number
of IRQs on QEMU as on the hardware and leaves the console clean
and nice.

People who want to create more accurate emulation can probably work
on top of this if need be. It is certainly closer to the hardware
behaviour than what we have today anyway.

Cc: Peter Maydell 
Signed-off-by: Linus Walleij 
---
 hw/display/pl110.c | 27 ++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/hw/display/pl110.c b/hw/display/pl110.c
index 8c7dcc6f0a69..777bb3f44503 100644
--- a/hw/display/pl110.c
+++ b/hw/display/pl110.c
@@ -12,6 +12,7 @@
 #include "ui/console.h"
 #include "framebuffer.h"
 #include "ui/pixel_ops.h"
+#include "qemu/timer.h"
 #include "qemu/log.h"
 
 #define PL110_CR_EN   0x001
@@ -19,6 +20,8 @@
 #define PL110_CR_BEBO 0x200
 #define PL110_CR_BEPO 0x400
 #define PL110_CR_PWR  0x800
+#define PL110_IE_NB   0x004
+#define PL110_IE_VC   0x008
 
 enum pl110_bppmode
 {
@@ -50,6 +53,7 @@ typedef struct PL110State {
 MemoryRegion iomem;
 MemoryRegionSection fbsection;
 QemuConsole *con;
+QEMUTimer *vblank_timer;
 
 int version;
 uint32_t timing[4];
@@ -320,7 +324,23 @@ static void pl110_resize(PL110State *s, int width, int 
height)
 /* Update interrupts.  */
 static void pl110_update(PL110State *s)
 {
-  /* TODO: Implement interrupts.  */
+/* Raise IRQ if enabled and any status bit is 1 */
+if (s->int_status & s->int_mask) {
+qemu_irq_raise(s->irq);
+} else {
+qemu_irq_lower(s->irq);
+}
+}
+
+static void pl110_vblank_interrupt(void *opaque)
+{
+PL110State *s = opaque;
+
+/* Fire the vertical compare and next base IRQs and re-arm */
+s->int_status |= (PL110_IE_NB | PL110_IE_VC);
+timer_mod(s->vblank_timer,
+  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / 
60);
+pl110_update(s);
 }
 
 static uint64_t pl110_read(void *opaque, hwaddr offset,
@@ -429,6 +449,10 @@ static void pl110_write(void *opaque, hwaddr offset,
 s->bpp = (val >> 1) & 7;
 if (pl110_enabled(s)) {
 qemu_console_resize(s->con, s->cols, s->rows);
+timer_mod(s->vblank_timer,
+  qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 
NANOSECONDS_PER_SECOND / 60);
+} else {
+timer_del(s->vblank_timer);
 }
 break;
 case 10: /* LCDICR */
@@ -474,6 +498,7 @@ static void pl110_realize(DeviceState *dev, Error **errp)
 memory_region_init_io(>iomem, OBJECT(s), _ops, s, "pl110", 
0x1000);
 sysbus_init_mmio(sbd, >iomem);
 sysbus_init_irq(sbd, >irq);
+s->vblank_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pl110_vblank_interrupt, 
s);
 qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1);
 s->con = graphic_console_init(dev, 0, _gfx_ops, s);
 }
-- 
2.14.3




Re: [Qemu-devel] [PATCH v3 12/12] sdcard: use the registerfields API to access the OCR register

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:21 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/sd/sd.h |  1 -
>  hw/sd/sd.c | 21 +
>  2 files changed, 13 insertions(+), 9 deletions(-)
>
> diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
> index bf1eb0713c..9bdb3c9285 100644
> --- a/include/hw/sd/sd.h
> +++ b/include/hw/sd/sd.h
> @@ -53,7 +53,6 @@
>  #define READY_FOR_DATA (1 << 8)
>  #define APP_CMD(1 << 5)
>  #define AKE_SEQ_ERROR  (1 << 3)
> -#define OCR_CCS_BITN30
>
>  typedef enum {
>  SD_VOLTAGE_0_4V = 400,  /* currently not supported */
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index f87e543f8f..437ce25f79 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -32,6 +32,7 @@
>  #include "qemu/osdep.h"
>  #include "hw/qdev.h"
>  #include "hw/hw.h"
> +#include "hw/registerfields.h"
>  #include "sysemu/block-backend.h"
>  #include "hw/sd/sd.h"
>  #include "qapi/error.h"
> @@ -47,8 +48,6 @@
>  //#define DEBUG_SD 1
>
>  #define ACMD41_ENQUIRY_MASK 0x00ff
> -#define OCR_POWER_UP0x8000
> -#define OCR_POWER_DELAY_NS  50 /* 0.5ms */
>
>  typedef enum {
>  sd_r0 = 0,/* no response */
> @@ -270,6 +269,11 @@ static uint16_t sd_crc16(void *message, size_t width)
>  return shift_reg;
>  }
>
> +#define OCR_POWER_DELAY_NS  50 /* 0.5ms */
> +
> +FIELD(OCR, CARD_CAPACITY,  30,  1) /* 0:SDSC, 1:SDHC/SDXC */
> +FIELD(OCR, CARD_POWER_UP,  31,  1)
> +
>  static void sd_reset_ocr(SDState *sd)
>  {
>  /* All voltages OK, Standard Capacity SD Memory Card, not yet powered up 
> */
> @@ -281,9 +285,10 @@ static void sd_ocr_powerup(void *opaque)
>  SDState *sd = opaque;
>
>  trace_sdcard_powerup();
> -/* Set powered up bit in OCR */
> -assert(!(sd->ocr & OCR_POWER_UP));
> -sd->ocr |= OCR_POWER_UP;
> +assert(!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP));
> +
> +/* card power-up OK */
> +sd->ocr = FIELD_DP32(sd->ocr, OCR, CARD_POWER_UP, 1);
>  }
>
>  static void sd_reset_scr(SDState *sd)
> @@ -574,7 +579,7 @@ static bool sd_ocr_vmstate_needed(void *opaque)
>  SDState *sd = opaque;
>
>  /* Include the OCR state (and timer) if it is not yet powered up */
> -return !(sd->ocr & OCR_POWER_UP);
> +return !FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP);
>  }
>
>  static const VMStateDescription sd_ocr_vmstate = {
> @@ -684,7 +689,7 @@ static void sd_erase(SDState *sd)
>  return;
>  }
>
> -if (extract32(sd->ocr, OCR_CCS_BITN, 1)) {
> +if (FIELD_EX32(sd->ocr, OCR, CARD_CAPACITY)) {
>  /* High capacity memory card: erase units are 512 byte blocks */
>  erase_start *= 512;
>  erase_end *= 512;
> @@ -1476,7 +1481,7 @@ static sd_rsp_type_t sd_app_command(SDState *sd,
>   * UEFI, which sends an initial enquiry ACMD41, but
>   * assumes that the card is in ready state as soon as it
>   * sees the power up bit set. */
> -if (!(sd->ocr & OCR_POWER_UP)) {
> +if (!FIELD_EX32(sd->ocr, OCR, CARD_POWER_UP)) {
>  if ((req.arg & ACMD41_ENQUIRY_MASK) != 0) {
>  timer_del(sd->ocr_power_timer);
>  sd_ocr_powerup(sd);
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v3 06/12] sdcard: do not trace CMD55 when expecting ACMD

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:21 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Acked-by: Alistair Francis 

Alistair

> ---
>  hw/sd/sd.c | 8 +---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index dc4b2329e4..27c08aa894 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -816,13 +816,15 @@ static void sd_lock_command(SDState *sd)
>  sd->card_status &= ~CARD_IS_LOCKED;
>  }
>
> -static sd_rsp_type_t sd_normal_command(SDState *sd,
> -   SDRequest req)
> +static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req)
>  {
>  uint32_t rca = 0x;
>  uint64_t addr = (sd->ocr & (1 << 30)) ? (uint64_t) req.arg << 9 : 
> req.arg;
>
> -trace_sdcard_normal_command(req.cmd, req.arg, sd_state_name(sd->state));
> +if (req.cmd != 55 || sd->expecting_acmd) {
> +trace_sdcard_normal_command(req.cmd, req.arg,
> +sd_state_name(sd->state));
> +}
>
>  /* Not interpreting this as an app command */
>  sd->card_status &= ~APP_CMD;
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v3 04/12] sdcard: replace fprintf() by qemu_hexdump()

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:21 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/sd/sd.c | 15 +--
>  1 file changed, 1 insertion(+), 14 deletions(-)
>
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index 3590099ce8..03263e08ae 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -44,13 +44,6 @@
>
>  //#define DEBUG_SD 1
>
> -#ifdef DEBUG_SD
> -#define DPRINTF(fmt, ...) \
> -do { fprintf(stderr, "SD: " fmt , ## __VA_ARGS__); } while (0)
> -#else
> -#define DPRINTF(fmt, ...) do {} while(0)
> -#endif
> -
>  #define ACMD41_ENQUIRY_MASK 0x00ff
>  #define OCR_POWER_UP0x8000
>  #define OCR_POWER_DELAY_NS  50 /* 0.5ms */
> @@ -1630,13 +1623,7 @@ send_response:
>  }
>
>  #ifdef DEBUG_SD
> -if (rsplen) {
> -int i;
> -DPRINTF("Response:");
> -for (i = 0; i < rsplen; i++)
> -fprintf(stderr, " %02x", response[i]);
> -fputc('\n', stderr);
> -}
> +qemu_hexdump((const char *)response, stderr, "Response", rsplen);
>  #endif
>
>  return rsplen;
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v8 10/14] hw/arm/xilinx_zynqmp: fix the capabilities/spec version to match the datasheet

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> checking Xilinx datasheet "UG1085" (v1.7)
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/arm/xlnx-zynqmp.c | 29 ++---
>  1 file changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
> index 325642058b..33d5fe53d8 100644
> --- a/hw/arm/xlnx-zynqmp.c
> +++ b/hw/arm/xlnx-zynqmp.c
> @@ -50,6 +50,8 @@
>  #define DPDMA_ADDR  0xfd4c
>  #define DPDMA_IRQ   116
>
> +#define SDHCI_CAPABILITIES  0x280737ec6481 /* Datasheet: UG1085 (v1.7) */
> +
>  static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
>  0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E,
>  };
> @@ -381,22 +383,27 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
> **errp)
>  sysbus_connect_irq(SYS_BUS_DEVICE(>sata), 0, gic_spi[SATA_INTR]);
>
>  for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
> -char *bus_name;
> -
> -object_property_set_bool(OBJECT(>sdhci[i]), true,
> - "realized", );
> +char *bus_name = g_strdup_printf("sd-bus%d", i);
> +SysBusDevice *sbd = SYS_BUS_DEVICE(>sdhci[i]);
> +Object *sdhci = OBJECT(>sdhci[i]);
> +
> +/* Compatible with:
> + * - SD Host Controller Specification Version 3.00
> + * - SDIO Specification Version 3.0
> + * - eMMC Specification Version 4.51
> + */
> +object_property_set_uint(sdhci, 3, "sd-spec-version", );
> +object_property_set_uint(sdhci, SDHCI_CAPABILITIES, "capareg", );
> +object_property_set_bool(sdhci, true, "realized", );
>  if (err) {
>  error_propagate(errp, err);
>  return;
>  }
> -sysbus_mmio_map(SYS_BUS_DEVICE(>sdhci[i]), 0,
> -sdhci_addr[i]);
> -sysbus_connect_irq(SYS_BUS_DEVICE(>sdhci[i]), 0,
> -   gic_spi[sdhci_intr[i]]);
> +sysbus_mmio_map(sbd, 0, sdhci_addr[i]);
> +sysbus_connect_irq(sbd, 0, gic_spi[sdhci_intr[i]]);
> +
>  /* Alias controller SD bus to the SoC itself */
> -bus_name = g_strdup_printf("sd-bus%d", i);
> -object_property_add_alias(OBJECT(s), bus_name,
> -  OBJECT(>sdhci[i]), "sd-bus",
> +object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus",
>_abort);
>  g_free(bus_name);
>  }
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v8 09/14] hw/arm/fsl-imx6: implement SDHCI Spec. v3

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Acked-by: Alistair Francis 

Alistair

> ---
> various FreeBSD console output from google search show this register having
> a value of 0x0377c800.
>
>  hw/arm/fsl-imx6.c | 7 +++
>  1 file changed, 7 insertions(+)
>
> diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
> index b0d4088290..1f4607f206 100644
> --- a/hw/arm/fsl-imx6.c
> +++ b/hw/arm/fsl-imx6.c
> @@ -27,6 +27,8 @@
>  #include "chardev/char.h"
>  #include "qemu/error-report.h"
>
> +#define IMX6_ESDHC_CAPABILITIES 0x057834b4
> +
>  #define NAME_SIZE 20
>
>  static void fsl_imx6_init(Object *obj)
> @@ -348,6 +350,11 @@ static void fsl_imx6_realize(DeviceState *dev, Error 
> **errp)
>  { FSL_IMX6_uSDHC4_ADDR, FSL_IMX6_uSDHC4_IRQ },
>  };
>
> +/* UHS-I SDIO3.0 SDR104 1.8V ADMA */
> +object_property_set_uint(OBJECT(>esdhc[i]), 3, "sd-spec-version",
> + );
> +object_property_set_uint(OBJECT(>esdhc[i]), 
> IMX6_ESDHC_CAPABILITIES,
> + "capareg", );
>  object_property_set_bool(OBJECT(>esdhc[i]), true, "realized", 
> );
>  if (err) {
>  error_propagate(errp, err);
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v8 11/14] hw/arm/xilinx_zynqmp: enable the UHS-I mode

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> see the Xilinx datasheet "UG1085" (v1.7)
>
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/arm/xlnx-zynqmp.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
> index 33d5fe53d8..bb4265a4ce 100644
> --- a/hw/arm/xlnx-zynqmp.c
> +++ b/hw/arm/xlnx-zynqmp.c
> @@ -394,6 +394,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
> **errp)
>   */
>  object_property_set_uint(sdhci, 3, "sd-spec-version", );
>  object_property_set_uint(sdhci, SDHCI_CAPABILITIES, "capareg", );
> +object_property_set_uint(sdhci, UHS_I, "uhs", );
>  object_property_set_bool(sdhci, true, "realized", );
>  if (err) {
>  error_propagate(errp, err);
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v8 06/14] sdhci: implement CMD/DAT[] fields in the Present State register

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> [based on a patch from Alistair Francis 
>  from qemu/xilinx tag xilinx-v2015.2]
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/sd/sdhci-internal.h |  2 ++
>  include/hw/sd/sd.h |  4 
>  hw/sd/core.c   | 34 ++
>  hw/sd/sd.c | 16 
>  hw/sd/sdhci.c  |  4 
>  hw/sd/trace-events |  2 ++
>  6 files changed, 62 insertions(+)
>
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index e7cbea297f..514ecd4841 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -82,6 +82,8 @@
>  #define SDHC_CARD_PRESENT  0x0001
>  #define SDHC_CARD_DETECT   0x0004
>  #define SDHC_WRITE_PROTECT 0x0008
> +FIELD(SDHC_PRNSTS, DAT_LVL,20, 4);
> +FIELD(SDHC_PRNSTS, CMD_LVL,24, 1);
>  #define TRANSFERRING_DATA(x)   \
>  ((x) & (SDHC_DOING_READ | SDHC_DOING_WRITE))
>
> diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
> index f086679493..bf1eb0713c 100644
> --- a/include/hw/sd/sd.h
> +++ b/include/hw/sd/sd.h
> @@ -103,6 +103,8 @@ typedef struct {
>  uint8_t (*read_data)(SDState *sd);
>  bool (*data_ready)(SDState *sd);
>  void (*set_voltage)(SDState *sd, uint16_t millivolts);
> +uint8_t (*get_dat_lines)(SDState *sd);
> +bool (*get_cmd_line)(SDState *sd);
>  void (*enable)(SDState *sd, bool enable);
>  bool (*get_inserted)(SDState *sd);
>  bool (*get_readonly)(SDState *sd);
> @@ -150,6 +152,8 @@ void sd_enable(SDState *sd, bool enable);
>   * an SDBus rather than directly with SDState)
>   */
>  void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
> +uint8_t sdbus_get_dat_lines(SDBus *sdbus);
> +bool sdbus_get_cmd_line(SDBus *sdbus);
>  int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
>  void sdbus_write_data(SDBus *sd, uint8_t value);
>  uint8_t sdbus_read_data(SDBus *sd);
> diff --git a/hw/sd/core.c b/hw/sd/core.c
> index 6d198ea775..3c6eae6c88 100644
> --- a/hw/sd/core.c
> +++ b/hw/sd/core.c
> @@ -41,6 +41,40 @@ static SDState *get_card(SDBus *sdbus)
>  return SD_CARD(kid->child);
>  }
>
> +uint8_t sdbus_get_dat_lines(SDBus *sdbus)
> +{
> +SDState *slave = get_card(sdbus);
> +uint8_t dat_lines = 0b; /* 4 bit bus width */
> +
> +if (slave) {
> +SDCardClass *sc = SD_CARD_GET_CLASS(slave);
> +
> +if (sc->get_dat_lines) {
> +dat_lines = sc->get_dat_lines(slave);
> +}
> +}
> +trace_sdbus_get_dat_lines(sdbus_name(sdbus), dat_lines);
> +
> +return dat_lines;
> +}
> +
> +bool sdbus_get_cmd_line(SDBus *sdbus)
> +{
> +SDState *slave = get_card(sdbus);
> +bool cmd_line = true;
> +
> +if (slave) {
> +SDCardClass *sc = SD_CARD_GET_CLASS(slave);
> +
> +if (sc->get_cmd_line) {
> +cmd_line = sc->get_cmd_line(slave);
> +}
> +}
> +trace_sdbus_get_cmd_line(sdbus_name(sdbus), cmd_line);
> +
> +return cmd_line;
> +}
> +
>  void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
>  {
>  SDState *card = get_card(sdbus);
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index 609b2da14f..ab9be561d2 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -126,8 +126,20 @@ struct SDState {
>  BlockBackend *blk;
>
>  bool enable;
> +uint8_t dat_lines;
> +bool cmd_line;
>  };
>
> +static uint8_t sd_get_dat_lines(SDState *sd)
> +{
> +return sd->enable ? sd->dat_lines : 0;
> +}
> +
> +static bool sd_get_cmd_line(SDState *sd)
> +{
> +return sd->enable ? sd->cmd_line : false;
> +}
> +
>  static void sd_set_voltage(SDState *sd, uint16_t millivolts)
>  {
>  switch (millivolts) {
> @@ -457,6 +469,8 @@ static void sd_reset(DeviceState *dev)
>  sd->blk_len = 0x200;
>  sd->pwd_len = 0;
>  sd->expecting_acmd = false;
> +sd->dat_lines = 0xf;
> +sd->cmd_line = true;
>  sd->multi_blk_cnt = 0;
>  }
>
> @@ -1938,6 +1952,8 @@ static void sd_class_init(ObjectClass *klass, void 
> *data)
>  dc->bus_type = TYPE_SD_BUS;
>
>  sc->set_voltage = sd_set_voltage;
> +sc->get_dat_lines = sd_get_dat_lines;
> +sc->get_cmd_line = sd_get_cmd_line;
>  sc->do_command = sd_do_command;
>  sc->write_data = sd_write_data;
>  sc->read_data = sd_read_data;
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index aec6ca4d14..b7fb262750 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -1003,6 +1003,10 @@ static uint64_t sdhci_read(void *opaque, hwaddr 
> offset, unsigned size)
>  break;
>  case SDHC_PRNSTS:
>  ret = s->prnsts;
> +ret = FIELD_DP32(ret, SDHC_PRNSTS, DAT_LVL,
> + sdbus_get_dat_lines(>sdbus));
> +ret = FIELD_DP32(ret, SDHC_PRNSTS, CMD_LVL,
> + 

Re: [Qemu-devel] [PATCH v8 08/14] hw/arm/bcm2835_peripherals: change maximum block size to 1kB

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> following the datasheet.
>
> Signed-off-by: Philippe Mathieu-Daudé 

Acked-by: Alistair Francis 

Alistair

> ---
>  hw/arm/bcm2835_peripherals.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
> index 0570cc4ad3..6b86a99b14 100644
> --- a/hw/arm/bcm2835_peripherals.c
> +++ b/hw/arm/bcm2835_peripherals.c
> @@ -19,7 +19,7 @@
>  #define BCM2835_VC_PERI_BASE 0x7e00
>
>  /* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
> -#define BCM2835_SDHC_CAPAREG 0x52034b4
> +#define BCM2835_SDHC_CAPAREG 0x52134b4
>
>  static void bcm2835_peripherals_init(Object *obj)
>  {
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v8 07/14] hw/arm/bcm2835_peripherals: implement SDHCI Spec. v3

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/arm/bcm2835_peripherals.c | 21 +
>  1 file changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
> index 12e0dd11af..0570cc4ad3 100644
> --- a/hw/arm/bcm2835_peripherals.c
> +++ b/hw/arm/bcm2835_peripherals.c
> @@ -254,14 +254,19 @@ static void bcm2835_peripherals_realize(DeviceState 
> *dev, Error **errp)
>  memory_region_add_subregion(>peri_mr, RNG_OFFSET,
>  sysbus_mmio_get_region(SYS_BUS_DEVICE(>rng), 0));
>
> -/* Extended Mass Media Controller */
> -object_property_set_int(OBJECT(>sdhci), BCM2835_SDHC_CAPAREG, 
> "capareg",
> -);
> -if (err) {
> -error_propagate(errp, err);
> -return;
> -}
> -
> +/* Extended Mass Media Controller
> + *
> + * Compatible with:
> + * - SD Host Controller Specification Version 3.0 Draft 1.0
> + * - SDIO Specification Version 3.0
> + * - MMC Specification Version 4.4
> + *
> + * For the exact details please refer to the Arasan documentation:
> + *   SD3.0_Host_AHB_eMMC4.4_Usersguide_ver5.9_jan11_10.pdf   ¯\_(ăƒ„)_/¯

I don't think we need the shrugging face in the comments.

Otherwise:

Reviewed-by: Alistair Francis 

Alistair


> + */
> +object_property_set_uint(OBJECT(>sdhci), 3, "sd-spec-version", );
> +object_property_set_uint(OBJECT(>sdhci), BCM2835_SDHC_CAPAREG, 
> "capareg",
> + );
>  object_property_set_bool(OBJECT(>sdhci), true, "pending-insert-quirk",
>   );
>  if (err) {
> --
> 2.15.1
>
>



[Qemu-devel] [PULL 0/1] virtio: quick fix

2018-01-23 Thread Michael S. Tsirkin
This is just a quick bugfix so people can make progress.
Will send a pull req with more patches queues later this week.

The following changes since commit 52483b067cce4a88ffbf8fbeea26de7549d2ad23:

  Merge remote-tracking branch 'remotes/huth/tags/pull-request-2018-01-22' into 
staging (2018-01-23 10:15:09 +)

are available in the git repository at:

  git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream

for you to fetch changes up to 3e59a4745a1668eeec94d142b0f5a7847b866a87:

  kvm-all: Partially reverts 4fe6d78b2e to remove the cleanup call (2018-01-24 
00:41:50 +0200)


virtio: quick fix

Fixes a regression in virtio that's causing issues
for many people.

Signed-off-by: Michael S. Tsirkin 


Jose Ricardo Ziviani (1):
  kvm-all: Partially reverts 4fe6d78b2e to remove the cleanup call

 accel/kvm/kvm-all.c | 4 
 1 file changed, 4 deletions(-)




[Qemu-devel] [PULL 1/1] kvm-all: Partially reverts 4fe6d78b2e to remove the cleanup call

2018-01-23 Thread Michael S. Tsirkin
From: Jose Ricardo Ziviani 

This commit partially reverts the commit 4fe6d78b2e because of issues
reported in the virtio.

Examples:

$ qemu-system-ppc64 -cpu POWER8 -nographic -vga none -m 4G \
  -M pseries,accel=kvm -netdev type=user,id=net0 \
  -device virtio-net-pci,netdev=net0 -drive file=../disk.qcow2,if=virtio

Populating /vdevice/nvram@7101
Populating /vdevice/v-scsi@7102
   SCSI: Looking for devices
  8200 CD-ROM   : "QEMU QEMU CD-ROM  2.5+"
Populating /pci@8002000
 00  (D) : 1af4 1000virtio [ net ]
Aborted

$ qemu-system-x86_64 -m 4G -enable-kvm -drive file=util.qcow2,if=virtio

Running QEMU with GTK 2.x is deprecated, and will be removed
in a future release. Please switch to GTK 3.x instead
[1]5282 abort

Reference http://lists.nongnu.org/archive/html/qemu-devel/2018-01/msg05457.html

Reported-by: Anton Blanchard 
Signed-off-by: Jose Ricardo Ziviani 
Reviewed-by: Daniel Henrique Barboza 
Tested-by: Daniel Henrique Barboza 
Reviewed-by: Michael S. Tsirkin 
Signed-off-by: Michael S. Tsirkin 
---
 accel/kvm/kvm-all.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 071f4f5..f290f48 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -812,10 +812,6 @@ static void kvm_mem_ioeventfd_del(MemoryListener *listener,
 if (r < 0) {
 abort();
 }
-
-if (e->cleanup) {
-e->cleanup(e);
-}
 }
 
 static void kvm_io_ioeventfd_add(MemoryListener *listener,
-- 
MST




Re: [Qemu-devel] [PATCH v8 05/14] sdhci: implement UHS-I voltage switch

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> [based on a patch from Alistair Francis 
>  from qemu/xilinx tag xilinx-v2015.2]
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  include/hw/sd/sd.h| 16 
>  include/hw/sd/sdhci.h |  1 +
>  hw/sd/core.c  | 13 +
>  hw/sd/sd.c| 13 +
>  hw/sd/sdhci.c | 12 +++-
>  hw/sd/trace-events|  1 +
>  6 files changed, 55 insertions(+), 1 deletion(-)
>
> diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
> index 96caefe373..f086679493 100644
> --- a/include/hw/sd/sd.h
> +++ b/include/hw/sd/sd.h
> @@ -55,6 +55,20 @@
>  #define AKE_SEQ_ERROR  (1 << 3)
>  #define OCR_CCS_BITN30
>
> +typedef enum {
> +SD_VOLTAGE_0_4V = 400,  /* currently not supported */
> +SD_VOLTAGE_1_8V = 1800,
> +SD_VOLTAGE_3_0V = 3000,
> +SD_VOLTAGE_3_3V = 3300,
> +} sd_voltage_mv_t;
> +
> +typedef enum  {
> +UHS_NOT_SUPPORTED   = 0,
> +UHS_I   = 1,
> +UHS_II  = 2,/* currently not supported */
> +UHS_III = 3,/* currently not supported */
> +} sd_uhs_mode_t;
> +
>  typedef enum {
>  sd_none = -1,
>  sd_bc = 0, /* broadcast -- no response */
> @@ -88,6 +102,7 @@ typedef struct {
>  void (*write_data)(SDState *sd, uint8_t value);
>  uint8_t (*read_data)(SDState *sd);
>  bool (*data_ready)(SDState *sd);
> +void (*set_voltage)(SDState *sd, uint16_t millivolts);
>  void (*enable)(SDState *sd, bool enable);
>  bool (*get_inserted)(SDState *sd);
>  bool (*get_readonly)(SDState *sd);
> @@ -134,6 +149,7 @@ void sd_enable(SDState *sd, bool enable);
>  /* Functions to be used by qdevified callers (working via
>   * an SDBus rather than directly with SDState)
>   */
> +void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
>  int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
>  void sdbus_write_data(SDBus *sd, uint8_t value);
>  uint8_t sdbus_read_data(SDBus *sd);
> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
> index 0fff941a98..06e3784e54 100644
> --- a/include/hw/sd/sdhci.h
> +++ b/include/hw/sd/sdhci.h
> @@ -93,6 +93,7 @@ typedef struct SDHCIState {
>  /* Configurable properties */
>  bool pending_insert_quirk; /* Quirk for Raspberry Pi card insert int */
>  uint8_t sd_spec_version;
> +uint8_t uhs_mode;
>  } SDHCIState;
>
>  #define TYPE_PCI_SDHCI "sdhci-pci"
> diff --git a/hw/sd/core.c b/hw/sd/core.c
> index 498284f109..6d198ea775 100644
> --- a/hw/sd/core.c
> +++ b/hw/sd/core.c
> @@ -41,6 +41,19 @@ static SDState *get_card(SDBus *sdbus)
>  return SD_CARD(kid->child);
>  }
>
> +void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts)
> +{
> +SDState *card = get_card(sdbus);
> +
> +trace_sdbus_set_voltage(sdbus_name(sdbus), millivolts);
> +if (card) {
> +SDCardClass *sc = SD_CARD_GET_CLASS(card);
> +
> +assert(sc->set_voltage);
> +sc->set_voltage(card, millivolts);
> +}
> +}
> +
>  int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
>  {
>  SDState *card = get_card(sdbus);
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index 35347a5bbc..609b2da14f 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -128,6 +128,18 @@ struct SDState {
>  bool enable;
>  };
>
> +static void sd_set_voltage(SDState *sd, uint16_t millivolts)
> +{
> +switch (millivolts) {
> +case 3001 ... 3600: /* SD_VOLTAGE_3_3V */
> +case 2001 ... 3000: /* SD_VOLTAGE_3_0V */
> +break;
> +default:
> +qemu_log_mask(LOG_GUEST_ERROR, "SD card voltage not supported: 
> %.3fV",
> +  millivolts / 1000.f);
> +}
> +}
> +
>  static void sd_set_mode(SDState *sd)
>  {
>  switch (sd->state) {
> @@ -1925,6 +1937,7 @@ static void sd_class_init(ObjectClass *klass, void 
> *data)
>  dc->reset = sd_reset;
>  dc->bus_type = TYPE_SD_BUS;
>
> +sc->set_voltage = sd_set_voltage;
>  sc->do_command = sd_do_command;
>  sc->write_data = sd_write_data;
>  sc->read_data = sd_read_data;
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index b7e69fbc22..aec6ca4d14 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -1255,7 +1255,16 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
> unsigned size)
>  sdhci_update_irq(s);
>  break;
>  case SDHC_ACMD12ERRSTS:
> -MASKED_WRITE(s->acmd12errsts, mask, value);
> +MASKED_WRITE(s->acmd12errsts, mask, value & UINT16_MAX);
> +if (s->uhs_mode >= UHS_I) {
> +MASKED_WRITE(s->hostctl2, mask >> 16, value >> 16);
> +
> +if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, V18_ENA)) {
> +sdbus_set_voltage(>sdbus, SD_VOLTAGE_1_8V);
> +} else {
> +

Re: [Qemu-devel] [PATCH v8 03/14] sdhci: implement the Host Control 2 register (tuning sequence)

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> [based on a patch from Alistair Francis 
>  from qemu/xilinx tag xilinx-v2015.2]
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/sd/sdhci-internal.h | 10 ++
>  include/hw/sd/sdhci.h  |  1 +
>  hw/sd/sdhci.c  | 22 +++---
>  3 files changed, 30 insertions(+), 3 deletions(-)
>
> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
> index 9111f6856a..e7cbea297f 100644
> --- a/hw/sd/sdhci-internal.h
> +++ b/hw/sd/sdhci-internal.h
> @@ -184,6 +184,16 @@ FIELD(SDHC_ACMD12ERRSTS, TIMEOUT_ERR,  1, 1);
>  FIELD(SDHC_ACMD12ERRSTS, CRC_ERR,  2, 1);
>  FIELD(SDHC_ACMD12ERRSTS, INDEX_ERR,4, 1);
>
> +/* Host Control Register 2 (since v3) */
> +#define SDHC_HOSTCTL2  0x3E
> +FIELD(SDHC_HOSTCTL2, UHS_MODE_SEL, 0, 3);
> +FIELD(SDHC_HOSTCTL2, V18_ENA,  3, 1); /* UHS-I only */
> +FIELD(SDHC_HOSTCTL2, DRIVER_STRENGTH,  4, 2); /* UHS-I only */
> +FIELD(SDHC_HOSTCTL2, EXECUTE_TUNING,   6, 1); /* UHS-I only */
> +FIELD(SDHC_HOSTCTL2, SAMPLING_CLKSEL,  7, 1); /* UHS-I only */
> +FIELD(SDHC_HOSTCTL2, ASYNC_INT,   14, 1);
> +FIELD(SDHC_HOSTCTL2, PRESET_ENA,  15, 1);
> +
>  /* HWInit Capabilities Register 0x05E80080 */
>  #define SDHC_CAPAB 0x40
>  FIELD(SDHC_CAPAB, TOCLKFREQ,   0, 6);
> diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
> index 5af9e0dc5a..0fff941a98 100644
> --- a/include/hw/sd/sdhci.h
> +++ b/include/hw/sd/sdhci.h
> @@ -71,6 +71,7 @@ typedef struct SDHCIState {
>  uint16_t norintsigen;  /* Normal Interrupt Signal Enable Register */
>  uint16_t errintsigen;  /* Error Interrupt Signal Enable Register */
>  uint16_t acmd12errsts; /* Auto CMD12 error status register */
> +uint16_t hostctl2; /* Host Control 2 */
>  uint64_t admasysaddr;  /* ADMA System Address Register */
>
>  /* Read-only registers */
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 013c35e585..b7e69fbc22 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -408,14 +408,29 @@ static void sdhci_end_transfer(SDHCIState *s)
>  static void sdhci_read_block_from_card(SDHCIState *s)
>  {
>  int index = 0;
> +uint8_t data;
> +const uint16_t blk_size = s->blksize & BLOCK_SIZE_MASK;
>
>  if ((s->trnmod & SDHC_TRNS_MULTI) &&
>  (s->trnmod & SDHC_TRNS_BLK_CNT_EN) && (s->blkcnt == 0)) {
>  return;
>  }
>
> -for (index = 0; index < (s->blksize & BLOCK_SIZE_MASK); index++) {
> -s->fifo_buffer[index] = sdbus_read_data(>sdbus);
> +for (index = 0; index < blk_size; index++) {
> +data = sdbus_read_data(>sdbus);
> +if (!FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
> +/* Device is not in tunning */
> +s->fifo_buffer[index] = data;
> +}
> +}
> +
> +if (FIELD_EX32(s->hostctl2, SDHC_HOSTCTL2, EXECUTE_TUNING)) {
> +/* Device is in tunning */
> +s->hostctl2 &= ~R_SDHC_HOSTCTL2_EXECUTE_TUNING_MASK;
> +s->hostctl2 |= R_SDHC_HOSTCTL2_SAMPLING_CLKSEL_MASK;
> +s->prnsts &= ~(SDHC_DAT_LINE_ACTIVE | SDHC_DOING_READ |
> +   SDHC_DATA_INHIBIT);
> +goto read_done;
>  }
>
>  /* New data now available for READ through Buffer Port Register */
> @@ -440,6 +455,7 @@ static void sdhci_read_block_from_card(SDHCIState *s)
>  }
>  }
>
> +read_done:
>  sdhci_update_irq(s);
>  }
>
> @@ -1005,7 +1021,7 @@ static uint64_t sdhci_read(void *opaque, hwaddr offset, 
> unsigned size)
>  ret = s->norintsigen | (s->errintsigen << 16);
>  break;
>  case SDHC_ACMD12ERRSTS:
> -ret = s->acmd12errsts;
> +ret = s->acmd12errsts | (s->hostctl2 << 16);
>  break;
>  case SDHC_CAPAB:
>  ret = (uint32_t)s->capareg;
> --
> 2.15.1
>
>



Re: [Qemu-devel] [PATCH v8 04/14] sdbus: add trace events

2018-01-23 Thread Alistair Francis
On Mon, Jan 22, 2018 at 7:06 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/sd/core.c   | 14 --
>  hw/sd/trace-events |  5 +
>  2 files changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/hw/sd/core.c b/hw/sd/core.c
> index 295dc44ab7..498284f109 100644
> --- a/hw/sd/core.c
> +++ b/hw/sd/core.c
> @@ -23,6 +23,12 @@
>  #include "hw/qdev-core.h"
>  #include "sysemu/block-backend.h"
>  #include "hw/sd/sd.h"
> +#include "trace.h"
> +
> +static inline const char *sdbus_name(SDBus *sdbus)
> +{
> +return sdbus->qbus.name;
> +}
>
>  static SDState *get_card(SDBus *sdbus)
>  {
> @@ -39,6 +45,7 @@ int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t 
> *response)
>  {
>  SDState *card = get_card(sdbus);
>
> +trace_sdbus_command(sdbus_name(sdbus), req->cmd, req->arg, req->crc);
>  if (card) {
>  SDCardClass *sc = SD_CARD_GET_CLASS(card);
>
> @@ -52,6 +59,7 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
>  {
>  SDState *card = get_card(sdbus);
>
> +trace_sdbus_write(sdbus_name(sdbus), value);
>  if (card) {
>  SDCardClass *sc = SD_CARD_GET_CLASS(card);
>
> @@ -62,14 +70,16 @@ void sdbus_write_data(SDBus *sdbus, uint8_t value)
>  uint8_t sdbus_read_data(SDBus *sdbus)
>  {
>  SDState *card = get_card(sdbus);
> +uint8_t value = 0;
>
>  if (card) {
>  SDCardClass *sc = SD_CARD_GET_CLASS(card);
>
> -return sc->read_data(card);
> +value = sc->read_data(card);
>  }
> +trace_sdbus_read(sdbus_name(sdbus), value);
>
> -return 0;
> +return value;
>  }
>
>  bool sdbus_data_ready(SDBus *sdbus)
> diff --git a/hw/sd/trace-events b/hw/sd/trace-events
> index 78d8707669..ea2746c8b7 100644
> --- a/hw/sd/trace-events
> +++ b/hw/sd/trace-events
> @@ -1,5 +1,10 @@
>  # See docs/devel/tracing.txt for syntax documentation.
>
> +# hw/sd/core.c
> +sdbus_command(const char *bus_name, uint8_t cmd, uint32_t arg, uint8_t crc) 
> "@%s CMD%02d arg 0x%08x crc 0x%02x"
> +sdbus_read(const char *bus_name, uint8_t value) "@%s value 0x%02x"
> +sdbus_write(const char *bus_name, uint8_t value) "@%s value 0x%02x"
> +
>  # hw/sd/sdhci.c
>  sdhci_set_inserted(const char *level) "card state changed: %s"
>  sdhci_send_command(uint8_t cmd, uint32_t arg) "CMD%02u ARG[0x%08x]"
> --
> 2.15.1
>
>



Re: [Qemu-devel] [qemu-s390x] [PATCH v4 04/10] s390-ccw: update libc

2018-01-23 Thread Collin L. Walling

On 01/23/2018 02:23 PM, Eric Blake wrote:

On 01/23/2018 12:26 PM, Collin L. Walling wrote:

[...]
+/**
+ * atoi:
+ * @str: the string to be converted.
+ *
+ * Given a string @str, convert it to an integer. Leading whitespace is
+ * ignored. The first character (after any whitespace) is checked for the
+ * negative sign. Any other non-numerical value will terminate the
+ * conversion.
+ *
+ * Returns: an integer converted from the string @str.
+ */
+int atoi(const char *str)
+{
+int val = 0;
+int sign = 1;
+
+if (!str || !str[0]) {
+return 0;
+}
+
+while (*str == ' ') {
+str++;
+}

That's not "any whitespace", but only spaces.  A fully compliant
implementation would be checking isspace(), but I don't expect you to
implement that; at a minimum, also checking '\t' would get you closer
(but not all the way to) compliance.



I'll fix the comment to be more clear.

I think it's okay to just have the menu code treat any other kind
of whitespace as an error (it will check before calling atoi). I
added support for negatives in bothfunctions because it was easy
enough to do so and for the sakeof completeness.

However, I worry trying to be 100% compliant will just bloat the
code when we only need it for very specific use cases.

Would you say what we have (along with the fix to itostr below) is
sufficient enough?






+static char *_itostr(int num, char *str, size_t len)
+{
+int num_idx = 0;
+int tmp = num;
+char sign = 0;
+
+if (!str) {
+return NULL;
+}
+
+/* Get index to ones place */
+while ((tmp /= 10) != 0) {
+num_idx++;
+}
+
+if (num < 0) {
+num *= -1;
+sign = 1;
+}

If num == INT_MIN, then num is still negative at this point...


+
+/* Check if we have enough space for num, sign, and null */
+if (len <= num_idx + sign + 1) {
+return NULL;
+}
+
+str[num_idx + sign + 1] = '\0';
+
+/* Convert int to string */
+while (num_idx >= 0) {
+str[num_idx + sign] = num % 10 + '0';

...which breaks this.

Either make it work, or document the corner case as unsupported.



Might as well just make it work at this point:

#define INT32_MIN 0x8000

static char *itostr(int num, char *str, size_t len)
{
    int num_idx = 0;
    int tmp = num;
    char sign = !!(num & INT32_MIN);

    if (!str) {
    return NULL;
    }

    /* Get index to ones place */
    while ((tmp /= 10) != 0) {
    num_idx++;
    }

    /* Check if we have enough space for num, sign, and null */
    if (len <= num_idx + sign + 1) {
    return NULL;
    }

    str[num_idx + sign + 1] = '\0';

    if (sign) {
    str[0] = '-';
    if (num == INT32_MIN) {
    str[num_idx + sign] = '8';
    num /= 10;
    num_idx--;
    }
    num *= -1;
    }

    /* Convert int to string */
    while (num_idx >= 0) {
    str[num_idx + sign] = num % 10 + '0';
    num /= 10;
    num_idx--;
    }

    return str;
}

Thoughts?

--
- Collin L Walling




[Qemu-devel] [PATCH v5 2/3] xlnx-zynqmp-rtc: Add basic time support

2018-01-23 Thread Alistair Francis
Allow the guest to determine the time set from the QEMU command line.

This includes adding a trace event to debug the new time.

Signed-off-by: Alistair Francis 
---
V5:
 - Recalculate tick_offset after migration
V4:
 - Use the .unimp property
V3:
 - Store an offset value
 - Use mktimegm()
 - Log unimplemented writes
V2:
 - Convert DB_PRINT() macro to trace

 include/hw/timer/xlnx-zynqmp-rtc.h |  3 +++
 hw/timer/xlnx-zynqmp-rtc.c | 52 ++
 hw/timer/trace-events  |  3 +++
 3 files changed, 58 insertions(+)

diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h 
b/include/hw/timer/xlnx-zynqmp-rtc.h
index 87649836cc..2867563bdd 100644
--- a/include/hw/timer/xlnx-zynqmp-rtc.h
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
@@ -79,6 +79,9 @@ typedef struct XlnxZynqMPRTC {
 qemu_irq irq_rtc_int;
 qemu_irq irq_addr_error_int;
 
+struct tm current_tm;
+uint32_t tick_offset;
+
 uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
 RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
 } XlnxZynqMPRTC;
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
index 707f145027..1d229870c5 100644
--- a/hw/timer/xlnx-zynqmp-rtc.c
+++ b/hw/timer/xlnx-zynqmp-rtc.c
@@ -29,6 +29,10 @@
 #include "hw/register.h"
 #include "qemu/bitops.h"
 #include "qemu/log.h"
+#include "hw/ptimer.h"
+#include "qemu/cutils.h"
+#include "sysemu/sysemu.h"
+#include "trace.h"
 #include "hw/timer/xlnx-zynqmp-rtc.h"
 
 #ifndef XLNX_ZYNQMP_RTC_ERR_DEBUG
@@ -47,6 +51,19 @@ static void addr_error_int_update_irq(XlnxZynqMPRTC *s)
 qemu_set_irq(s->irq_addr_error_int, pending);
 }
 
+static uint32_t rtc_get_count(XlnxZynqMPRTC *s)
+{
+int64_t now = qemu_clock_get_ns(rtc_clock);
+return s->tick_offset + now / NANOSECONDS_PER_SECOND;
+}
+
+static uint64_t current_time_postr(RegisterInfo *reg, uint64_t val64)
+{
+XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
+
+return rtc_get_count(s);
+}
+
 static void rtc_int_status_postw(RegisterInfo *reg, uint64_t val64)
 {
 XlnxZynqMPRTC *s = XLNX_ZYNQMP_RTC(reg->opaque);
@@ -97,13 +114,17 @@ static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, 
uint64_t val64)
 
 static const RegisterAccessInfo rtc_regs_info[] = {
 {   .name = "SET_TIME_WRITE",  .addr = A_SET_TIME_WRITE,
+.unimp = MAKE_64BIT_MASK(0, 32),
 },{ .name = "SET_TIME_READ",  .addr = A_SET_TIME_READ,
 .ro = 0x,
+.post_read = current_time_postr,
 },{ .name = "CALIB_WRITE",  .addr = A_CALIB_WRITE,
+.unimp = MAKE_64BIT_MASK(0, 32),
 },{ .name = "CALIB_READ",  .addr = A_CALIB_READ,
 .ro = 0x1f,
 },{ .name = "CURRENT_TIME",  .addr = A_CURRENT_TIME,
 .ro = 0x,
+.post_read = current_time_postr,
 },{ .name = "CURRENT_TICK",  .addr = A_CURRENT_TICK,
 .ro = 0x,
 },{ .name = "ALARM",  .addr = A_ALARM,
@@ -143,6 +164,10 @@ static void rtc_reset(DeviceState *dev)
 register_reset(>regs_info[i]);
 }
 
+trace_xlnx_zynqmp_rtc_gettime(s->current_tm.tm_year, s->current_tm.tm_mon,
+  s->current_tm.tm_mday, s->current_tm.tm_hour,
+  s->current_tm.tm_min, s->current_tm.tm_sec);
+
 rtc_int_update_irq(s);
 addr_error_int_update_irq(s);
 }
@@ -178,14 +203,41 @@ static void rtc_init(Object *obj)
 sysbus_init_mmio(sbd, >iomem);
 sysbus_init_irq(sbd, >irq_rtc_int);
 sysbus_init_irq(sbd, >irq_addr_error_int);
+
+qemu_get_timedate(>current_tm, 0);
+s->tick_offset = mktimegm(>current_tm) -
+qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
+}
+
+static int rtc_post_load(void *opaque, int version_id)
+{
+XlnxZynqMPRTC *s = opaque;
+
+/* The tick_offset is added to the current time to determine the guest
+ * time. After migration we don't want to use the original time as that
+ * will indicate to the guest that time has passed, so we need to
+ * recalculate the tick_offset here.
+ */
+s->tick_offset = mktimegm(>current_tm) -
+qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
+
+return 0;
 }
 
 static const VMStateDescription vmstate_rtc = {
 .name = TYPE_XLNX_ZYNQMP_RTC,
 .version_id = 1,
 .minimum_version_id = 1,
+.post_load = rtc_post_load,
 .fields = (VMStateField[]) {
 VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPRTC, XLNX_ZYNQMP_RTC_R_MAX),
+VMSTATE_INT32(current_tm.tm_sec, XlnxZynqMPRTC),
+VMSTATE_INT32(current_tm.tm_min, XlnxZynqMPRTC),
+VMSTATE_INT32(current_tm.tm_hour, XlnxZynqMPRTC),
+VMSTATE_INT32(current_tm.tm_wday, XlnxZynqMPRTC),
+VMSTATE_INT32(current_tm.tm_mday, XlnxZynqMPRTC),
+VMSTATE_INT32(current_tm.tm_mon, XlnxZynqMPRTC),
+VMSTATE_INT32(current_tm.tm_year, XlnxZynqMPRTC),
 VMSTATE_END_OF_LIST(),
 }
 };
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 640722b5d1..e6e042fddb 

[Qemu-devel] [PATCH v5 3/3] xlnx-zynqmp: Connect the RTC device

2018-01-23 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Peter Maydell 
Reviewed-by: Philippe Mathieu-Daudé 
---

 include/hw/arm/xlnx-zynqmp.h |  2 ++
 hw/arm/xlnx-zynqmp.c | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
index 3e6fb9b7bd..9e8c9e18dd 100644
--- a/include/hw/arm/xlnx-zynqmp.h
+++ b/include/hw/arm/xlnx-zynqmp.h
@@ -28,6 +28,7 @@
 #include "hw/ssi/xilinx_spips.h"
 #include "hw/dma/xlnx_dpdma.h"
 #include "hw/display/xlnx_dp.h"
+#include "hw/timer/xlnx-zynqmp-rtc.h"
 
 #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
 #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \
@@ -90,6 +91,7 @@ typedef struct XlnxZynqMPState {
 XlnxZynqMPQSPIPS qspi;
 XlnxDPState dp;
 XlnxDPDMAState dpdma;
+XlnxZynqMPRTC rtc;
 
 char *boot_cpu;
 ARMCPU *boot_cpu_ptr;
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index 325642058b..deef583c2a 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -50,6 +50,9 @@
 #define DPDMA_ADDR  0xfd4c
 #define DPDMA_IRQ   116
 
+#define RTC_ADDR0xffa6
+#define RTC_IRQ 26
+
 static const uint64_t gem_addr[XLNX_ZYNQMP_NUM_GEMS] = {
 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E,
 };
@@ -183,6 +186,9 @@ static void xlnx_zynqmp_init(Object *obj)
 
 object_initialize(>dpdma, sizeof(s->dpdma), TYPE_XLNX_DPDMA);
 qdev_set_parent_bus(DEVICE(>dpdma), sysbus_get_default());
+
+object_initialize(>rtc, sizeof(s->rtc), TYPE_XLNX_ZYNQMP_RTC);
+qdev_set_parent_bus(DEVICE(>rtc), sysbus_get_default());
 }
 
 static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
@@ -454,6 +460,14 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error 
**errp)
  _abort);
 sysbus_mmio_map(SYS_BUS_DEVICE(>dpdma), 0, DPDMA_ADDR);
 sysbus_connect_irq(SYS_BUS_DEVICE(>dpdma), 0, gic_spi[DPDMA_IRQ]);
+
+object_property_set_bool(OBJECT(>rtc), true, "realized", );
+if (err) {
+error_propagate(errp, err);
+return;
+}
+sysbus_mmio_map(SYS_BUS_DEVICE(>rtc), 0, RTC_ADDR);
+sysbus_connect_irq(SYS_BUS_DEVICE(>rtc), 0, gic_spi[RTC_IRQ]);
 }
 
 static Property xlnx_zynqmp_props[] = {
-- 
2.14.1




[Qemu-devel] [PATCH v5 1/3] xlnx-zynqmp-rtc: Initial commit

2018-01-23 Thread Alistair Francis
Initial commit of the ZynqMP RTC device.

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
---

v5:
 - Don't use intermediate val
V2:
 - Delete unused realise function
 - Remove DB_PRINT()

 include/hw/timer/xlnx-zynqmp-rtc.h |  84 +++
 hw/timer/xlnx-zynqmp-rtc.c | 214 +
 hw/timer/Makefile.objs |   1 +
 3 files changed, 299 insertions(+)
 create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
 create mode 100644 hw/timer/xlnx-zynqmp-rtc.c

diff --git a/include/hw/timer/xlnx-zynqmp-rtc.h 
b/include/hw/timer/xlnx-zynqmp-rtc.h
new file mode 100644
index 00..87649836cc
--- /dev/null
+++ b/include/hw/timer/xlnx-zynqmp-rtc.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
+ *
+ * Copyright (c) 2017 Xilinx Inc.
+ *
+ * Written-by: Alistair Francis 
+ *
+ * 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 "hw/register.h"
+
+#define TYPE_XLNX_ZYNQMP_RTC "xlnx-zynmp.rtc"
+
+#define XLNX_ZYNQMP_RTC(obj) \
+ OBJECT_CHECK(XlnxZynqMPRTC, (obj), TYPE_XLNX_ZYNQMP_RTC)
+
+REG32(SET_TIME_WRITE, 0x0)
+REG32(SET_TIME_READ, 0x4)
+REG32(CALIB_WRITE, 0x8)
+FIELD(CALIB_WRITE, FRACTION_EN, 20, 1)
+FIELD(CALIB_WRITE, FRACTION_DATA, 16, 4)
+FIELD(CALIB_WRITE, MAX_TICK, 0, 16)
+REG32(CALIB_READ, 0xc)
+FIELD(CALIB_READ, FRACTION_EN, 20, 1)
+FIELD(CALIB_READ, FRACTION_DATA, 16, 4)
+FIELD(CALIB_READ, MAX_TICK, 0, 16)
+REG32(CURRENT_TIME, 0x10)
+REG32(CURRENT_TICK, 0x14)
+FIELD(CURRENT_TICK, VALUE, 0, 16)
+REG32(ALARM, 0x18)
+REG32(RTC_INT_STATUS, 0x20)
+FIELD(RTC_INT_STATUS, ALARM, 1, 1)
+FIELD(RTC_INT_STATUS, SECONDS, 0, 1)
+REG32(RTC_INT_MASK, 0x24)
+FIELD(RTC_INT_MASK, ALARM, 1, 1)
+FIELD(RTC_INT_MASK, SECONDS, 0, 1)
+REG32(RTC_INT_EN, 0x28)
+FIELD(RTC_INT_EN, ALARM, 1, 1)
+FIELD(RTC_INT_EN, SECONDS, 0, 1)
+REG32(RTC_INT_DIS, 0x2c)
+FIELD(RTC_INT_DIS, ALARM, 1, 1)
+FIELD(RTC_INT_DIS, SECONDS, 0, 1)
+REG32(ADDR_ERROR, 0x30)
+FIELD(ADDR_ERROR, STATUS, 0, 1)
+REG32(ADDR_ERROR_INT_MASK, 0x34)
+FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
+REG32(ADDR_ERROR_INT_EN, 0x38)
+FIELD(ADDR_ERROR_INT_EN, MASK, 0, 1)
+REG32(ADDR_ERROR_INT_DIS, 0x3c)
+FIELD(ADDR_ERROR_INT_DIS, MASK, 0, 1)
+REG32(CONTROL, 0x40)
+FIELD(CONTROL, BATTERY_DISABLE, 31, 1)
+FIELD(CONTROL, OSC_CNTRL, 24, 4)
+FIELD(CONTROL, SLVERR_ENABLE, 0, 1)
+REG32(SAFETY_CHK, 0x50)
+
+#define XLNX_ZYNQMP_RTC_R_MAX (R_SAFETY_CHK + 1)
+
+typedef struct XlnxZynqMPRTC {
+SysBusDevice parent_obj;
+MemoryRegion iomem;
+qemu_irq irq_rtc_int;
+qemu_irq irq_addr_error_int;
+
+uint32_t regs[XLNX_ZYNQMP_RTC_R_MAX];
+RegisterInfo regs_info[XLNX_ZYNQMP_RTC_R_MAX];
+} XlnxZynqMPRTC;
diff --git a/hw/timer/xlnx-zynqmp-rtc.c b/hw/timer/xlnx-zynqmp-rtc.c
new file mode 100644
index 00..707f145027
--- /dev/null
+++ b/hw/timer/xlnx-zynqmp-rtc.c
@@ -0,0 +1,214 @@
+/*
+ * QEMU model of the Xilinx ZynqMP Real Time Clock (RTC).
+ *
+ * Copyright (c) 2017 Xilinx Inc.
+ *
+ * Written-by: Alistair Francis 
+ *
+ * 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 

[Qemu-devel] [PATCH v5 0/3] Add and connect the ZynqMP RTC

2018-01-23 Thread Alistair Francis
V5:
 - Recalculate tick_offset after migration

V4:
 - Use the RegisterAccessInfo .unimp functionality

V3:
 - Store an offset value
 - Use mktimegm()
 - Log unimplemented writes

V2:
 - Delete unused realise function
 - Add cover letter
 - Convert DB_PRINT() macro to trace


Alistair Francis (3):
  xlnx-zynqmp-rtc: Initial commit
  xlnx-zynqmp-rtc: Add basic time support
  xlnx-zynqmp: Connect the RTC device

 include/hw/arm/xlnx-zynqmp.h   |   2 +
 include/hw/timer/xlnx-zynqmp-rtc.h |  87 
 hw/arm/xlnx-zynqmp.c   |  14 ++
 hw/timer/xlnx-zynqmp-rtc.c | 266 +
 hw/timer/Makefile.objs |   1 +
 hw/timer/trace-events  |   3 +
 6 files changed, 373 insertions(+)
 create mode 100644 include/hw/timer/xlnx-zynqmp-rtc.h
 create mode 100644 hw/timer/xlnx-zynqmp-rtc.c

-- 
2.14.1




Re: [Qemu-devel] [PATCH v4 1/7] accel/tcg: add size paremeter in tlb_fill()

2018-01-23 Thread Laurent Vivier
Le 18/01/2018 à 20:38, Laurent Vivier a écrit :
> The MC68040 MMU provides the size of the access that
> triggers the page fault.
> 
> This size is set in the Special Status Word which
> is written in the stack frame of the access fault
> exception.
> 
> So we need the size in m68k_cpu_unassigned_access() and
> m68k_cpu_handle_mmu_fault().
> 
> To be able to do that, this patch modifies the prototype of
> handle_mmu_fault handler, tlb_fill() and probe_write().
> do_unassigned_access() already includes a size parameter.

I'd like to send a pull request for m68k MMU series, and 68040 MMU
relies on this patch.

If someone disagrees with this change, it's time to say it!

Thanks,
Laurent




Re: [Qemu-devel] [PATCH V4 0/7] CAN bus support for QEMU (SJA1000 PCI so far)

2018-01-23 Thread Pavel Pisa
Hello Philippe,

On Monday 22 of January 2018 12:35:33 Philippe Mathieu-Daudé wrote:
> Hi Pavel,
>
> On 01/14/2018 05:14 PM, p...@cmp.felk.cvut.cz wrote:
>
> I think your series is quite ready to get accepted, although I'm not
> sure through with tree it will goes.
>
> Most of my review comments are not blocking issues and might get
> addressed later (like having an abstract sja1000).

Great, I would be happy to reach acceptable state when development
can switch to incremental mode as time allows. I hope than even
actual state is usable from reports (at least for some usescases).

> The principal issue I'd like to discuss with Paolo/Marc-André is the
> chardev backend, they might say it's OK to accept it in this current
> state and refactor the CANBus backend later.

Do you think QOM based? I would like it to be implemented
that way but I need some assistance where to look how this
object kind should be implemented and from which base object
inherit from. But I prefer to left that for later work.

I would definitely like to use some mechanism which allows
to get rid of externally visible pointer and need to assign
it in the stub. It has been my initial idea and your review
sumbled across this hack as well. But I need suggestion what
is the preferred way for QEMU.

When Linux specific object file is linked in then some local
function needs to be called before QOM instances population.
I know how to do that GCC specific/non-portable way

static void __attribute__((constructor)) can_socketcan_setup_variant(void)
{

}

but I expect that something like

module_init()

in can_socketcan.c should be used.

Problem is that there is not module_init
type for plain function in include/qemu/module.h

MODULE_INIT_BLOCK,
MODULE_INIT_OPTS,
MODULE_INIT_QOM,
MODULE_INIT_TRACE,
MODULE_INIT_MAX

I expect that QOM object would solve that in future
but I would be happy to left it simple for now.

What is preferred solution there?

> I'd still avoid using directly the socket() syscall and use the QEMU
> socket API instead (also suggested by Daniel).

I have already switched to qemu_socket(), implementation
looks fine and I have tested that it works.
I have tested functionality and updated can-pci branch.

> I have been thinking a bit about how to test some frame operations
> (rather than the PCI devices) and the Linux vcan driver might be a good
> option (Virtual Local CAN Interface). This is also useful to test this
> series without having CAN hardware. How to use vcan might be worth his
> own paragraph in docs/can.txt.
>
> Do you think some of your tests can be added in the QEMU test suite
> (qtests)?

I have added some more infomation into docs file

+ The CAN interface of the host system has to be configured for proper
+ bitrate and set up. Configuration is not propagated from emulated
+ devices through bus to the physical host device. Example configuration
+ for 1 Mbit/s
+
+   ip link set can0 type can bitrate 100
+   ip link set can0 up
+
+ Virtual (host local only) can interface can be used on the host
+ side instead of physical interface
+
+   ip link add dev can0 type vcan
+
+ The CAN interface on the host side can be used to analyze CAN
+ traffic with "candump" command which is included in "can-utils".
+
+   candump can0

As for the automatic testing, iproute2 tools are required
on host and guest side (considering use of Linux)
and kernel with CAN drivers support.
Root access is required on the host side to setup CAN
interface. Some simple tool is required. It can be based
on can-utils code or our older canping code for example.

Best wishes,

Pavel



Re: [Qemu-devel] [PATCH v1 06/21] RISC-V FPU Support

2018-01-23 Thread Michael Clark
On Wed, Jan 3, 2018 at 12:10 PM, Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 01/02/2018 04:44 PM, Michael Clark wrote:
> > +/* convert RISC-V rounding mode to IEEE library numbers */
> > +unsigned int ieee_rm[] = {
>
> static const.


Done.

> +/* obtain rm value to use in computation
> > + * as the last step, convert rm codes to what the softfloat library
> expects
> > + * Adapted from Spike's decode.h:RM
> > + */
> > +#define RM ({ \
> > +if (rm == 7) {\
> > +rm = env->frm;   \
> > +} \
> > +if (rm > 4) { \
> > +helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
> > +} \
> > +ieee_rm[rm]; })
>
> Please use inline functions and not these macros.
>

Done.

In fact the previous code would, with normal control flow, dereference
ieee_rm[rm] with an out of bounds round mode so assuming
helper_raise_exception does a longjmp, i've inserted g_assert_not_reached()
after the exception. An analyser could detect that ieee_rm has an out of
bounds access assuming normal control flow. e.g.

static inline void set_fp_round_mode(CPURISCVState *env, uint64_t rm)
{
if (rm == 7) {
rm = env->frm;
} else if (rm > 4) {
helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST);
g_assert_not_reached();
}
set_float_rounding_mode(ieee_rm[rm], >fp_status);
}



> Probably this applies to some of the helpers that I've already reviewed,
> but
> you're going to need to use an exception raising function that also
> performs an
> unwind (usually via cpu_loop_exit_restore).  The GETPC() that feeds the
> unwind
> must be placed in the outer-most helper (including inlines).
>
> > +#ifndef CONFIG_USER_ONLY
> > +#define require_fp if (!(env->mstatus & MSTATUS_FS)) { \
> > +helper_raise_exception(env, RISCV_EXCP_ILLEGAL_INST); \
> > +}
>
> If you included MSTATUS_FS in cpu_get_tb_cpu_state flags, then you could be
> checking for this at translation time instead of at run time.


I'll keep a note of this but I might attempt this later. We have some other
changes in this area with repsect to cpu_mmu_index.

Are translations not implicitly indexed by cpu_mmu_index? i.e. do we also
need to add cpu_mmu_index to cpu_get_tb_cpu_state flags to prevent code
translated for one value of mmu_index running in code with another value of
mmu_index (in the case of riscv, we currently return processor mode /
privilege level in cpu_mmu_index).


> > +/* convert softfloat library flag numbers to RISC-V */
> > +unsigned int softfloat_flags_to_riscv(unsigned int flags)
> > +{
> > +int rv_flags = 0;
> > +rv_flags |= (flags & float_flag_inexact) ? 1 : 0;
> > +rv_flags |= (flags & float_flag_underflow) ? 2 : 0;
> > +rv_flags |= (flags & float_flag_overflow) ? 4 : 0;
> > +rv_flags |= (flags & float_flag_divbyzero) ? 8 : 0;
> > +rv_flags |= (flags & float_flag_invalid) ? 16 : 0;
>
> FPEXC_NX et al.
>
> > +/* adapted from Spike's decode.h:set_fp_exceptions */
> > +#define set_fp_exceptions() do { \
> > +env->fflags |= softfloat_flags_to_riscv(get_float_exception_flags(\
> > +>fp_status)); \
> > +set_float_exception_flags(0, >fp_status); \
> > +} while (0)
>
> inline function.  Usually written as
>
>   int flags = get_float_exception_flags(>fp_status);
>   if (flags) {
> set_float_exception_flags(0, >fp_status);
> env->fflags |= softfloat_flags_to_riscv(flags);
>   }
>
> since we really do expect exceptions to be exceptional.


Done.

> +uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
> > +uint64_t frs3, uint64_t rm)
> > +{
> > +require_fp;
> > +set_float_rounding_mode(RM, >fp_status);
> > +frs1 = float32_muladd(frs1, frs2, frs3 ^ (uint32_t)INT32_MIN, 0,
> > +  >fp_status);
>
> Given that RISC-V always returns a default NaN, you obviously do not care
> about
> the sign of a NaN result.  Therefore you should use float_muladd_negate_c
> as
> the fourth argument here and not perform the sign flip manually.


Now working on feedback from here on...

Here is the WIP changelog for the v4 spin...

v4

- Move code to set round mode into set_fp_round_mode function
- Convert set_fp_exceptions from a macro to an inline function
- Convert round mode helper into an inline function
- Make fpu_helper ieee_rm array static const
- Include cpu_mmu_index in cpu_get_tb_cpu_state flags
- Eliminate MPRV influence on mmu_index
- Remove unrecoverable do_unassigned_access function
- Only update PTE accessed and dirty bits if necessary
- Remove unnecessary tlb_flush in set_mode as mode is in mmu_idx
- Remove buggy support for misa writes. misa writes are optional
  and are not implemented in any known 

Re: [Qemu-devel] [RFC PATCH v5 00/24] replay additions

2018-01-23 Thread no-reply
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: 20180123085319.3419.97865.stgit@pasha-VirtualBox
Subject: [Qemu-devel] [RFC PATCH v5 00/24] replay additions

=== 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'
7bf3acd69e replay: don't drain/flush bdrv queue while RR is working
118caf566c replay: save vmstate of the asynchronous events
b6fa3637ca replay: don't process async events when warping the clock
0e1e55563f scripts/replay-dump.py: replay log dumper
3489724f30 replay: avoid recursive call of checkpoints
75a73acfa7 replay: check return values of fwrite
3d3262c821 replay: don't destroy mutex at exit
4d2655dec4 replay: push replay_mutex_lock up the call tree
b9c7226ddc replay: make locking visible outside replay code
a47cfc4db0 replay/replay-internal.c: track holding of replay_lock
c657632acd replay/replay.c: bump REPLAY_VERSION again
c521dd3598 kvm: remove BQL lock/unlock
2be8734669 hax: remove BQL lock/unlock
30c15c0df4 cpus: push BQL lock to qemu_*_wait_io_event
78f277557a target/arm/arm-powertctl: drop BQL assertions
08be174c57 replay: save prior value of the host clock
3e3d5ca056 replay: added replay log format description
f3669453d9 replay: fix save/load vm for non-empty queue
d937b951cd replay: fixed replay_enable_events
5db02472ff replay: fix processing async events
402642f588 replay: disable default snapshot for record/replay
b7ef6d1c7c blkreplay: create temporary overlay for underlaying devices
70ce7a5b5e block: implement bdrv_snapshot_goto for blkreplay
72412e52b0 cpu-exec: fix exception_index handling

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-j6fnd_ns/src/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
  BUILD   centos6
  GEN 
/var/tmp/patchew-tester-tmp-j6fnd_ns/src/docker-src.2018-01-23-04.28.37.5337/qemu.tar
Cloning into 
'/var/tmp/patchew-tester-tmp-j6fnd_ns/src/docker-src.2018-01-23-04.28.37.5337/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-j6fnd_ns/src/docker-src.2018-01-23-04.28.37.5337/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-j6fnd_ns/src/docker-src.2018-01-23-04.28.37.5337/qemu.tar.vroot/ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out 
'10739aa26051a5d49d88132604539d3ed085e72e'
  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 
mesa-libgbm-devel pixman-devel SDL-devel spice-glib-devel 
spice-server-devel tar vte-devel xen-devel zlib-devel
HOSTNAME=a3014d90fb2c
MAKEFLAGS= -j8
J=8
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
TARGET_LIST=
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
FEATURES= dtc
DEBUG=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu 
--prefix=/tmp/qemu-test/install
No C++ compiler available; disabling C++ specific optional code
Install prefix/tmp/qemu-test/install
BIOS directory/tmp/qemu-test/install/share/qemu
firmware path /tmp/qemu-test/install/share/qemu-firmware
binary directory  /tmp/qemu-test/install/bin
library 

Re: [Qemu-devel] [PULL 13/13] linux-user: implement renameat2

2018-01-23 Thread Palmer Dabbelt

On Tue, 23 Jan 2018 12:13:07 PST (-0800), laur...@vivier.eu wrote:

Le 23/01/2018 à 20:13, Palmer Dabbelt a écrit :

On Tue, 23 Jan 2018 06:48:07 PST (-0800), laur...@vivier.eu wrote:

From: Andreas Schwab 

This is needed for new architectures like RISC-V which do not provide any
other rename-like syscall.

Signed-off-by: Andreas Schwab 
Reviewed-by: Laurent Vivier 
Message-Id: 
Signed-off-by: Laurent Vivier 
---
 linux-user/syscall.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 104408c050..74378947f0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -600,6 +600,24 @@ static int sys_utimensat(int dirfd, const char
*pathname,
 #endif
 #endif /* TARGET_NR_utimensat */

+#ifdef TARGET_NR_renameat2
+#if defined(__NR_renameat2)
+#define __NR_sys_renameat2 __NR_renameat2
+_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
+  const char *, new, unsigned int, flags)
+#else
+static int sys_renameat2(int oldfd, const char *old,
+ int newfd, const char *new, int flags)
+{
+    if (flags == 0) {
+    return renameat(oldfd, old, newfd, new);
+    }
+    errno = ENOSYS;
+    return -1;
+}
+#endif
+#endif /* TARGET_NR_renameat2 */
+
 #ifdef CONFIG_INOTIFY
 #include 

@@ -8426,6 +8444,22 @@ abi_long do_syscall(void *cpu_env, int num,
abi_long arg1,
 }
 break;
 #endif
+#if defined(TARGET_NR_renameat2)
+    case TARGET_NR_renameat2:
+    {
+    void *p2;
+    p  = lock_user_string(arg2);
+    p2 = lock_user_string(arg4);
+    if (!p || !p2) {
+    ret = -TARGET_EFAULT;
+    } else {
+    ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
+    }
+    unlock_user(p2, arg4, 0);
+    unlock_user(p, arg2, 0);
+    }
+    break;
+#endif
 #ifdef TARGET_NR_mkdir
 case TARGET_NR_mkdir:
 if (!(p = lock_user_string(arg1)))


Thanks!  My patch got lost in the shuffle, but I think these are
functionally identical.  Feel free to add my


I've seen your patch, but Andreas has implemented what was requested by
Peter (use renameat() when flags == 0), so I took his one.


Ya, I wrote another one do to that bug forgot to send it :)




Reviewed-by: Palmer Dabbelt 


To late for that (it's a pull request), sorry.


OK, no problem.  I'm a bit new to QEMU.

Thanks!



Thank you,
Laurent




[Qemu-devel] [PATCH] target/arm: implement SM4 instructions

2018-01-23 Thread Ard Biesheuvel
This implements emulation of the new SM4 instructions that have
been added as an optional extension to the ARMv8 Crypto Extensions
in ARM v8.2.

Signed-off-by: Ard Biesheuvel 
---

I went ahead and did the implementation according to the pseudocode in
the ARM ARM, even though i have no test code or reference vectors to
compare it against. (There is some example code in the ARM ARM as well,
but I haven't played with that)

 target/arm/cpu.h   |  1 +
 target/arm/crypto_helper.c | 91 
 target/arm/helper.h|  3 +
 target/arm/translate-a64.c |  8 ++
 4 files changed, 103 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 18383666e02d..bad13a76d06c 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1375,6 +1375,7 @@ enum arm_features {
 ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */
 ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
 ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */
+ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
index c1d9f765cd40..b42c7e046ba3 100644
--- a/target/arm/crypto_helper.c
+++ b/target/arm/crypto_helper.c
@@ -609,3 +609,94 @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, 
uint32_t imm2,
 rd[0] = d.l[0];
 rd[1] = d.l[1];
 }
+
+static uint8_t const sm4_sbox[] = {
+0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
+0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
+0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
+0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
+0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
+0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
+0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
+0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
+0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
+0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
+0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
+0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
+0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
+0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
+0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
+0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
+0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
+0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
+0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
+0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
+0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
+0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
+0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
+0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
+0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
+0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
+0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
+0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
+0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
+0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
+0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
+0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
+};
+
+void HELPER(crypto_sm4e)(void *vd, void *vn)
+{
+uint64_t *rd = vd;
+uint64_t *rn = vn;
+union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
+union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
+uint32_t t, i;
+
+for (i = 0; i < 3; i++) {
+t = CR_ST_WORD(d, (i + 1) % 4) ^
+CR_ST_WORD(d, (i + 2) % 4) ^
+CR_ST_WORD(d, (i + 3) % 4) ^
+CR_ST_WORD(n, i);
+
+t = sm4_sbox[t & 0xff] |
+sm4_sbox[(t >> 8) & 0xff] << 8 |
+sm4_sbox[(t >> 16) & 0xff] << 16 |
+sm4_sbox[(t >> 24) & 0xff] << 24;
+
+CR_ST_WORD(d, i) ^= t ^ rol32(t, 2) ^ rol32(t, 10) ^ rol32(t, 18) ^
+rol32(t, 24);
+}
+
+rd[0] = d.l[0];
+rd[1] = d.l[1];
+}
+
+void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm)
+{
+uint64_t *rd = vd;
+uint64_t *rn = vn;
+uint64_t *rm = vm;
+union CRYPTO_STATE d;
+union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
+union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
+uint32_t t, i;
+
+d = n;
+for (i = 0; i < 3; i++) {
+t = CR_ST_WORD(d, (i + 1) % 4) ^
+CR_ST_WORD(d, (i + 2) % 4) ^
+CR_ST_WORD(d, (i + 3) % 4) ^
+CR_ST_WORD(m, i);
+
+t = sm4_sbox[t & 0xff] |
+sm4_sbox[(t >> 8) & 0xff] << 8 |
+sm4_sbox[(t >> 16) & 0xff] << 16 |
+sm4_sbox[(t >> 24) & 0xff] << 24;
+
+CR_ST_WORD(d, i) ^= t ^ rol32(t, 13) ^ rol32(t, 23);
+}
+
+rd[0] = d.l[0];
+rd[1] = d.l[1];
+}
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 2d0bba10c006..ee5b0e98f624 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -544,6 +544,9 @@ 

Re: [Qemu-devel] [PATCH v10 05/14] migration: Create ram_multifd_page

2018-01-23 Thread Dr. David Alan Gilbert
* Juan Quintela (quint...@redhat.com) wrote:
> The function still don't use multifd, but we have simplified
> ram_save_page, xbzrle and RDMA stuff is gone.  We have added a new
> counter and a new flag for this type of pages.
> 
> Signed-off-by: Juan Quintela 
> 
> --
> Add last_page parameter
> Add commets for done and address
> Remove multifd field, it is the same than normal pages
> Merge next patch, now we send multiple pages at a time
> Remove counter for multifd pages, it is identical to normal pages
> Use iovec's instead of creating the equivalent.
> Clear memory used by pages (dave)
> Use g_new0(danp)
> define MULTIFD_CONTINUE
> now pages member is a pointer
> Fix off-by-one in number of pages in one packet
> ---
>  migration/ram.c| 159 
> -
>  migration/trace-events |   2 +
>  2 files changed, 160 insertions(+), 1 deletion(-)
> 
> diff --git a/migration/ram.c b/migration/ram.c
> index aef5a323f3..5d6b46ac23 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -52,6 +52,7 @@
>  #include "migration/block.h"
>  #include "sysemu/sysemu.h"
>  #include "qemu/uuid.h"
> +#include "qemu/iov.h"
>  
>  /***/
>  /* ram save/restore */
> @@ -71,6 +72,7 @@
>  #define RAM_SAVE_FLAG_XBZRLE   0x40
>  /* 0x80 is reserved in migration.h start with 0x100 next */
>  #define RAM_SAVE_FLAG_COMPRESS_PAGE0x100
> +#define RAM_SAVE_FLAG_MULTIFD_PAGE 0x200
>  
>  static inline bool is_zero_range(uint8_t *p, uint64_t size)
>  {
> @@ -395,14 +397,36 @@ static void compress_threads_save_setup(void)
>  
>  /* Multiple fd's */
>  
> +/* used to continue on the same multifd group */
> +#define MULTIFD_CONTINUE UINT16_MAX
> +
> +typedef struct {
> +/* number of used pages */

  Telling us it's used doesn't help much; if I understand
right, this is for accumulating them into one large block
before actually sending them?

> +uint32_t used;
> +/* number of allocated pages */
> +uint32_t allocated;
> +/* global number of generated multifd packets */
> +uint32_t seq;
> +struct iovec *iov;
> +RAMBlock *block;
> +} multifd_pages_t;
> +
>  struct MultiFDSendParams {
> +/* not changed */

???

>  uint8_t id;
>  char *name;
>  QemuThread thread;
>  QIOChannel *c;
>  QemuSemaphore sem;
>  QemuMutex mutex;
> +/* protected by param mutex */
>  bool quit;
> +multifd_pages_t *pages;
> +/* how many patches has sent this channel */

s/patches/packets/

> +uint32_t packets_sent;
> +/* protected by multifd mutex */
> +/* has the thread finish the last submitted job */
> +bool done;
>  };
>  typedef struct MultiFDSendParams MultiFDSendParams;
>  
> @@ -410,8 +434,31 @@ struct {
>  MultiFDSendParams *params;
>  /* number of created threads */
>  int count;
> +QemuMutex mutex;
> +QemuSemaphore sem;
> +multifd_pages_t *pages;
>  } *multifd_send_state;
>  
> +static void multifd_pages_init(multifd_pages_t **ppages, size_t size)

What is the 'size' here - it's allocated pages for something?

> +{
> +multifd_pages_t *pages = g_new0(multifd_pages_t, 1);
> +
> +pages->allocated = size;
> +pages->iov = g_new0(struct iovec, size);
> +*ppages = pages;
> +}
> +
> +static void multifd_pages_clear(multifd_pages_t *pages)
> +{
> +pages->used = 0;
> +pages->allocated = 0;
> +pages->seq = 0;
> +pages->block = NULL;
> +g_free(pages->iov);
> +pages->iov = NULL;
> +g_free(pages);
> +}
> +
>  static void terminate_multifd_send_threads(Error *errp)
>  {
>  int i;
> @@ -453,9 +500,13 @@ int multifd_save_cleanup(Error **errp)
>  socket_send_channel_destroy(p->c);
>  g_free(p->name);
>  p->name = NULL;
> +multifd_pages_clear(p->pages);
> +p->pages = NULL;
>  }
>  g_free(multifd_send_state->params);
>  multifd_send_state->params = NULL;
> +multifd_pages_clear(multifd_send_state->pages);
> +multifd_send_state->pages = NULL;
>  g_free(multifd_send_state);
>  multifd_send_state = NULL;
>  return ret;
> @@ -482,6 +533,7 @@ static void *multifd_send_thread(void *opaque)
>  terminate_multifd_send_threads(local_err);
>  return NULL;
>  }
> +qemu_sem_post(_send_state->sem);
>  
>  while (true) {
>  qemu_mutex_lock(>mutex);
> @@ -489,9 +541,24 @@ static void *multifd_send_thread(void *opaque)
>  qemu_mutex_unlock(>mutex);
>  break;
>  }
> +if (p->pages->used) {
> +p->pages->used = 0;
> +qemu_mutex_unlock(>mutex);
> +
> +trace_multifd_send(p->id, p->pages->seq, p->pages->used);

but p->pages->used is just been set to 0?

> +/* ToDo: send page here */
> +
> +qemu_mutex_lock(_send_state->mutex);
> +p->done = true;
> +p->packets_sent++;
> +

Re: [Qemu-devel] [PULL 13/13] linux-user: implement renameat2

2018-01-23 Thread Laurent Vivier
Le 23/01/2018 à 20:13, Palmer Dabbelt a écrit :
> On Tue, 23 Jan 2018 06:48:07 PST (-0800), laur...@vivier.eu wrote:
>> From: Andreas Schwab 
>>
>> This is needed for new architectures like RISC-V which do not provide any
>> other rename-like syscall.
>>
>> Signed-off-by: Andreas Schwab 
>> Reviewed-by: Laurent Vivier 
>> Message-Id: 
>> Signed-off-by: Laurent Vivier 
>> ---
>>  linux-user/syscall.c | 34 ++
>>  1 file changed, 34 insertions(+)
>>
>> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
>> index 104408c050..74378947f0 100644
>> --- a/linux-user/syscall.c
>> +++ b/linux-user/syscall.c
>> @@ -600,6 +600,24 @@ static int sys_utimensat(int dirfd, const char
>> *pathname,
>>  #endif
>>  #endif /* TARGET_NR_utimensat */
>>
>> +#ifdef TARGET_NR_renameat2
>> +#if defined(__NR_renameat2)
>> +#define __NR_sys_renameat2 __NR_renameat2
>> +_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
>> +  const char *, new, unsigned int, flags)
>> +#else
>> +static int sys_renameat2(int oldfd, const char *old,
>> + int newfd, const char *new, int flags)
>> +{
>> +    if (flags == 0) {
>> +    return renameat(oldfd, old, newfd, new);
>> +    }
>> +    errno = ENOSYS;
>> +    return -1;
>> +}
>> +#endif
>> +#endif /* TARGET_NR_renameat2 */
>> +
>>  #ifdef CONFIG_INOTIFY
>>  #include 
>>
>> @@ -8426,6 +8444,22 @@ abi_long do_syscall(void *cpu_env, int num,
>> abi_long arg1,
>>  }
>>  break;
>>  #endif
>> +#if defined(TARGET_NR_renameat2)
>> +    case TARGET_NR_renameat2:
>> +    {
>> +    void *p2;
>> +    p  = lock_user_string(arg2);
>> +    p2 = lock_user_string(arg4);
>> +    if (!p || !p2) {
>> +    ret = -TARGET_EFAULT;
>> +    } else {
>> +    ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
>> +    }
>> +    unlock_user(p2, arg4, 0);
>> +    unlock_user(p, arg2, 0);
>> +    }
>> +    break;
>> +#endif
>>  #ifdef TARGET_NR_mkdir
>>  case TARGET_NR_mkdir:
>>  if (!(p = lock_user_string(arg1)))
> 
> Thanks!  My patch got lost in the shuffle, but I think these are
> functionally identical.  Feel free to add my

I've seen your patch, but Andreas has implemented what was requested by
Peter (use renameat() when flags == 0), so I took his one.

> Reviewed-by: Palmer Dabbelt 

To late for that (it's a pull request), sorry.

Thank you,
Laurent



Re: [Qemu-devel] [PATCH v5 2/4] target/arm: implement SHA-3 instructions

2018-01-23 Thread Ard Biesheuvel
On 22 January 2018 at 17:26, Ard Biesheuvel  wrote:
> This implements emulation of the new SHA-3 instructions that have
> been added as an optional extensions to the ARMv8 Crypto Extensions
> in ARM v8.2.
>
> Signed-off-by: Ard Biesheuvel 
> ---
>  target/arm/cpu.h   |   1 +
>  target/arm/translate-a64.c | 148 +++-
>  2 files changed, 145 insertions(+), 4 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 32a18510e70b..d0b19e0cbc88 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1373,6 +1373,7 @@ enum arm_features {
>  ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
>  ARM_FEATURE_SVE, /* has Scalable Vector Extension */
>  ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions 
> */
> +ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */
>  };
>
>  static inline int arm_feature(CPUARMState *env, int feature)
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 888f5a39a283..10f2e518f303 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -11162,9 +11162,10 @@ static void 
> disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
>  feature = ARM_FEATURE_V8_SHA512;
>  genfn = gen_helper_crypto_sha512su1;
>  break;
> -default:
> -unallocated_encoding(s);
> -return;
> +case 3: /* RAX1 */
> +feature = ARM_FEATURE_V8_SHA3;
> +genfn = NULL;
> +break;
>  }
>  } else {
>  unallocated_encoding(s);
> @@ -11193,7 +11194,28 @@ static void 
> disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
>  tcg_temp_free_ptr(tcg_rn_ptr);
>  tcg_temp_free_ptr(tcg_rm_ptr);
>  } else {
> -g_assert_not_reached();
> +TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
> +int pass;
> +
> +tcg_op1 = tcg_temp_new_i64();
> +tcg_op2 = tcg_temp_new_i64();
> +tcg_res[0] = tcg_temp_new_i64();
> +tcg_res[1] = tcg_temp_new_i64();
> +
> +for (pass = 0; pass < 2; pass++) {
> +read_vec_element(s, tcg_op1, rn, pass, MO_64);
> +read_vec_element(s, tcg_op2, rm, pass, MO_64);
> +
> +tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
> +tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
> +}
> +write_vec_element(s, tcg_res[0], rd, 0, MO_64);
> +write_vec_element(s, tcg_res[1], rd, 1, MO_64);
> +
> +tcg_temp_free(tcg_op1);
> +tcg_temp_free(tcg_op2);
> +tcg_temp_free(tcg_res[0]);
> +tcg_temp_free(tcg_res[1]);
>  }
>  }
>
> @@ -11240,6 +11262,122 @@ static void 
> disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
>  tcg_temp_free_ptr(tcg_rn_ptr);
>  }
>
> +/* Crypto four-register
> + *  31   23 22 21 20  16 15  14  10 95 40
> + * +---+-+--+---+--+--+--+
> + * | 1 1 0 0 1 1 1 0 0 | Op0 |  Rm  | 0 |  Ra  |  Rn  |  Rd  |
> + * +---+-+--+---+--+--+--+
> + */
> +static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
> +{
> +int op0 = extract32(insn, 21, 2);
> +int rm = extract32(insn, 16, 5);
> +int ra = extract32(insn, 10, 5);
> +int rn = extract32(insn, 5, 5);
> +int rd = extract32(insn, 0, 5);
> +int feature;
> +
> +switch (op0) {
> +case 0: /* EOR3 */
> +case 1: /* BCAX */
> +feature = ARM_FEATURE_V8_SHA3;
> +break;
> +default:
> +unallocated_encoding(s);
> +return;
> +}
> +
> +if (!arm_dc_feature(s, feature)) {
> +unallocated_encoding(s);
> +return;
> +}
> +
> +if (!fp_access_check(s)) {
> +return;
> +}
> +
> +if (op0 < 2) {
> +TCG_i64 tcg_op1, tcg_op2, tcg_op3, tcg_res[2];

Apologies, there's a typo here: TCGv_i64 not TCG_i64

Let me know if I need to resend.

> +int pass;
> +
> +tcg_op1 = tcg_temp_new_i64();
> +tcg_op2 = tcg_temp_new_i64();
> +tcg_op3 = tcg_temp_new_i64();
> +tcg_res[0] = tcg_temp_new_i64();
> +tcg_res[1] = tcg_temp_new_i64();
> +
> +for (pass = 0; pass < 2; pass++) {
> +read_vec_element(s, tcg_op1, rn, pass, MO_64);
> +read_vec_element(s, tcg_op2, rm, pass, MO_64);
> +read_vec_element(s, tcg_op3, ra, pass, MO_64);
> +
> +if (op0 == 0) {
> +/* EOR3 */
> +tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op3);
> +} else {
> +/* BCAX */
> +tcg_gen_andc_i64(tcg_res[pass], tcg_op2, tcg_op3);
> +}
> +tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
> +}
> +write_vec_element(s, tcg_res[0], rd, 0, MO_64);
> +

Re: [Qemu-devel] [PATCH v2 11/20] fpu/softfloat: re-factor add/sub

2018-01-23 Thread Alex Bennée

Peter Maydell  writes:


>
>> +float_status *status)
>> +{
>> +if (part.exp == parm->exp_max) {
>> +if (part.frac == 0) {
>> +part.cls = float_class_inf;
>> +} else {
>> +#ifdef NO_SIGNALING_NANS
>
> The old code didn't seem to need to ifdef this; why's the new
> code different? (at some point we'll want to make this a runtime
> setting so we can support one binary handling CPUs with it both
> set and unset, but that is a far future thing we can ignore for now)

It does, but it's hidden behind propagateFloatXXNaN which in turn calls
floatXX_is_quiet/signalling_nan which are altered by the #ifdefs.

>
>> +part.cls = float_class_qnan;
>> +#else
>> +int64_t msb = part.frac << (parm->frac_shift + 2);
>> +if ((msb < 0) == status->snan_bit_is_one) {
>> +part.cls = float_class_snan;
>> +} else {
>> +part.cls = float_class_qnan;
>> +}
>> +#endif
>> +}
>> +} else if (part.exp == 0) {
>> +if (likely(part.frac == 0)) {
>> +part.cls = float_class_zero;
>> +} else if (status->flush_inputs_to_zero) {
>> +float_raise(float_flag_input_denormal, status);
>> +part.cls = float_class_zero;
>> +part.frac = 0;
>> +} else {
>> +int shift = clz64(part.frac) - 1;
>> +part.cls = float_class_normal;
>
> This is really confusing. This is a *denormal*, but we're setting
> the classification to "normal" ? (It's particularly confusing in
> the code that uses the decomposed numbers, because it looks like
> "if (a.cls == float_class_normal...)" is handling the normal-number
> case and denormals are going to be in a later if branch, but actually
> it's dealing with both.)

The code deals with canonicalized numbers - so unless we explicitly
flush denormals to zero they can be treated like any other for the rest
of the code.

What would you prefer? A comment in FloatClass?


>> +
>> +static float16 float16_round_pack_canonical(decomposed_parts p, 
>> float_status *s)
>> +{
>> +switch (p.cls) {
>> +case float_class_dnan:
>> +return float16_default_nan(s);
>> +case float_class_msnan:
>> +return float16_maybe_silence_nan(float16_pack_raw(p), s);
>
> I think you will find that doing the silencing of the NaNs like this
> isn't quite the right approach. Specifically, for Arm targets we
> currently have a bug in float-to-float conversion from a wider
> format to a narrower one when the input is a signaling NaN that we
> want to silence, and its non-zero mantissa bits are all at the
> less-significant end of the mantissa such that they don't fit into
> the narrower format. If you pack the float into a float16 first and
> then call maybe_silence_nan() on it you've lost the info about those
> low bits which the silence function needs to know to return the
> right answer. What you want to do instead is pass the silence_nan
> function the decomposed value.

So this is an inherited bug from softfloat-specialize.h? I guess we need
a common specific decomposed specialisation we can use for all the sizes.

>
> (The effect of this bug is that we return a default NaN, with the
> sign bit clear, but the Arm FPConvertNaN pseudocode says that we
> should effectively get the default NaN but with the same sign bit
> as the input SNaN.)
>
> Given that this is a bug currently in the version we have, we don't
> necessarily need to fix it now, but I thought I'd mention it since
> the redesign has almost but not quite managed to deliver the right
> information to the silencing code to allow us to fix it soon :-)

So comment for now? Currently all the information for decomposed is kept
internal to softfloat.c - I'm not sure we want to expose the internals
to a wider audience? Especially as these inline helpers in specialize.h
are also used by helpers.


>> +
>> +
>> +/*
>> + * Returns the result of adding the absolute values of the
>> + * floating-point values `a' and `b'. If `subtract' is set, the sum is
>> + * negated before being returned. `subtract' is ignored if the result
>> + * is a NaN. The addition is performed according to the IEC/IEEE
>> + * Standard for Binary Floating-Point Arithmetic.
>> + */
>
> This comment doesn't seem to match what the code is doing,
> because it says it adds the absolute values of 'a' and 'b',
> but the code looks at a_sign and b_sign to decide whether it's
> doing an addition or subtraction rather than ignoring the signs
> (as you would for absolute arithmetic).
>
> Put another way, this comment has been copied from the old addFloat64Sigs()
> and not updated to account for the way the new function includes handling
> of subFloat64Sigs().
>
>> +
>> +static decomposed_parts add_decomposed(decomposed_parts a, decomposed_parts 
>> b,
>> +   bool subtract, float_status *s)
>> +{
>> 

Re: [Qemu-devel] [PATCH qemu v2] RFC: vfio-pci: Allow mmap of MSIX BAR

2018-01-23 Thread Alex Williamson
On Fri, 19 Jan 2018 14:15:43 +0100
Auger Eric  wrote:

> Hi,
> 
> On 19/01/18 04:25, Alex Williamson wrote:
> > On Fri, 19 Jan 2018 13:41:41 +1100
> > Alexey Kardashevskiy  wrote:
> >   
> >> On 19/01/18 08:59, Alex Williamson wrote:  
> >>> On Tue, 16 Jan 2018 16:17:58 +1100
> >>> Alexey Kardashevskiy  wrote:
> >>> 
>  On 06/01/18 02:29, Alex Williamson wrote:
> > On Fri, 5 Jan 2018 10:48:07 +0100
> > Auger Eric  wrote:
> >   
> >> Hi Alexey,
> >>
> >> On 15/12/17 07:29, Alexey Kardashevskiy wrote:  
> >>> This makes use of a new VFIO_REGION_INFO_CAP_MSIX_MAPPABLE capability
> >>> which tells that a region with MSIX data can be mapped entirely, i.e.
> >>> the VFIO PCI driver won't prevent MSIX vectors area from being mapped.
> >>>
> >>> With this change, all BARs are mapped in a single chunk and MSIX 
> >>> vectors
> >>> are emulated on top unless the machine requests not to by defining and
> >>> enabling a new "vfio-no-msix-emulation" property. At the moment only
> >>> sPAPR machine does so - it prohibits MSIX emulation and does not allow
> >>> enabling it as it does not define the "set" callback for the new 
> >>> property;
> >>> the new property also does not appear in "-machine pseries,help".
> >>>
> >>> If the new capability is present, this puts MSIX IO memory region 
> >>> under
> >>> mapped memory region. If the capability is not there, it falls back to
> >>> the old behaviour with the sparse capability.
> >>>
> >>> In MSIX vectors section is not aligned to the page size, the KVM 
> >>> memory
> >>> listener does not register it with the KVM as a memory slot and MSIX 
> >>> is
> >>> emulated by QEMU as before.
> >>>
> >>> This requires the kernel change - "vfio-pci: Allow mapping MSIX BAR" -
> >>> for the new capability: 
> >>> https://www.spinics.net/lists/kvm/msg160282.html
> >>>
> >>> Signed-off-by: Alexey Kardashevskiy 
> >>> ---
> >>>
> >>> This is mtree and flatview BEFORE this patch:
> >>>
> >>> "info mtree":
> >>> memory-region: p...@8002000.mmio
> >>>   - (prio 0, i/o): 
> >>> p...@8002000.mmio
> >>> 2100-2100 (prio 1, i/o): 0001:03:00.0 BAR 
> >>> 1
> >>>   2100e000-2100e5ff (prio 0, i/o): msix-table
> >>>   2100f000-2100f00f (prio 0, i/o): msix-pba 
> >>> [disabled]
> >>> 2104-2107 (prio 1, i/o): 0001:03:00.0 BAR 
> >>> 3
> >>>   2104-2107 (prio 0, ramd): 0001:03:00.0 
> >>> BAR 3 mmaps[0]
> >>>
> >>> "info mtree -f":
> >>> FlatView #0
> >>>  AS "memory", root: system
> >>>  AS "cpu-memory", root: system
> >>>  Root memory region: system
> >>>   -7fff (prio 0, ram): ppc_spapr.ram
> >>>   2100-2100dfff (prio 1, i/o): 0001:03:00.0 BAR 1
> >>>   2100e000-2100e5ff (prio 0, i/o): msix-table
> >>>   2100e600-2100 (prio 1, i/o): 0001:03:00.0 BAR 1 
> >>> @e600
> >>>   2104-2107 (prio 0, ramd): 0001:03:00.0 BAR 
> >>> 3 mmaps[0]
> >>>
> >>>
> >>>
> >>> This is AFTER this patch applied:
> >>>
> >>> "info mtree":
> >>> memory-region: p...@8002000.mmio
> >>>   - (prio 0, i/o): 
> >>> p...@8002000.mmio
> >>> 2100-2100 (prio 1, i/o): 0001:03:00.0 BAR 
> >>> 1
> >>>   2100-2100 (prio 0, ramd): 0001:03:00.0 
> >>> BAR 1 mmaps[0]
> >>> 2100e000-2100e5ff (prio 0, i/o): msix-table 
> >>> [disabled]
> >>> 2100f000-2100f00f (prio 0, i/o): msix-pba 
> >>> [disabled]
> >>> 2104-2107 (prio 1, i/o): 0001:03:00.0 BAR 
> >>> 3
> >>>   2104-2107 (prio 0, ramd): 0001:03:00.0 
> >>> BAR 3 mmaps[0]
> >>>
> >>>
> >>> "info mtree -f":
> >>> FlatView #2
> >>>  AS "memory", root: system
> >>>  AS "cpu-memory", root: system
> >>>  Root memory region: system
> >>>   -7fff (prio 0, ram): ppc_spapr.ram
> >>>   2100-2100 (prio 0, ramd): 0001:03:00.0 BAR 
> >>> 1 mmaps[0]
> >>>   2104-2107 (prio 0, ramd): 0001:03:00.0 BAR 
> >>> 3 mmaps[0]
> >>>
> >>>
> >>>
> >>> This is AFTER this patch applied AND spapr_get_msix_emulation() 
> >>> patched
> >>> to enable emulation:
> >>>
> >>> "info mtree":
> >>> memory-region: 

Re: [Qemu-devel] [PATCH qemu v3] RFC: vfio-pci: Allow mmap of MSIX BAR

2018-01-23 Thread Alex Williamson
On Tue, 23 Jan 2018 16:34:34 +0100
Auger Eric  wrote:

> Hi Alexey,
> On 23/01/18 02:22, Alexey Kardashevskiy wrote:
> > This makes use of a new VFIO_REGION_INFO_CAP_MSIX_MAPPABLE capability
> > which tells that a region with MSIX data can be mapped entirely, i.e.
> > the VFIO PCI driver won't prevent MSIX vectors area from being mapped.
> > 
> > With this change, all BARs are mapped in a single chunk and MSIX vectors
> > are emulated on top unless the machine requests not to by defining and
> > enabling a new "vfio-no-msix-emulation" property. At the moment only
> > sPAPR machine does so - it prohibits MSIX emulation and does not allow
> > enabling it as it does not define the "set" callback for the new property;
> > the new property also does not appear in "-machine pseries,help".
> > 
> > If MSIX vectors section is not aligned to the page size, the KVM memory
> > listener does not register it with the KVM as a memory slot and MSIX is
> > emulated by QEMU as before. This may create MMIO RAM memory sections with
> > an address or/and a size not aligned which will make vfio_dma_map() fail;
> > to address this, this makes treats such failures as non-fatal.
> > 
> > This requires the kernel change - "vfio-pci: Allow mapping MSIX BAR" -
> > for the new capability: https://www.spinics.net/lists/kvm/msg160282.html
> > 
> > Signed-off-by: Alexey Kardashevskiy 
> > ---
> > Changes:
> > v3:
> > * vfio_listener_region_add() won't make qemu exit if failed on MMIO MR
> > 
> > ---
> >  include/hw/vfio/vfio-common.h |  1 +
> >  linux-headers/linux/vfio.h|  5 +
> >  hw/ppc/spapr.c|  7 +++
> >  hw/vfio/common.c  | 19 +++
> >  hw/vfio/pci.c | 10 ++
> >  5 files changed, 42 insertions(+)
> > 
> > diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> > index f3a2ac9..927d600 100644
> > --- a/include/hw/vfio/vfio-common.h
> > +++ b/include/hw/vfio/vfio-common.h
> > @@ -171,6 +171,7 @@ int vfio_get_region_info(VFIODevice *vbasedev, int 
> > index,
> >   struct vfio_region_info **info);
> >  int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
> >   uint32_t subtype, struct vfio_region_info 
> > **info);
> > +bool vfio_is_cap_present(VFIODevice *vbasedev, uint16_t cap_type, int 
> > region);
> >  #endif
> >  extern const MemoryListener vfio_prereg_listener;
> >  
> > diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
> > index 4312e96..b45182e 100644
> > --- a/linux-headers/linux/vfio.h
> > +++ b/linux-headers/linux/vfio.h
> > @@ -301,6 +301,11 @@ struct vfio_region_info_cap_type {
> >  #define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
> >  #define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG  (3)
> >  
> > +/*
> > + * The MSIX mappable capability informs that MSIX data of a BAR can be 
> > mmapped.
> > + */
> > +#define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3
> > +
> >  /**
> >   * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
> >   * struct vfio_irq_info)
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index d1acfe8..5ff43ce 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -2789,6 +2789,11 @@ static void spapr_set_modern_hotplug_events(Object 
> > *obj, bool value,
> >  spapr->use_hotplug_event_source = value;
> >  }
> >  
> > +static bool spapr_get_msix_emulation(Object *obj, Error **errp)
> > +{
> > +return true;
> > +}
> > +
> >  static char *spapr_get_resize_hpt(Object *obj, Error **errp)
> >  {
> >  sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
> > @@ -2870,6 +2875,8 @@ static void spapr_instance_init(Object *obj)
> >  object_property_set_description(obj, "vsmt",
> >  "Virtual SMT: KVM behaves as if this 
> > were"
> >  " the host's SMT mode", _abort);
> > +object_property_add_bool(obj, "vfio-no-msix-emulation",
> > + spapr_get_msix_emulation, NULL, NULL);
> >  }
> >  
> >  static void spapr_machine_finalizefn(Object *obj)
> > diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> > index b77be3a..842c5b2 100644
> > --- a/hw/vfio/common.c
> > +++ b/hw/vfio/common.c
> > @@ -530,6 +530,10 @@ static void vfio_listener_region_add(MemoryListener 
> > *listener,
> >  return;
> >  
> >  fail:
> > +if (memory_region_is_ram_device(section->mr)) {
> > +error_report("failed to vfio_dma_map. pci p2p may not work");
> > +return;
> > +}  
> 
> I don't think this is an acceptable solution as it produces plenty of
> errors such as
> 
> qemu-system-aarch64: VFIO_MAP_DMA: -22
> qemu-system-aarch64: vfio_dma_map(0x30a7ab90, 0x80, 0x2000,
> 0xfffd79a0) = -22 (Invalid argument)

This much of the error above could be avoided by looking at the type1
page size bitmap before trying to perform the mapping.

> 

Re: [Qemu-devel] [PATCH v2 0/4] Updates based on feedback.

2018-01-23 Thread Eduardo Habkost
On Mon, Jan 22, 2018 at 01:07:45PM -0800, Justin Terry (VM) wrote:
> Updates based on review feedback.
> 
> 1. Fixes style issues and properly ran the scripts/checkpatch pre submission.
> 2. Added migration blockers for CPUID, dirty memory tracking, and 
> XSAVE/XRSTOR.
> 3. Fixed some bugs around register states when using bios vs efi.

For reference to others, v1 seems to be:

  Subject: [PATCH 0/4] Implements the Windows Hypervisor Platform accelerator
  https://www.mail-archive.com/qemu-devel@nongnu.org/msg505710.html

> 
> Justin Terry (VM) (4):
>   Add the Windows Hypervisor Platform accelerator.
>   Add the WHPX vcpu API
>   Introduce the WHPX impl
>   Add the WHPX acceleration enlightenments
> 
>  accel/stubs/Makefile.objs |9 +-
>  accel/stubs/whpx-stub.c   |   48 ++
>  configure |   48 +-
>  cpus.c|   66 ++-
>  include/sysemu/hw_accel.h |   13 +
>  include/sysemu/whpx.h |   40 ++
>  qemu-options.hx   |8 +-
>  target/i386/Makefile.objs |1 +
>  target/i386/helper.c  |2 +-
>  target/i386/whpx-all.c| 1366 
> +
>  10 files changed, 1590 insertions(+), 11 deletions(-)
>  create mode 100644 accel/stubs/whpx-stub.c
>  create mode 100644 include/sysemu/whpx.h
>  create mode 100644 target/i386/whpx-all.c
> 
> -- 
> 2.7.4
> 

-- 
Eduardo



Re: [Qemu-devel] [PATCH v10 04/14] migration: Start of multiple fd work

2018-01-23 Thread Dr. David Alan Gilbert
* Juan Quintela (quint...@redhat.com) wrote:
> We create new channels for each new thread created. We send through
> them in a packed struct.  This way we can check we connect the right
> channels in both sides.
> 
> Signed-off-by: Juan Quintela 

General comment; given it's reasonably large, it would be nice to split
this into a send and a receive patch.
Some tracing wouldn't do any harm - it's going to be fun debugging
failures where some sockets connect and then fail, so tracing would
help.


> --
> Split SocketArgs into incoming and outgoing args
> 
> Use UUID's on the initial message, so we are sure we are connecting to
> the right channel.
> 
> Remove init semaphore.  Now that we use uuids on the init message, we
> know that this is our channel.
> 
> Fix recv socket destwroy, we were destroying send channels.
> This was very interesting, because we were using an unreferred object
> without problems.
> 
> Move to struct of pointers
> init channel sooner.
> split recv thread creation.
> listen on main thread
> We count the number of created threads to know when we need to stop listening
> Use g_strdup_printf
> report channel id on errors
> Add name parameter
> Use local_err
> Add Error * parameter to socket_send_channel_create()
> Use qio_channel_*_all
> Use asynchronous connect
> Use an struct to send all fields
> Use default uuid
> Fix local_err = NULL (dave)
> Make lines 80 lines long (checkpatch)
> Move multifd_new_channel() and multifd_recv_thread() to later patches
> when used.
> Add __attribute__(packad)
> Use UUIDs are opaques isntead of the ASCII represantation
> rename migrate_new_channel_async to migrate_new_send_channel_async
> rename recv_channel_destroy to _unref.  And create the pairing _ref.
> ---
>  migration/migration.c |   7 +++-
>  migration/ram.c   | 114 
> +++---
>  migration/ram.h   |   3 ++
>  migration/socket.c|  39 -
>  migration/socket.h|  10 +
>  5 files changed, 137 insertions(+), 36 deletions(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c
> index e506b9c2c6..77fc17f723 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -426,7 +426,7 @@ void migration_ioc_process_incoming(QIOChannel *ioc)
>  QEMUFile *f = qemu_fopen_channel_input(ioc);
>  migration_fd_process_incoming(f);
>  }
> -/* We still only have a single channel.  Nothing to do here yet */
> +multifd_recv_new_channel(ioc);

OK, that looks a little odd at the moment - do we grow the
recv_new_channel and still leave the first one in there?

>  }
>  
>  /**
> @@ -437,6 +437,11 @@ void migration_ioc_process_incoming(QIOChannel *ioc)
>   */
>  bool migration_has_all_channels(void)
>  {
> +if (migrate_use_multifd()) {
> +int thread_count = migrate_multifd_channels();
> +
> +return thread_count == multifd_created_channels();
> +}
>  return true;
>  }
>  
> diff --git a/migration/ram.c b/migration/ram.c
> index 5a109efeda..aef5a323f3 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -36,6 +36,7 @@
>  #include "xbzrle.h"
>  #include "ram.h"
>  #include "migration.h"
> +#include "socket.h"
>  #include "migration/register.h"
>  #include "migration/misc.h"
>  #include "qemu-file.h"
> @@ -49,6 +50,8 @@
>  #include "qemu/rcu_queue.h"
>  #include "migration/colo.h"
>  #include "migration/block.h"
> +#include "sysemu/sysemu.h"
> +#include "qemu/uuid.h"
>  
>  /***/
>  /* ram save/restore */
> @@ -396,6 +399,7 @@ struct MultiFDSendParams {
>  uint8_t id;
>  char *name;
>  QemuThread thread;
> +QIOChannel *c;
>  QemuSemaphore sem;
>  QemuMutex mutex;
>  bool quit;
> @@ -412,6 +416,15 @@ static void terminate_multifd_send_threads(Error *errp)
>  {
>  int i;
>  
> +if (errp) {
> +MigrationState *s = migrate_get_current();
> +migrate_set_error(s, errp);
> +if (s->state == MIGRATION_STATUS_SETUP ||
> +s->state == MIGRATION_STATUS_ACTIVE) {
> +migrate_set_state(>state, s->state,
> +  MIGRATION_STATUS_FAILED);
> +}
> +}
>  for (i = 0; i < multifd_send_state->count; i++) {
>  MultiFDSendParams *p = _send_state->params[i];
>  
> @@ -437,6 +450,7 @@ int multifd_save_cleanup(Error **errp)
>  qemu_thread_join(>thread);
>  qemu_mutex_destroy(>mutex);
>  qemu_sem_destroy(>sem);
> +socket_send_channel_destroy(p->c);
>  g_free(p->name);
>  p->name = NULL;
>  }
> @@ -447,9 +461,27 @@ int multifd_save_cleanup(Error **errp)
>  return ret;
>  }
>  
> +typedef struct {
> +uint32_t version;
> +unsigned char uuid[16]; /* QemuUUID */
> +uint8_t id;
> +} __attribute__((packed)) MultiFDInit_t;
> +
>  static void *multifd_send_thread(void *opaque)
>  {
>  MultiFDSendParams *p = opaque;
> +

Re: [Qemu-devel] [PULL 0/8] x86 queue, 2018-01-17

2018-01-23 Thread Eduardo Habkost
On Tue, Jan 23, 2018 at 12:15:27PM -0600, Michael Roth wrote:
> Quoting Christian Borntraeger (2018-01-23 03:59:39)
> > 
> > 
> > On 01/23/2018 09:40 AM, Christian Ehrhardt wrote:
> > > On Thu, Jan 18, 2018 at 2:51 PM, Peter Maydell  
> > > wrote:
> > >> On 18 January 2018 at 02:01, Eduardo Habkost  wrote:
> > >>> The following changes since commit 
> > >>> 8e5dc9ba49743b46d955ec7dacb04e42ae7ada7c:
> > >>>
> > >>>   Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180116' 
> > >>> into staging (2018-01-16 17:36:39 +)
> > >>>
> > >>> are available in the Git repository at:
> > >>>
> > >>>   git://github.com/ehabkost/qemu.git tags/x86-pull-request
> > >>>
> > >>> for you to fetch changes up to 6cfbc54e8903a9bcc0346119949162d040c144c1:
> > >>>
> > >>>   i386: Add EPYC-IBPB CPU model (2018-01-17 23:54:39 -0200)
> > >>>
> > >>> 
> > >>> x86 queue, 2018-01-17
> > >>>
> > >>> Highlight: new CPU models that expose CPU features that guests
> > >>> can use to mitigate CVE-2017-5715 (Spectre variant #2).
> > >>>
> > >>
> > >> Applied, thanks.
> > >>
> > >> -- PMM
> > >>
> > > 
> > > Hi,
> > > I was kind of clinging to [1] so far and had the expectation that all
> > > those would be wrapped up in 2.11.1 once ready.
> > > I see that the s390x changes are targeted to qemu-stable (well to
> > > admit I suggested so referring the article above).
> > > So I'd expected to see this series to show up on qemu-stable as well
> > > but haven't seen it so far.
> > > 
> > > Therefore I wanted to ask if there was a change of plans in that
> > > regard or if it needs just a few days more to see (part of) this
> > > series on qemu-stable and on its way into 2.11.1?
> > > 
> > > [1]: https://www.qemu.org/2018/01/04/spectre/
> > 
> > Adding Michael,
> > 
> > Yes, I think it makes sense to have the guest enablement for the spectre 
> > mitigations available in 2.11.1 for all architectures that provide it. 
> > (this queue for x86, Connies pending S390 patches, whatever Power
> > and arm will do).
> 
> That's my plan as well, but IIUC the QEMU side of these patches rely on
> a KVM flag that in turn relies on this series:
> 
>   https://lkml.org/lkml/2018/1/20/158

Actually it depends on:
https://lkml.org/lkml/2018/1/9/329
([PATCH v2 0/8] KVM: x86: expose CVE-2017-5715 ("Spectre variant 2") 
mitigations to guest)

The ability to expose IBRS to guests doesn't seem to depend on
the host kernel using IBRS to protect itself.  But I guess it
will be easier to merge that code after Linux developers decide
what they'll do.  Paolo, what's your take on this?

Note that there are released OSes that use IBRS (Windows and
RHEL), so even if upstream Linux decide to not rely on IBRS,
users will probably want to expose IBRS to VMs as soon as KVM
becomes able to do that.

BUT:

> 
> But that's still in RFC and Linus seems to have reservations with the
> current code. Since coordinating these all this to users/downstreams is
> somewhat of a mess I was thinking we should accompany the 2.11.1 release
> with a blog post on the various options/backports/microcode needed throughout
> the stack to enable the fixes, but until there's a stable patchset on
> the linux side I'm not sure there's much worth in putting out the 2.11.1
> release (if I'm missing something here please let me know).

I'm inclined to agree.  I merged the -IBRS CPU models expecting
that the fixes would be included quickly in upstream Linux too,
but it was not the case.

To be honest, I don't think adding new CPU models are the proper
solution for the problem.  They are just a quick solution that
doesn't require intrusive changes in the management stack.

Meltdown & Spectre made us painfully aware of limitations of
management stacks out there (esp. OpenStack): they normally don't
have an easy mechanism to enable CPU features that are not part
of an existing CPU model name.  A good management stack would be
able to use, e.g., "-cpu Westmere,+spec-ctrl" instead of
"Westmere-IBRS" if it knows all the hosts on a given
cluster/migration-set/whatever-it-is-called support the feature.
The same applies to other flags like ibpb and pcid.

There's work being done on OpenStack to fix this,
e.g.: https://review.openstack.org/#/c/534384/


That said, we will probably want to include MSR code and the CPU
feature flag names (spec-ctrl and ibpb) on the stable branch as
soon as possible.  This way, people will have the option to
manually enable those features (or make them automatically
available using "-cpu host") before a decision is made regarding
CPU model names.

I can send a patch series to -stable including only those
patches, if it makes the work easier.


> 
> There's also the testing aspect of this, which I'd at least like to cover
> on the x86 side. I've be doing some basic testing on top of early versions
> of the IBRS patches and KVM patches, but I'd really like to make 

Re: [Qemu-devel] [PATCH v4 04/10] s390-ccw: update libc

2018-01-23 Thread Eric Blake
On 01/23/2018 12:26 PM, Collin L. Walling wrote:
> Moved:
>   memcmp from bootmap.h to libc.h (renamed from _memcmp)
>   strlen from sclp.c to libc.h (renamed from _strlen)
> 
> Added C standard functions:
>   atoi
>   isdigit
> 
> Added non C-standard function:
>   itostr
> 
> Signed-off-by: Collin L. Walling 
> Acked-by: Christian Borntraeger 
> Reviewed-by: Janosch Frank 
> ---

> +/**
> + * atoi:
> + * @str: the string to be converted.
> + *
> + * Given a string @str, convert it to an integer. Leading whitespace is
> + * ignored. The first character (after any whitespace) is checked for the
> + * negative sign. Any other non-numerical value will terminate the
> + * conversion.
> + *
> + * Returns: an integer converted from the string @str.
> + */
> +int atoi(const char *str)
> +{
> +int val = 0;
> +int sign = 1;
> +
> +if (!str || !str[0]) {
> +return 0;
> +}
> +
> +while (*str == ' ') {
> +str++;
> +}

That's not "any whitespace", but only spaces.  A fully compliant
implementation would be checking isspace(), but I don't expect you to
implement that; at a minimum, also checking '\t' would get you closer
(but not all the way to) compliance.


> +static char *_itostr(int num, char *str, size_t len)
> +{
> +int num_idx = 0;
> +int tmp = num;
> +char sign = 0;
> +
> +if (!str) {
> +return NULL;
> +}
> +
> +/* Get index to ones place */
> +while ((tmp /= 10) != 0) {
> +num_idx++;
> +}
> +
> +if (num < 0) {
> +num *= -1;
> +sign = 1;
> +}

If num == INT_MIN, then num is still negative at this point...

> +
> +/* Check if we have enough space for num, sign, and null */
> +if (len <= num_idx + sign + 1) {
> +return NULL;
> +}
> +
> +str[num_idx + sign + 1] = '\0';
> +
> +/* Convert int to string */
> +while (num_idx >= 0) {
> +str[num_idx + sign] = num % 10 + '0';

...which breaks this.

Either make it work, or document the corner case as unsupported.

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



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH v4 00/10] Interactive Boot Menu for DASD and SCSI Guests on s390x

2018-01-23 Thread Eric Blake
On 01/23/2018 12:26 PM, Collin L. Walling wrote:
> --- [v4] ---
> 
> This round mostly includes some general cleanup to bootmap.c. Checkpatch did 
> not like any variation of "strtoi", so I properly implemented atoi instead.

strtol is actually a better interface than atoi (as it can report
errors); but for a fallback code used only on known boot parameters,
implementing the simpler atoi is probably fine.

> 
>   - itostr and atoi now handle negative numbers (though not necessary 
>   for these patches, it is available for robustness)


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



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PULL 13/13] linux-user: implement renameat2

2018-01-23 Thread Palmer Dabbelt

On Tue, 23 Jan 2018 06:48:07 PST (-0800), laur...@vivier.eu wrote:

From: Andreas Schwab 

This is needed for new architectures like RISC-V which do not provide any
other rename-like syscall.

Signed-off-by: Andreas Schwab 
Reviewed-by: Laurent Vivier 
Message-Id: 
Signed-off-by: Laurent Vivier 
---
 linux-user/syscall.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 104408c050..74378947f0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -600,6 +600,24 @@ static int sys_utimensat(int dirfd, const char *pathname,
 #endif
 #endif /* TARGET_NR_utimensat */

+#ifdef TARGET_NR_renameat2
+#if defined(__NR_renameat2)
+#define __NR_sys_renameat2 __NR_renameat2
+_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
+  const char *, new, unsigned int, flags)
+#else
+static int sys_renameat2(int oldfd, const char *old,
+ int newfd, const char *new, int flags)
+{
+if (flags == 0) {
+return renameat(oldfd, old, newfd, new);
+}
+errno = ENOSYS;
+return -1;
+}
+#endif
+#endif /* TARGET_NR_renameat2 */
+
 #ifdef CONFIG_INOTIFY
 #include 

@@ -8426,6 +8444,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
arg1,
 }
 break;
 #endif
+#if defined(TARGET_NR_renameat2)
+case TARGET_NR_renameat2:
+{
+void *p2;
+p  = lock_user_string(arg2);
+p2 = lock_user_string(arg4);
+if (!p || !p2) {
+ret = -TARGET_EFAULT;
+} else {
+ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
+}
+unlock_user(p2, arg4, 0);
+unlock_user(p, arg2, 0);
+}
+break;
+#endif
 #ifdef TARGET_NR_mkdir
 case TARGET_NR_mkdir:
 if (!(p = lock_user_string(arg1)))


Thanks!  My patch got lost in the shuffle, but I think these are functionally 
identical.  Feel free to add my


Reviewed-by: Palmer Dabbelt 



Re: [Qemu-devel] [PATCH v1 1/2] Revert "build-sys: silence make by default or V=0"

2018-01-23 Thread Eric Blake
On 01/23/2018 10:47 AM, Daniel P. Berrange wrote:
> This reverts commit 42a77f1ce4934b243df003f95bda88530631387a.
> 
> The primary intention of this change was to silence messages
> like
> 
>   make[1]: '/home/berrange/src/virt/qemu/capstone/libcapstone.a' is up to 
> date.
> 
> which we get when calling make recursively with explicit
> targets.
> 
> The problem is that this change affected every make target,
> not merely the targets that triggered these "is up to date"
> messages. As a result any targets that were not invoking
> commands via "$(call quiet-command ...)" suddenly become
> silent. This is particularly bad for "make install" which
> now appears todo nothing.
> 
> Rather than go through every make rule and try to identify
> places where we now need to explicitly print a message to
> show work taking place, just revert the change.
> 
> To address the original problem of silencing "is up to date"
> messages, we simply add --quiet to the SUBDIR_MAKEVARS
> variable, so it only affects us on recursive make calls.

As for solving the original intended issue, this patch silences the
message about libcapstone, and reverting back to a known state is more
conservative, so I'm okay with this going in.

Tested-by: Eric Blake 


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



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH v1 2/2] make: fix help message reference to bogus V=0 variable

2018-01-23 Thread Eric Blake
On 01/23/2018 10:47 AM, Daniel P. Berrange wrote:
> The make rules for building QEMU are mostly silent by default. They can
> be made verbose by setting the variable V=1. The default state does not
> however correspond to a V=0 setting - $(V) must be undefined / empty to
> get the default quiet build.

Makefiles generated by automake support V=0; how hard would it be to
instead tweak things so that 'V=' and 'V=0' have the same effect?

> 
> Signed-off-by: Daniel P. Berrange 
> ---
>  Makefile | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/Makefile b/Makefile
> index c263190b8d..554ba69ced 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -940,4 +940,5 @@ ifdef QEMU_GA_MSI_ENABLED
>  endif
>   @echo  ''
>  endif
> - @echo  '  $(MAKE) V=0|1 [targets] 0 => quiet build (default), 1 => 
> verbose build'
> + @echo  '  $(MAKE) [targets]  (quiet build, default)'
> + @echo  '  $(MAKE) V=1 [targets]  (verbose build)'
> 

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



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [qemu-s390x] [PULL 0/8] x86 queue, 2018-01-17

2018-01-23 Thread Michael Roth
Quoting Cornelia Huck (2018-01-23 04:50:45)
> On Tue, 23 Jan 2018 11:34:18 +0100
> Christian Ehrhardt  wrote:
> 
> > On Tue, Jan 23, 2018 at 10:59 AM, Christian Borntraeger
> >  wrote:
> > >
> > >
> > > On 01/23/2018 09:40 AM, Christian Ehrhardt wrote:  
> > >> On Thu, Jan 18, 2018 at 2:51 PM, Peter Maydell 
> > >>  wrote:  
> > >>> On 18 January 2018 at 02:01, Eduardo Habkost  
> > >>> wrote:  
> >  The following changes since commit 
> >  8e5dc9ba49743b46d955ec7dacb04e42ae7ada7c:
> > 
> >    Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180116' 
> >  into staging (2018-01-16 17:36:39 +)
> > 
> >  are available in the Git repository at:
> > 
> >    git://github.com/ehabkost/qemu.git tags/x86-pull-request
> > 
> >  for you to fetch changes up to 
> >  6cfbc54e8903a9bcc0346119949162d040c144c1:
> > 
> >    i386: Add EPYC-IBPB CPU model (2018-01-17 23:54:39 -0200)
> > 
> >  
> >  x86 queue, 2018-01-17
> > 
> >  Highlight: new CPU models that expose CPU features that guests
> >  can use to mitigate CVE-2017-5715 (Spectre variant #2).
> >   
> > >>>
> > >>> Applied, thanks.
> > >>>
> > >>> -- PMM
> > >>>  
> > >>
> > >> Hi,
> > >> I was kind of clinging to [1] so far and had the expectation that all
> > >> those would be wrapped up in 2.11.1 once ready.
> > >> I see that the s390x changes are targeted to qemu-stable (well to
> > >> admit I suggested so referring the article above).
> > >> So I'd expected to see this series to show up on qemu-stable as well
> > >> but haven't seen it so far.
> > >>
> > >> Therefore I wanted to ask if there was a change of plans in that
> > >> regard or if it needs just a few days more to see (part of) this
> > >> series on qemu-stable and on its way into 2.11.1?
> > >>
> > >> [1]: https://www.qemu.org/2018/01/04/spectre/  
> > >
> > > Adding Michael,
> > >
> > > Yes, I think it makes sense to have the guest enablement for the spectre
> > > mitigations available in 2.11.1 for all architectures that provide it.
> > > (this queue for x86, Connies pending S390 patches, whatever Power
> > > and arm will do).  
> > 
> > Also adding Suraj for a statement in this regard about his "[QEMU-PPC]
> > [PATCH V5 0/7] target/ppc: Rework spapr_caps" series which I think is
> > the PPC version of all of this right?
> > Not sure who to add for Arm :-/
> > 
> > @Cornelia - the consumers of these stable changes in particular IMHO
> > are Distributions for security updates.
> > Seeing at least one backport into 2.11.1 would be very helpful to
> > avoid issues that would not apply to a forward thinking 2.12 commit.
> > Such a (even short distance) backport being done by the Author would
> > have the lowest risk of such issues creeping in.
> > I'm not so sure on 2.(<11).x  - but one backport at least into the
> > latest release would be very nice to fulfill the [1] announcement
> > referenced above and provide a first release of these important
> > changes available earlier than full 2.12.
> 
> I agree that a backport unto 2.11.x is useful.
> 
> But I still think we should clarify the purpose of our stable tree --
> not necessarily in this thread, though.
> 

Generally the idea is a development cycle's worth of bug/security fixes
that a distro that bases on, say, 2.11, can pull in without any other
changes throughout their stack. Stuff like this is somewhat of an
exceptional case because it doesn't have any benefit to someone who
just drops it into their existing stack, but if it seems likely they'll
become reliant on it then it makes sense. We've done this in the past to
fix stuff like migration breakages that were discovered after release
and required new machine options. Certainly not an ideal situation
though.



Re: [Qemu-devel] [PATCH v2] kvm-all: Partially reverts 4fe6d78b2e to remove the cleanup call

2018-01-23 Thread Daniel Henrique Barboza


On 01/23/2018 03:54 PM, Jose Ricardo Ziviani wrote:

This commit partially reverts the commit 4fe6d78b2e because of issues
reported in the virtio.

Examples:

$ qemu-system-ppc64 -cpu POWER8 -nographic -vga none -m 4G \
   -M pseries,accel=kvm -netdev type=user,id=net0 \
   -device virtio-net-pci,netdev=net0 -drive file=../disk.qcow2,if=virtio

Populating /vdevice/nvram@7101
Populating /vdevice/v-scsi@7102
SCSI: Looking for devices
   8200 CD-ROM   : "QEMU QEMU CD-ROM  2.5+"
Populating /pci@8002000
  00  (D) : 1af4 1000virtio [ net ]
Aborted

$ qemu-system-x86_64 -m 4G -enable-kvm -drive file=util.qcow2,if=virtio

Running QEMU with GTK 2.x is deprecated, and will be removed
in a future release. Please switch to GTK 3.x instead
[1]5282 abort

Reference http://lists.nongnu.org/archive/html/qemu-devel/2018-01/msg05457.html

Reported-by: Anton Blanchard 
Signed-off-by: Jose Ricardo Ziviani 
---


This patch also fixed a migration problem I was investigating today. 
Turns out 4fe6d78b2e
is also to be blamed for this P8 -> P8 migration being broken in current 
master:



$ sudo ./qemu-system-ppc64 --enable-kvm --nographic -vga none -machine 
pseries -m 4G,slots=32,maxmem=32G -smp 1,maxcpus=32 -device 
virtio-blk-pci,drive=rootdisk -drive 
file=/home/danielhb/vm_imgs/f26.qcow2,if=none,cache=none,format=qcow2,id=rootdisk 
-incoming tcp:0:

qemu-system-ppc64: load of migration failed: Input/output error


Reverting 4fe6d78b2e or applying this patch fixes this migration issue too.


Reviewed-by: Daniel Henrique Barboza 
Tested-by: Daniel Henrique Barboza 



  accel/kvm/kvm-all.c | 4 
  1 file changed, 4 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 071f4f57c0..f290f487a5 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -812,10 +812,6 @@ static void kvm_mem_ioeventfd_del(MemoryListener *listener,
  if (r < 0) {
  abort();
  }
-
-if (e->cleanup) {
-e->cleanup(e);
-}
  }

  static void kvm_io_ioeventfd_add(MemoryListener *listener,





Re: [Qemu-devel] [PATCH v2 2/5] tpm: replace GThreadPool with AIO threadpool

2018-01-23 Thread Stefan Berger

On 01/19/2018 09:11 AM, Marc-André Lureau wrote:

The TPM backend uses a GThreadPool to handle IO in a seperate
thread. However, GThreadPool isn't integrated with Qemu main loops,
making it unnecessarily complicated to deal with.

Qemu has a AIO threadpool, that is better integrated with loops and
various IO functions, provides completion BH by default etc.

Remove the only user of GThreadPool from qemu, use AIO threadpool.

Note that the backend:
- no longer accepts queing multiple requests (unneeded so far)
- increase ref to itself when handling a command, for extra safety
- tpm_backend_thread_end() is renamed tpm_backend_finish_sync() and
will wait for completion of BH (request_completed), which will help
migration handling.

Signed-off-by: Marc-André Lureau 


I have been using this for a while:
Tested-by: Stefan Berger 
Reviewed-by: Stefan Berger 



---
  include/sysemu/tpm_backend.h | 12 --
  backends/tpm.c   | 52 +++-
  2 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index 0d6c994a62..a69593e0cd 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -45,9 +45,8 @@ struct TPMBackend {
  /*< protected >*/
  TPMIf *tpmif;
  bool opened;
-GThreadPool *thread_pool;
  bool had_startup_error;
-QEMUBH *bh;
+TPMBackendCmd *cmd;

  /*  */
  char *id;
@@ -196,6 +195,15 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
   */
  size_t tpm_backend_get_buffer_size(TPMBackend *s);

+/**
+ * tpm_backend_finish_sync:
+ * @s: the backend to call into
+ *
+ * Finish the pending command synchronously (this will call aio_poll()
+ * on qemu main AIOContext until it ends)
+ */
+void tpm_backend_finish_sync(TPMBackend *s);
+
  /**
   * tpm_backend_query_tpm:
   * @s: the backend
diff --git a/backends/tpm.c b/backends/tpm.c
index 91222c5164..143807aa37 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -19,30 +19,35 @@
  #include "sysemu/tpm.h"
  #include "qemu/thread.h"
  #include "qemu/main-loop.h"
+#include "block/thread-pool.h"
+#include "qemu/error-report.h"

-static void tpm_backend_request_completed_bh(void *opaque)
+static void tpm_backend_request_completed(void *opaque, int ret)
  {
  TPMBackend *s = TPM_BACKEND(opaque);
  TPMIfClass *tic = TPM_IF_GET_CLASS(s->tpmif);

  tic->request_completed(s->tpmif);
+
+/* no need for atomic, as long the BQL is taken */
+s->cmd = NULL;
+object_unref(OBJECT(s));
  }

-static void tpm_backend_worker_thread(gpointer data, gpointer user_data)
+static int tpm_backend_worker_thread(gpointer data)
  {
-TPMBackend *s = TPM_BACKEND(user_data);
+TPMBackend *s = TPM_BACKEND(data);
  TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);

-k->handle_request(s, (TPMBackendCmd *)data);
+k->handle_request(s, s->cmd);

-qemu_bh_schedule(s->bh);
+return 0;
  }

-static void tpm_backend_thread_end(TPMBackend *s)
+void tpm_backend_finish_sync(TPMBackend *s)
  {
-if (s->thread_pool) {
-g_thread_pool_free(s->thread_pool, FALSE, TRUE);
-s->thread_pool = NULL;
+while (s->cmd) {
+aio_poll(qemu_get_aio_context(), true);
  }
  }

@@ -74,10 +79,7 @@ int tpm_backend_startup_tpm(TPMBackend *s, size_t buffersize)
  TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);

  /* terminate a running TPM */
-tpm_backend_thread_end(s);
-
-s->thread_pool = g_thread_pool_new(tpm_backend_worker_thread, s, 1, TRUE,
-   NULL);
+tpm_backend_finish_sync(s);

  res = k->startup_tpm ? k->startup_tpm(s, buffersize) : 0;

@@ -93,7 +95,17 @@ bool tpm_backend_had_startup_error(TPMBackend *s)

  void tpm_backend_deliver_request(TPMBackend *s, TPMBackendCmd *cmd)
  {
-g_thread_pool_push(s->thread_pool, cmd, NULL);
+ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
+
+if (s->cmd != NULL) {
+error_report("There is a TPM request pending");
+return;
+}
+
+s->cmd = cmd;
+object_ref(OBJECT(s));
+thread_pool_submit_aio(pool, tpm_backend_worker_thread, s,
+   tpm_backend_request_completed, s);
  }

  void tpm_backend_reset(TPMBackend *s)
@@ -104,7 +116,7 @@ void tpm_backend_reset(TPMBackend *s)
  k->reset(s);
  }

-tpm_backend_thread_end(s);
+tpm_backend_finish_sync(s);

  s->had_startup_error = false;
  }
@@ -159,28 +171,18 @@ TPMInfo *tpm_backend_query_tpm(TPMBackend *s)
  return info;
  }

-static void tpm_backend_instance_init(Object *obj)
-{
-TPMBackend *s = TPM_BACKEND(obj);
-
-s->bh = qemu_bh_new(tpm_backend_request_completed_bh, s);
-}
-
  static void tpm_backend_instance_finalize(Object *obj)
  {
  TPMBackend *s = TPM_BACKEND(obj);

  object_unref(OBJECT(s->tpmif));
  g_free(s->id);

[Qemu-devel] [PATCH v4 07/10] s390-ccw: read stage2 boot loader data to find menu

2018-01-23 Thread Collin L. Walling
Read the stage2 boot loader data block-by-block. We scan the
current block for the string "zIPL" to detect the start of the
boot menu banner. We then load the adjacent blocks (previous
block and next block) to account for the possibility of menu
data spanning multiple blocks.

Signed-off-by: Collin L. Walling 
---
 pc-bios/s390-ccw/bootmap.c | 94 +++---
 pc-bios/s390-ccw/bootmap.h |  1 +
 pc-bios/s390-ccw/menu.c|  5 +++
 pc-bios/s390-ccw/menu.h|  1 +
 4 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 0da4c7f..7d7e0c5 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -13,6 +13,7 @@
 #include "bootmap.h"
 #include "virtio.h"
 #include "bswap.h"
+#include "menu.h"
 
 #ifdef DEBUG
 /* #define DEBUG_FALLBACK */
@@ -83,6 +84,10 @@ static void jump_to_IPL_code(uint64_t address)
 
 static unsigned char _bprs[8*1024]; /* guessed "max" ECKD sector size */
 static const int max_bprs_entries = sizeof(_bprs) / sizeof(ExtEckdBlockPtr);
+static uint8_t _s2[MAX_SECTOR_SIZE * 3] 
__attribute__((__aligned__(PAGE_SIZE)));
+static void *s2_prev_blk = _s2;
+static void *s2_cur_blk = _s2 + MAX_SECTOR_SIZE;
+static void *s2_next_blk = _s2 + MAX_SECTOR_SIZE * 2;
 
 static inline void verify_boot_info(BootInfo *bip)
 {
@@ -182,7 +187,76 @@ static block_number_t load_eckd_segments(block_number_t 
blk, uint64_t *address)
 return block_nr;
 }
 
-static void run_eckd_boot_script(block_number_t bmt_block_nr)
+static bool find_zipl_boot_menu_banner(int *offset)
+{
+int i;
+
+/* Menu banner starts with "zIPL" */
+for (i = 0; i < virtio_get_block_size() - 4; i++) {
+if (magic_match(s2_cur_blk + i, ZIPL_MAGIC_EBCDIC)) {
+*offset = i;
+return true;
+}
+}
+
+return false;
+}
+
+static int eckd_get_boot_menu_index(block_number_t s1b_block_nr)
+{
+block_number_t cur_block_nr;
+block_number_t prev_block_nr = 0;
+block_number_t next_block_nr = 0;
+EckdStage1b *s1b = (void *)sec;
+int offset;
+int i;
+
+/* Get Stage1b data */
+memset(sec, FREE_SPACE_FILLER, sizeof(sec));
+read_block(s1b_block_nr, s1b, "Cannot read stage1b boot loader");
+
+memset(_s2, FREE_SPACE_FILLER, sizeof(_s2));
+
+/* Get Stage2 data */
+for (i = 0; i < STAGE2_BLK_CNT_MAX; i++) {
+cur_block_nr = eckd_block_num(s1b->seek[i].chs);
+
+if (!cur_block_nr) {
+break;
+}
+
+read_block(cur_block_nr, s2_cur_blk, "Cannot read stage2 boot loader");
+
+if (find_zipl_boot_menu_banner()) {
+/* Load the adjacent blocks to account for the
+ * possibility of menu data spanning multiple blocks.
+ */
+if (prev_block_nr) {
+read_block(prev_block_nr, s2_prev_blk,
+   "Cannot read stage2 boot loader");
+}
+
+if (i + 1 < STAGE2_BLK_CNT_MAX) {
+next_block_nr = eckd_block_num(s1b->seek[i + 1].chs);
+}
+
+if (next_block_nr) {
+read_block(next_block_nr, s2_next_blk,
+   "Cannot read stage2 boot loader");
+}
+
+return menu_get_zipl_boot_index(s2_cur_blk, offset);
+}
+
+prev_block_nr = cur_block_nr;
+}
+
+sclp_print("No zipl boot menu data found. Booting default entry.");
+return 0;
+}
+
+static void run_eckd_boot_script(block_number_t bmt_block_nr,
+ block_number_t s1b_block_nr)
 {
 int i;
 unsigned int loadparm = get_loadparm_index();
@@ -191,6 +265,10 @@ static void run_eckd_boot_script(block_number_t 
bmt_block_nr)
 BootMapTable *bmt = (void *)sec;
 BootMapScript *bms = (void *)sec;
 
+if (menu_check_flags(BOOT_MENU_FLAG_BOOT_OPTS | BOOT_MENU_FLAG_ZIPL_OPTS)) 
{
+loadparm = eckd_get_boot_menu_index(s1b_block_nr);
+}
+
 debug_print_int("loadparm", loadparm);
 IPL_assert(loadparm < 31, "loadparm value greater than"
" maximum number of boot entries allowed");
@@ -223,7 +301,7 @@ static void ipl_eckd_cdl(void)
 XEckdMbr *mbr;
 EckdCdlIpl2 *ipl2 = (void *)sec;
 IplVolumeLabel *vlbl = (void *)sec;
-block_number_t bmt_block_nr;
+block_number_t bmt_block_nr, s1b_block_nr;
 
 /* we have just read the block #0 and recognized it as "IPL1" */
 sclp_print("CDL\n");
@@ -241,6 +319,9 @@ static void ipl_eckd_cdl(void)
 /* save pointer to Boot Map Table */
 bmt_block_nr = eckd_block_num(mbr->blockptr.xeckd.bptr.chs);
 
+/* save pointer to Stage1b Data */
+s1b_block_nr = eckd_block_num(ipl2->stage1.seek[0].chs);
+
 memset(sec, FREE_SPACE_FILLER, sizeof(sec));
 read_block(2, vlbl, "Cannot read Volume Label at block 2");
 IPL_assert(magic_match(vlbl->key, VOL1_MAGIC),
@@ -249,7 +330,7 @@ static void 

[Qemu-devel] [PATCH v4 09/10] s390-ccw: read user input for boot index via the SCLP console

2018-01-23 Thread Collin L. Walling
Implements an sclp_read function to capture input from the
console and a wrapper function that handles parsing certain
characters and adding input to a buffer. The input is checked
for any erroneous values and is handled appropriately.

A prompt will persist until input is entered or the timeout
expires (if one was set). Example:

Please choose (default will boot in 10 seconds):

Correct input will boot the respective boot index. If the
user's input is empty, 0, or if the timeout expires, then
the default zipl entry will be chosen. If the input is
within the range of available boot entries, then the
selection will be booted. Any erroneous input will cancel
the timeout and re-prompt the user.

Signed-off-by: Collin L. Walling 
---
 pc-bios/s390-ccw/menu.c | 152 +++-
 pc-bios/s390-ccw/s390-ccw.h |   2 +
 pc-bios/s390-ccw/sclp.c |  20 ++
 pc-bios/s390-ccw/virtio.c   |   2 +-
 4 files changed, 172 insertions(+), 4 deletions(-)

diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index 174285e..24d4bba 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -12,16 +12,162 @@
 #include "menu.h"
 #include "s390-ccw.h"
 
-static uint8_t flags;
-static uint64_t timeout;
+#define KEYCODE_NO_INP '\0'
+#define KEYCODE_ESCAPE '\033'
+#define KEYCODE_BACKSP '\177'
+#define KEYCODE_ENTER  '\r'
 
 /* Offsets from zipl fields to zipl banner start */
 #define ZIPL_TIMEOUT_OFFSET 138
 #define ZIPL_FLAG_OFFSET140
 
+#define TOD_CLOCK_SECOND0xf424
+
+static uint8_t flags;
+static uint64_t timeout;
+
+static inline void enable_clock_int(void)
+{
+uint64_t tmp = 0;
+
+asm volatile(
+"stctg  0,0,%0\n"
+"oi 6+%0, 0x8\n"
+"lctlg  0,0,%0"
+: : "Q" (tmp) : "memory"
+);
+}
+
+static inline void disable_clock_int(void)
+{
+uint64_t tmp = 0;
+
+asm volatile(
+"stctg  0,0,%0\n"
+"ni 6+%0, 0xf7\n"
+"lctlg  0,0,%0"
+: : "Q" (tmp) : "memory"
+);
+}
+
+static inline void set_clock_comparator(uint64_t time)
+{
+asm volatile("sckc %0" : : "Q" (time));
+}
+
+static inline bool check_clock_int(void)
+{
+uint16_t *code = (uint16_t *)0x86; /* low-core external interrupt code */
+
+consume_sclp_int();
+
+return *code == 0x1004;
+}
+
+static int read_prompt(char *buf, size_t len)
+{
+char inp[2] = {};
+uint8_t idx = 0;
+uint64_t time;
+
+if (timeout) {
+time = get_clock() + (timeout * TOD_CLOCK_SECOND);
+set_clock_comparator(time);
+enable_clock_int();
+timeout = 0;
+}
+
+while (!check_clock_int()) {
+
+/* Process only one character at a time */
+sclp_read(inp, 1);
+
+switch (inp[0]) {
+case KEYCODE_NO_INP:
+case KEYCODE_ESCAPE:
+continue;
+case KEYCODE_BACKSP:
+if (idx > 0) {
+buf[--idx] = 0;
+sclp_print("\b \b");
+}
+continue;
+case KEYCODE_ENTER:
+disable_clock_int();
+return idx;
+}
+
+/* Echo input and add to buffer */
+if (idx < len) {
+buf[idx] = inp[0];
+sclp_print(inp);
+idx++;
+}
+}
+
+disable_clock_int();
+*buf = 0;
+
+return 0;
+}
+
+static int get_index(void)
+{
+char buf[10];
+int len;
+int i;
+
+memset(buf, 0, sizeof(buf));
+
+len = read_prompt(buf, sizeof(buf));
+
+/* If no input, boot default */
+if (len == 0) {
+return 0;
+}
+
+/* Check for erroneous input */
+for (i = 0; i < len; i++) {
+if (!isdigit(buf[i])) {
+return -1;
+}
+}
+
+return atoi(buf);
+}
+
+static void boot_menu_prompt(bool retry)
+{
+char tmp[6];
+
+if (retry) {
+sclp_print("\nError: undefined configuration"
+   "\nPlease choose:\n");
+} else if (timeout > 0) {
+sclp_print("Please choose (default will boot in ");
+sclp_print(itostr(timeout, tmp, sizeof(tmp)));
+sclp_print(" seconds):\n");
+} else {
+sclp_print("Please choose:\n");
+}
+}
+
 static int get_boot_index(int entries)
 {
-return 0; /* Implemented next patch */
+int boot_index;
+bool retry = false;
+char tmp[5];
+
+do {
+boot_menu_prompt(retry);
+boot_index = get_index();
+retry = true;
+} while (boot_index < 0 || boot_index >= entries);
+
+sclp_print("\nBooting entry #");
+sclp_print(itostr(boot_index, tmp, sizeof(tmp)));
+
+return boot_index;
 }
 
 static void zipl_println(const char *data, size_t len)
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 25d4d21..df4bc88 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -71,6 +71,7 @@ unsigned int get_loadparm_index(void);
 void 

[Qemu-devel] [PATCH v4 03/10] s390-ccw: refactor IPL structs

2018-01-23 Thread Collin L. Walling
ECKD DASDs have different IPL structures for CDL and LDL
formats. The current Ipl1 and Ipl2 structs follow the CDL
format, so we prepend "EckdCdl" to them. Boot info for LDL
has been moved to a new struct: EckdLdlIpl1.

Also introduce structs for IPL stages 1 and 1b.

Signed-off-by: Collin L. Walling 
Acked-by: Janosch Frank 
---
 pc-bios/s390-ccw/bootmap.c | 12 +-
 pc-bios/s390-ccw/bootmap.h | 55 --
 2 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 621adbe..b01e0f6 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -221,7 +221,7 @@ static void run_eckd_boot_script(block_number_t 
bmt_block_nr)
 static void ipl_eckd_cdl(void)
 {
 XEckdMbr *mbr;
-Ipl2 *ipl2 = (void *)sec;
+EckdCdlIpl2 *ipl2 = (void *)sec;
 IplVolumeLabel *vlbl = (void *)sec;
 block_number_t bmt_block_nr;
 
@@ -231,7 +231,7 @@ static void ipl_eckd_cdl(void)
 memset(sec, FREE_SPACE_FILLER, sizeof(sec));
 read_block(1, ipl2, "Cannot read IPL2 record at block 1");
 
-mbr = >u.x.mbr;
+mbr = >mbr;
 IPL_assert(magic_match(mbr, ZIPL_MAGIC), "No zIPL section in IPL2 
record.");
 IPL_assert(block_size_ok(mbr->blockptr.xeckd.bptr.size),
"Bad block size in zIPL section of IPL2 record.");
@@ -281,7 +281,7 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode)
 static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
 {
 block_number_t bmt_block_nr;
-BootInfo *bip = (void *)(sec + 0x70); /* BootInfo is MBR for LDL */
+EckdLdlIpl1 *ipl1 = (void *)sec;
 
 if (mode != ECKD_LDL_UNLABELED) {
 print_eckd_ldl_msg(mode);
@@ -292,15 +292,15 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
 memset(sec, FREE_SPACE_FILLER, sizeof(sec));
 read_block(0, sec, "Cannot read block 0 to grab boot info.");
 if (mode == ECKD_LDL_UNLABELED) {
-if (!magic_match(bip->magic, ZIPL_MAGIC)) {
+if (!magic_match(ipl1->bip.magic, ZIPL_MAGIC)) {
 return; /* not applicable layout */
 }
 sclp_print("unlabeled LDL.\n");
 }
-verify_boot_info(bip);
+verify_boot_info(>bip);
 
 /* save pointer to Boot Map Table */
-bmt_block_nr = eckd_block_num(bip->bp.ipl.bm_ptr.eckd.bptr.chs);
+bmt_block_nr = eckd_block_num(ipl1->bip.bp.ipl.bm_ptr.eckd.bptr.chs);
 
 run_eckd_boot_script(bmt_block_nr);
 /* no return */
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index 260ac2a..460ec1a 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -237,22 +237,45 @@ typedef struct BootInfo {  /* @ 0x70, record #0   
 */
 } bp;
 } __attribute__ ((packed)) BootInfo; /* see also XEckdMbr   */
 
-typedef struct Ipl1 {
-unsigned char key[4]; /* == "IPL1" */
-unsigned char data[24];
-} __attribute__((packed)) Ipl1;
-
-typedef struct Ipl2 {
-unsigned char key[4]; /* == "IPL2" */
-union {
-unsigned char data[144];
-struct {
-unsigned char reserved1[92-4];
-XEckdMbr mbr;
-unsigned char reserved2[144-(92-4)-sizeof(XEckdMbr)];
-} x;
-} u;
-} __attribute__((packed)) Ipl2;
+/*
+ * Structs for IPL
+ */
+#define STAGE2_BLK_CNT_MAX  24 /* Stage 1b can load up to 24 blocks */
+
+typedef struct EckdCdlIpl1 {
+uint8_t key[4]; /* == "IPL1" */
+uint8_t data[24];
+} __attribute__((packed)) EckdCdlIpl1;
+
+typedef struct EckdSeekArg {
+uint16_t pad;
+EckdCHS chs;
+uint8_t pad2;
+} __attribute__ ((packed)) EckdSeekArg;
+
+typedef struct EckdStage1b {
+uint8_t reserved[32 * STAGE2_BLK_CNT_MAX];
+struct EckdSeekArg seek[STAGE2_BLK_CNT_MAX];
+uint8_t unused[64];
+} __attribute__ ((packed)) EckdStage1b;
+
+typedef struct EckdStage1 {
+uint8_t reserved[72];
+struct EckdSeekArg seek[2];
+} __attribute__ ((packed)) EckdStage1;
+
+typedef struct EckdCdlIpl2 {
+uint8_t key[4]; /* == "IPL2" */
+struct EckdStage1 stage1;
+XEckdMbr mbr;
+uint8_t reserved[24];
+} __attribute__((packed)) EckdCdlIpl2;
+
+typedef struct EckdLdlIpl1 {
+uint8_t reserved[24];
+struct EckdStage1 stage1;
+BootInfo bip; /* BootInfo is MBR for LDL */
+} __attribute__((packed)) EckdLdlIpl1;
 
 typedef struct IplVolumeLabel {
 unsigned char key[4]; /* == "VOL1" */
-- 
2.7.4




[Qemu-devel] [PATCH v4 08/10] s390-ccw: print zipl boot menu

2018-01-23 Thread Collin L. Walling
When the boot menu options are present and the guest's
disk has been configured by the zipl tool, then the user
will be presented with an interactive boot menu with
labeled entries. An example of what the menu might look
like:

zIPL v1.37.1-build-20170714 interactive boot menu.

  0. default (linux-4.13.0)

  1. linux-4.13.0
  2. performance
  3. kvm

Signed-off-by: Collin L. Walling 
---
 pc-bios/s390-ccw/menu.c | 51 -
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index de12c73..174285e 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -10,13 +10,62 @@
  */
 
 #include "menu.h"
+#include "s390-ccw.h"
 
 static uint8_t flags;
 static uint64_t timeout;
 
+/* Offsets from zipl fields to zipl banner start */
+#define ZIPL_TIMEOUT_OFFSET 138
+#define ZIPL_FLAG_OFFSET140
+
+static int get_boot_index(int entries)
+{
+return 0; /* Implemented next patch */
+}
+
+static void zipl_println(const char *data, size_t len)
+{
+char buf[len + 2];
+
+ebcdic_to_ascii(data, buf, len);
+buf[len] = '\n';
+buf[len + 1] = '\0';
+
+sclp_print(buf);
+}
+
 int menu_get_zipl_boot_index(const void *stage2, int offset)
 {
-return 0; /* implemented next patch */
+const char *data = stage2 + offset;
+uint16_t flag;
+size_t len;
+int ct;
+
+flag = *(uint16_t *)(data - ZIPL_FLAG_OFFSET);
+
+if (flags & BOOT_MENU_FLAG_ZIPL_OPTS) {
+if (flag) {
+timeout = *(uint16_t *)(data - ZIPL_TIMEOUT_OFFSET);
+} else {
+return 0; /* Boot default */
+}
+}
+
+/* Print and count all menu items, including the banner */
+for (ct = 0; *data; ct++) {
+len = strlen(data);
+zipl_println(data, len);
+data += len + 1;
+
+if (ct < 2) {
+sclp_print("\n");
+}
+}
+
+sclp_print("\n");
+
+return get_boot_index(ct - 1);
 }
 
 void menu_set_parms(uint8_t boot_menu_flag, uint16_t boot_menu_timeout)
-- 
2.7.4




[Qemu-devel] [PATCH v4 05/10] s390-ccw: parse and set boot menu options

2018-01-23 Thread Collin L. Walling
Set boot menu options for an s390 guest and store them in
the iplb. These options are set via the QEMU command line
option:

-boot menu=on|off[,splash-time=X]

or via the libvirt domain xml:


  


Where X represents some positive integer representing
milliseconds.

Any value set for loadparm will override all boot menu options.
If loadparm=PROMPT, then the menu will be enabled without a
timeout.

The absence of any boot options on the command line will flag
to later use the zipl boot loader values.

Signed-off-by: Collin L. Walling 
Reviewed-by: Janosch Frank 
Reviewed-by: Thomas Huth 
---
 hw/s390x/ipl.c  | 55 +
 hw/s390x/ipl.h  | 11 --
 pc-bios/s390-ccw/iplb.h |  8 +--
 3 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 0d06fc1..a1eb8fe 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -23,6 +23,8 @@
 #include "hw/s390x/ebcdic.h"
 #include "ipl.h"
 #include "qemu/error-report.h"
+#include "qemu/config-file.h"
+#include "qemu/cutils.h"
 
 #define KERN_IMAGE_START0x01UL
 #define KERN_PARM_AREA  0x010480UL
@@ -219,6 +221,56 @@ static Property s390_ipl_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void s390_ipl_set_boot_menu(IplParameterBlock *iplb)
+{
+QemuOptsList *plist = qemu_find_opts("boot-opts");
+QemuOpts *opts = QTAILQ_FIRST(>head);
+uint8_t *flags;
+uint16_t *timeout;
+const char *tmp;
+unsigned long result = 0;
+
+switch (iplb->pbt) {
+case S390_IPL_TYPE_CCW:
+flags = >ccw.boot_menu_flags;
+timeout = >ccw.boot_menu_timeout;
+break;
+case S390_IPL_TYPE_QEMU_SCSI:
+flags = >scsi.boot_menu_flags;
+timeout = >scsi.boot_menu_timeout;
+break;
+default:
+error_report("boot menu is not supported for this device type.");
+return;
+}
+
+/* In the absence of -boot menu, use zipl parameters */
+if (!qemu_opt_get(opts, "menu")) {
+*flags = BOOT_MENU_FLAG_ZIPL_OPTS;
+} else if (boot_menu) {
+*flags = BOOT_MENU_FLAG_BOOT_OPTS;
+
+tmp = qemu_opt_get(opts, "splash-time");
+
+if (tmp && qemu_strtoul(tmp, NULL, 10, )) {
+error_report("splash-time value is invalid, forcing it to 0.");
+*timeout = 0;
+return;
+}
+
+result = (result + 500) / 1000; /* Round and convert to seconds */
+
+if (result > 0x) {
+error_report("splash-time value is greater than 65535000,"
+ " forcing it to 65535000.");
+*timeout = 0x;
+return;
+}
+
+*timeout = cpu_to_be16(result);
+}
+}
+
 static bool s390_gen_initial_iplb(S390IPLState *ipl)
 {
 DeviceState *dev_st;
@@ -273,6 +325,9 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
 if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
 ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
 }
+
+s390_ipl_set_boot_menu(>iplb);
+
 return true;
 }
 
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 8a705e0..48e82cf 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -15,9 +15,14 @@
 #include "hw/qdev.h"
 #include "cpu.h"
 
+#define BOOT_MENU_FLAG_BOOT_OPTS 0x80
+#define BOOT_MENU_FLAG_ZIPL_OPTS 0x40
+
 struct IplBlockCcw {
 uint64_t netboot_start_addr;
-uint8_t  reserved0[77];
+uint8_t  reserved0[74];
+uint16_t boot_menu_timeout;
+uint8_t  boot_menu_flags;
 uint8_t  ssid;
 uint16_t devno;
 uint8_t  vm_flags;
@@ -51,7 +56,9 @@ struct IplBlockQemuScsi {
 uint32_t lun;
 uint16_t target;
 uint16_t channel;
-uint8_t  reserved0[77];
+uint8_t  reserved0[74];
+uint16_t boot_menu_timeout;
+uint8_t  boot_menu_flags;
 uint8_t  ssid;
 uint16_t devno;
 } QEMU_PACKED;
diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h
index 890aed9..fe909d2 100644
--- a/pc-bios/s390-ccw/iplb.h
+++ b/pc-bios/s390-ccw/iplb.h
@@ -14,7 +14,9 @@
 
 struct IplBlockCcw {
 uint64_t netboot_start_addr;
-uint8_t  reserved0[77];
+uint8_t  reserved0[74];
+uint16_t boot_menu_timeout;
+uint8_t  boot_menu_flags;
 uint8_t  ssid;
 uint16_t devno;
 uint8_t  vm_flags;
@@ -48,7 +50,9 @@ struct IplBlockQemuScsi {
 uint32_t lun;
 uint16_t target;
 uint16_t channel;
-uint8_t  reserved0[77];
+uint8_t  reserved0[74];
+uint16_t boot_menu_timeout;
+uint8_t  boot_menu_flags;
 uint8_t  ssid;
 uint16_t devno;
 } __attribute__ ((packed));
-- 
2.7.4




  1   2   3   >