Re: [Qemu-devel] [RFC PATCH 0/2] ARM: add QMP command to query GIC version

2016-02-14 Thread Fam Zheng
On Mon, 02/15 15:34, Peter Xu wrote:
> On Mon, Feb 15, 2016 at 12:54:57AM -0600, Wei Huang wrote:
> > On 2/13/16 23:41, Peter Xu wrote:
> > > One question: how should I make this command "ARM only"? I see that
> > > in qmp-commands.hx, I can use something like "#if defined
> > > TARGET_ARM" to block out ARM specified commands, however how should
> > > I do the similiar thing in qapi-schema.json?
> > 
> > This situation is similar to "rtc-reset-reinjection", right? I think You
> > can disable this feature on other arch's by setting
> > QERR_FEATURE_DISABLED in file like monitor.c.
> 
> Yes. Will include this when post the real patches.

Yes, I think returning an error for non-ARM targets suffices.

Fam




Re: [Qemu-devel] [RFC PATCH 0/2] ARM: add QMP command to query GIC version

2016-02-14 Thread Peter Xu
On Mon, Feb 15, 2016 at 12:54:57AM -0600, Wei Huang wrote:
> On 2/13/16 23:41, Peter Xu wrote:
> > Please help review whether the interface suits our need, also please
> > point out any error I have made.
> 
> I tested QEMU with these patches and they were able to work on a native
> ARM64 machine.

Thanks for the verification. :)

> 
> > 
> > One question: how should I make this command "ARM only"? I see that
> > in qmp-commands.hx, I can use something like "#if defined
> > TARGET_ARM" to block out ARM specified commands, however how should
> > I do the similiar thing in qapi-schema.json?
> 
> This situation is similar to "rtc-reset-reinjection", right? I think You
> can disable this feature on other arch's by setting
> QERR_FEATURE_DISABLED in file like monitor.c.

Yes. Will include this when post the real patches.

Thanks!
Peter



Re: [Qemu-devel] [PATCH V3 1/2] net/filter-mirror:Add filter-mirror

2016-02-14 Thread Zhang Chen



On 02/15/2016 01:23 PM, Jason Wang wrote:


On 02/04/2016 05:00 PM, Zhang Chen wrote:


On 02/04/2016 03:43 PM, Zhang Chen wrote:

From: ZhangChen 

Filter-mirror is a netfilter plugin.
It gives qemu the ability to copy and mirror guest's
net packet. we output packet to chardev.

To make it compact, how about "It gives qemu the ability to mirror
packets to a chardev."?


OK, will fix it in next version.


usage:

-netdev tap,id=hn0
-chardev socket,id=mirror0,host=ip_primary,port=X,server,nowait
-filter-mirror,id=m0,netdev=hn0,queue=tx/rx/all,outdev=mirror0

An issue with mirror (and dump) is that it can not work correctly with
the netdev that has a vnet header. Need to fix this, a possible solution
is to checksum the buffer and strip the header before passing it to a
chardev.



Thanks, I don't consider about vnet, we will fix it in next version.


Signed-off-by: ZhangChen 
Signed-off-by: Wen Congyang 
Reviewed-by: Yang Hongyang 
Reviewed-by: zhanghailiang 
---
   net/Makefile.objs   |   1 +
   net/filter-mirror.c | 171

   qemu-options.hx |   5 ++
   vl.c|   3 +-
   4 files changed, 179 insertions(+), 1 deletion(-)
   create mode 100644 net/filter-mirror.c

diff --git a/net/Makefile.objs b/net/Makefile.objs
index 5fa2f97..de06ebe 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -15,3 +15,4 @@ common-obj-$(CONFIG_VDE) += vde.o
   common-obj-$(CONFIG_NETMAP) += netmap.o
   common-obj-y += filter.o
   common-obj-y += filter-buffer.o
+common-obj-y += traffic-mirror.o

s/traffic-mirror.o/filter-mirror.o/ rebase error


diff --git a/net/filter-mirror.c b/net/filter-mirror.c
new file mode 100644
index 000..87ccaf5
--- /dev/null
+++ b/net/filter-mirror.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Author: Zhang Chen 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "net/filter.h"
+#include "net/net.h"
+#include "qemu-common.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi-visit.h"
+#include "qom/object.h"
+#include "qemu/main-loop.h"
+#include "qemu/error-report.h"
+#include "trace.h"
+#include "sysemu/char.h"
+#include "qemu/iov.h"
+#include "qemu/sockets.h"
+
+#define FILTER_MIRROR(obj) \
+OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR)
+
+#define TYPE_FILTER_MIRROR "filter-mirror"
+
+typedef struct MirrorState {
+NetFilterState parent_obj;
+char *outdev;
+CharDriverState *chr_out;
+} MirrorState;
+
+static ssize_t filter_mirror_send(NetFilterState *nf,
+   const struct iovec *iov,
+   int iovcnt)
+{
+MirrorState *s = FILTER_MIRROR(nf);
+ssize_t ret = 0;
+ssize_t size = 0;
+uint32_t len =  0;
+char *buf;
+
+size = iov_size(iov, iovcnt);
+len = htonl(size);
+if (!size) {
+return 0;
+}
+
+buf = g_malloc0(size);
+iov_to_buf(iov, iovcnt, 0, buf, size);
+ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *),
sizeof(len));
+if (ret < 0) {

I believe we should also fail when ret < sizeof(len) and modify the
caller check in filter_mirror_iov(). To make this a little bit easier,
there's no need to return ssize_t here (otherwise, caller need to call
iov_size() before checking the return value), just return 0 for success
and -EFXXX for failure.


OK, will fix it in next version

Thanks
zhangchen


Other looks good.



.



--
Thanks
zhangchen






Re: [Qemu-devel] [PATCH v15 0/9] Block replication for continuous checkpoints

2016-02-14 Thread Changlong Xie

Hi all

It seems no any review during the long Spring festival. Ping :)

Thanks
-Xie

On 02/05/2016 12:17 PM, Changlong Xie wrote:

Block replication is a very important feature which is used for
continuous checkpoints(for example: COLO).

You can get the detailed information about block replication from here:
http://wiki.qemu.org/Features/BlockReplication

Usage:
Please refer to docs/block-replication.txt

This patch series is based on the following patch series:
1. http://lists.nongnu.org/archive/html/qemu-devel/2015-12/msg04570.html

Patch status:
1. Acked patches: none
2. Reviewed patches: patch 4
3. Updated patches: patch 3, 4, 5, 7, 8
Note: patch 7 is a new patch that introduces genernal start/stop/checkpoint/
get_error
APIs.

You can get the patch here:
https://github.com/Pating/qemu/tree/changlox/block-replication-v15

You can get the patch with framework here:
https://github.com/Pating/qemu/tree/changlox/colo_framework_v14

TODO:
1. Continuous block replication. It will be started after basic functions
are accepted.

Changs Log:
V15:
1. Rebase to the newest codes
2. Fix typos and coding style addresed Eric's comments
3. Address Stefan's comments
1) Make backup_do_checkpoint public, drop the changes on BlockJobDriver
2) Update the message and description for [PATCH 4/9]
3) Make replication_(start/stop/do_checkpoint)_all as global interfaces
4) Introduce AioContext lock to protect start/stop/do_checkpoint callbacks
5) Use BdrvChild instead of holding on to BlockDriverState * pointers
4. Clear BDRV_O_INACTIVE for hidden disk's open_flags since commit 09e0c771
5. Introduce replication_get_error_all to check replication status
6. Remove useless discard interface
V14:
1. Implement auto complete active commit
2. Implement active commit block job for replication.c
3. Address the comments from Stefan, add replication-specific API and data
structure, also remove old block layer APIs
V13:
1. Rebase to the newest codes
2. Remove redundant marcos and semicolon in replication.c
3. Fix typos in block-replication.txt
V12:
1. Rebase to the newest codes
2. Use backing reference to replcace 'allow-write-backing-file'
V11:
1. Reopen the backing file when starting blcok replication if it is not
opened in R/W mode
2. Unblock BLOCK_OP_TYPE_BACKUP_SOURCE and BLOCK_OP_TYPE_BACKUP_TARGET
when opening backing file
3. Block the top BDS so there is only one block job for the top BDS and
its backing chain.
V10:
1. Use blockdev-remove-medium and blockdev-insert-medium to replace backing
reference.
2. Address the comments from Eric Blake
V9:
1. Update the error messages
2. Rebase to the newest qemu
3. Split child add/delete support. These patches are sent in another patchset.
V8:
1. Address Alberto Garcia's comments
V7:
1. Implement adding/removing quorum child. Remove the option non-connect.
2. Simplify the backing refrence option according to Stefan Hajnoczi's 
suggestion
V6:
1. Rebase to the newest qemu.
V5:
1. Address the comments from Gong Lei
2. Speed the failover up. The secondary vm can take over very quickly even
if there are too many I/O requests.
V4:
1. Introduce a new driver replication to avoid touch nbd and qcow2.
V3:
1: use error_setg() instead of error_set()
2. Add a new block job API
3. Active disk, hidden disk and nbd target uses the same AioContext
4. Add a testcase to test new hbitmap API
V2:
1. Redesign the secondary qemu(use image-fleecing)
2. Use Error objects to return error message
3. Address the comments from Max Reitz and Eric Blake

Changlong Xie (1):
   Introduce new APIs to do replication operation

Wen Congyang (8):
   unblock backup operations in backing file
   Store parent BDS in BdrvChild
   Backup: clear all bitmap when doing block checkpoint
   Link backup into block core
   docs: block replication's description
   auto complete active commit
   Implement new driver for block replication
   support replication driver in blockdev-add

  Makefile.objs  |   1 +
  block.c|  19 ++
  block/Makefile.objs|   3 +-
  block/backup.c |  15 ++
  block/mirror.c |  13 +-
  block/replication.c| 594 +
  blockdev.c |   2 +-
  docs/block-replication.txt | 238 ++
  include/block/block_int.h  |   6 +-
  qapi/block-core.json   |  33 ++-
  qemu-img.c |   2 +-
  replication.c  |  94 +++
  replication.h  |  53 
  13 files changed, 1063 insertions(+), 10 deletions(-)
  create mode 100644 block/replication.c
  create mode 100644 docs/block-replication.txt
  create mode 100644 replication.c
  create mode 100644 replication.h







Re: [Qemu-devel] [RFC PATCH 0/2] ARM: add QMP command to query GIC version

2016-02-14 Thread Wei Huang


On 2/13/16 23:41, Peter Xu wrote:
> For ARM platform, we still do not have any interface to query
> whether current QEMU/host support specific GIC version. This
> patchset is trying to add one QMP interface for that. By querying
> the GIC capability using the new interface, one should know exactly
> what GIC version(s) the platform will support. The capability bits
> will be decided by both QEMU and host kernel.
> 
> The current patchset only provides interface for review. Its handler
> is a fake one which returns empty always.
> 
> The command interface I am planning to add is something like this:
> 
> -> { "execute": "query-gic-capability" }
> <- { "return": [ "gicv2", "gicv2-kvm", "gicv3-kvm" ] }
> 
> Currently, all the possible supported GIC versions are:
> 
> - gicv2:  GIC version 2 without kernel IRQ chip
> - gicv2-kvm:  GIC version 2 with kernel IRQ chip
> - gicv3:  GIC version 3 without kernel IRQ chip (not supported)
> - gicv3-kvm:  GIC version 3 with kernel IRQ chip
> 
> Since "gicv3" is still not supported (to use GICv3, kernel irqchip
> support is required for now, which corresponds to "gicv3-kvm"),
> currently the maximum superset of the result should be:
> 
> ["gicv2", "gicv2-kvm", "gicv3-kvm"]
> 
> Please help review whether the interface suits our need, also please
> point out any error I have made.

I tested QEMU with these patches and they were able to work on a native
ARM64 machine.

> 
> One question: how should I make this command "ARM only"? I see that
> in qmp-commands.hx, I can use something like "#if defined
> TARGET_ARM" to block out ARM specified commands, however how should
> I do the similiar thing in qapi-schema.json?

This situation is similar to "rtc-reset-reinjection", right? I think You
can disable this feature on other arch's by setting
QERR_FEATURE_DISABLED in file like monitor.c.

> 
> Thanks!
> Peter
> 
> Peter Xu (2):
>   arm: gic: add GICType
>   arm: gic: add "query-gic-capability" interface
> 
>  qapi-schema.json | 28 
>  qmp-commands.hx  | 25 +
>  qmp.c|  5 +
>  scripts/qapi.py  |  1 +
>  4 files changed, 59 insertions(+)
> 



Re: [Qemu-devel] [PATCH V3 2/2] tests/test-filter-mirror:add filter-mirror unit test

2016-02-14 Thread Jason Wang


On 02/04/2016 03:43 PM, Zhang Chen wrote:
> From: ZhangChen 
>
> Using qtest qmp interface to implement following cases:
> 1) add/remove filter-mirror
> 2) add a filter-mirror then delete the netdev
> 3) add/remove more than one filter-mirrors
> 4) add more than one filter-mirrors and then delete the netdev

The steps here is rather similar to test-netfilter.c. Let's try to
generalize them instead of duplicating codes.

> 5) add filter-mirror with:
>-object filter-mirror,id=qtest-f0,netdev=qtest-bn0,queue=tx,outdev=mirror0
>
>then inject packet from the socket connected to qtest-bn0,
>filter-mirror will copy and mirror the packet to mirror0.
>we read packet from mirror0 and then compare to what we inject.
>del filter-mirror.
>
> we start qemu with:
> -netdev socket,id=qtest-bn0,listen=127.0.0.1:9005
> -device e1000,netdev=qtest-bn0,id=qtest-e0
> -chardev socket,id=mirror0,host=127.0.0.1,port=9003,server,nowait
> -chardev socket,id=mirror1,host=127.0.0.1,port=9004,server,nowait

Hardcoded port is not good here since it may cause false positive
(consider the tests may be trigged by lots of automated script both
upstream and downstream). A better solution is using socketpair(2) and
passing pre-created fd(s) to file chardev.

>
> Signed-off-by: zhangchen 
> Signed-off-by: Wen Congyang 
>

[...]



[Qemu-devel] [PATCH v3] linux-user: add option to intercept execve() syscalls

2016-02-14 Thread Petros Angelatos
In order for one to use QEMU user mode emulation under a chroot, it is
required to use binfmt_misc. This can be avoided by QEMU never doing a
raw execve() to the host system.

Introduce a new option, -execve, that uses the current QEMU interpreter
to intercept execve().

qemu_execve() will prepend the interpreter path , similar to what
binfmt_misc would do, and then pass the modified execve() to the host.

It is necessary to parse hashbang scripts in that function otherwise
the kernel will try to run the interpreter of a script without QEMU and
get an invalid exec format error.

Signed-off-by: Petros Angelatos 
Tested-by: Laurent Vivier 
Reviewed-by: Laurent Vivier 
---
v3 changes:
- rebase the patchset against current code


 linux-user/main.c|  36 
 linux-user/qemu.h|   1 +
 linux-user/syscall.c | 117 ++-
 3 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index e719a2d..0596e6e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -17,6 +17,7 @@
  *  along with this program; if not, see .
  */
 #include "qemu/osdep.h"
+#include 
 #include 
 #include 
 #include 
@@ -75,6 +76,7 @@ static void usage(int exitcode);
 
 static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
 const char *qemu_uname_release;
+const char *qemu_execve_path;
 
 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
we allocate a bigger stack. Need a better solution, for example
@@ -3824,6 +3826,38 @@ static void handle_arg_guest_base(const char *arg)
 have_guest_base = 1;
 }
 
+static void handle_arg_execve(const char *arg)
+{
+const char *execfn;
+char buf[PATH_MAX];
+char *ret;
+int len;
+
+/* try getauxval() */
+execfn = (const char *) getauxval(AT_EXECFN);
+
+if (execfn != 0) {
+ret = realpath(execfn, buf);
+
+if (ret != NULL) {
+qemu_execve_path = strdup(buf);
+return;
+}
+}
+
+/* try /proc/self/exe */
+len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+
+if (len != -1) {
+buf[len] = '\0';
+qemu_execve_path = strdup(buf);
+return;
+}
+
+fprintf(stderr, "qemu_execve: unable to determine intepreter's path\n");
+exit(EXIT_FAILURE);
+}
+
 static void handle_arg_reserved_va(const char *arg)
 {
 char *p;
@@ -3909,6 +3943,8 @@ static const struct qemu_argument arg_table[] = {
  "uname",  "set qemu uname release string to 'uname'"},
 {"B",  "QEMU_GUEST_BASE",  true,  handle_arg_guest_base,
  "address","set guest_base address to 'address'"},
+{"execve", "QEMU_EXECVE",  false, handle_arg_execve,
+ "",   "use this interpreter when a process calls execve()"},
 {"R",  "QEMU_RESERVED_VA", true,  handle_arg_reserved_va,
  "size",   "reserve 'size' bytes for guest virtual address space"},
 {"d",  "QEMU_LOG", true,  handle_arg_log,
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index bd90cc3..0d9b058 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -140,6 +140,7 @@ void init_task_state(TaskState *ts);
 void task_settid(TaskState *);
 void stop_all_tasks(void);
 extern const char *qemu_uname_release;
+extern const char *qemu_execve_path;
 extern unsigned long mmap_min_addr;
 
 /* ??? See if we can avoid exposing so much of the loader internals.  */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 54ce14a..61b7326 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -99,6 +99,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
 #include 
 #include 
 #include 
+#include 
 #include "linux_loop.h"
 #include "uname.h"
 
@@ -5842,6 +5843,118 @@ static target_timer_t get_timer_id(abi_long arg)
 return timerid;
 }
 
+/* qemu_execve() Must return target values and target errnos. */
+static abi_long qemu_execve(char *filename, char *argv[],
+  char *envp[])
+{
+char *i_arg = NULL, *i_name = NULL;
+char **new_argp;
+int argc, fd, ret, i, offset = 3;
+char *cp;
+char buf[BINPRM_BUF_SIZE];
+
+/* normal execve case */
+if (qemu_execve_path == NULL || *qemu_execve_path == 0) {
+return get_errno(execve(filename, argv, envp));
+}
+
+for (argc = 0; argv[argc] != NULL; argc++) {
+/* nothing */ ;
+}
+
+fd = open(filename, O_RDONLY);
+if (fd == -1) {
+return get_errno(fd);
+}
+
+ret = read(fd, buf, BINPRM_BUF_SIZE);
+if (ret == -1) {
+close(fd);
+return get_errno(ret);
+}
+
+/* if we have less than 2 bytes, we can guess it is not executable */
+if (ret < 2) {
+close(fd);
+return -host_to_target_errno(ENOEXEC);
+}
+
+close(fd);
+
+/* adapted from the kernel
+ * 

Re: [Qemu-devel] [PATCH V3 1/2] net/filter-mirror:Add filter-mirror

2016-02-14 Thread Jason Wang


On 02/04/2016 05:00 PM, Zhang Chen wrote:
>
>
> On 02/04/2016 03:43 PM, Zhang Chen wrote:
>> From: ZhangChen 
>>
>> Filter-mirror is a netfilter plugin.
>> It gives qemu the ability to copy and mirror guest's
>> net packet. we output packet to chardev.

To make it compact, how about "It gives qemu the ability to mirror
packets to a chardev."?

>>
>> usage:
>>
>> -netdev tap,id=hn0
>> -chardev socket,id=mirror0,host=ip_primary,port=X,server,nowait
>> -filter-mirror,id=m0,netdev=hn0,queue=tx/rx/all,outdev=mirror0

An issue with mirror (and dump) is that it can not work correctly with
the netdev that has a vnet header. Need to fix this, a possible solution
is to checksum the buffer and strip the header before passing it to a
chardev.

>>
>> Signed-off-by: ZhangChen 
>> Signed-off-by: Wen Congyang 
>> Reviewed-by: Yang Hongyang 
>> Reviewed-by: zhanghailiang 
>> ---
>>   net/Makefile.objs   |   1 +
>>   net/filter-mirror.c | 171
>> 
>>   qemu-options.hx |   5 ++
>>   vl.c|   3 +-
>>   4 files changed, 179 insertions(+), 1 deletion(-)
>>   create mode 100644 net/filter-mirror.c
>>
>> diff --git a/net/Makefile.objs b/net/Makefile.objs
>> index 5fa2f97..de06ebe 100644
>> --- a/net/Makefile.objs
>> +++ b/net/Makefile.objs
>> @@ -15,3 +15,4 @@ common-obj-$(CONFIG_VDE) += vde.o
>>   common-obj-$(CONFIG_NETMAP) += netmap.o
>>   common-obj-y += filter.o
>>   common-obj-y += filter-buffer.o
>> +common-obj-y += traffic-mirror.o
>
> s/traffic-mirror.o/filter-mirror.o/ rebase error
>
>> diff --git a/net/filter-mirror.c b/net/filter-mirror.c
>> new file mode 100644
>> index 000..87ccaf5
>> --- /dev/null
>> +++ b/net/filter-mirror.c
>> @@ -0,0 +1,171 @@
>> +/*
>> + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
>> + * Copyright (c) 2016 FUJITSU LIMITED
>> + * Copyright (c) 2016 Intel Corporation
>> + *
>> + * Author: Zhang Chen 
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>> + * later.  See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "net/filter.h"
>> +#include "net/net.h"
>> +#include "qemu-common.h"
>> +#include "qapi/qmp/qerror.h"
>> +#include "qapi-visit.h"
>> +#include "qom/object.h"
>> +#include "qemu/main-loop.h"
>> +#include "qemu/error-report.h"
>> +#include "trace.h"
>> +#include "sysemu/char.h"
>> +#include "qemu/iov.h"
>> +#include "qemu/sockets.h"
>> +
>> +#define FILTER_MIRROR(obj) \
>> +OBJECT_CHECK(MirrorState, (obj), TYPE_FILTER_MIRROR)
>> +
>> +#define TYPE_FILTER_MIRROR "filter-mirror"
>> +
>> +typedef struct MirrorState {
>> +NetFilterState parent_obj;
>> +char *outdev;
>> +CharDriverState *chr_out;
>> +} MirrorState;
>> +
>> +static ssize_t filter_mirror_send(NetFilterState *nf,
>> +   const struct iovec *iov,
>> +   int iovcnt)
>> +{
>> +MirrorState *s = FILTER_MIRROR(nf);
>> +ssize_t ret = 0;
>> +ssize_t size = 0;
>> +uint32_t len =  0;
>> +char *buf;
>> +
>> +size = iov_size(iov, iovcnt);
>> +len = htonl(size);
>> +if (!size) {
>> +return 0;
>> +}
>> +
>> +buf = g_malloc0(size);
>> +iov_to_buf(iov, iovcnt, 0, buf, size);
>> +ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *),
>> sizeof(len));
>> +if (ret < 0) {

I believe we should also fail when ret < sizeof(len) and modify the
caller check in filter_mirror_iov(). To make this a little bit easier,
there's no need to return ssize_t here (otherwise, caller need to call
iov_size() before checking the return value), just return 0 for success
and -EFXXX for failure.

Other looks good.




[Qemu-devel] [PATCH qemu] update-linux-headers: Add userfaultfd.h

2016-02-14 Thread Alexey Kardashevskiy
userfailtfd.h is used by post-copy migration so include it to
the update-linux-headers.sh as we want it updated altogether with
other kernel headers.

Signed-off-by: Alexey Kardashevskiy 
---
 scripts/update-linux-headers.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index ff5b0c7..6aa8407 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -103,7 +103,7 @@ done
 rm -rf "$output/linux-headers/linux"
 mkdir -p "$output/linux-headers/linux"
 for header in kvm.h kvm_para.h vfio.h vhost.h \
-  psci.h; do
+  psci.h userfaultfd.h; do
 cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux"
 done
 rm -rf "$output/linux-headers/asm-generic"
-- 
2.5.0.rc3




Re: [Qemu-devel] [PATCH V2] quorum: fix segfault when read fails in fifo mode

2016-02-14 Thread Changlong Xie

On 02/05/2016 11:46 PM, Eric Blake wrote:

On 02/04/2016 07:25 PM, Changlong Xie wrote:

Signed-off-by: Wen Congyang 
Signed-off-by: Changlong Xie 
---
  block/quorum.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/block/quorum.c b/block/quorum.c
index a5ae4b8..11cc60b 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -286,7 +286,8 @@ static void quorum_aio_cb(void *opaque, int ret)

  if (acb->is_read && s->read_pattern == QUORUM_READ_PATTERN_FIFO) {
  /* We try to read next child in FIFO order if we fail to read */
-if (ret < 0 && ++acb->child_iter < s->num_children) {
+if (ret < 0 && (acb->child_iter + 1) < s->num_children) {


Could shorten this as
   if (ret < 0 && acb->child_iter <= s->num_children) {
but I'm not sure it's worth the mental gymnastics.


Hi Eric

Just the same to me. Since it has been applied to block branch. Let's 
keep the original one.


Thanks
-Xie








Re: [Qemu-devel] [Qemu-block] [PATCH v9 3/3] qmp: add monitor command to add/remove a child

2016-02-14 Thread Changlong Xie

On 02/11/2016 02:02 AM, Max Reitz wrote:

On 25.12.2015 10:22, Changlong Xie wrote:

From: Wen Congyang 

The new QMP command name is x-blockdev-change. It's just for adding/removing
quorum's child now, and doesn't support all kinds of children, all kinds of
operations, nor all block drivers. So it is experimental now.

Signed-off-by: Wen Congyang 
Signed-off-by: zhanghailiang 
Signed-off-by: Gonglei 
Signed-off-by: Changlong Xie 
---
  blockdev.c   | 54 
  qapi/block-core.json | 23 ++
  qmp-commands.hx  | 47 +
  3 files changed, 124 insertions(+)

diff --git a/blockdev.c b/blockdev.c
index 64dbfeb..4e62fdf 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3836,6 +3836,60 @@ out:
  aio_context_release(aio_context);
  }

+static BlockDriverState *bdrv_find_child(BlockDriverState *parent_bs,
+ const char *child_name)
+{
+BdrvChild *child;
+
+QLIST_FOREACH(child, _bs->children, next) {
+if (strcmp(child->name, child_name) == 0) {
+return child->bs;
+}
+}
+
+return NULL;
+}
+
+void qmp_x_blockdev_change(const char *parent, bool has_child,
+   const char *child, bool has_node,
+   const char *node, Error **errp)
+{
+BlockDriverState *parent_bs, *child_bs = NULL, *new_bs = NULL;
+
+parent_bs = bdrv_lookup_bs(parent, parent, errp);
+if (!parent_bs) {
+return;
+}
+
+if (has_child == has_node) {
+if (has_child) {
+error_setg(errp, "The paramter child and node is conflict");


"The parameters child and node are in conflict"

Or, more naturally:

"child and node may not be specified at the same time"



OK


+} else {
+error_setg(errp, "Either child or node should be specified");


s/should/must/


Ok




+}
+return;
+}
+
+if (has_child) {
+child_bs = bdrv_find_child(parent_bs, child);
+if (!child_bs) {
+error_setg(errp, "Node '%s' doesn't have child %s",


s/doesn't/does not/

(This is a personal opinion, but a pretty strong one.)

Also, if you put quotes around the node name, maybe you should do the
same around the child name.


OK




+   parent, child);
+return;
+}
+bdrv_del_child(parent_bs, child_bs, errp);
+}
+
+if (has_node) {
+new_bs = bdrv_find_node(node);
+if (!new_bs) {
+error_setg(errp, "Node '%s' not found", node);
+return;
+}
+bdrv_add_child(parent_bs, new_bs, errp);
+}
+}
+
  BlockJobInfoList *qmp_query_block_jobs(Error **errp)
  {
  BlockJobInfoList *head = NULL, **p_next = 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 1a5d9ce..fe63c6d 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2408,3 +2408,26 @@
  ##
  { 'command': 'block-set-write-threshold',
'data': { 'node-name': 'str', 'write-threshold': 'uint64' } }
+
+##
+# @x-blockdev-change
+#
+# Dynamically reconfigure the block driver state graph. It can be used
+# to add, remove, insert or replace a block driver state. Currently only


I'd prefer "graph node" over BDS in this line.


ok




+# the Quorum driver implements this feature to add or remove its child.
+# This is useful to fix a broken quorum child.
+#


I'd like a list here what this command does depending on the parameters
given. For instance:

If @(new-)node is specified, it will be inserted under @parent. @child
may not be specified in this case.

If both @parent and @child are specified but @(new-)node is not, @child
will be detached from @parent.



ok


+# @parent: the id or name of the node that will be changed.


I don't know. The parent will actually not be changed, it's an edge that
will be changed; and the parent is the parent node of that edge. Just put

@parent: the id or name of the parent node

here.



Yes, you are right here.


+#
+# @child: #optional the name of the child that will be deleted.


For now. But maybe that will change in the future. Generally, it is just
the child node of the edge that will be changed. So just putting

@child: #optional the name of a child under the given parent node

(Let's hope this is clear enough that people know that this is not a
node name.)



ok


+#
+# @node: #optional the name of the node will be added.


Maybe this should be named new-node instead.

Also: "...of the node that will be added."


Yes, it's more clear.




+#
+# Note: this command is experimental, and its API is not stable.
+#
+# Since: 2.6
+##
+{ 'command': 'x-blockdev-change',
+  'data' : { 'parent': 'str',
+ '*child': 'str',
+ '*node': 'str' } }
diff --git a/qmp-commands.hx 

Re: [Qemu-devel] [PATCH v12 1/2] mirror: Rewrite mirror_iteration

2016-02-14 Thread Fam Zheng
On Sun, 02/14 22:49, Jeff Cody wrote:
> On Feb 14, 2016 21:19, "Fam Zheng"  wrote:
> >
> > On Mon, 02/08 13:54, Max Reitz wrote:
> > > On 07.02.2016 13:46, Fam Zheng wrote:
> > > > On Sat, 02/06 14:24, Max Reitz wrote:
> > > >> On 05.02.2016 03:00, Fam Zheng wrote:
> > > >>> The "pnum < nb_sectors" condition in deciding whether to actually
> copy
> > > >>> data is unnecessarily strict, and the qiov initialization is
> > > >>> unnecessarily for bdrv_aio_write_zeroes and bdrv_aio_discard.
> > > >>>
> > > >>> Rewrite mirror_iteration to fix both flaws.
> > > >>>
> > > >>> The output of iotests 109 is updated because we now report the
> offset
> > > >>> and len slightly differently in mirroring progress.
> > > >>>
> > > >>> Signed-off-by: Fam Zheng 
> > > >>> ---
> > > >>>  block/mirror.c | 335
> +++--
> > > >>>  tests/qemu-iotests/109.out |  80 +--
> > > >>>  trace-events   |   1 -
> > > >>>  3 files changed, 243 insertions(+), 173 deletions(-)
> > > >>>
> > > >>> diff --git a/block/mirror.c b/block/mirror.c
> > > >>> index 2c0edfa..48cd0b3 100644
> > > >>> --- a/block/mirror.c
> > > >>> +++ b/block/mirror.c
> > > >>
> > > >> [...]
> > > >>
> > > >>> @@ -449,16 +520,16 @@ static void coroutine_fn mirror_run(void
> *opaque)
> > > >>>   */
> > > >>>  bdrv_get_backing_filename(s->target, backing_filename,
> > > >>>sizeof(backing_filename));
> > > >>> -if (backing_filename[0] && !s->target->backing) {
> > > >>> -ret = bdrv_get_info(s->target, );
> > > >>> -if (ret < 0) {
> > > >>> -goto immediate_exit;
> > > >>> -}
> > > >>> -if (s->granularity < bdi.cluster_size) {
> > > >>> -s->buf_size = MAX(s->buf_size, bdi.cluster_size);
> > > >>> -s->cow_bitmap = bitmap_new(length);
> > > >>> -}
> > > >>> +if (!bdrv_get_info(s->target, ) && bdi.cluster_size) {
> > > >>
> > > >> This should be bdi.has_cluster_size...
> > > >
> > > > has_cluster_size is a member of ImageInfo not BlockDriverInfo, and is
> derived
> > > > from (bdi.cluster_size != 0).
> > >
> > > You're right, my bad.
> > >
> > > >>> +target_cluster_size = bdi.cluster_size;
> > > >>
> > > >> ...and maybe we want an explicit minimum of BDRV_SECTOR_SIZE here;
> but I
> > > >> guess this is already assumed all over the block layer, so it may be
> > > >> fine without.
> > > >
> > > > Okay, it doesn't hurt to add an assert here.
> > >
> > > I'd be happy to take the patch without, too (although I wouldn't decline
> > > a follow-up adding an assertion).
> > >
> > > Reviewed-by: Max Reitz 
> >
> > Thanks! Shall we merge this now?
> >
> > Fam
> >
> 
> I think so - I'll go ahead and apply it to my block branch, unless there
> are any objections.

Great! Thanks Jeff.

Fam



Re: [Qemu-devel] [PATCH] usb: check RNDIS buffer offsets & length

2016-02-14 Thread P J P
+-- On Tue, 9 Feb 2016, P J P wrote --+
| +-- On Fri, 5 Feb 2016, P J P wrote --+
| | From: Prasad J Pandit 
| | 
| | When processing remote NDIS control message packets, the USB Net
| | device emulator uses a fixed length(4096) data buffer. The incoming
| | informationBufferOffset & Length combination could cross that range.
| | Check control message buffer offsets and length to avoid it.
| | 
| | Reported-by: Qinghao Tang 
| 
| ...ping!

Ping...Gerd?
--
 - P J P
47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F



Re: [Qemu-devel] [PATCH] net: ne2000: check ring buffer control registers

2016-02-14 Thread P J P
+-- On Tue, 9 Feb 2016, P J P wrote --+
| +-- On Fri, 5 Feb 2016, Jason Wang wrote --+
| | I suspect this could even work. Consider after realizing, s->stop is
| | zero, any attempt to set STARTPG will fail?
| 
|  Ie after 'pci_ne2000_realize'? It does not seem to set or reset s->stop 
| register.
|  
| | This may not be sufficient, consider:
| | 
| | set start to 1
| | set stop to 100
| | set boundary to 50
| | then set stop to 10
| 
|   I think any attempts to define the ring buffer limits should reset 
| 'boundary' and 'curpag' registers to s->start(STARTPG). I wonder if a driver 
| should be allowed to fiddle with the ring buffers location inside 
contorller's 
| memory. It does not seem right.
|  
| | I'm thinking maybe we need check during receiving like what we did in
| | dd793a74882477ca38d49e191110c17dfee51dcc?
| 
|   Check if (s->start == s->stop) at each receive call?


Ping...Jason?
--
 - P J P
47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F



Re: [Qemu-devel] [V4 1/4] hw/i386: Introduce AMD IO MMU

2016-02-14 Thread David kiarie
On Mon, Feb 15, 2016 at 6:41 AM, David kiarie  wrote:
> On Thu, Feb 4, 2016 at 6:03 PM, Michael S. Tsirkin  wrote:
>> On Mon, Jan 18, 2016 at 06:25:42PM +0300, David Kiarie wrote:
>>> Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
>>> The IO MMU does basic translation, error checking and has a
>>> minimal IOTLB implementation.
>>>
>>> Signed-off-by: David Kiarie 
>>> ---
>>>  hw/i386/Makefile.objs |1 +
>>>  hw/i386/amd_iommu.c   | 1409 
>>> +
>>>  hw/i386/amd_iommu.h   |  399 ++
>>>  include/hw/pci/pci.h  |2 +
>>>  4 files changed, 1811 insertions(+)
>>>  create mode 100644 hw/i386/amd_iommu.c
>>>  create mode 100644 hw/i386/amd_iommu.h
>>>
>>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>>> index b52d5b8..2f1a265 100644
>>> --- a/hw/i386/Makefile.objs
>>> +++ b/hw/i386/Makefile.objs
>>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>>  obj-y += pc.o pc_piix.o pc_q35.o
>>>  obj-y += pc_sysfw.o
>>>  obj-y += intel_iommu.o
>>> +obj-y += amd_iommu.o
>>>  obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>>
>>>  obj-y += kvmvapic.o
>>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>>> new file mode 100644
>>> index 000..20111fe
>>> --- /dev/null
>>> +++ b/hw/i386/amd_iommu.c
>>> @@ -0,0 +1,1409 @@
>>> +/*
>>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>>> + *
>>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>>> + * Copyright (C) 2015 David Kiarie, 
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or
>>> + * (at your option) any later version.
>>> +
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> +
>>> + * You should have received a copy of the GNU General Public License along
>>> + * with this program; if not, see .
>>> + *
>>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>>
>> Link to hardware spec?
>>
>>> + *
>>> + */
>>> +#include "hw/i386/amd_iommu.h"
>>> +
>>> +//#define DEBUG_AMD_IOMMU
>>> +#ifdef DEBUG_AMD_IOMMU
>>> +enum {
>>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>>> +};
>>> +
>>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>>> +
>>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>>> +## __VA_ARGS__); } \
>>> +} while (0)
>>> +#else
>>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>>> +#endif
>>> +
>>> +/* configure MMIO registers at startup/reset */
>>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
>>> +   uint64_t romask, uint64_t w1cmask)
>>> +{
>>> +stq_le_p(>mmior[addr], val);
>>> +stq_le_p(>romask[addr], romask);
>>> +stq_le_p(>w1cmask[addr], w1cmask);
>>> +}
>>> +
>>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>>> +{
>>> +return lduw_le_p(>mmior[addr]);
>>> +}
>>> +
>>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>>> +{
>>> +return ldl_le_p(>mmior[addr]);
>>> +}
>>> +
>>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>>> +{
>>> +return ldq_le_p(>mmior[addr]);
>>> +}
>>> +
>>> +/* internal write */
>>> +static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr 
>>> addr)
>>> +{
>>> +stq_le_p(>mmior[addr], val);
>>> +}
>>> +
>>> +/* external write */
>>> +static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
>>> +{
>>> +uint16_t romask = lduw_le_p(>romask[addr]);
>>> +uint16_t w1cmask = lduw_le_p(>w1cmask[addr]);
>>> +uint16_t oldval = lduw_le_p(>mmior[addr]);
>>> +stw_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & 
>>> oldval));
>>> +}
>>> +
>>> +static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
>>> +{
>>> +uint32_t romask = ldl_le_p(>romask[addr]);
>>> +uint32_t w1cmask = ldl_le_p(>w1cmask[addr]);
>>> +uint32_t oldval = ldl_le_p(>mmior[addr]);
>>> +stl_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & 
>>> oldval));
>>> +}
>>> +
>>> +static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
>>> +{
>>> +uint64_t romask = ldq_le_p(>romask[addr]);
>>> +uint64_t w1cmask = ldq_le_p(>w1cmask[addr]);
>>> +uint32_t oldval = ldq_le_p(>mmior[addr]);
>>> +stq_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & 
>>> oldval));
>>> +}
>>> +

Re: [Qemu-devel] [PATCH v12 1/2] mirror: Rewrite mirror_iteration

2016-02-14 Thread Jeff Cody
On Feb 14, 2016 21:19, "Fam Zheng"  wrote:
>
> On Mon, 02/08 13:54, Max Reitz wrote:
> > On 07.02.2016 13:46, Fam Zheng wrote:
> > > On Sat, 02/06 14:24, Max Reitz wrote:
> > >> On 05.02.2016 03:00, Fam Zheng wrote:
> > >>> The "pnum < nb_sectors" condition in deciding whether to actually
copy
> > >>> data is unnecessarily strict, and the qiov initialization is
> > >>> unnecessarily for bdrv_aio_write_zeroes and bdrv_aio_discard.
> > >>>
> > >>> Rewrite mirror_iteration to fix both flaws.
> > >>>
> > >>> The output of iotests 109 is updated because we now report the
offset
> > >>> and len slightly differently in mirroring progress.
> > >>>
> > >>> Signed-off-by: Fam Zheng 
> > >>> ---
> > >>>  block/mirror.c | 335
+++--
> > >>>  tests/qemu-iotests/109.out |  80 +--
> > >>>  trace-events   |   1 -
> > >>>  3 files changed, 243 insertions(+), 173 deletions(-)
> > >>>
> > >>> diff --git a/block/mirror.c b/block/mirror.c
> > >>> index 2c0edfa..48cd0b3 100644
> > >>> --- a/block/mirror.c
> > >>> +++ b/block/mirror.c
> > >>
> > >> [...]
> > >>
> > >>> @@ -449,16 +520,16 @@ static void coroutine_fn mirror_run(void
*opaque)
> > >>>   */
> > >>>  bdrv_get_backing_filename(s->target, backing_filename,
> > >>>sizeof(backing_filename));
> > >>> -if (backing_filename[0] && !s->target->backing) {
> > >>> -ret = bdrv_get_info(s->target, );
> > >>> -if (ret < 0) {
> > >>> -goto immediate_exit;
> > >>> -}
> > >>> -if (s->granularity < bdi.cluster_size) {
> > >>> -s->buf_size = MAX(s->buf_size, bdi.cluster_size);
> > >>> -s->cow_bitmap = bitmap_new(length);
> > >>> -}
> > >>> +if (!bdrv_get_info(s->target, ) && bdi.cluster_size) {
> > >>
> > >> This should be bdi.has_cluster_size...
> > >
> > > has_cluster_size is a member of ImageInfo not BlockDriverInfo, and is
derived
> > > from (bdi.cluster_size != 0).
> >
> > You're right, my bad.
> >
> > >>> +target_cluster_size = bdi.cluster_size;
> > >>
> > >> ...and maybe we want an explicit minimum of BDRV_SECTOR_SIZE here;
but I
> > >> guess this is already assumed all over the block layer, so it may be
> > >> fine without.
> > >
> > > Okay, it doesn't hurt to add an assert here.
> >
> > I'd be happy to take the patch without, too (although I wouldn't decline
> > a follow-up adding an assertion).
> >
> > Reviewed-by: Max Reitz 
>
> Thanks! Shall we merge this now?
>
> Fam
>

I think so - I'll go ahead and apply it to my block branch, unless there
are any objections.

Jeff


[Qemu-devel] [PATCH v2 16/16] tcg-mips: Use mipsr6 instructions in calls

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 32 
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 447dbcf..16118f7 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -336,7 +336,9 @@ typedef enum {
 OPC_SH   = 051 << 26,
 OPC_SW   = 053 << 26,
 OPC_BC   = 062 << 26,
+OPC_JIC  = 066 << 26,
 OPC_LD   = 067 << 26,
+OPC_JIALC= 076 << 26,
 OPC_SD   = 077 << 26,
 
 OPC_SPECIAL  = 000 << 26,
@@ -1364,28 +1366,32 @@ static void tcg_out_movcond(TCGContext *s, TCGCond 
cond, TCGReg ret,
 }
 }
 
-static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
+static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg,
+ bool tail, bool want_delay)
 {
 /* Note that the ABI requires the called function's address to be
loaded into T9, even if a direct branch is in range.  */
 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
 
 /* But do try a direct branch, allowing the cpu better insn prefetch.  */
-if (tail) {
-if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
-tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
-}
+if (tcg_out_opc_jmp(s, tail ? OPC_J : OPC_JAL, arg)) {
+/* jmp emitted */
+} else if (use_mips32r6_instructions && !want_delay) {
+tcg_out_opc_reg(s, tail ? OPC_JIC : OPC_JIALC, 0, TCG_REG_T9, 0);
+return;
+} else if (tail) {
+tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
 } else {
-if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
-tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
-}
+tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
+}
+if (!want_delay) {
+tcg_out_nop(s);
 }
 }
 
 static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
 {
-tcg_out_call_int(s, arg, false);
-tcg_out_nop(s);
+tcg_out_call_int(s, arg, false, false);
 }
 
 #if defined(CONFIG_SOFTMMU)
@@ -1596,7 +1602,8 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 }
 i = tcg_out_call_iarg_imm(s, i, oi);
 i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
-tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)], false);
+tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)],
+ false, true);
 /* delay slot */
 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
 
@@ -1660,7 +1667,8 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
computation to take place in the return address register.  */
 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
 i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
-tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true);
+tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)],
+ true, true);
 /* delay slot */
 tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
 }
-- 
2.5.0




[Qemu-devel] [PATCH v2 14/16] tcg-mips: Use mips64r6 instructions in constant addition

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 59 ++-
 1 file changed, 49 insertions(+), 10 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 52e1edc..ab72715 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -221,12 +221,26 @@ static int target_parse_constraint(TCGArgConstraint *ct, 
const char **pct_str)
 case 'I':
 ct->ct |= TCG_CT_CONST_U16;
 break;
+case 'a':
+/* mips r6 can add any constant without needing a temporary.  */
+if (use_mips32r6_instructions) {
+ct->ct |= TCG_CT_CONST;
+break;
+}
+/* fallthru */
 case 'J':
 ct->ct |= TCG_CT_CONST_S16;
 break;
 case 'K':
 ct->ct |= TCG_CT_CONST_P2M1;
 break;
+case 's':
+/* mips r6 can subtract any constant without needing a temporary.  */
+if (use_mips32r6_instructions) {
+ct->ct |= TCG_CT_CONST;
+break;
+}
+/* fallthru */
 case 'N':
 ct->ct |= TCG_CT_CONST_N16;
 break;
@@ -797,9 +811,10 @@ static inline void tcg_out_ext32u(TCGContext *s, TCGReg 
ret, TCGReg arg)
 }
 
 static void tcg_out_r6_ofs(TCGContext *s, MIPSInsn opl, MIPSInsn oph,
-   TCGReg reg0, TCGReg reg1, tcg_target_long ofs)
+   TCGReg reg0, TCGReg reg1,
+   tcg_target_long ofs, bool is_mem)
 {
-TCGReg scratch = TCG_TMP0;
+TCGReg scratch = is_mem ? TCG_TMP0 : reg0;
 int16_t lo = ofs;
 int32_t hi = ofs - lo;
 
@@ -810,9 +825,15 @@ static void tcg_out_r6_ofs(TCGContext *s, MIPSInsn opl, 
MIPSInsn oph,
 /* Bits are set in the high 32-bit half.  Thus we require the
use of DAHI and/or DATI.  The R6 manual recommends addition
of immediates in order of mid to high (DAUI, DAHI, DATI, OPL)
-   in order to simplify hardware recognizing these sequences.  */
+   in order to simplify hardware recognizing these sequences.
+   Ignore this wrt DADDIU if it will save one instruction.  */
 
-tcg_out_opc_imm(s, OPC_DAUI, scratch, reg1, hi >> 16);
+if (hi == 0 && lo != 0 && !is_mem) {
+tcg_out_opc_imm(s, OPC_DADDIU, scratch, reg1, lo);
+lo = 0;
+} else if (hi != 0 || reg1 != scratch) {
+tcg_out_opc_imm(s, OPC_DAUI, scratch, reg1, hi >> 16);
+}
 
 tmp = ofs >> 16 >> 16;
 if (tmp & 0x) {
@@ -827,14 +848,16 @@ static void tcg_out_r6_ofs(TCGContext *s, MIPSInsn opl, 
MIPSInsn oph,
 tcg_out_opc_imm(s, oph, scratch, reg1, hi >> 16);
 reg1 = scratch;
 }
-tcg_out_opc_imm(s, opc, reg0, reg1, lo);
+if (is_mem || lo != 0 || reg0 != reg1) {
+tcg_out_opc_imm(s, opl, reg0, reg1, lo);
+}
 }
 
 static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
  TCGReg addr, intptr_t ofs)
 {
 if (use_mips32r6_instructions) {
-tcg_out_r6_ofs(s, opc, ALIAS_PAUI, data, addr, ofs);
+tcg_out_r6_ofs(s, opc, ALIAS_PAUI, data, addr, ofs, true);
 return;
 }
 
@@ -1846,9 +1869,17 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 break;
 
 case INDEX_op_add_i32:
+if (use_mips32r6_instructions && c2) {
+tcg_out_r6_ofs(s, OPC_ADDIU, OPC_AUI, a0, a1, (int32_t)a2, false);
+break;
+}
 i1 = OPC_ADDU, i2 = OPC_ADDIU;
 goto do_binary;
 case INDEX_op_add_i64:
+if (use_mips32r6_instructions && c2) {
+tcg_out_r6_ofs(s, OPC_DADDIU, OPC_DAUI, a0, a1, a2, false);
+break;
+}
 i1 = OPC_DADDU, i2 = OPC_DADDIU;
 goto do_binary;
 case INDEX_op_or_i32:
@@ -1868,9 +1899,17 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 break;
 
 case INDEX_op_sub_i32:
+if (use_mips32r6_instructions && c2) {
+tcg_out_r6_ofs(s, OPC_ADDIU, OPC_AUI, a0, a1, (int32_t)-a2, false);
+break;
+}
 i1 = OPC_SUBU, i2 = OPC_ADDIU;
 goto do_subtract;
 case INDEX_op_sub_i64:
+if (use_mips32r6_instructions && c2) {
+tcg_out_r6_ofs(s, OPC_DADDIU, OPC_DAUI, a0, a1, -a2, false);
+break;
+}
 i1 = OPC_DSUBU, i2 = OPC_DADDIU;
 do_subtract:
 if (c2) {
@@ -2202,7 +2241,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
 { INDEX_op_st16_i32, { "rZ", "r" } },
 { INDEX_op_st_i32, { "rZ", "r" } },
 
-{ INDEX_op_add_i32, { "r", "rZ", "rJ" } },
+{ INDEX_op_add_i32, { "r", "rZ", "ra" } },
 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
 #if !use_mips32r6_instructions
 { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
@@ -2214,7 +2253,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
 { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
 { 

Re: [Qemu-devel] [PATCH v2 00/16] tcg mips64 and mips r6 improvements

2016-02-14 Thread Richard Henderson

On 02/15/2016 02:42 PM, Richard Henderson wrote:

Changes since v1:
   * Some bugs pointed out by Mark fixed.


Bah.  Brain fart -- not Mark, James.
Which also means I used the wrong --cc option too.

Ho hum.


r~



[Qemu-devel] [PATCH v2 12/16] tcg-mips: Improve tcg_out_movi for mips64

2016-02-14 Thread Richard Henderson
For r6, the ADDIUPC, ALUIPC, DAHI and DATI instructions can eliminate 2-4
insns off the pre-r6 full 64-bit immediate load sequence.

For pre-r6, NAL can do the same for the special, but common, case of the
return address for the qemu_ld/st slow paths.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 117 ++
 1 file changed, 109 insertions(+), 8 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 8fb2ab0..b4239cb 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -282,7 +282,9 @@ typedef enum {
 OPC_ORI  = 015 << 26,
 OPC_XORI = 016 << 26,
 OPC_LUI  = 017 << 26,
+OPC_AUI  = OPC_LUI,
 OPC_DADDIU   = 031 << 26,
+OPC_DAUI = 035 << 26,
 OPC_LB   = 040 << 26,
 OPC_LH   = 041 << 26,
 OPC_LW   = 043 << 26,
@@ -362,6 +364,9 @@ typedef enum {
 OPC_REGIMM   = 001 << 26,
 OPC_BLTZ = OPC_REGIMM | (000 << 16),
 OPC_BGEZ = OPC_REGIMM | (001 << 16),
+OPC_DAHI = OPC_REGIMM | (006 << 16),
+OPC_NAL  = OPC_REGIMM | (020 << 16) | 1,  /* bltzal zero, .+8 */
+OPC_DATI = OPC_REGIMM | (036 << 16),
 
 OPC_SPECIAL2 = 034 << 26,
 OPC_MUL_R5   = OPC_SPECIAL2 | 002,
@@ -381,6 +386,10 @@ typedef enum {
 OPC_SEB  = OPC_SPECIAL3 | 02040,
 OPC_SEH  = OPC_SPECIAL3 | 03040,
 
+OPC_PCREL= 073 << 26,
+OPC_ADDIUPC  = OPC_PCREL | (0 << 19),
+OPC_ALUIPC   = OPC_PCREL | (3 << 19) | (7 << 16),
+
 /* MIPS r6 doesn't have JR, JALR should be used instead */
 OPC_JR   = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
 
@@ -427,6 +436,17 @@ static inline void tcg_out_opc_imm(TCGContext *s, MIPSInsn 
opc,
 tcg_out32(s, inst);
 }
 
+static inline void tcg_out_opc_pc19(TCGContext *s, MIPSInsn opc,
+TCGReg rs, TCGArg imm)
+{
+int32_t inst;
+
+inst = opc;
+inst |= (rs & 0x1F) << 21;
+inst |= (imm & 0x7);
+tcg_out32(s, inst);
+}
+
 /*
  * Type bitfield
  */
@@ -555,6 +575,9 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type,
 static void tcg_out_movi(TCGContext *s, TCGType type,
  TCGReg ret, tcg_target_long arg)
 {
+uintptr_t pc = (uintptr_t)s->code_ptr;
+intptr_t disp;
+
 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
 arg = (int32_t)arg;
 }
@@ -566,18 +589,96 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
 tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
 return;
 }
+
+/* PC-relative address load, part 1.  The out-of-line slow paths
+   of qemu_ld/st compute the "return address" of the in-line fast
+   path, so that we can find the guest instruction that triggered
+   the memory fault.  Here, we can do that in one instruction.  */
+if (use_mips32r6_instructions && (arg & 3) == 0) {
+disp = arg - pc;
+if (disp == sextract32(disp, 0, 21)) {
+tcg_out_opc_pc19(s, OPC_ADDIUPC, ret, disp >> 2);
+return;
+}
+}
+
 if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) {
 tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
-} else {
-tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1);
-if (arg & 0xull) {
-tcg_out_dsll(s, ret, ret, 16);
-tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16);
-tcg_out_dsll(s, ret, ret, 16);
-} else {
-tcg_out_dsll(s, ret, ret, 32);
+goto do_lo16;
+}
+
+if (use_mips32r6_instructions) {
+tcg_target_long tmp;
+TCGReg in;
+
+/* PC-relative address load, part 2.  Here we are able to compute
+   a +- 2GB relative address in two instructions.  This not likely
+   to be within code_gen_buffer, but a helper function address or
+   other host memory that just happens to be in range.  */
+disp = sextract64(arg, 16, 48) - sextract64(pc, 16, 48);
+if (disp == (int16_t)disp) {
+tcg_out_opc_imm(s, OPC_ALUIPC, 0, ret, disp);
+goto do_lo16;
+}
+
+/* The R6 manual recommends construction of immediates in
+   order of low to high (ADDI, AUI, DAHI, DATI) in order
+   to simplify hardware recognizing these sequences.  */
+
+in = TCG_REG_ZERO;
+tmp = (int16_t)arg;
+if (tmp) {
+tcg_out_opc_imm(s, OPC_ADDIU, ret, in, tmp);
+in = ret;
 }
+arg = (arg - tmp) >> 16;
+tmp = (int16_t)arg;
+
+/* Note that DAHI and DATI only have one register operand,
+   and are thus we must put a zero low part in place.  Also
+   note that we already eliminated simple 32-bit constants
+   so we know this must happen.  */
+if (tmp || in != ret) {
+tcg_out_opc_imm(s, OPC_AUI, ret, in, tmp);
+}
+arg 

[Qemu-devel] [PATCH v2 15/16] tcg-mips: Use mipsr6 instructions in branches

2016-02-14 Thread Richard Henderson
Using compact branches, when possible, avoids a delay slot nop.

Signed-off-by: Richard Henderson 
---
 include/elf.h |   4 +
 tcg/mips/tcg-target.c | 270 +++---
 2 files changed, 218 insertions(+), 56 deletions(-)

diff --git a/include/elf.h b/include/elf.h
index 1098d21..6e52ba0 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -352,6 +352,10 @@ typedef struct {
 #define R_MIPS_CALLHI1630
 #define R_MIPS_CALLLO1631
 /*
+ * Incomplete list of MIPS R6 relocation types.
+ */
+#define R_MIPS_PC26_S2  61
+/*
  * This range is reserved for vendor specific relocations.
  */
 #define R_MIPS_LOVENDOR100
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index ab72715..447dbcf 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -154,6 +154,19 @@ static inline void reloc_pc16(tcg_insn_unit *pc, 
tcg_insn_unit *target)
 *pc = deposit32(*pc, 0, 16, reloc_pc16_val(pc, target));
 }
 
+static inline uint32_t reloc_pc26_val(tcg_insn_unit *pc, tcg_insn_unit *target)
+{
+/* Let the compiler perform the right-shift as part of the arithmetic.  */
+ptrdiff_t disp = target - (pc + 1);
+tcg_debug_assert(disp == sextract32(disp, 0, 26));
+return disp & 0x1ff;
+}
+
+static inline void reloc_pc26(tcg_insn_unit *pc, tcg_insn_unit *target)
+{
+*pc = deposit32(*pc, 0, 26, reloc_pc16_val(pc, target));
+}
+
 static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit *target)
 {
 tcg_debug_assertuintptr_t)pc ^ (uintptr_t)target) & 0xf000) == 0);
@@ -168,9 +181,17 @@ static inline void reloc_26(tcg_insn_unit *pc, 
tcg_insn_unit *target)
 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
 intptr_t value, intptr_t addend)
 {
-tcg_debug_assert(type == R_MIPS_PC16);
 tcg_debug_assert(addend == 0);
-reloc_pc16(code_ptr, (tcg_insn_unit *)value);
+switch (type) {
+case R_MIPS_PC16:
+reloc_pc16(code_ptr, (tcg_insn_unit *)value);
+   break;
+case R_MIPS_PC26_S2:
+reloc_pc26(code_ptr, (tcg_insn_unit *)value);
+   break;
+default:
+tcg_abort();
+}
 }
 
 #define TCG_CT_CONST_ZERO 0x100
@@ -288,7 +309,10 @@ typedef enum {
 OPC_BEQ  = 004 << 26,
 OPC_BNE  = 005 << 26,
 OPC_BLEZ = 006 << 26,
+OPC_BGEUC= OPC_BLEZ,/* R6: rs != 0, rt != 0, rs != rt */
 OPC_BGTZ = 007 << 26,
+OPC_BLTUC= OPC_BGTZ,/* R6: rs != 0, rt != 0, rs != rt */
+OPC_BEQC = 010 << 26,   /* R6: rs > rt */
 OPC_ADDIU= 011 << 26,
 OPC_SLTI = 012 << 26,
 OPC_SLTIU= 013 << 26,
@@ -297,6 +321,9 @@ typedef enum {
 OPC_XORI = 016 << 26,
 OPC_LUI  = 017 << 26,
 OPC_AUI  = OPC_LUI,
+OPC_BGEC = 026 << 26,
+OPC_BLTC = 027 << 26,
+OPC_BNEC = 030 << 26,   /* R6: rs > rt */
 OPC_DADDIU   = 031 << 26,
 OPC_DAUI = 035 << 26,
 OPC_LB   = 040 << 26,
@@ -308,6 +335,7 @@ typedef enum {
 OPC_SB   = 050 << 26,
 OPC_SH   = 051 << 26,
 OPC_SW   = 053 << 26,
+OPC_BC   = 062 << 26,
 OPC_LD   = 067 << 26,
 OPC_SD   = 077 << 26,
 
@@ -421,6 +449,33 @@ typedef enum {
  ? OPC_SRL : OPC_DSRL,
 } MIPSInsn;
 
+static inline void tcg_out_nop(TCGContext *s)
+{
+tcg_out32(s, 0);
+}
+
+/*
+ * Protect against a mips r6 forbidden slot.  If the previously
+ * emitted insn has a forbidden slot, emit a nop.
+ */
+
+static void nop_forbidden_slot(TCGContext *s)
+{
+if (use_mips32r6_instructions && s->code_ptr > s->code_buf) {
+tcg_insn_unit prev = s->code_ptr[-1];
+switch (prev & 0xfc00u) {
+case OPC_BGEC:
+case OPC_BLTC:
+case OPC_BGEUC:
+case OPC_BLTUC:
+case OPC_BEQC:
+case OPC_BNEC:
+tcg_out_nop(s);
+break;
+}
+}
+}
+
 /*
  * Type reg
  */
@@ -496,17 +551,30 @@ static inline void tcg_out_opc_bf64(TCGContext *s, 
MIPSInsn opc, MIPSInsn opm,
 /*
  * Type branch
  */
-static inline void tcg_out_opc_br(TCGContext *s, MIPSInsn opc,
-  TCGReg rt, TCGReg rs)
+static void tcg_out_opc_br(TCGContext *s, MIPSInsn opc, TCGReg rt, TCGReg rs)
 {
+uint16_t offset;
+
+nop_forbidden_slot(s);
+
 /* We pay attention here to not modify the branch target by reading
the existing value and using it again. This ensure that caches and
memory are kept coherent during retranslation. */
-uint16_t offset = (uint16_t)*s->code_ptr;
-
+offset = (uint16_t)*s->code_ptr;
 tcg_out_opc_imm(s, opc, rt, rs, offset);
 }
 
+static void tcg_out_opc_br_pc16(TCGContext *s, MIPSInsn opc,
+TCGReg rt, TCGReg rs, TCGLabel *l)
+{
+tcg_out_opc_br(s, opc, rt, rs);
+if (l->has_value) {
+reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
+} 

[Qemu-devel] [PATCH v2 08/16] tcg-mips: Adjust prologue for mips64

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 56 ---
 1 file changed, 26 insertions(+), 30 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index d1266ef..4a3f11a 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -716,16 +716,6 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, 
TCGReg arg,
 tcg_out_ldst(s, opc, arg, arg1, arg2);
 }
 
-static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
-{
-if (val == (int16_t)val) {
-tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
-} else {
-tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, val);
-tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_TMP0);
-}
-}
-
 static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
 TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
 bool cbh, bool is_sub)
@@ -2224,42 +2214,48 @@ static tcg_insn_unit *align_code_ptr(TCGContext *s)
 return s->code_ptr;
 }
 
+/* Stack frame parameters.  */
+#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
+#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
+#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
+
+#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
+ + TCG_TARGET_STACK_ALIGN - 1) \
+& -TCG_TARGET_STACK_ALIGN)
+#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
+
+/* We're expecting to be able to use an immediate for frame allocation.  */
+QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff);
+
 /* Generate global QEMU prologue and epilogue code */
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
-int i, frame_size;
-
-/* reserve some stack space, also for TCG temps. */
-frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
- + TCG_STATIC_CALL_ARGS_SIZE
- + CPU_TEMP_BUF_NLONGS * sizeof(long);
-frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
- ~(TCG_TARGET_STACK_ALIGN - 1);
-tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
-  + TCG_STATIC_CALL_ARGS_SIZE,
-  CPU_TEMP_BUF_NLONGS * sizeof(long));
+int i;
+
+tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
 
 /* TB prologue */
-tcg_out_addi(s, TCG_REG_SP, -frame_size);
-for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
-tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
-   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
+tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
+for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
 }
 
 /* Call generated code */
 tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
+/* delay slot */
 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
-tb_ret_addr = s->code_ptr;
 
 /* TB epilogue */
-for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
-tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
-   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
+tb_ret_addr = s->code_ptr;
+for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
+   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
 }
 
 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
 /* delay slot */
-tcg_out_addi(s, TCG_REG_SP, frame_size);
+tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
 
 if (use_mips32r2_instructions) {
 return;
-- 
2.5.0




[Qemu-devel] [PATCH v2 09/16] tcg-mips: Add tcg unwind info

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 44 
 1 file changed, 44 insertions(+)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 4a3f11a..25b079b 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -2420,3 +2420,47 @@ void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t 
addr)
 *ptr = deposit32(*ptr, 0, 26, addr >> 2);
 flush_icache_range(jmp_addr, jmp_addr + 4);
 }
+
+typedef struct {
+DebugFrameHeader h;
+uint8_t fde_def_cfa[4];
+uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
+} DebugFrame;
+
+#define ELF_HOST_MACHINE EM_MIPS
+/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
+   which is good because they're really quite complicated for MIPS.  */
+
+static const DebugFrame debug_frame = {
+.h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
+.h.cie.id = -1,
+.h.cie.version = 1,
+.h.cie.code_align = 1,
+.h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
+.h.cie.return_column = TCG_REG_RA,
+
+/* Total FDE size does not include the "len" member.  */
+.h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
+
+.fde_def_cfa = {
+12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
+(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
+(FRAME_SIZE >> 7)
+},
+.fde_reg_ofs = {
+0x80 + 16, 9,   /* DW_CFA_offset, s0, -72 */
+0x80 + 17, 8,   /* DW_CFA_offset, s2, -64 */
+0x80 + 18, 7,   /* DW_CFA_offset, s3, -56 */
+0x80 + 19, 6,   /* DW_CFA_offset, s4, -48 */
+0x80 + 20, 5,   /* DW_CFA_offset, s5, -40 */
+0x80 + 21, 4,   /* DW_CFA_offset, s6, -32 */
+0x80 + 22, 3,   /* DW_CFA_offset, s7, -24 */
+0x80 + 30, 2,   /* DW_CFA_offset, s8, -16 */
+0x80 + 31, 1,   /* DW_CFA_offset, ra,  -8 */
+}
+};
+
+void tcg_register_jit(void *buf, size_t buf_size)
+{
+tcg_register_jit_int(buf, buf_size, _frame, sizeof(debug_frame));
+}
-- 
2.5.0




[Qemu-devel] [PATCH v2 11/16] tcg-mips: Adjust calling conventions for mips64

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 21 +++--
 tcg/mips/tcg-target.h | 19 +++
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index f61d6c7..8fb2ab0 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -98,10 +98,6 @@ static const TCGReg tcg_target_reg_alloc_order[] = {
 TCG_REG_S8,
 
 /* Call clobbered registers.  */
-TCG_REG_T0,
-TCG_REG_T1,
-TCG_REG_T2,
-TCG_REG_T3,
 TCG_REG_T4,
 TCG_REG_T5,
 TCG_REG_T6,
@@ -112,17 +108,27 @@ static const TCGReg tcg_target_reg_alloc_order[] = {
 TCG_REG_V0,
 
 /* Argument registers, opposite order of allocation.  */
+TCG_REG_T3,
+TCG_REG_T2,
+TCG_REG_T1,
+TCG_REG_T0,
 TCG_REG_A3,
 TCG_REG_A2,
 TCG_REG_A1,
 TCG_REG_A0,
 };
 
-static const TCGReg tcg_target_call_iarg_regs[4] = {
+static const TCGReg tcg_target_call_iarg_regs[] = {
 TCG_REG_A0,
 TCG_REG_A1,
 TCG_REG_A2,
-TCG_REG_A3
+TCG_REG_A3,
+#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
+TCG_REG_T0,
+TCG_REG_T1,
+TCG_REG_T2,
+TCG_REG_T3,
+#endif
 };
 
 static const TCGReg tcg_target_call_oarg_regs[2] = {
@@ -2453,6 +2459,9 @@ static void tcg_target_init(TCGContext *s)
 {
 tcg_target_detect_isa();
 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0x);
+if (TCG_TARGET_REG_BITS == 64) {
+tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I64], 0x);
+}
 tcg_regset_set(tcg_target_call_clobber_regs,
(1 << TCG_REG_V0) |
(1 << TCG_REG_V1) |
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 1a9e54c..3eb771f 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -26,7 +26,14 @@
 #ifndef TCG_TARGET_MIPS 
 #define TCG_TARGET_MIPS 1
 
-#define TCG_TARGET_REG_BITS 32
+#if _MIPS_SIM == _ABIO32
+# define TCG_TARGET_REG_BITS 32
+#elif _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
+# define TCG_TARGET_REG_BITS 64
+#else
+# error "Unknown ABI"
+#endif
+
 #define TCG_TARGET_INSN_UNIT_SIZE 4
 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 16
 #define TCG_TARGET_NB_REGS 32
@@ -70,9 +77,13 @@ typedef enum {
 } TCGReg;
 
 /* used for function call generation */
-#define TCG_TARGET_STACK_ALIGN 8
-#define TCG_TARGET_CALL_STACK_OFFSET 16
-#define TCG_TARGET_CALL_ALIGN_ARGS 1
+#define TCG_TARGET_STACK_ALIGN16
+#if _MIPS_SIM == _ABIO32
+# define TCG_TARGET_CALL_STACK_OFFSET 16
+#else
+# define TCG_TARGET_CALL_STACK_OFFSET 0
+#endif
+#define TCG_TARGET_CALL_ALIGN_ARGS1
 
 /* MOVN/MOVZ instructions detection */
 #if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
-- 
2.5.0




[Qemu-devel] [PATCH v2 07/16] tcg-mips: Adjust load/store functions for mips64

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 0451acb..d1266ef 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -689,7 +689,7 @@ static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, 
TCGReg data,
 if (ofs != lo) {
 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
 if (addr != TCG_REG_ZERO) {
-tcg_out_opc_reg(s, OPC_ADDU, TCG_TMP0, TCG_TMP0, addr);
+tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP0, TCG_TMP0, addr);
 }
 addr = TCG_TMP0;
 }
@@ -699,13 +699,21 @@ static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, 
TCGReg data,
 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
   TCGReg arg1, intptr_t arg2)
 {
-tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
+MIPSInsn opc = OPC_LD;
+if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
+opc = OPC_LW;
+}
+tcg_out_ldst(s, opc, arg, arg1, arg2);
 }
 
 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
   TCGReg arg1, intptr_t arg2)
 {
-tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
+MIPSInsn opc = OPC_SD;
+if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
+opc = OPC_SW;
+}
+tcg_out_ldst(s, opc, arg, arg1, arg2);
 }
 
 static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
-- 
2.5.0




[Qemu-devel] [PATCH v2 04/16] tcg-mips: Support 64-bit opcodes

2016-02-14 Thread Richard Henderson
Bulk patch adding 64-bit opcodes into tcg_out_op.  Note that
mips64 is as yet neither complete nor enabled.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 322 --
 tcg/mips/tcg-target.h |  41 +++
 2 files changed, 353 insertions(+), 10 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 71de3bb..5ce52ad 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -429,6 +429,21 @@ static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn 
opc, TCGReg rt,
 tcg_out32(s, inst);
 }
 
+static inline void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
+MIPSInsn oph, TCGReg rt, TCGReg rs,
+int msb, int lsb)
+{
+if (lsb >= 32) {
+opc = oph;
+msb -= 32;
+lsb -= 32;
+} else if (msb >= 32) {
+opc = opm;
+msb -= 32;
+}
+tcg_out_opc_bf(s, opc, rt, rs, msb, lsb);
+}
+
 /*
  * Type branch
  */
@@ -459,6 +474,18 @@ static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn 
opc,
 
 }
 
+static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2,
+ TCGReg rd, TCGReg rt, TCGArg sa)
+{
+int32_t inst;
+
+inst = (sa & 32 ? opc2 : opc1);
+inst |= (rt & 0x1F) << 16;
+inst |= (rd & 0x1F) << 11;
+inst |= (sa & 0x1F) <<  6;
+tcg_out32(s, inst);
+}
+
 /*
  * Type jump.
  * Returns true if the branch was in range and the insn was emitted.
@@ -487,6 +514,21 @@ static inline void tcg_out_nop(TCGContext *s)
 tcg_out32(s, 0);
 }
 
+static inline void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
+{
+tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
+}
+
+static inline void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
+{
+tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSRL32, rd, rt, sa);
+}
+
+static inline void tcg_out_dsra(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
+{
+tcg_out_opc_sa64(s, OPC_DSRA, OPC_DSRA32, rd, rt, sa);
+}
+
 static inline void tcg_out_mov(TCGContext *s, TCGType type,
TCGReg ret, TCGReg arg)
 {
@@ -565,6 +607,27 @@ static void tcg_out_bswap32(TCGContext *s, TCGReg ret, 
TCGReg arg)
 }
 }
 
+static void tcg_out_bswap32u(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+if (use_mips32r2_instructions) {
+tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
+tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
+tcg_out_dsrl(s, ret, ret, 32);
+} else {
+abort();
+}
+}
+
+static void tcg_out_bswap64(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+if (use_mips32r2_instructions) {
+tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
+tcg_out_opc_reg(s, OPC_DSHD, ret, 0, arg);
+} else {
+abort();
+}
+}
+
 static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
 {
 if (use_mips32r2_instructions) {
@@ -585,6 +648,16 @@ static inline void tcg_out_ext16s(TCGContext *s, TCGReg 
ret, TCGReg arg)
 }
 }
 
+static inline void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+if (use_mips32r2_instructions) {
+tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
+} else {
+tcg_out_dsll(s, ret, arg, 32);
+tcg_out_dsrl(s, ret, ret, 32);
+}
+}
+
 static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
  TCGReg addr, intptr_t ofs)
 {
@@ -1454,6 +1527,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 {
 TCGReg b0 = TCG_REG_ZERO;
 
+a0 = (intptr_t)a0;
 if (a0 & ~0x) {
 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0x);
 b0 = TCG_REG_V0;
@@ -1487,28 +1561,45 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 break;
 
 case INDEX_op_ld8u_i32:
+case INDEX_op_ld8u_i64:
 i1 = OPC_LBU;
 goto do_ldst;
 case INDEX_op_ld8s_i32:
+case INDEX_op_ld8s_i64:
 i1 = OPC_LB;
 goto do_ldst;
 case INDEX_op_ld16u_i32:
+case INDEX_op_ld16u_i64:
 i1 = OPC_LHU;
 goto do_ldst;
 case INDEX_op_ld16s_i32:
+case INDEX_op_ld16s_i64:
 i1 = OPC_LH;
 goto do_ldst;
 case INDEX_op_ld_i32:
+case INDEX_op_ld32s_i64:
 i1 = OPC_LW;
 goto do_ldst;
+case INDEX_op_ld32u_i64:
+i1 = OPC_LWU;
+goto do_ldst;
+case INDEX_op_ld_i64:
+i1 = OPC_LD;
+goto do_ldst;
 case INDEX_op_st8_i32:
+case INDEX_op_st8_i64:
 i1 = OPC_SB;
 goto do_ldst;
 case INDEX_op_st16_i32:
+case INDEX_op_st16_i64:
 i1 = OPC_SH;
 goto do_ldst;
 case INDEX_op_st_i32:
+case INDEX_op_st32_i64:
 i1 = OPC_SW;
+goto do_ldst;
+case INDEX_op_st_i64:
+i1 = OPC_SD;
 do_ldst:
 tcg_out_ldst(s, i1, a0, a1, a2);
 

[Qemu-devel] [PATCH v2 06/16] tcg-mips: Adjust move functions for mips64

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 34 +-
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 88c032c..0451acb 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -536,23 +536,39 @@ static inline void tcg_out_mov(TCGContext *s, TCGType 
type,
 {
 /* Simple reg-reg move, optimising out the 'do nothing' case */
 if (ret != arg) {
-tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
+tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO);
 }
 }
 
-static inline void tcg_out_movi(TCGContext *s, TCGType type,
-TCGReg reg, tcg_target_long arg)
+static void tcg_out_movi(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
 {
+if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
+arg = (int32_t)arg;
+}
 if (arg == (int16_t)arg) {
-tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
-} else if (arg == (uint16_t)arg) {
-tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
+tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
+return;
+}
+if (arg == (uint16_t)arg) {
+tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
+return;
+}
+if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) {
+tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
 } else {
-tcg_out_opc_imm(s, OPC_LUI, reg, TCG_REG_ZERO, arg >> 16);
-if (arg & 0x) {
-tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0x);
+tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1);
+if (arg & 0xull) {
+tcg_out_dsll(s, ret, ret, 16);
+tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16);
+tcg_out_dsll(s, ret, ret, 16);
+} else {
+tcg_out_dsll(s, ret, ret, 32);
 }
 }
+if (arg & 0x) {
+tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0x);
+}
 }
 
 static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
-- 
2.5.0




[Qemu-devel] [PATCH v2 13/16] tcg-mips: Use mips64r6 instructions in tcg_out_ldst

2016-02-14 Thread Richard Henderson
The DAUI, DAHI, and DATI insns can be used to eliminate
one extra instruction in these cases.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 40 
 1 file changed, 40 insertions(+)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index b4239cb..52e1edc 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -402,6 +402,7 @@ typedef enum {
 /* Aliases for convenience.  */
 ALIAS_PADD = sizeof(void *) == 4 ? OPC_ADDU : OPC_DADDU,
 ALIAS_PADDI= sizeof(void *) == 4 ? OPC_ADDIU : OPC_DADDIU,
+ALIAS_PAUI = sizeof(void *) == 4 ? OPC_AUI : OPC_DAUI,
 ALIAS_TSRL = TARGET_LONG_BITS == 32 || TCG_TARGET_REG_BITS == 32
  ? OPC_SRL : OPC_DSRL,
 } MIPSInsn;
@@ -795,9 +796,48 @@ static inline void tcg_out_ext32u(TCGContext *s, TCGReg 
ret, TCGReg arg)
 }
 }
 
+static void tcg_out_r6_ofs(TCGContext *s, MIPSInsn opl, MIPSInsn oph,
+   TCGReg reg0, TCGReg reg1, tcg_target_long ofs)
+{
+TCGReg scratch = TCG_TMP0;
+int16_t lo = ofs;
+int32_t hi = ofs - lo;
+
+ofs = ofs - hi - lo;
+if (oph == OPC_DAUI && ofs != 0) {
+tcg_target_long tmp;
+
+/* Bits are set in the high 32-bit half.  Thus we require the
+   use of DAHI and/or DATI.  The R6 manual recommends addition
+   of immediates in order of mid to high (DAUI, DAHI, DATI, OPL)
+   in order to simplify hardware recognizing these sequences.  */
+
+tcg_out_opc_imm(s, OPC_DAUI, scratch, reg1, hi >> 16);
+
+tmp = ofs >> 16 >> 16;
+if (tmp & 0x) {
+tcg_out_opc_imm(s, OPC_DAHI, 0, scratch, tmp);
+}
+tmp = (tmp - (int16_t)tmp) >> 16;
+if (tmp) {
+tcg_out_opc_imm(s, OPC_DATI, 0, scratch, tmp);
+}
+reg1 = scratch;
+} else if (hi != 0) {
+tcg_out_opc_imm(s, oph, scratch, reg1, hi >> 16);
+reg1 = scratch;
+}
+tcg_out_opc_imm(s, opc, reg0, reg1, lo);
+}
+
 static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
  TCGReg addr, intptr_t ofs)
 {
+if (use_mips32r6_instructions) {
+tcg_out_r6_ofs(s, opc, ALIAS_PAUI, data, addr, ofs);
+return;
+}
+
 int16_t lo = ofs;
 if (ofs != lo) {
 tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
-- 
2.5.0




[Qemu-devel] [PATCH v2 10/16] tcg-mips: Adjust qemu_ld/st for mips64

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 188 ++
 1 file changed, 130 insertions(+), 58 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 25b079b..f61d6c7 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -33,8 +33,14 @@
 # define MIPS_BE  0
 #endif
 
-#define LO_OFF(MIPS_BE * 4)
-#define HI_OFF(4 - LO_OFF)
+#if TCG_TARGET_REG_BITS == 32
+# define LO_OFF  (MIPS_BE * 4)
+# define HI_OFF  (4 - LO_OFF)
+#else
+extern int link_error(void);
+# define LO_OFF  link_error()
+# define HI_OFF  link_error()
+#endif
 
 #ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
@@ -188,7 +194,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, 
const char **pct_str)
 tcg_regset_set(ct->u.regs, 0x);
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
 #if defined(CONFIG_SOFTMMU)
-if (TARGET_LONG_BITS == 64) {
+if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
 }
 #endif
@@ -198,11 +204,11 @@ static int target_parse_constraint(TCGArgConstraint *ct, 
const char **pct_str)
 tcg_regset_set(ct->u.regs, 0x);
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
 #if defined(CONFIG_SOFTMMU)
-if (TARGET_LONG_BITS == 32) {
-tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
-} else {
+if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
+} else {
+tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
 }
 #endif
 break;
@@ -1080,6 +1086,10 @@ static void * const qemu_ld_helpers[16] = {
 [MO_BESW] = helper_be_ldsw_mmu,
 [MO_BEUL] = helper_be_ldul_mmu,
 [MO_BEQ]  = helper_be_ldq_mmu,
+#if TCG_TARGET_REG_BITS == 64
+[MO_LESL] = helper_le_ldsl_mmu,
+[MO_BESL] = helper_be_ldsl_mmu,
+#endif
 };
 
 static void * const qemu_st_helpers[16] = {
@@ -1107,6 +1117,9 @@ static int tcg_out_call_iarg_reg(TCGContext *s, int i, 
TCGReg arg)
 if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
 tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
 } else {
+/* For N32 and N64, the initial offset is different.  But there
+   we also have 8 argument register so we don't run out here.  */
+tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
 tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
 }
 return i + 1;
@@ -1148,6 +1161,7 @@ static int tcg_out_call_iarg_imm(TCGContext *s, int i, 
TCGArg arg)
 
 static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
 {
+tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
 i = (i + 1) & ~1;
 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
 i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
@@ -1161,6 +1175,7 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
  tcg_insn_unit *label_ptr[2], bool is_load)
 {
 TCGMemOp s_bits = get_memop(oi) & MO_SIZE;
+target_ulong mask = TARGET_PAGE_MASK | ((1 << s_bits) - 1);
 int mem_index = get_mmuidx(oi);
 int cmp_off
 = (is_load
@@ -1168,11 +1183,11 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg 
base, TCGReg addrl,
: offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
 int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
 
-tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addrl,
+tcg_out_opc_sa(s, ALIAS_TSRL, TCG_REG_A0, addrl,
TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
 tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
 (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
-tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
+tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
 
 /* Compensate for very large offsets.  */
 if (add_off >= 0x8000) {
@@ -1182,43 +1197,48 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg 
base, TCGReg addrl,
 QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
tlb_table[NB_MMU_MODES - 1][1])
   > 0x7ff0 + 0x7fff);
-tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
+tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
 cmp_off -= 0x7ff0;
 add_off -= 0x7ff0;
 }
 
-/* Load the (low half) tlb comparator.  */
-tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0,
-cmp_off + (TARGET_LONG_BITS == 64 ? LO_OFF : 0));
-
-/* Mask the page bits, keeping the alignment bits to compare against.
-   In between on 32-bit targets, load the tlb addend for the fast path.  */
-tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1,
- 

[Qemu-devel] [PATCH v2 05/16] tcg-mips: Add bswap32u and bswap64

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 102 --
 1 file changed, 99 insertions(+), 3 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 5ce52ad..88c032c 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -126,6 +126,8 @@ static const TCGReg tcg_target_call_oarg_regs[2] = {
 
 static tcg_insn_unit *tb_ret_addr;
 static tcg_insn_unit *bswap32_addr;
+static tcg_insn_unit *bswap32u_addr;
+static tcg_insn_unit *bswap64_addr;
 
 static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
 {
@@ -614,7 +616,10 @@ static void tcg_out_bswap32u(TCGContext *s, TCGReg ret, 
TCGReg arg)
 tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
 tcg_out_dsrl(s, ret, ret, 32);
 } else {
-abort();
+tcg_out_bswap_subr(s, bswap32u_addr);
+/* delay slot -- never omit the insn, like tcg_out_mov might.  */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
+tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
 }
 }
 
@@ -624,7 +629,10 @@ static void tcg_out_bswap64(TCGContext *s, TCGReg ret, 
TCGReg arg)
 tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
 tcg_out_opc_reg(s, OPC_DSHD, ret, 0, arg);
 } else {
-abort();
+tcg_out_bswap_subr(s, bswap64_addr);
+/* delay slot -- never omit the insn, like tcg_out_mov might.  */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
+tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
 }
 }
 
@@ -2233,7 +2241,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 return;
 }
 
-/* Bswap subroutine: Input in TCG_TMP0, output in TCG_TMP3;
+/* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
clobbers TCG_TMP1, TCG_TMP2.  */
 
 /*
@@ -2259,6 +2267,94 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
 /* t3 = dcba -- delay slot */
 tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+
+if (TCG_TARGET_REG_BITS == 32) {
+return;
+}
+
+/*
+ * bswap32u -- unsigned 32-bit swap.  a0 = abcd.
+ */
+bswap32u_addr = align_code_ptr(s);
+/* t1 = ()000d */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff);
+/* t3 = 000a */
+tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24);
+/* t1 = ()d000 */
+tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
+/* t2 = 00c0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
+/* t3 = d00a */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+/* t1 = 0abc */
+tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
+/* t2 = 0c00 */
+tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
+/* t1 = 00b0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
+/* t3 = dc0a */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
+tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
+/* t3 = dcba -- delay slot */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+
+/*
+ * bswap64 -- 64-bit swap.  a0 = abcdefgh
+ */
+bswap64_addr = align_code_ptr(s);
+/* t3 = h000 */
+tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56);
+/* t1 = 000a */
+tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56);
+
+/* t2 = 00g0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
+/* t3 = h00a */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+/* t1 = 0abc */
+tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40);
+/* t2 = 0g00 */
+tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
+/* t1 = 00b0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
+
+/* t3 = hg0a */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
+/* t2 = abcd */
+tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32);
+/* t3 = hgba */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+
+/* t1 = 00c0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00);
+/* t2 = 000d */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff);
+/* t1 = 0c00 */
+tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8);
+/* t2 = d000 */
+tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24);
+
+/* t3 = hg000cba */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+/* t1 = 00abcdef */
+tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 16);
+/* t3 = hg00dcba */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
+
+/* t2 = 000f */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP1, 0x00ff);
+/* t1 = 00e0 */
+tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
+/* t2 = 00f0 */
+tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
+/* t1 = 000e */
+tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
+
+/* t3 = hgf0dcba */
+tcg_out_opc_reg(s, 

[Qemu-devel] [PATCH v2 03/16] tcg-mips: Add mips64 opcodes

2016-02-14 Thread Richard Henderson
Since the mips manual tables are in octal, reorg all of the opcodes
into that format for clarity.  Note that the 64-bit opcodes are as
yet unused.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 191 +++---
 1 file changed, 117 insertions(+), 74 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 3f33cca..71de3bb 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -255,80 +255,117 @@ static inline int tcg_target_const_match(tcg_target_long 
val, TCGType type,
 
 /* instruction opcodes */
 typedef enum {
-OPC_J= 0x02 << 26,
-OPC_JAL  = 0x03 << 26,
-OPC_BEQ  = 0x04 << 26,
-OPC_BNE  = 0x05 << 26,
-OPC_BLEZ = 0x06 << 26,
-OPC_BGTZ = 0x07 << 26,
-OPC_ADDIU= 0x09 << 26,
-OPC_SLTI = 0x0A << 26,
-OPC_SLTIU= 0x0B << 26,
-OPC_ANDI = 0x0C << 26,
-OPC_ORI  = 0x0D << 26,
-OPC_XORI = 0x0E << 26,
-OPC_LUI  = 0x0F << 26,
-OPC_LB   = 0x20 << 26,
-OPC_LH   = 0x21 << 26,
-OPC_LW   = 0x23 << 26,
-OPC_LBU  = 0x24 << 26,
-OPC_LHU  = 0x25 << 26,
-OPC_LWU  = 0x27 << 26,
-OPC_SB   = 0x28 << 26,
-OPC_SH   = 0x29 << 26,
-OPC_SW   = 0x2B << 26,
-
-OPC_SPECIAL  = 0x00 << 26,
-OPC_SLL  = OPC_SPECIAL | 0x00,
-OPC_SRL  = OPC_SPECIAL | 0x02,
-OPC_ROTR = OPC_SPECIAL | (0x01 << 21) | 0x02,
-OPC_SRA  = OPC_SPECIAL | 0x03,
-OPC_SLLV = OPC_SPECIAL | 0x04,
-OPC_SRLV = OPC_SPECIAL | 0x06,
-OPC_ROTRV= OPC_SPECIAL | (0x01 <<  6) | 0x06,
-OPC_SRAV = OPC_SPECIAL | 0x07,
-OPC_JR_R5= OPC_SPECIAL | 0x08,
-OPC_JALR = OPC_SPECIAL | 0x09,
-OPC_MOVZ = OPC_SPECIAL | 0x0A,
-OPC_MOVN = OPC_SPECIAL | 0x0B,
-OPC_MFHI = OPC_SPECIAL | 0x10,
-OPC_MFLO = OPC_SPECIAL | 0x12,
-OPC_MULT = OPC_SPECIAL | 0x18,
-OPC_MUL_R6   = OPC_SPECIAL | (0x02 <<  6) | 0x18,
-OPC_MUH  = OPC_SPECIAL | (0x03 <<  6) | 0x18,
-OPC_MULTU= OPC_SPECIAL | 0x19,
-OPC_MULU = OPC_SPECIAL | (0x02 <<  6) | 0x19,
-OPC_MUHU = OPC_SPECIAL | (0x03 <<  6) | 0x19,
-OPC_DIV  = OPC_SPECIAL | 0x1A,
-OPC_DIV_R6   = OPC_SPECIAL | (0x02 <<  6) | 0x1A,
-OPC_MOD  = OPC_SPECIAL | (0x03 <<  6) | 0x1A,
-OPC_DIVU = OPC_SPECIAL | 0x1B,
-OPC_DIVU_R6  = OPC_SPECIAL | (0x02 <<  6) | 0x1B,
-OPC_MODU = OPC_SPECIAL | (0x03 <<  6) | 0x1B,
-OPC_ADDU = OPC_SPECIAL | 0x21,
-OPC_SUBU = OPC_SPECIAL | 0x23,
-OPC_AND  = OPC_SPECIAL | 0x24,
-OPC_OR   = OPC_SPECIAL | 0x25,
-OPC_XOR  = OPC_SPECIAL | 0x26,
-OPC_NOR  = OPC_SPECIAL | 0x27,
-OPC_SLT  = OPC_SPECIAL | 0x2A,
-OPC_SLTU = OPC_SPECIAL | 0x2B,
-OPC_SELEQZ   = OPC_SPECIAL | 0x35,
-OPC_SELNEZ   = OPC_SPECIAL | 0x37,
-
-OPC_REGIMM   = 0x01 << 26,
-OPC_BLTZ = OPC_REGIMM | (0x00 << 16),
-OPC_BGEZ = OPC_REGIMM | (0x01 << 16),
-
-OPC_SPECIAL2 = 0x1c << 26,
-OPC_MUL_R5   = OPC_SPECIAL2 | 0x002,
-
-OPC_SPECIAL3 = 0x1f << 26,
-OPC_EXT  = OPC_SPECIAL3 | 0x000,
-OPC_INS  = OPC_SPECIAL3 | 0x004,
-OPC_WSBH = OPC_SPECIAL3 | 0x0a0,
-OPC_SEB  = OPC_SPECIAL3 | 0x420,
-OPC_SEH  = OPC_SPECIAL3 | 0x620,
+OPC_J= 002 << 26,
+OPC_JAL  = 003 << 26,
+OPC_BEQ  = 004 << 26,
+OPC_BNE  = 005 << 26,
+OPC_BLEZ = 006 << 26,
+OPC_BGTZ = 007 << 26,
+OPC_ADDIU= 011 << 26,
+OPC_SLTI = 012 << 26,
+OPC_SLTIU= 013 << 26,
+OPC_ANDI = 014 << 26,
+OPC_ORI  = 015 << 26,
+OPC_XORI = 016 << 26,
+OPC_LUI  = 017 << 26,
+OPC_DADDIU   = 031 << 26,
+OPC_LB   = 040 << 26,
+OPC_LH   = 041 << 26,
+OPC_LW   = 043 << 26,
+OPC_LBU  = 044 << 26,
+OPC_LHU  = 045 << 26,
+OPC_LWU  = 047 << 26,
+OPC_SB   = 050 << 26,
+OPC_SH   = 051 << 26,
+OPC_SW   = 053 << 26,
+OPC_LD   = 067 << 26,
+OPC_SD   = 077 << 26,
+
+OPC_SPECIAL  = 000 << 26,
+OPC_SLL  = OPC_SPECIAL | 000,
+OPC_SRL  = OPC_SPECIAL | 002,
+OPC_ROTR = OPC_SPECIAL | 002 | (1 << 21),
+OPC_SRA  = OPC_SPECIAL | 003,
+OPC_SLLV = OPC_SPECIAL | 004,
+OPC_SRLV = OPC_SPECIAL | 006,
+OPC_ROTRV= OPC_SPECIAL | 006 | 0100,
+OPC_SRAV = OPC_SPECIAL | 007,
+OPC_JR_R5= OPC_SPECIAL | 010,
+OPC_JALR = OPC_SPECIAL | 011,
+OPC_MOVZ = OPC_SPECIAL | 012,
+OPC_MOVN = OPC_SPECIAL | 013,
+OPC_MFHI = OPC_SPECIAL | 020,
+OPC_MFLO = OPC_SPECIAL | 022,
+OPC_DSLLV= OPC_SPECIAL | 024,
+OPC_DSRLV= OPC_SPECIAL | 026,
+OPC_DROTRV   = OPC_SPECIAL | 026 | 0100,
+OPC_DSRAV= OPC_SPECIAL | 027,
+OPC_MULT = OPC_SPECIAL | 030,
+OPC_MUL_R6   = 

[Qemu-devel] [PATCH v2 02/16] tcg-mips: Move bswap code to a subroutine

2016-02-14 Thread Richard Henderson
Without the mips32r2 instructions to perform swapping, bswap is quite large,
dominating the size of each reverse-endian qemu_ld/qemu_st operation.

Create a subroutine in the prologue block.  The subroutine requires extra
reserved registers (TCG_TMP[23]).  Using these within qemu_ld means that
we need not place additional restrictions on the qemu_ld outputs.

Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 207 +-
 tcg/mips/tcg-target.h |   2 +-
 2 files changed, 139 insertions(+), 70 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index ebb936d..3f33cca 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -75,6 +75,8 @@ static const char * const 
tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
 
 #define TCG_TMP0  TCG_REG_AT
 #define TCG_TMP1  TCG_REG_T9
+#define TCG_TMP2  TCG_REG_T8
+#define TCG_TMP3  TCG_REG_T7
 
 /* check if we really need so many registers :P */
 static const TCGReg tcg_target_reg_alloc_order[] = {
@@ -123,6 +125,7 @@ static const TCGReg tcg_target_call_oarg_regs[2] = {
 };
 
 static tcg_insn_unit *tb_ret_addr;
+static tcg_insn_unit *bswap32_addr;
 
 static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
 {
@@ -178,12 +181,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, 
const char **pct_str)
 ct->ct |= TCG_CT_REG;
 tcg_regset_set(ct->u.regs, 0x);
 break;
-case 'L': /* qemu_ld output arg constraint */
-ct->ct |= TCG_CT_REG;
-tcg_regset_set(ct->u.regs, 0x);
-tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
-break;
-case 'l': /* qemu_ld input arg constraint */
+case 'L': /* qemu_ld input arg constraint */
 ct->ct |= TCG_CT_REG;
 tcg_regset_set(ct->u.regs, 0x);
 tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
@@ -505,29 +503,22 @@ static inline void tcg_out_bswap16s(TCGContext *s, TCGReg 
ret, TCGReg arg)
 }
 }
 
-static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
+static void tcg_out_bswap_subr(TCGContext *s, tcg_insn_unit *sub)
+{
+bool ok = tcg_out_opc_jmp(s, OPC_JAL, sub);
+tcg_debug_assert(ok);
+}
+
+static void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
 {
 if (use_mips32r2_instructions) {
 tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
 tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
 } else {
-/* ret and arg must be different and can't be register at */
-if (ret == arg || ret == TCG_TMP0 || arg == TCG_TMP0) {
-tcg_abort();
-}
-
-tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
-
-tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 24);
-tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
-
-tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, arg, 0xff00);
-tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8);
-tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
-
-tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
-tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0xff00);
-tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
+tcg_out_bswap_subr(s, bswap32_addr);
+/* delay slot -- never omit the insn, like tcg_out_mov might.  */
+tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
+tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
 }
 }
 
@@ -1026,7 +1017,7 @@ static int tcg_out_call_iarg_reg2(TCGContext *s, int i, 
TCGReg al, TCGReg ah)
 }
 
 /* Perform the tlb comparison operation.  The complete host address is
-   placed in BASE.  Clobbers AT, T0, A0.  */
+   placed in BASE.  Clobbers TMP0, TMP1, A0.  */
 static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
  TCGReg addrh, TCGMemOpIdx oi,
  tcg_insn_unit *label_ptr[2], bool is_load)
@@ -1202,46 +1193,72 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 }
 #endif
 
-static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
+static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
TCGReg base, TCGMemOp opc)
 {
 switch (opc & (MO_SSIZE | MO_BSWAP)) {
 case MO_UB:
-tcg_out_opc_imm(s, OPC_LBU, datalo, base, 0);
+tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
 break;
 case MO_SB:
-tcg_out_opc_imm(s, OPC_LB, datalo, base, 0);
+tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
 break;
 case MO_UW | MO_BSWAP:
 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
-tcg_out_bswap16(s, datalo, TCG_TMP1);
+tcg_out_bswap16(s, lo, TCG_TMP1);
 break;
 case MO_UW:
-tcg_out_opc_imm(s, OPC_LHU, datalo, base, 0);
+tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
 break;
 case MO_SW | MO_BSWAP:
 tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
-

[Qemu-devel] [PATCH v2 00/16] tcg mips64 and mips r6 improvements

2016-02-14 Thread Richard Henderson
Changes since v1:
  * Some bugs pointed out by Mark fixed.
  * Canonicalize the whole file on tcg_debug_assert.
  * Switch bswap code to subroutine earlier; the first patch is
standalone for mips32, and there is no longer an intermediate
patch with inline bswap for mips64.
  * Use NAL for pre-r6 mips64 loading of the slow path return address.


r~


Richard Henderson (16):
  tcg-mips: Always use tcg_debug_assert
  tcg-mips: Move bswap code to a subroutine
  tcg-mips: Add mips64 opcodes
  tcg-mips: Support 64-bit opcodes
  tcg-mips: Add bswap32u and bswap64
  tcg-mips: Adjust move functions for mips64
  tcg-mips: Adjust load/store functions for mips64
  tcg-mips: Adjust prologue for mips64
  tcg-mips: Add tcg unwind info
  tcg-mips: Adjust qemu_ld/st for mips64
  tcg-mips: Adjust calling conventions for mips64
  tcg-mips: Improve tcg_out_movi for mips64
  tcg-mips: Use mips64r6 instructions in tcg_out_ldst
  tcg-mips: Use mips64r6 instructions in constant addition
  tcg-mips: Use mipsr6 instructions in branches
  tcg-mips: Use mipsr6 instructions in calls

 include/elf.h |4 +
 tcg/mips/tcg-target.c | 1651 +++--
 tcg/mips/tcg-target.h |   60 +-
 3 files changed, 1386 insertions(+), 329 deletions(-)

-- 
2.5.0




[Qemu-devel] [PATCH v2 01/16] tcg-mips: Always use tcg_debug_assert

2016-02-14 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/mips/tcg-target.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 2dc4998..ebb936d 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -128,7 +128,7 @@ static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, 
tcg_insn_unit *target)
 {
 /* Let the compiler perform the right-shift as part of the arithmetic.  */
 ptrdiff_t disp = target - (pc + 1);
-assert(disp == (int16_t)disp);
+tcg_debug_assert(disp == (int16_t)disp);
 return disp & 0x;
 }
 
@@ -139,7 +139,7 @@ static inline void reloc_pc16(tcg_insn_unit *pc, 
tcg_insn_unit *target)
 
 static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit *target)
 {
-assertuintptr_t)pc ^ (uintptr_t)target) & 0xf000) == 0);
+tcg_debug_assertuintptr_t)pc ^ (uintptr_t)target) & 0xf000) == 0);
 return ((uintptr_t)target >> 2) & 0x3ff;
 }
 
@@ -151,8 +151,8 @@ static inline void reloc_26(tcg_insn_unit *pc, 
tcg_insn_unit *target)
 static void patch_reloc(tcg_insn_unit *code_ptr, int type,
 intptr_t value, intptr_t addend)
 {
-assert(type == R_MIPS_PC16);
-assert(addend == 0);
+tcg_debug_assert(type == R_MIPS_PC16);
+tcg_debug_assert(addend == 0);
 reloc_pc16(code_ptr, (tcg_insn_unit *)value);
 }
 
@@ -433,7 +433,7 @@ static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, 
void *target)
 if ((from ^ dest) & -(1 << 28)) {
 return false;
 }
-assert((dest & 3) == 0);
+tcg_debug_assert((dest & 3) == 0);
 
 inst = opc;
 inst |= (dest >> 2) & 0x3ff;
@@ -808,9 +808,9 @@ static void tcg_out_setcond2(TCGContext *s, TCGCond cond, 
TCGReg ret,
 TCGReg tmp0 = TCG_TMP0;
 TCGReg tmp1 = ret;
 
-assert(ret != TCG_TMP0);
+tcg_debug_assert(ret != TCG_TMP0);
 if (ret == ah || ret == bh) {
-assert(ret != TCG_TMP1);
+tcg_debug_assert(ret != TCG_TMP1);
 tmp1 = TCG_TMP1;
 }
 
@@ -1471,8 +1471,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
 case INDEX_op_and_i32:
 if (c2 && a2 != (uint16_t)a2) {
 int msb = ctz32(~a2) - 1;
-assert(use_mips32r2_instructions);
-assert(is_p2m1(a2));
+tcg_debug_assert(use_mips32r2_instructions);
+tcg_debug_assert(is_p2m1(a2));
 tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
 break;
 }
-- 
2.5.0




Re: [Qemu-devel] [V4 1/4] hw/i386: Introduce AMD IO MMU

2016-02-14 Thread David kiarie
On Thu, Feb 4, 2016 at 6:03 PM, Michael S. Tsirkin  wrote:
> On Mon, Jan 18, 2016 at 06:25:42PM +0300, David Kiarie wrote:
>> Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
>> The IO MMU does basic translation, error checking and has a
>> minimal IOTLB implementation.
>>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/i386/Makefile.objs |1 +
>>  hw/i386/amd_iommu.c   | 1409 
>> +
>>  hw/i386/amd_iommu.h   |  399 ++
>>  include/hw/pci/pci.h  |2 +
>>  4 files changed, 1811 insertions(+)
>>  create mode 100644 hw/i386/amd_iommu.c
>>  create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index b52d5b8..2f1a265 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>  obj-y += pc.o pc_piix.o pc_q35.o
>>  obj-y += pc_sysfw.o
>>  obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>  obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>  obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..20111fe
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,1409 @@
>> +/*
>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see .
>> + *
>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>
> Link to hardware spec?
>
>> + *
>> + */
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +//#define DEBUG_AMD_IOMMU
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +/* configure MMIO registers at startup/reset */
>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
>> +   uint64_t romask, uint64_t w1cmask)
>> +{
>> +stq_le_p(>mmior[addr], val);
>> +stq_le_p(>romask[addr], romask);
>> +stq_le_p(>w1cmask[addr], w1cmask);
>> +}
>> +
>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return lduw_le_p(>mmior[addr]);
>> +}
>> +
>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldl_le_p(>mmior[addr]);
>> +}
>> +
>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldq_le_p(>mmior[addr]);
>> +}
>> +
>> +/* internal write */
>> +static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr 
>> addr)
>> +{
>> +stq_le_p(>mmior[addr], val);
>> +}
>> +
>> +/* external write */
>> +static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
>> +{
>> +uint16_t romask = lduw_le_p(>romask[addr]);
>> +uint16_t w1cmask = lduw_le_p(>w1cmask[addr]);
>> +uint16_t oldval = lduw_le_p(>mmior[addr]);
>> +stw_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
>> +}
>> +
>> +static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
>> +{
>> +uint32_t romask = ldl_le_p(>romask[addr]);
>> +uint32_t w1cmask = ldl_le_p(>w1cmask[addr]);
>> +uint32_t oldval = ldl_le_p(>mmior[addr]);
>> +stl_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
>> +}
>> +
>> +static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
>> +{
>> +uint64_t romask = ldq_le_p(>romask[addr]);
>> +uint64_t w1cmask = ldq_le_p(>w1cmask[addr]);
>> +uint32_t oldval = ldq_le_p(>mmior[addr]);
>> +stq_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
>> +}
>> +
>> +static void amd_iommu_log_event(AMDIOMMUState *s, uint16_t *evt)
>> +{
>> +/* event logging not enabled */
>> +if (!s->evtlog_enabled || *(uint64_t *)>mmior[MMIO_STATUS]
>> +   | MMIO_STATUS_EVT_OVF) {
>
> Pls 

[Qemu-devel] VirtIO-GPU 3D OpenGL Hardware Acceleration for VMs

2016-02-14 Thread Saket Sinha
Hi,

It seems upstream Linux/Gallium3D/Mesa/Qemu/KVM has recently gained
virtualized support for 3D/OpenGL hardware acceleration in VMs,
allowing using the GPU of the host in VMs.

As per my understanding the following components are needed -

- Linux 4.4 kernel includes the DRM driver for VirtIO-GPU 3D
acceleration (needed in the VM).
- Qemu 2.5  includes the VirtIO-GPU 3D mode support.
- Gallium3D VirGL driver is included in Mesa git (needed in the VM,
supports up to OpenGL 3.3 atm).
- On the host *any* OpenGL driver (for the host GPU obviously), no
special requirements there.

In order to do test this, if I can be guided as to what are the right
applications to test the entire Graphic stack on a QEMU-KVM Virtual
machine, I shall be grateful.






Regards,
Saket Sinha



Re: [Qemu-devel] [PATCH v15 7/9] Introduce new APIs to do replication operation

2016-02-14 Thread Changlong Xie

On 02/15/2016 08:57 AM, Hailiang Zhang wrote:

On 2016/2/5 12:18, Changlong Xie wrote:

Signed-off-by: Wen Congyang 
Signed-off-by: zhanghailiang 
Signed-off-by: Gonglei 
Signed-off-by: Changlong Xie 
---
  Makefile.objs|  1 +
  qapi/block-core.json | 13 
  replication.c| 94

  replication.h| 53 +
  4 files changed, 161 insertions(+)
  create mode 100644 replication.c
  create mode 100644 replication.h

diff --git a/Makefile.objs b/Makefile.objs
index 06b95c7..a8c74b7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -15,6 +15,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
  block-obj-$(CONFIG_WIN32) += aio-win32.o
  block-obj-y += block/
  block-obj-y += qemu-io-cmds.o
+block-obj-y += replication.o

  block-obj-m = block/

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 7e9e8fe..12362b8 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2002,6 +2002,19 @@
  '*read-pattern': 'QuorumReadPattern' } }

  ##
+# @ReplicationMode
+#
+# An enumeration of replication modes.
+#
+# @primary: Primary mode, the vm's state will be sent to secondary QEMU.
+#
+# @secondary: Secondary mode, receive the vm's state from primary QEMU.
+#
+# Since: 2.6
+##
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+
+##
  # @BlockdevOptions
  #
  # Options for creating a block device.
diff --git a/replication.c b/replication.c
new file mode 100644
index 000..e8ac2f0
--- /dev/null
+++ b/replication.c
@@ -0,0 +1,94 @@
+/*
+ * Replication filter
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2016 FUJITSU LIMITED
+ *
+ * Author:
+ *   Wen Congyang 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "replication.h"
+
+static QLIST_HEAD(, ReplicationState) replication_states;
+
+ReplicationState *replication_new(void *opaque, ReplicationOps *ops)
+{
+ReplicationState *rs;
+
+rs = g_new0(ReplicationState, 1);
+rs->opaque = opaque;
+rs->ops = ops;
+QLIST_INSERT_HEAD(_states, rs, node);
+
+return rs;
+}
+
+void replication_remove(ReplicationState *rs)
+{
+QLIST_REMOVE(rs, node);
+g_free(rs);
+}
+
+/*
+ * The caller of the function *MUST* make sure vm stopped
+ */
+void replication_start_all(ReplicationMode mode, Error **errp)
+{


Is this public API is only used for block ?
If yes, I'd like it with a 'block_' prefix.


+ReplicationState *rs, *next;
+
+QLIST_FOREACH_SAFE(rs, _states, node, next) {
+if (rs->ops && rs->ops->start) {
+rs->ops->start(rs, mode, errp);
+}
+if (*errp != NULL) {


This is incorrect, you miss checking if errp is NULL,
if errp is NULL, there will be an error that accessing memory at address
0x0.
Same with other places in this patch.


You are right, will fix in next version.

Thanks
-Xie




+return;
+}
+}
+}
+
+void replication_do_checkpoint_all(Error **errp)
+{
+ReplicationState *rs, *next;
+
+QLIST_FOREACH_SAFE(rs, _states, node, next) {
+if (rs->ops && rs->ops->checkpoint) {
+rs->ops->checkpoint(rs, errp);
+}
+if (*errp != NULL) {
+return;



+}
+}
+}
+
+void replication_get_error_all(Error **errp)
+{
+ReplicationState *rs, *next;
+
+QLIST_FOREACH_SAFE(rs, _states, node, next) {
+if (rs->ops && rs->ops->get_error) {
+rs->ops->get_error(rs, errp);
+}
+if (*errp != NULL) {



+return;
+}
+}
+}
+
+void replication_stop_all(bool failover, Error **errp)
+{
+ReplicationState *rs, *next;
+
+QLIST_FOREACH_SAFE(rs, _states, node, next) {
+if (rs->ops && rs->ops->stop) {
+rs->ops->stop(rs, failover, errp);
+}
+if (*errp != NULL) {
+return;
+}
+}
+}
diff --git a/replication.h b/replication.h
new file mode 100644
index 000..faea649
--- /dev/null
+++ b/replication.h
@@ -0,0 +1,53 @@
+/*
+ * Replication filter
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2016 FUJITSU LIMITED
+ *
+ * Author:
+ *   Wen Congyang 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef REPLICATION_H
+#define REPLICATION_H
+
+#include "sysemu/sysemu.h"
+
+typedef struct ReplicationOps ReplicationOps;
+typedef struct ReplicationState ReplicationState;
+typedef void (*Start)(ReplicationState *rs, ReplicationMode mode,
Error **errp);
+typedef void (*Stop)(ReplicationState *rs, bool failover, 

Re: [Qemu-devel] [PATCH v12 1/2] mirror: Rewrite mirror_iteration

2016-02-14 Thread Fam Zheng
On Mon, 02/08 13:54, Max Reitz wrote:
> On 07.02.2016 13:46, Fam Zheng wrote:
> > On Sat, 02/06 14:24, Max Reitz wrote:
> >> On 05.02.2016 03:00, Fam Zheng wrote:
> >>> The "pnum < nb_sectors" condition in deciding whether to actually copy
> >>> data is unnecessarily strict, and the qiov initialization is
> >>> unnecessarily for bdrv_aio_write_zeroes and bdrv_aio_discard.
> >>>
> >>> Rewrite mirror_iteration to fix both flaws.
> >>>
> >>> The output of iotests 109 is updated because we now report the offset
> >>> and len slightly differently in mirroring progress.
> >>>
> >>> Signed-off-by: Fam Zheng 
> >>> ---
> >>>  block/mirror.c | 335 
> >>> +++--
> >>>  tests/qemu-iotests/109.out |  80 +--
> >>>  trace-events   |   1 -
> >>>  3 files changed, 243 insertions(+), 173 deletions(-)
> >>>
> >>> diff --git a/block/mirror.c b/block/mirror.c
> >>> index 2c0edfa..48cd0b3 100644
> >>> --- a/block/mirror.c
> >>> +++ b/block/mirror.c
> >>
> >> [...]
> >>
> >>> @@ -449,16 +520,16 @@ static void coroutine_fn mirror_run(void *opaque)
> >>>   */
> >>>  bdrv_get_backing_filename(s->target, backing_filename,
> >>>sizeof(backing_filename));
> >>> -if (backing_filename[0] && !s->target->backing) {
> >>> -ret = bdrv_get_info(s->target, );
> >>> -if (ret < 0) {
> >>> -goto immediate_exit;
> >>> -}
> >>> -if (s->granularity < bdi.cluster_size) {
> >>> -s->buf_size = MAX(s->buf_size, bdi.cluster_size);
> >>> -s->cow_bitmap = bitmap_new(length);
> >>> -}
> >>> +if (!bdrv_get_info(s->target, ) && bdi.cluster_size) {
> >>
> >> This should be bdi.has_cluster_size...
> > 
> > has_cluster_size is a member of ImageInfo not BlockDriverInfo, and is 
> > derived
> > from (bdi.cluster_size != 0).
> 
> You're right, my bad.
> 
> >>> +target_cluster_size = bdi.cluster_size;
> >>
> >> ...and maybe we want an explicit minimum of BDRV_SECTOR_SIZE here; but I
> >> guess this is already assumed all over the block layer, so it may be
> >> fine without.
> > 
> > Okay, it doesn't hurt to add an assert here.
> 
> I'd be happy to take the patch without, too (although I wouldn't decline
> a follow-up adding an assertion).
> 
> Reviewed-by: Max Reitz 

Thanks! Shall we merge this now?

Fam



Re: [Qemu-devel] [Qemu-ppc] [PATCH] spapr: skip configuration section during migration of older machines

2016-02-14 Thread David Gibson
On Fri, Feb 12, 2016 at 12:14:59PM +0100, Greg Kurz wrote:
> On Fri, 12 Feb 2016 16:24:26 +1100
> David Gibson  wrote:
> 
> > On Thu, Feb 11, 2016 at 04:53:40PM +, Dr. David Alan Gilbert wrote:
> > > * Greg Kurz (gk...@linux.vnet.ibm.com) wrote:  
> > > > On Mon, 08 Feb 2016 16:59:47 +0100
> > > > Greg Kurz  wrote:  
> > > > > Since QEMU 2.4, we have a configuration section in the migration 
> > > > > stream.
> > > > > This must be skipped for older machines, like it is already done for 
> > > > > x86.
> > > > >   
> > > > 
> > > > Ouch ! It is more complex than I thought... the migration of pseries-2.3
> > > > machine is already broken between QEMU-2.3 and QEMU-2.4. So this patch
> > > > fixes indeed migration of a pseries-2.3 machine from QEMU-2.3, but it
> > > > breaks migration of the same machine from QEMU-2.4 and up.
> > > > 
> > > > Not sure how to deal with that... is it reasonable to assume that
> > > > pseries-2.3 running with QEMU-2.3 is the common case ? If so, this
> > > > patch would bring more help than harm.  
> > > 
> > > Unfortunately we can not fix history, so we have to pick something to fix.
> > > So unless there is another reason, then I normally say keep it working
> > > between the latest versions of qemu; i.e. if someone is running qemu 2.5 
> > > with
> > > -M 2.3  then dont break it when they try and migrate to 2.6, even though
> > > this would fix an older qemu migrating into 2.6.  
> > 
> > Yeah, I tend to agree, but I'd change my mind if there's evidence that
> > the older qemu is much more widely deployed.
> > 
> 
> I don't know how to provide proofs for that... just hints.
> 
> FWIW, both currently supported IBM's PowerKVM distros are based on older
> QEMU (2.0 and 2.3), same for LTS ubuntu (2.0) and standard ubuntu (2.3).
> 
> I believe SLE 12, SLE 12 SP1 and RHEV don't ship a newer QEMU but I'm
> not sure... Of course fedora already ships QEMU 2.4.1 but I don't
> think so many people use it in production on expensive POWER8 based
> hardware.

That's convincing enough for me.  With your machine option patch is
anything more needed to make migration from qemu 2.3 work without
manual intervention?

Given the above I'm happy to break migration from 2.4 (by default) in
favour of migration from 2.3.

> > IIUC that would entail no actual change to the code yes?  But I think
> > we should put a comment there saying what the fix would be to talk to
> > the older qemu, and why we chose not to apply it.
> > 
> 
> Something like:
> 
> /* QEMU 2.4 introduced a configuration section in the migration stream.
>  * It is mandatory for all machine types but it is possible to disable
>  * it to stay compatible with older machines. Unfortunately, QEMU 2.4
>  * got released without addressing the compatibility issue for pseries.
>  * As a consequence, pseries-2.3 and older machines cannot be migrated
>  * from QEMU <= 2.3 to QEMU >= 2.4. This won't be fixed as it would
>  * break migration of these older pseries when started with the latest
>  * QEMU, and we don't want that.
>  */
> 
> And Dave's suggestion to disable configuration section from the command
> line could allow to workaround the issue. I have the patch already, I'll
> do some testing and post shortly.
> 
> > > However, as discussed on irc you might be able to fudge it; for example
> > > using qemu_peek_byte to test whether or not you have a configuration
> > > section, and making it not error for some machine types.   This isn't
> > > pretty, but if it's important for you to get the coniguration working
> > > then it's the type of trick that might work.
> > > 
> > > Dave
> > >   
> > > >   
> > > > > Fixes: 61964c23e5ddd5a33f15699e45ce126f879e3e33
> > > > > Cc: qemu-sta...@nongnu.org
> > > > > Signed-off-by: Greg Kurz 
> > > > > ---
> > > > >  hw/ppc/spapr.c |1 +
> > > > >  1 file changed, 1 insertion(+)
> > > > > 
> > > > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > > > > index 5bd8fd3ef842..bca7cb8a5d27 100644
> > > > > --- a/hw/ppc/spapr.c
> > > > > +++ b/hw/ppc/spapr.c
> > > > > @@ -2446,6 +2446,7 @@ static void 
> > > > > spapr_machine_2_3_instance_options(MachineState *machine)
> > > > >  spapr_machine_2_4_instance_options(machine);
> > > > >  savevm_skip_section_footers();
> > > > >  global_state_set_optional();
> > > > > +savevm_skip_configuration();
> > > > >  }
> > > > > 
> > > > >  static void spapr_machine_2_3_class_options(MachineClass *mc)
> > > > > 
> > > > >   
> > > >   
> > 
> 

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH v15 7/9] Introduce new APIs to do replication operation

2016-02-14 Thread Wen Congyang
On 02/15/2016 08:57 AM, Hailiang Zhang wrote:
> On 2016/2/5 12:18, Changlong Xie wrote:
>> Signed-off-by: Wen Congyang 
>> Signed-off-by: zhanghailiang 
>> Signed-off-by: Gonglei 
>> Signed-off-by: Changlong Xie 
>> ---
>>   Makefile.objs|  1 +
>>   qapi/block-core.json | 13 
>>   replication.c| 94 
>> 
>>   replication.h| 53 +
>>   4 files changed, 161 insertions(+)
>>   create mode 100644 replication.c
>>   create mode 100644 replication.h
>>
>> diff --git a/Makefile.objs b/Makefile.objs
>> index 06b95c7..a8c74b7 100644
>> --- a/Makefile.objs
>> +++ b/Makefile.objs
>> @@ -15,6 +15,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
>>   block-obj-$(CONFIG_WIN32) += aio-win32.o
>>   block-obj-y += block/
>>   block-obj-y += qemu-io-cmds.o
>> +block-obj-y += replication.o
>>
>>   block-obj-m = block/
>>
>> diff --git a/qapi/block-core.json b/qapi/block-core.json
>> index 7e9e8fe..12362b8 100644
>> --- a/qapi/block-core.json
>> +++ b/qapi/block-core.json
>> @@ -2002,6 +2002,19 @@
>>   '*read-pattern': 'QuorumReadPattern' } }
>>
>>   ##
>> +# @ReplicationMode
>> +#
>> +# An enumeration of replication modes.
>> +#
>> +# @primary: Primary mode, the vm's state will be sent to secondary QEMU.
>> +#
>> +# @secondary: Secondary mode, receive the vm's state from primary QEMU.
>> +#
>> +# Since: 2.6
>> +##
>> +{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
>> +
>> +##
>>   # @BlockdevOptions
>>   #
>>   # Options for creating a block device.
>> diff --git a/replication.c b/replication.c
>> new file mode 100644
>> index 000..e8ac2f0
>> --- /dev/null
>> +++ b/replication.c
>> @@ -0,0 +1,94 @@
>> +/*
>> + * Replication filter
>> + *
>> + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
>> + * Copyright (c) 2016 Intel Corporation
>> + * Copyright (c) 2016 FUJITSU LIMITED
>> + *
>> + * Author:
>> + *   Wen Congyang 
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "replication.h"
>> +
>> +static QLIST_HEAD(, ReplicationState) replication_states;
>> +
>> +ReplicationState *replication_new(void *opaque, ReplicationOps *ops)
>> +{
>> +ReplicationState *rs;
>> +
>> +rs = g_new0(ReplicationState, 1);
>> +rs->opaque = opaque;
>> +rs->ops = ops;
>> +QLIST_INSERT_HEAD(_states, rs, node);
>> +
>> +return rs;
>> +}
>> +
>> +void replication_remove(ReplicationState *rs)
>> +{
>> +QLIST_REMOVE(rs, node);
>> +g_free(rs);
>> +}
>> +
>> +/*
>> + * The caller of the function *MUST* make sure vm stopped
>> + */
>> +void replication_start_all(ReplicationMode mode, Error **errp)
>> +{
> 
> Is this public API is only used for block ?
> If yes, I'd like it with a 'block_' prefix.

No, we hope it can be used for nic too.

Thanks
Wen Congyang

> 
>> +ReplicationState *rs, *next;
>> +
>> +QLIST_FOREACH_SAFE(rs, _states, node, next) {
>> +if (rs->ops && rs->ops->start) {
>> +rs->ops->start(rs, mode, errp);
>> +}
>> +if (*errp != NULL) {
> 
> This is incorrect, you miss checking if errp is NULL,
> if errp is NULL, there will be an error that accessing memory at address 0x0.
> Same with other places in this patch.
> 
>> +return;
>> +}
>> +}
>> +}
>> +
>> +void replication_do_checkpoint_all(Error **errp)
>> +{
>> +ReplicationState *rs, *next;
>> +
>> +QLIST_FOREACH_SAFE(rs, _states, node, next) {
>> +if (rs->ops && rs->ops->checkpoint) {
>> +rs->ops->checkpoint(rs, errp);
>> +}
>> +if (*errp != NULL) {
>> +return;
> 
>> +}
>> +}
>> +}
>> +
>> +void replication_get_error_all(Error **errp)
>> +{
>> +ReplicationState *rs, *next;
>> +
>> +QLIST_FOREACH_SAFE(rs, _states, node, next) {
>> +if (rs->ops && rs->ops->get_error) {
>> +rs->ops->get_error(rs, errp);
>> +}
>> +if (*errp != NULL) {
> 
>> +return;
>> +}
>> +}
>> +}
>> +
>> +void replication_stop_all(bool failover, Error **errp)
>> +{
>> +ReplicationState *rs, *next;
>> +
>> +QLIST_FOREACH_SAFE(rs, _states, node, next) {
>> +if (rs->ops && rs->ops->stop) {
>> +rs->ops->stop(rs, failover, errp);
>> +}
>> +if (*errp != NULL) {
>> +return;
>> +}
>> +}
>> +}
>> diff --git a/replication.h b/replication.h
>> new file mode 100644
>> index 000..faea649
>> --- /dev/null
>> +++ b/replication.h
>> @@ -0,0 +1,53 @@
>> +/*
>> + * Replication filter
>> + *
>> + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
>> + * Copyright (c) 2016 Intel Corporation
>> + * Copyright (c) 2016 FUJITSU LIMITED
>> + *
>> + * Author:
>> + 

Re: [Qemu-devel] [PATCH v15 7/9] Introduce new APIs to do replication operation

2016-02-14 Thread Hailiang Zhang

On 2016/2/5 12:18, Changlong Xie wrote:

Signed-off-by: Wen Congyang 
Signed-off-by: zhanghailiang 
Signed-off-by: Gonglei 
Signed-off-by: Changlong Xie 
---
  Makefile.objs|  1 +
  qapi/block-core.json | 13 
  replication.c| 94 
  replication.h| 53 +
  4 files changed, 161 insertions(+)
  create mode 100644 replication.c
  create mode 100644 replication.h

diff --git a/Makefile.objs b/Makefile.objs
index 06b95c7..a8c74b7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -15,6 +15,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
  block-obj-$(CONFIG_WIN32) += aio-win32.o
  block-obj-y += block/
  block-obj-y += qemu-io-cmds.o
+block-obj-y += replication.o

  block-obj-m = block/

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 7e9e8fe..12362b8 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2002,6 +2002,19 @@
  '*read-pattern': 'QuorumReadPattern' } }

  ##
+# @ReplicationMode
+#
+# An enumeration of replication modes.
+#
+# @primary: Primary mode, the vm's state will be sent to secondary QEMU.
+#
+# @secondary: Secondary mode, receive the vm's state from primary QEMU.
+#
+# Since: 2.6
+##
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+
+##
  # @BlockdevOptions
  #
  # Options for creating a block device.
diff --git a/replication.c b/replication.c
new file mode 100644
index 000..e8ac2f0
--- /dev/null
+++ b/replication.c
@@ -0,0 +1,94 @@
+/*
+ * Replication filter
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2016 FUJITSU LIMITED
+ *
+ * Author:
+ *   Wen Congyang 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "replication.h"
+
+static QLIST_HEAD(, ReplicationState) replication_states;
+
+ReplicationState *replication_new(void *opaque, ReplicationOps *ops)
+{
+ReplicationState *rs;
+
+rs = g_new0(ReplicationState, 1);
+rs->opaque = opaque;
+rs->ops = ops;
+QLIST_INSERT_HEAD(_states, rs, node);
+
+return rs;
+}
+
+void replication_remove(ReplicationState *rs)
+{
+QLIST_REMOVE(rs, node);
+g_free(rs);
+}
+
+/*
+ * The caller of the function *MUST* make sure vm stopped
+ */
+void replication_start_all(ReplicationMode mode, Error **errp)
+{


Is this public API is only used for block ?
If yes, I'd like it with a 'block_' prefix.


+ReplicationState *rs, *next;
+
+QLIST_FOREACH_SAFE(rs, _states, node, next) {
+if (rs->ops && rs->ops->start) {
+rs->ops->start(rs, mode, errp);
+}
+if (*errp != NULL) {


This is incorrect, you miss checking if errp is NULL,
if errp is NULL, there will be an error that accessing memory at address 0x0.
Same with other places in this patch.


+return;
+}
+}
+}
+
+void replication_do_checkpoint_all(Error **errp)
+{
+ReplicationState *rs, *next;
+
+QLIST_FOREACH_SAFE(rs, _states, node, next) {
+if (rs->ops && rs->ops->checkpoint) {
+rs->ops->checkpoint(rs, errp);
+}
+if (*errp != NULL) {
+return;



+}
+}
+}
+
+void replication_get_error_all(Error **errp)
+{
+ReplicationState *rs, *next;
+
+QLIST_FOREACH_SAFE(rs, _states, node, next) {
+if (rs->ops && rs->ops->get_error) {
+rs->ops->get_error(rs, errp);
+}
+if (*errp != NULL) {



+return;
+}
+}
+}
+
+void replication_stop_all(bool failover, Error **errp)
+{
+ReplicationState *rs, *next;
+
+QLIST_FOREACH_SAFE(rs, _states, node, next) {
+if (rs->ops && rs->ops->stop) {
+rs->ops->stop(rs, failover, errp);
+}
+if (*errp != NULL) {
+return;
+}
+}
+}
diff --git a/replication.h b/replication.h
new file mode 100644
index 000..faea649
--- /dev/null
+++ b/replication.h
@@ -0,0 +1,53 @@
+/*
+ * Replication filter
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2016 FUJITSU LIMITED
+ *
+ * Author:
+ *   Wen Congyang 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef REPLICATION_H
+#define REPLICATION_H
+
+#include "sysemu/sysemu.h"
+
+typedef struct ReplicationOps ReplicationOps;
+typedef struct ReplicationState ReplicationState;
+typedef void (*Start)(ReplicationState *rs, ReplicationMode mode, Error 
**errp);
+typedef void (*Stop)(ReplicationState *rs, bool failover, Error **errp);
+typedef void (*Checkpoint)(ReplicationState *rs, Error **errp);
+typedef void 

Re: [Qemu-devel] [PATCH v2 00/13] cuda: misc fixes and cleanups

2016-02-14 Thread David Gibson
On Sun, Feb 14, 2016 at 07:01:48PM +, Mark Cave-Ayland wrote:
> On 07/02/16 20:34, Hervé Poussineau wrote:
> 
> > Hi,
> > 
> > This patchset cleans up a little bit the Apple CUDA emulation:
> > - correctly reject commands with wrong parameters
> > - support changing the frequency of auto-polling
> > - support changing device list probed in auto-poll
> > - add logs when using FILE_SERVER_FLAG/SET_POWER_MESSAGE
> > - remove unused commands (GET/SET_6805_ADDR)
> > - remove unimplemented GET_SET_IIC/COMBINED_FORMAT_IIC
> > 
> > GET_SET_IIC/COMBINED_FORMAT_IIC commands should be added again once
> > we implement the I2C bus provided by CUDA.
> > 
> > Hervé
> > 
> > Hervé Poussineau (13):
> >   cuda: add a framework to handle commands
> >   cuda: move unknown commands reject out of switch
> >   cuda: port AUTOPOLL command to new framework
> >   cuda: port SET_AUTO_RATE command to new framework
> >   cuda: port SET_DEVICE_LIST command to new framework
> >   cuda: port POWERDOWN command to new framework
> >   cuda: port RESET_SYSTEM command to new framework
> >   cuda: port FILE_SERVER_FLAG command to new framework
> >   cuda: port SET_POWER_MESSAGES command to new framework
> >   cuda: port GET_TIME command to new framework
> >   cuda: port SET_TIME command to new framework
> >   cuda: remove GET_6805_ADDR command
> >   cuda: remove CUDA_GET_SET_IIC/CUDA_COMBINED_FORMAT_IIC commands
> > 
> >  hw/input/adb.c |  18 ++--
> >  hw/misc/macio/cuda.c   | 279 
> > -
> >  hw/ppc/mac.h   |   2 +
> >  include/hw/input/adb.h |   2 +-
> >  4 files changed, 217 insertions(+), 84 deletions(-)
> 
> Reviewed-by: Mark Cave-Ayland 
> 
> This looks good to me, and again passes all my local tests. The only
> thing I noticed was that there were no changes related to
> qemu_log_mask() as per David's comments on patch 2 but other than that I
> think this patchset is fine to merge for 2.6.

Thanks for this, I've merged the series to ppc-for-2.6.

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [Qemu-devel] [PATCH v2 00/13] cuda: misc fixes and cleanups

2016-02-14 Thread Hervé Poussineau

Le 14/02/2016 20:01, Mark Cave-Ayland a écrit :

On 07/02/16 20:34, Hervé Poussineau wrote:


Hi,

This patchset cleans up a little bit the Apple CUDA emulation:
- correctly reject commands with wrong parameters
- support changing the frequency of auto-polling
- support changing device list probed in auto-poll
- add logs when using FILE_SERVER_FLAG/SET_POWER_MESSAGE
- remove unused commands (GET/SET_6805_ADDR)
- remove unimplemented GET_SET_IIC/COMBINED_FORMAT_IIC

GET_SET_IIC/COMBINED_FORMAT_IIC commands should be added again once
we implement the I2C bus provided by CUDA.

Hervé

Hervé Poussineau (13):
   cuda: add a framework to handle commands
   cuda: move unknown commands reject out of switch
   cuda: port AUTOPOLL command to new framework
   cuda: port SET_AUTO_RATE command to new framework
   cuda: port SET_DEVICE_LIST command to new framework
   cuda: port POWERDOWN command to new framework
   cuda: port RESET_SYSTEM command to new framework
   cuda: port FILE_SERVER_FLAG command to new framework
   cuda: port SET_POWER_MESSAGES command to new framework
   cuda: port GET_TIME command to new framework
   cuda: port SET_TIME command to new framework
   cuda: remove GET_6805_ADDR command
   cuda: remove CUDA_GET_SET_IIC/CUDA_COMBINED_FORMAT_IIC commands

  hw/input/adb.c |  18 ++--
  hw/misc/macio/cuda.c   | 279 -
  hw/ppc/mac.h   |   2 +
  include/hw/input/adb.h |   2 +-
  4 files changed, 217 insertions(+), 84 deletions(-)


Reviewed-by: Mark Cave-Ayland 

This looks good to me, and again passes all my local tests. The only
thing I noticed was that there were no changes related to
qemu_log_mask() as per David's comments on patch 2 but other than that I
think this patchset is fine to merge for 2.6.


qemu_log_mask() doesn't represent the same thing than trace events, even if 
they can go to the same output file.
I always run QEMU with -d guest_errors,unimp to see if something wrong happens 
on guest side.
I have no knowledge of all traces in all devices, to know which ones are 
important at first run.
However, if I want to detail one device behaviour, I can enable specific traces 
for this device.

Note also that new qemu_log_mask() calls are added, like in 
cc28296d82ce179e81ee6d0b9cfb7f6a79ffc1c6

Hervé



Re: [Qemu-devel] [PATCH 2/3] i.MX: Add the Freescale SPI Controller

2016-02-14 Thread mar.krzeminski



W dniu 14.02.2016 o 17:56, Jean-Christophe DUBOIS pisze:

Le 14/02/2016 12:52, mar.krzeminski a écrit :

Hello,

W dniu 13.02.2016 o 17:06, Jean-Christophe Dubois pisze:

Signed-off-by: Jean-Christophe Dubois 
---
  hw/ssi/Makefile.objs |   1 +
  hw/ssi/imx_spi.c | 449 
+++

  include/hw/ssi/imx_spi.h | 104 +++
  3 files changed, 554 insertions(+)
  create mode 100644 hw/ssi/imx_spi.c
  create mode 100644 include/hw/ssi/imx_spi.h

diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
index 9555825..fcbb79e 100644
--- a/hw/ssi/Makefile.objs
+++ b/hw/ssi/Makefile.objs
@@ -4,3 +4,4 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
obj-$(CONFIG_OMAP) += omap_spi.o
+obj-$(CONFIG_IMX) += imx_spi.o
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
new file mode 100644
index 000..9f7f4fe
--- /dev/null
+++ b/hw/ssi/imx_spi.c
@@ -0,0 +1,449 @@
+/*
+ * IMX SPI Controller
+ *
+ * Copyright (c) 2016 Jean-Christophe Dubois 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 
or later.

+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw/ssi/imx_spi.h"
+#include "sysemu/sysemu.h"
+
+#ifndef DEBUG_IMX_SPI
+#define DEBUG_IMX_SPI 0
+#endif
+
+#define DPRINTF(fmt, args...) \
+do { \
+if (DEBUG_IMX_SPI) { \
+fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SPI, \
+ __func__, ##args); \
+} \
+} while (0)
+
+static char const *imx_spi_reg_name(uint32_t reg)
+{
+static char unknown[20];
+
+switch (reg) {
+case ECSPI_RXDATA:
+return  "ECSPI_RXDATA";
+case ECSPI_TXDATA:
+return  "ECSPI_TXDATA";
+case ECSPI_CONREG:
+return  "ECSPI_CONREG";
+case ECSPI_CONFIGREG:
+return  "ECSPI_CONFIGREG";
+case ECSPI_INTREG:
+return  "ECSPI_INTREG";
+case ECSPI_DMAREG:
+return  "ECSPI_DMAREG";
+case ECSPI_STATREG:
+return  "ECSPI_STATREG";
+case ECSPI_PERIODREG:
+return  "ECSPI_PERIODREG";
+case ECSPI_TESTREG:
+return  "ECSPI_TESTREG";
+case ECSPI_MSGDATA:
+return  "ECSPI_MSGDATA";
+default:
+sprintf(unknown, "%d ?", reg);
+return unknown;
+}
+}
+
+static const VMStateDescription vmstate_imx_spi = {
+.name = TYPE_IMX_SPI,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_FIFO32(tx_fifo, IMXSPIState),
+VMSTATE_FIFO32(rx_fifo, IMXSPIState),
+VMSTATE_UINT32_ARRAY(regs, IMXSPIState, ECSPI_MAX),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx_spi_txfifo_reset(IMXSPIState *s)
+{
+fifo32_reset(>tx_fifo);
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
+}
+
+static void imx_spi_rxfifo_reset(IMXSPIState *s)
+{
+fifo32_reset(>rx_fifo);
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RO;
+}
+
+static void imx_spi_update_irq(IMXSPIState *s)
+{
+int level;
+
+if (fifo32_is_empty(>rx_fifo)) {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
+} else {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RR;
+}
+
+if (fifo32_is_full(>rx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RF;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
+}
+
+if (fifo32_is_empty(>tx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TE;
+}
+
+if (fifo32_is_full(>tx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TF;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
+}
+
+level = s->regs[ECSPI_STATREG] & s->regs[ECSPI_INTREG] ? 1 : 0;
+
+if (s->previous_level != level) {
+DPRINTF("setting IRQ a level %d\n", level);
+s->previous_level = level;
+qemu_set_irq(s->irq, level);
+}
+
+DPRINTF("IRQ level is %d\n", level);
+}
+
+static uint8_t imx_spi_selected_channel(IMXSPIState *s)
+{
+return EXTRACT(s->regs[ECSPI_CONREG], 
ECSPI_CONREG_CHANNEL_SELECT);

+}
+
+static uint32_t imx_spi_burst_length(IMXSPIState *s)
+{
+return EXTRACT(s->regs[ECSPI_CONREG], 
ECSPI_CONREG_BURST_LENGTH) + 1;

+}
+
+static bool imx_spi_is_enabled(IMXSPIState *s)
+{
+return (s->regs[ECSPI_CONREG] & ECSPI_CONREG_EN) ? true : false;
+}
+
+static bool imx_spi_channel_is_master(IMXSPIState *s)
+{
+uint8_t mode = EXTRACT(s->regs[ECSPI_CONREG], 
ECSPI_CONREG_CHANNEL_MODE);

+
+return (mode & (1 << imx_spi_selected_channel(s))) ? true : false;
+}
+
+static bool imx_spi_is_multiple_master_burst(IMXSPIState *s)
+{
+uint8_t wave = EXTRACT(s->regs[ECSPI_CONFIGREG], 
ECSPI_CONFIGREG_SS_CTL);

+
+return 

Re: [Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-02-14 Thread David kiarie
On Sun, Feb 14, 2016 at 4:07 PM, Michael S. Tsirkin  wrote:
> On Sun, Feb 14, 2016 at 02:54:36PM +0200, Marcel Apfelbaum wrote:
>> On 01/18/2016 05:25 PM, David Kiarie wrote:
>> >Add IVRS table for AMD IO MMU.
>> >
>> >Signed-off-by: David Kiarie 
>> >---
>> >  hw/i386/acpi-build.c| 70 
>> > +
>> >  include/hw/acpi/acpi-defs.h | 55 +++
>> >  2 files changed, 125 insertions(+)
>> >
>> >diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>> >index 78758e2..5c0d6b7 100644
>> >--- a/hw/i386/acpi-build.c
>> >+++ b/hw/i386/acpi-build.c
>> >@@ -52,6 +52,7 @@
>> >  #include "hw/pci/pci_bus.h"
>> >  #include "hw/pci-host/q35.h"
>> >  #include "hw/i386/intel_iommu.h"
>> >+#include "hw/i386/amd_iommu.h"
>> >  #include "hw/timer/hpet.h"
>> >
>> >  #include "hw/acpi/aml-build.h"
>> >@@ -2424,6 +2425,70 @@ build_dmar_q35(GArray *table_data, GArray *linker)
>> >  }
>> >
>> >  static void
>> >+build_amd_iommu(GArray *table_data, GArray *linker)
>> >+{
>> >+int iommu_start = table_data->len;
>> >+bool iommu_ambig;
>> >+
>> >+AcpiAMDIOMMUIVRS *ivrs;
>> >+AcpiAMDIOMMUHardwareUnit *iommu;
>> >+
>> >+/* IVRS definition */
>> >+ivrs = acpi_data_push(table_data, sizeof(*ivrs));
>> >+ivrs->revision = cpu_to_le16(ACPI_IOMMU_IVRS_TYPE);
>> >+ivrs->length = cpu_to_le16((sizeof(*ivrs) + sizeof(*iommu)));
>> >+ivrs->v_common_info = cpu_to_le64(AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
>> >+
>> >+AMDIOMMUState *s = (AMDIOMMUState *)object_resolve_path_type("",
>> >+TYPE_AMD_IOMMU_DEVICE, _ambig);
>> >+
>> >+/* IVDB definition */
>> >+iommu = acpi_data_push(table_data, sizeof(*iommu));
>> >+if (!iommu_ambig) {
>>
>> Hi,
>>
>> If the reference to AMD IOMMU is ambiguous and the table is not added to ACPI
>> I think we should report the error to user, something like error_report.
>>
>> >+iommu->type = cpu_to_le16(0x10);
>> >+/* IVHD flags */
>> >+iommu->flags = cpu_to_le16(iommu->flags);
>> >+iommu->flags = cpu_to_le16(IVHD_HT_TUNEN | IVHD_PPRSUP | 
>> >IVHD_IOTLBSUP
>> >+   | IVHD_PREFSUP);
>> >+iommu->length = cpu_to_le16(sizeof(*iommu));
>> >+iommu->device_id = cpu_to_le16(PCI_DEVICE_ID_RD890_IOMMU);
>> >+iommu->capability_offset = cpu_to_le16(s->capab_offset);
>> >+iommu->mmio_base = cpu_to_le64(s->mmio.addr);
>> >+iommu->pci_segment = 0;
>> >+iommu->interrupt_info = 0;
>> >+/* EFR features */
>> >+iommu->efr_register = cpu_to_le64(IVHD_EFR_GTSUP | IVHD_EFR_HATS
>> >+  | IVHD_EFR_GATS);
>> >+iommu->efr_register = cpu_to_le64(iommu->efr_register);
>> >+/* device entries */
>> >+memset(iommu->dev_entries, 0, 20);
>> >+/* Add device flags here
>> >+ *  create entries for devices to be treated specially by IO MMU,
>> >+ *  currently we report all devices to IO MMU with no special flags
>> >+ *  DTE settings made here apply to all devices
>> >+ *  Refer to AMD IOMMU spec Table 97
>> >+ */
>> >+iommu->dev_entries[12] = 3;
>> >+iommu->dev_entries[16] = 4;
>> >+iommu->dev_entries[17] = 0xff;
>> >+iommu->dev_entries[18] = 0xff;
>> >+}
>> >+
>> >+build_header(linker, table_data, (void *)(table_data->data + 
>> >iommu_start),
>> >+ "IVRS", table_data->len - iommu_start, 1, NULL);
>> >+}
>> >+
>> >+static bool acpi_has_amd_iommu(void)
>> >+{
>> >+bool ambiguous;
>> >+Object *amd_iommu;
>> >+
>> >+amd_iommu = object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE,
>> >+ );
>> >+return amd_iommu && !ambiguous;
>> >+}
>> >+
>> >+static void
>> >  build_dsdt(GArray *table_data, GArray *linker,
>> > AcpiPmInfo *pm, AcpiMiscInfo *misc)
>> >  {
>> >@@ -2691,6 +2756,11 @@ void acpi_build(PcGuestInfo *guest_info, 
>> >AcpiBuildTables *tables)
>> >  build_dmar_q35(tables_blob, tables->linker);
>> >  }
>> >
>> >+if (acpi_has_amd_iommu() && !acpi_has_iommu()) {
>>
>> Since we have the acpi_has_amd_iommu function now, maybe is time to rename
>> acpi_has_iommu to acpi_has_intel_iommu or better have a standard has_iommu 
>> that
>> returns an enum type (NONE/INTEL/AMD).
>>
>> By the way, do we really need to check !acpi_has_iommu() if there is
>> an AMD IOMMU in the system? Having both in the same system is a not (yet) 
>> supported configuration,
>> right?
>>
>> Thanks,
>> Marcel
>>
>
> Long term the right thing to do is to add description
> for each IOMMU present in the system.
> For example, we might have multiple intel iommus.

Yeah, we could have multiple AMD IO MMUs in a system too but I don't
see a generic way to add multiple descriptions since they could have
different settings.

>
>> >+

Re: [Qemu-devel] [PATCH v2 00/13] cuda: misc fixes and cleanups

2016-02-14 Thread Mark Cave-Ayland
On 07/02/16 20:34, Hervé Poussineau wrote:

> Hi,
> 
> This patchset cleans up a little bit the Apple CUDA emulation:
> - correctly reject commands with wrong parameters
> - support changing the frequency of auto-polling
> - support changing device list probed in auto-poll
> - add logs when using FILE_SERVER_FLAG/SET_POWER_MESSAGE
> - remove unused commands (GET/SET_6805_ADDR)
> - remove unimplemented GET_SET_IIC/COMBINED_FORMAT_IIC
> 
> GET_SET_IIC/COMBINED_FORMAT_IIC commands should be added again once
> we implement the I2C bus provided by CUDA.
> 
> Hervé
> 
> Hervé Poussineau (13):
>   cuda: add a framework to handle commands
>   cuda: move unknown commands reject out of switch
>   cuda: port AUTOPOLL command to new framework
>   cuda: port SET_AUTO_RATE command to new framework
>   cuda: port SET_DEVICE_LIST command to new framework
>   cuda: port POWERDOWN command to new framework
>   cuda: port RESET_SYSTEM command to new framework
>   cuda: port FILE_SERVER_FLAG command to new framework
>   cuda: port SET_POWER_MESSAGES command to new framework
>   cuda: port GET_TIME command to new framework
>   cuda: port SET_TIME command to new framework
>   cuda: remove GET_6805_ADDR command
>   cuda: remove CUDA_GET_SET_IIC/CUDA_COMBINED_FORMAT_IIC commands
> 
>  hw/input/adb.c |  18 ++--
>  hw/misc/macio/cuda.c   | 279 
> -
>  hw/ppc/mac.h   |   2 +
>  include/hw/input/adb.h |   2 +-
>  4 files changed, 217 insertions(+), 84 deletions(-)

Reviewed-by: Mark Cave-Ayland 

This looks good to me, and again passes all my local tests. The only
thing I noticed was that there were no changes related to
qemu_log_mask() as per David's comments on patch 2 but other than that I
think this patchset is fine to merge for 2.6.


ATB,

Mark.




[Qemu-devel] [PATCH] tests: add pxe e1000 test

2016-02-14 Thread Victor Kaplansky
The test is based on bios-tables-test.c.  It creates a file with
a boot sector image and loads it into a guest using PXE and TFTP
functionality.

Cc: Jason Wang 
Signed-off-by: Victor Kaplansky 
Suggested-by: Michael S. Tsirkin 
---
 tests/pxe-test.c | 141 +++
 tests/Makefile   |   2 +
 2 files changed, 143 insertions(+)
 create mode 100644 tests/pxe-test.c

diff --git a/tests/pxe-test.c b/tests/pxe-test.c
new file mode 100644
index ..3a45698d
--- /dev/null
+++ b/tests/pxe-test.c
@@ -0,0 +1,141 @@
+/*
+ * PXE test cases.
+ *
+ * Copyright (c) 2013 Red Hat Inc.
+ *
+ * Authors:
+ *  Michael S. Tsirkin ,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include "qemu-common.h"
+#include "libqtest.h"
+
+#define LOW(x) ((x) & 0xff)
+#define HIGH(x) ((x) >> 8)
+
+#define SIGNATURE 0xdead
+#define SIGNATURE_OFFSET 0x10
+#define BOOT_SECTOR_ADDRESS 0x7c00
+#define NETNAME "net0"
+
+/* Boot sector code: write SIGNATURE into memory,
+ * then halt.
+ * Q35 machine requires a minimum 0x7e000 bytes disk.
+ * (bug or feature?)
+ */
+static uint8_t boot_sector[0x7e000] = {
+/* The first sector will be placed at RAM address 7C00, and
+ * the BIOS transfers control to 7C00
+ */
+
+/* Data Segment register should be initialized, since pxe
+ * boot loader can leave it dirty.
+ */
+
+/* 7c00: move $,%ax */
+[0x00] = 0xb8,
+[0x01] = 0x00,
+[0x02] = 0x00,
+/* 7c03: move %ax,%ds */
+[0x03] = 0x8e,
+[0x04] = 0xd8,
+
+/* 7c05: mov $0xdead,%ax */
+[0x05] = 0xb8,
+[0x06] = LOW(SIGNATURE),
+[0x07] = HIGH(SIGNATURE),
+/* 7c08:  mov %ax,0x7c10 */
+[0x08] = 0xa3,
+[0x09] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
+[0x0a] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
+
+/* 7c0b cli */
+[0x0b] = 0xfa,
+/* 7c0c: hlt */
+[0x0c] = 0xf4,
+/* 7c0e: jmp 0x7c07=0x7c0f-3 */
+[0x0d] = 0xeb,
+[0x0e] = LOW(-3),
+/* We mov 0xdead here: set value to make debugging easier */
+[SIGNATURE_OFFSET] = LOW(0xface),
+[SIGNATURE_OFFSET + 1] = HIGH(0xface),
+/* End of boot sector marker */
+[0x1FE] = 0x55,
+[0x1FF] = 0xAA,
+};
+
+static const char *disk = "tests/pxe-test-disk.raw";
+
+static void test_pxe_e1000_one(const char *params)
+{
+char *args;
+uint8_t signature_low;
+uint8_t signature_high;
+uint16_t signature;
+int i;
+
+args = g_strdup_printf("-machine accel=tcg "
+   "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s "
+   "%s ",
+   disk, params);
+
+qtest_start(args);
+
+   /* Wait at most 1 minute */
+#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
+#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
+
+/* Poll until code has run and modified memory.  Once it has we know BIOS
+ * initialization is done.  TODO: check that IP reached the halt
+ * instruction.
+ */
+for (i = 0; i < TEST_CYCLES; ++i) {
+signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
+signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
+signature = (signature_high << 8) | signature_low;
+if (signature == SIGNATURE) {
+break;
+}
+g_usleep(TEST_DELAY);
+}
+
+g_assert_cmphex(signature, ==, SIGNATURE);
+
+qtest_quit(global_qtest);
+g_free(args);
+}
+
+static void test_pxe_e1000(void)
+{
+test_pxe_e1000_one("-device virtio-net-pci,netdev=" NETNAME);
+}
+
+int main(int argc, char *argv[])
+{
+const char *arch = qtest_get_arch();
+FILE *f = fopen(disk, "w");
+int ret;
+
+if (!f) {
+fprintf(stderr, "Couldn't open \"%s\": %s", disk, strerror(errno));
+return 1;
+}
+fwrite(boot_sector, 1, sizeof boot_sector, f);
+fclose(f);
+
+g_test_init(, , NULL);
+
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+qtest_add_func("pxe/e1000", test_pxe_e1000);
+}
+ret = g_test_run();
+unlink(disk);
+return ret;
+}
diff --git a/tests/Makefile b/tests/Makefile
index 650e654e..2de51e4d 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -173,6 +173,7 @@ check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
 gcov-files-i386-y += hw/block/hd-geometry.c
 check-qtest-i386-y += tests/boot-order-test$(EXESUF)
 check-qtest-i386-y += tests/bios-tables-test$(EXESUF)
+check-qtest-i386-y += tests/pxe-test$(EXESUF)
 check-qtest-i386-y += tests/rtc-test$(EXESUF)
 check-qtest-i386-y += tests/ipmi-kcs-test$(EXESUF)
 check-qtest-i386-y += tests/ipmi-bt-test$(EXESUF)
@@ -519,6 +520,7 @@ tests/ipmi-bt-test$(EXESUF): tests/ipmi-bt-test.o
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 

Re: [Qemu-devel] [PATCH] tests: add pxe e1000 test

2016-02-14 Thread Michael S. Tsirkin
On Sun, Feb 14, 2016 at 02:10:17PM +0200, Victor Kaplansky wrote:
> The test is based on bios-tables-test.c.  It creates a file with
> a boot sector image and loads it into a guest using PXE and TFTP
> functionality.
> 
> Cc: Jason Wang 
> Signed-off-by: Victor Kaplansky 
> Suggested-by: Michael S. Tsirkin 

Looks good to me, except it actually tests virtio and not e1000.
It's probably easiest to test them both straight away.

> ---
>  tests/pxe-test.c | 141 
> +++
>  tests/Makefile   |   2 +
>  2 files changed, 143 insertions(+)
>  create mode 100644 tests/pxe-test.c
> 
> diff --git a/tests/pxe-test.c b/tests/pxe-test.c
> new file mode 100644
> index ..3a45698d
> --- /dev/null
> +++ b/tests/pxe-test.c
> @@ -0,0 +1,141 @@
> +/*
> + * PXE test cases.
> + *
> + * Copyright (c) 2013 Red Hat Inc.
> + *
> + * Authors:
> + *  Michael S. Tsirkin ,
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include "qemu-common.h"
> +#include "libqtest.h"
> +
> +#define LOW(x) ((x) & 0xff)
> +#define HIGH(x) ((x) >> 8)
> +
> +#define SIGNATURE 0xdead
> +#define SIGNATURE_OFFSET 0x10
> +#define BOOT_SECTOR_ADDRESS 0x7c00
> +#define NETNAME "net0"
> +
> +/* Boot sector code: write SIGNATURE into memory,
> + * then halt.
> + * Q35 machine requires a minimum 0x7e000 bytes disk.
> + * (bug or feature?)
> + */
> +static uint8_t boot_sector[0x7e000] = {
> +/* The first sector will be placed at RAM address 7C00, and
> + * the BIOS transfers control to 7C00
> + */
> +
> +/* Data Segment register should be initialized, since pxe
> + * boot loader can leave it dirty.
> + */
> +
> +/* 7c00: move $,%ax */
> +[0x00] = 0xb8,
> +[0x01] = 0x00,
> +[0x02] = 0x00,
> +/* 7c03: move %ax,%ds */
> +[0x03] = 0x8e,
> +[0x04] = 0xd8,
> +
> +/* 7c05: mov $0xdead,%ax */
> +[0x05] = 0xb8,
> +[0x06] = LOW(SIGNATURE),
> +[0x07] = HIGH(SIGNATURE),
> +/* 7c08:  mov %ax,0x7c10 */
> +[0x08] = 0xa3,
> +[0x09] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
> +[0x0a] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
> +
> +/* 7c0b cli */
> +[0x0b] = 0xfa,
> +/* 7c0c: hlt */
> +[0x0c] = 0xf4,
> +/* 7c0e: jmp 0x7c07=0x7c0f-3 */
> +[0x0d] = 0xeb,
> +[0x0e] = LOW(-3),
> +/* We mov 0xdead here: set value to make debugging easier */
> +[SIGNATURE_OFFSET] = LOW(0xface),
> +[SIGNATURE_OFFSET + 1] = HIGH(0xface),
> +/* End of boot sector marker */
> +[0x1FE] = 0x55,
> +[0x1FF] = 0xAA,
> +};
> +
> +static const char *disk = "tests/pxe-test-disk.raw";
> +
> +static void test_pxe_e1000_one(const char *params)
> +{
> +char *args;
> +uint8_t signature_low;
> +uint8_t signature_high;
> +uint16_t signature;
> +int i;
> +
> +args = g_strdup_printf("-machine accel=tcg "
> +   "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s "
> +   "%s ",
> +   disk, params);
> +
> +qtest_start(args);
> +
> +   /* Wait at most 1 minute */
> +#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
> +#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
> +
> +/* Poll until code has run and modified memory.  Once it has we know BIOS
> + * initialization is done.  TODO: check that IP reached the halt
> + * instruction.
> + */
> +for (i = 0; i < TEST_CYCLES; ++i) {
> +signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
> +signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
> +signature = (signature_high << 8) | signature_low;
> +if (signature == SIGNATURE) {
> +break;
> +}
> +g_usleep(TEST_DELAY);
> +}
> +
> +g_assert_cmphex(signature, ==, SIGNATURE);
> +
> +qtest_quit(global_qtest);
> +g_free(args);
> +}
> +
> +static void test_pxe_e1000(void)
> +{
> +test_pxe_e1000_one("-device virtio-net-pci,netdev=" NETNAME);
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +const char *arch = qtest_get_arch();
> +FILE *f = fopen(disk, "w");
> +int ret;
> +
> +if (!f) {
> +fprintf(stderr, "Couldn't open \"%s\": %s", disk, strerror(errno));
> +return 1;
> +}
> +fwrite(boot_sector, 1, sizeof boot_sector, f);
> +fclose(f);
> +
> +g_test_init(, , NULL);
> +
> +if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
> +qtest_add_func("pxe/e1000", test_pxe_e1000);
> +}
> +ret = g_test_run();
> +unlink(disk);
> +return ret;

I can imagine sharing code with bios test.
Move the common stuff into tests/boot-sector.c + tests/boot-sector.h,
and add api e.g.

Re: [Qemu-devel] [V4 4/4] hw/pci-host: Emulate AMD IO MMU

2016-02-14 Thread Marcel Apfelbaum

On 01/18/2016 05:25 PM, David Kiarie wrote:

Support AMD IO MMU emulation in q35 and piix chipsets

Signed-off-by: David Kiarie 
---
  hw/pci-host/piix.c | 11 +++
  hw/pci-host/q35.c  | 14 --
  2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index b0d7e31..3ba245d 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -35,6 +35,7 @@
  #include "hw/i386/ioapic.h"
  #include "qapi/visitor.h"
  #include "qemu/error-report.h"
+#include "hw/i386/amd_iommu.h"

  /*
   * I440FX chipset data sheet.
@@ -297,6 +298,16 @@ static void i440fx_pcihost_realize(DeviceState *dev, Error 
**errp)

  sysbus_add_io(sbd, 0xcfc, >data_mem);
  sysbus_init_ioports(sbd, 0xcfc, 4);
+
+/* AMD IOMMU (AMD-Vi) */
+if (g_strcmp0(object_property_get_str(qdev_get_machine(), "iommu", NULL),
+  "amd") == 0) {


Hi,

Minor comments, here you can use the same qdev_get_machine())->iommu as used 
below
and the same AMD_IOMMU_STR instead of "amd".

Do I understand correctly that we can have an AMD IOMMU working on an i440fx 
machine (non PCI Express)?

Thanks,
Marcel


+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+iommu = pci_create_simple(s->bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(s->bus, bridge_host_amd_iommu, iommu_state);
+}
  }

  static void i440fx_realize(PCIDevice *dev, Error **errp)
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 1fb4707..0c60e3c 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -30,6 +30,7 @@
  #include "hw/hw.h"
  #include "hw/pci-host/q35.h"
  #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"

  /
   * Q35 host
@@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
   mch->pci_address_space, >pam_regions[i+1],
   PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
  }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR) == 0) {
+/* Intel IOMMU (VT-d) */
  mch_init_dmar(mch);
+} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, AMD_IOMMU_STR)
+   == 0) {
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
  }
  }







Re: [Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-02-14 Thread Michael S. Tsirkin
On Sun, Feb 14, 2016 at 02:54:36PM +0200, Marcel Apfelbaum wrote:
> On 01/18/2016 05:25 PM, David Kiarie wrote:
> >Add IVRS table for AMD IO MMU.
> >
> >Signed-off-by: David Kiarie 
> >---
> >  hw/i386/acpi-build.c| 70 
> > +
> >  include/hw/acpi/acpi-defs.h | 55 +++
> >  2 files changed, 125 insertions(+)
> >
> >diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> >index 78758e2..5c0d6b7 100644
> >--- a/hw/i386/acpi-build.c
> >+++ b/hw/i386/acpi-build.c
> >@@ -52,6 +52,7 @@
> >  #include "hw/pci/pci_bus.h"
> >  #include "hw/pci-host/q35.h"
> >  #include "hw/i386/intel_iommu.h"
> >+#include "hw/i386/amd_iommu.h"
> >  #include "hw/timer/hpet.h"
> >
> >  #include "hw/acpi/aml-build.h"
> >@@ -2424,6 +2425,70 @@ build_dmar_q35(GArray *table_data, GArray *linker)
> >  }
> >
> >  static void
> >+build_amd_iommu(GArray *table_data, GArray *linker)
> >+{
> >+int iommu_start = table_data->len;
> >+bool iommu_ambig;
> >+
> >+AcpiAMDIOMMUIVRS *ivrs;
> >+AcpiAMDIOMMUHardwareUnit *iommu;
> >+
> >+/* IVRS definition */
> >+ivrs = acpi_data_push(table_data, sizeof(*ivrs));
> >+ivrs->revision = cpu_to_le16(ACPI_IOMMU_IVRS_TYPE);
> >+ivrs->length = cpu_to_le16((sizeof(*ivrs) + sizeof(*iommu)));
> >+ivrs->v_common_info = cpu_to_le64(AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
> >+
> >+AMDIOMMUState *s = (AMDIOMMUState *)object_resolve_path_type("",
> >+TYPE_AMD_IOMMU_DEVICE, _ambig);
> >+
> >+/* IVDB definition */
> >+iommu = acpi_data_push(table_data, sizeof(*iommu));
> >+if (!iommu_ambig) {
> 
> Hi,
> 
> If the reference to AMD IOMMU is ambiguous and the table is not added to ACPI
> I think we should report the error to user, something like error_report.
> 
> >+iommu->type = cpu_to_le16(0x10);
> >+/* IVHD flags */
> >+iommu->flags = cpu_to_le16(iommu->flags);
> >+iommu->flags = cpu_to_le16(IVHD_HT_TUNEN | IVHD_PPRSUP | 
> >IVHD_IOTLBSUP
> >+   | IVHD_PREFSUP);
> >+iommu->length = cpu_to_le16(sizeof(*iommu));
> >+iommu->device_id = cpu_to_le16(PCI_DEVICE_ID_RD890_IOMMU);
> >+iommu->capability_offset = cpu_to_le16(s->capab_offset);
> >+iommu->mmio_base = cpu_to_le64(s->mmio.addr);
> >+iommu->pci_segment = 0;
> >+iommu->interrupt_info = 0;
> >+/* EFR features */
> >+iommu->efr_register = cpu_to_le64(IVHD_EFR_GTSUP | IVHD_EFR_HATS
> >+  | IVHD_EFR_GATS);
> >+iommu->efr_register = cpu_to_le64(iommu->efr_register);
> >+/* device entries */
> >+memset(iommu->dev_entries, 0, 20);
> >+/* Add device flags here
> >+ *  create entries for devices to be treated specially by IO MMU,
> >+ *  currently we report all devices to IO MMU with no special flags
> >+ *  DTE settings made here apply to all devices
> >+ *  Refer to AMD IOMMU spec Table 97
> >+ */
> >+iommu->dev_entries[12] = 3;
> >+iommu->dev_entries[16] = 4;
> >+iommu->dev_entries[17] = 0xff;
> >+iommu->dev_entries[18] = 0xff;
> >+}
> >+
> >+build_header(linker, table_data, (void *)(table_data->data + 
> >iommu_start),
> >+ "IVRS", table_data->len - iommu_start, 1, NULL);
> >+}
> >+
> >+static bool acpi_has_amd_iommu(void)
> >+{
> >+bool ambiguous;
> >+Object *amd_iommu;
> >+
> >+amd_iommu = object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE,
> >+ );
> >+return amd_iommu && !ambiguous;
> >+}
> >+
> >+static void
> >  build_dsdt(GArray *table_data, GArray *linker,
> > AcpiPmInfo *pm, AcpiMiscInfo *misc)
> >  {
> >@@ -2691,6 +2756,11 @@ void acpi_build(PcGuestInfo *guest_info, 
> >AcpiBuildTables *tables)
> >  build_dmar_q35(tables_blob, tables->linker);
> >  }
> >
> >+if (acpi_has_amd_iommu() && !acpi_has_iommu()) {
> 
> Since we have the acpi_has_amd_iommu function now, maybe is time to rename
> acpi_has_iommu to acpi_has_intel_iommu or better have a standard has_iommu 
> that
> returns an enum type (NONE/INTEL/AMD).
> 
> By the way, do we really need to check !acpi_has_iommu() if there is
> an AMD IOMMU in the system? Having both in the same system is a not (yet) 
> supported configuration,
> right?
> 
> Thanks,
> Marcel
> 

Long term the right thing to do is to add description
for each IOMMU present in the system.
For example, we might have multiple intel iommus.

> >+acpi_add_table(table_offsets, tables_blob);
> >+build_amd_iommu(tables_blob, tables->linker);
> >+}
> >+
> >  if (acpi_has_nvdimm()) {
> >  nvdimm_build_acpi(table_offsets, tables_blob, tables->linker);
> >  }
> >diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> >index c7a03d4..a161358 100644
> >--- 

Re: [Qemu-devel] [V4 2/4] hw/core: Add AMD IO MMU to machine properties

2016-02-14 Thread Marcel Apfelbaum

On 01/18/2016 06:21 PM, Marcel Apfelbaum wrote:

On 01/18/2016 05:25 PM, David Kiarie wrote:

Add IO MMU as a string to machine properties which
is used to control whether and the type of IO MMU
to emulate

Signed-off-by: David Kiarie 
---

[...]

Hi,

I am sorry for bugging you, please don't re-post before
you get more meaningful reviews,


I meant "meaningful reviews" *from others*, not from me :)
If you have the time, please do re-post.

Anyway, I will give it a try and read the AMD IOMMU spec, maybe I can help
with patch [1/4] review.

Thanks,
Marcel

[...]



Re: [Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-02-14 Thread Marcel Apfelbaum

On 01/18/2016 05:25 PM, David Kiarie wrote:

Add IVRS table for AMD IO MMU.

Signed-off-by: David Kiarie 
---
  hw/i386/acpi-build.c| 70 +
  include/hw/acpi/acpi-defs.h | 55 +++
  2 files changed, 125 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 78758e2..5c0d6b7 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -52,6 +52,7 @@
  #include "hw/pci/pci_bus.h"
  #include "hw/pci-host/q35.h"
  #include "hw/i386/intel_iommu.h"
+#include "hw/i386/amd_iommu.h"
  #include "hw/timer/hpet.h"

  #include "hw/acpi/aml-build.h"
@@ -2424,6 +2425,70 @@ build_dmar_q35(GArray *table_data, GArray *linker)
  }

  static void
+build_amd_iommu(GArray *table_data, GArray *linker)
+{
+int iommu_start = table_data->len;
+bool iommu_ambig;
+
+AcpiAMDIOMMUIVRS *ivrs;
+AcpiAMDIOMMUHardwareUnit *iommu;
+
+/* IVRS definition */
+ivrs = acpi_data_push(table_data, sizeof(*ivrs));
+ivrs->revision = cpu_to_le16(ACPI_IOMMU_IVRS_TYPE);
+ivrs->length = cpu_to_le16((sizeof(*ivrs) + sizeof(*iommu)));
+ivrs->v_common_info = cpu_to_le64(AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
+
+AMDIOMMUState *s = (AMDIOMMUState *)object_resolve_path_type("",
+TYPE_AMD_IOMMU_DEVICE, _ambig);
+
+/* IVDB definition */
+iommu = acpi_data_push(table_data, sizeof(*iommu));
+if (!iommu_ambig) {


Hi,

If the reference to AMD IOMMU is ambiguous and the table is not added to ACPI
I think we should report the error to user, something like error_report.


+iommu->type = cpu_to_le16(0x10);
+/* IVHD flags */
+iommu->flags = cpu_to_le16(iommu->flags);
+iommu->flags = cpu_to_le16(IVHD_HT_TUNEN | IVHD_PPRSUP | IVHD_IOTLBSUP
+   | IVHD_PREFSUP);
+iommu->length = cpu_to_le16(sizeof(*iommu));
+iommu->device_id = cpu_to_le16(PCI_DEVICE_ID_RD890_IOMMU);
+iommu->capability_offset = cpu_to_le16(s->capab_offset);
+iommu->mmio_base = cpu_to_le64(s->mmio.addr);
+iommu->pci_segment = 0;
+iommu->interrupt_info = 0;
+/* EFR features */
+iommu->efr_register = cpu_to_le64(IVHD_EFR_GTSUP | IVHD_EFR_HATS
+  | IVHD_EFR_GATS);
+iommu->efr_register = cpu_to_le64(iommu->efr_register);
+/* device entries */
+memset(iommu->dev_entries, 0, 20);
+/* Add device flags here
+ *  create entries for devices to be treated specially by IO MMU,
+ *  currently we report all devices to IO MMU with no special flags
+ *  DTE settings made here apply to all devices
+ *  Refer to AMD IOMMU spec Table 97
+ */
+iommu->dev_entries[12] = 3;
+iommu->dev_entries[16] = 4;
+iommu->dev_entries[17] = 0xff;
+iommu->dev_entries[18] = 0xff;
+}
+
+build_header(linker, table_data, (void *)(table_data->data + iommu_start),
+ "IVRS", table_data->len - iommu_start, 1, NULL);
+}
+
+static bool acpi_has_amd_iommu(void)
+{
+bool ambiguous;
+Object *amd_iommu;
+
+amd_iommu = object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE,
+ );
+return amd_iommu && !ambiguous;
+}
+
+static void
  build_dsdt(GArray *table_data, GArray *linker,
 AcpiPmInfo *pm, AcpiMiscInfo *misc)
  {
@@ -2691,6 +2756,11 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables 
*tables)
  build_dmar_q35(tables_blob, tables->linker);
  }

+if (acpi_has_amd_iommu() && !acpi_has_iommu()) {


Since we have the acpi_has_amd_iommu function now, maybe is time to rename
acpi_has_iommu to acpi_has_intel_iommu or better have a standard has_iommu that
returns an enum type (NONE/INTEL/AMD).

By the way, do we really need to check !acpi_has_iommu() if there is
an AMD IOMMU in the system? Having both in the same system is a not (yet) 
supported configuration,
right?

Thanks,
Marcel



+acpi_add_table(table_offsets, tables_blob);
+build_amd_iommu(tables_blob, tables->linker);
+}
+
  if (acpi_has_nvdimm()) {
  nvdimm_build_acpi(table_offsets, tables_blob, tables->linker);
  }
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index c7a03d4..a161358 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -570,4 +570,59 @@ typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit;
  /* Masks for Flags field above */
  #define ACPI_DMAR_INCLUDE_PCI_ALL   1

+/* IVRS constants */
+#define ACPI_IOMMU_HARDWAREUNIT_TYPE 0x10
+#define ACPI_IOMMU_IVRS_TYPE 0x1
+#define AMD_IOMMU_HOST_ADDRESS_WIDTH 39UL
+
+/* AMD IOMMU IVRS table */
+struct AcpiAMDIOMMUIVRS {
+ACPI_TABLE_HEADER_DEF
+uint32_t v_common_info; /* common virtualization information */
+uint64_t reserved;  /* reserved  */
+} QEMU_PACKED;

Re: [Qemu-devel] [PATCH 2/2] hw/9pfs: fix alignment issue when host filesystem block size is larger than client msize

2016-02-14 Thread Aneesh Kumar K.V
Jevon Qiao  writes:

> The following patch is to fix alignment issue when host filesystem block 
> size
> is larger than client msize.
>
> Thanks,
> Jevon

That is not the right format to send patch. You can send them as a
series using git-send-email.

>
> From: Jevon Qiao 
> Date: Sun, 14 Feb 2016 15:11:08 +0800
> Subject: [PATCH] hw/9pfs: fix alignment issue when host filesystem block 
> size
>   is larger than client msize.
>
> Per the previous implementation, iounit will be assigned to be 0 after the
> first if statement as (s->msize - P9_IOHDRSZ)/stbuf.f_bsize will be zero 
> when
> host filesystem block size is larger than msize. Finally, iounit will be 
> equal
> to s->msize - P9_IOHDRSZ, which is usually not aligned.
>
> Signed-off-by: Jevon Qiao 
> ---
>   hw/9pfs/virtio-9p.c | 19 ---
>   1 file changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
> index f972731..005d3a8 100644
> --- a/hw/9pfs/virtio-9p.c
> +++ b/hw/9pfs/virtio-9p.c
> @@ -1326,7 +1326,7 @@ out_nofid:
>   static int32_t get_iounit(V9fsPDU *pdu, V9fsPath *path)
>   {
>   struct statfs stbuf;
> -int32_t iounit = 0;
> +int32_t iounit = 0, unit = 0;
>   V9fsState *s = pdu->s;
>
>   /*
> @@ -1334,8 +1334,21 @@ static int32_t get_iounit(V9fsPDU *pdu, V9fsPath 
> *path)
>* and as well as less than (client msize - P9_IOHDRSZ))
>*/
>   if (!v9fs_co_statfs(pdu, path, )) {
> -iounit = stbuf.f_bsize;
> -iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize;
> +/*
> + * If host filesystem block size is larger than client msize,
> + * we will use PAGESIZE as the unit. The reason why we choose
> + * PAGESIZE is because the data will be splitted in terms of
> + * PAGESIZE in the virtio layer. In this case, the final
> + * iounit is equal to the value of ((msize/unit) - 1) * unit.
> + */
> +if (stbuf.f_bsize > s->msize) {
> +iounit = 4096;
> +unit = 4096;

What page size it should be guest or host ?. Also why 4096 ?. ppc64 use
64K page size.


> +} else {
> +iounit = stbuf.f_bsize;
> +unit = stbuf.f_bsize;
> +}
> +iounit *= (s->msize - P9_IOHDRSZ)/unit;
>   }
>   if (!iounit) {
>   iounit = s->msize - P9_IOHDRSZ;
> -- 

-aneesh




Re: [Qemu-devel] [PULL 48/49] i386: populate floppy drive information in DSDT

2016-02-14 Thread Michael S. Tsirkin
On Sat, Feb 13, 2016 at 12:26:53PM -0500, Kevin O'Connor wrote:
> On Tue, Feb 09, 2016 at 07:36:12PM +0100, Laszlo Ersek wrote:
> > On 02/09/16 17:22, John Snow wrote:
> > > On 02/09/2016 10:52 AM, Roman Kagan wrote:
> > >> On Mon, Feb 08, 2016 at 03:20:47PM -0500, John Snow wrote:
> > >>> On 02/08/2016 08:14 AM, Roman Kagan wrote:
> >  On Fri, Feb 05, 2016 at 07:25:07PM +0100, Igor Mammedov wrote:
> > >> +aml_append(fdi,
> > >> +aml_int(cylinders - 1));  /* Maximum Cylinder Number */
> > > this puts uint64_t(-1) in AML i.e. cylinders == 0 and overflow 
> > > happens here
> > >
> > > CCing Jon
> > 
> >  I guess this is the effect of John's fdc rework.  I used to think zero
> >  geometry was impossible at the time this patch was developed.
> > 
> >  I wonder if it hasn't been fixed already by
> > 
> >    commit fd9bdbd3459e5b9d51534f0747049bc5b6145e07
> >    Author: John Snow 
> >    Date:   Wed Feb 3 11:28:55 2016 -0500
> > 
> >    fdc: fix detection under Linux
> > >>>
> > >>> Yes, hopefully solved on my end. The geometry values for an empty disk
> > >>> are not well defined (they certainly don't have any *meaning*) so if you
> > >>> are populating tables based on an empty drive, I just hope you also have
> > >>> the mechanisms needed to update said tables when the media changes.
> > >>
> > >> I don't.  At the time the patch was developed there basically were no
> > >> mechanisms to update the geometry at all (and this was what you patchset
> > >> addressed, in particular, wasn't it?) so I didn't care.
> > >>
> > > 
> > > That's not true.
> > > 
> > > You could swap different 1.44MB-class diskettes for other geometries,
> > > check this out:
> > > 
> > > static const FDFormat fd_formats[] = {
> > > /* First entry is default format */
> > > /* 1.44 MB 3"1/2 floppy disks */
> > > { FDRIVE_DRV_144, 18, 80, 1, FDRIVE_RATE_500K, },
> > > { FDRIVE_DRV_144, 20, 80, 1, FDRIVE_RATE_500K, },
> > > { FDRIVE_DRV_144, 21, 80, 1, FDRIVE_RATE_500K, },
> > > { FDRIVE_DRV_144, 21, 82, 1, FDRIVE_RATE_500K, },
> > > { FDRIVE_DRV_144, 21, 83, 1, FDRIVE_RATE_500K, },
> > > { FDRIVE_DRV_144, 22, 80, 1, FDRIVE_RATE_500K, },
> > > { FDRIVE_DRV_144, 23, 80, 1, FDRIVE_RATE_500K, },
> > > { FDRIVE_DRV_144, 24, 80, 1, FDRIVE_RATE_500K, },
> > > ...
> > > 
> > > You absolutely could get different sector and track counts before my
> > > patchset.
> > > 
> > > 
> > >> Now if it actually has to be fully dynamic it's gonna be more
> > >> involved...
> > >>
> > >>> What do the guests use these values for? Are they fixed at boot?
> > >>
> > >> Only Windows guests use it so it's hard to tell.  I can only claim that
> > >> if I stick bogus values into that ACPI object the guest fails to read
> > >> the floppy.
> > 
> > We discussed this with John a bit on IRC.
> > 
> > In my opinion, the real mess in this case is in the ACPI spec itself. If
> > you re-read the _FDI control method's description, the Package that it
> > returns contains *dynamic* geometry data, about the *disk* (not *drive*):
> > 
> > - Maximum Cylinder Number // Integer (WORD)
> > - Maximum Sector Number   // Integer (WORD)
> > - Maximum Head Number // Integer (WORD)
> 
> FWIW, that's not how I read the ACPI specification.  I read it as
> saying that the information should be filled with the maximum number
> of CHS that the drive can support.  So, even if a smaller disk happens
> to be in the drive the maximum the drive supports would not change.

I agree. It says:
This object returns information about a floppy disk drive. This
information is the same as
that returned by the INT 13 Function 08H on Intel Architecture PCs.

So disk drive, not disk information.

And FWIW I have an old "the undocumented PC" book which says
this about int 13h function 8 (read diskette drive parameters):

"Remember this data is *not* the limits of the media in the drive,
but the maximum capability of the specified drive".

> Also, FWIW, SeaBIOS uses the standard 1.44MB floppy controller timing
> information even if a 5.25 drive is found - as far as I know this
> information is only ever used on PIO to the floppy controller and the
> QEMU floppy controller doesn't care what timing parameters it is
> programmed with.
> 
> -Kevin



[Qemu-devel] crash with -incoming and -snapshot

2016-02-14 Thread Paolo Bonzini
Reproducer:

x86_64-softmmu/qemu-system-x86_64 \
   -incoming tcp:localhost:12345 -snapshot \
   /vm/virt_test/images/jeos-21-64-base.qcow2


Weird as it may seem, this actually makes some sense for testing
migration with non-shared storage...

Paolo



Re: [Qemu-devel] crash with -incoming and -snapshot

2016-02-14 Thread Paolo Bonzini


On 14/02/2016 16:52, Paolo Bonzini wrote:
> Reproducer:
> 
> x86_64-softmmu/qemu-system-x86_64 \
>-incoming tcp:localhost:12345 -snapshot \
>/vm/virt_test/images/jeos-21-64-base.qcow2
> 
> 
> Weird as it may seem, this actually makes some sense for testing
> migration with non-shared storage...

In fact, migration with non-shared storage (migrate -b) is broken in
general, even without -snapshot.

Paolo



[Qemu-devel] [PATCH v2] tests: add pxe e1000 and virtio-pci tests

2016-02-14 Thread Victor Kaplansky
The test is based on bios-tables-test.c.  It creates a file with
the boot sector image and loads it into a guest using PXE and TFTP
functionality.

Cc: Jason Wang 
Signed-off-by: Victor Kaplansky 
Suggested-by: Michael S. Tsirkin 
---
v2:
- added a one more test for virtio-pci device, so the test
  consists of two test cases now.
- following a proposal by Michael S. Tsirkin, code handling
  boot sector details was factored out to boot-sector.[ch]
  for usage by both pxe-test and bios-tables-test.


 tests/boot-sector.h  |  26 +++
 tests/bios-tables-test.c |  72 +++-
 tests/boot-sector.c  | 119 +++
 tests/pxe-test.c |  69 +++
 tests/Makefile   |   5 +-
 5 files changed, 224 insertions(+), 67 deletions(-)
 create mode 100644 tests/boot-sector.h
 create mode 100644 tests/boot-sector.c
 create mode 100644 tests/pxe-test.c

diff --git a/tests/boot-sector.h b/tests/boot-sector.h
new file mode 100644
index ..38be0290
--- /dev/null
+++ b/tests/boot-sector.h
@@ -0,0 +1,26 @@
+/*
+ * QEMU boot sector testing helpers.
+ *
+ * Copyright (c) 2016 Red Hat Inc.
+ *
+ * Authors:
+ *  Michael S. Tsirkin 
+ *  Victor Kaplansky 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TEST_BOOT_SECTOR
+#define TEST_BOOT_SECTOR
+
+/* Create boot disk file.  */
+int boot_sector_init(const char *fname);
+
+/* Loop until signature in memory is OK.  */
+void boot_sector_test(void);
+
+/* unlink boot disk file.  */
+void boot_sector_cleanup(const char *fname);
+
+#endif /* TEST_BOOT_SECTOR */
diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 75ec330c..3488058a 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -20,6 +20,7 @@
 #include "hw/acpi/acpi-defs.h"
 #include "hw/smbios/smbios.h"
 #include "qemu/bitmap.h"
+#include "boot-sector.h"
 
 #define MACHINE_PC "pc"
 #define MACHINE_Q35 "q35"
@@ -53,13 +54,6 @@ typedef struct {
 struct smbios_21_entry_point smbios_ep_table;
 } test_data;
 
-#define LOW(x) ((x) & 0xff)
-#define HIGH(x) ((x) >> 8)
-
-#define SIGNATURE 0xdead
-#define SIGNATURE_OFFSET 0x10
-#define BOOT_SECTOR_ADDRESS 0x7c00
-
 #define ACPI_READ_FIELD(field, addr)   \
 do {   \
 switch (sizeof(field)) {   \
@@ -119,35 +113,6 @@ typedef struct {
 g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
 } while (0)
 
-/* Boot sector code: write SIGNATURE into memory,
- * then halt.
- * Q35 machine requires a minimum 0x7e000 bytes disk.
- * (bug or feature?)
- */
-static uint8_t boot_sector[0x7e000] = {
-/* 7c00: mov $0xdead,%ax */
-[0x00] = 0xb8,
-[0x01] = LOW(SIGNATURE),
-[0x02] = HIGH(SIGNATURE),
-/* 7c03:  mov %ax,0x7c10 */
-[0x03] = 0xa3,
-[0x04] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
-[0x05] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
-/* 7c06: cli */
-[0x06] = 0xfa,
-/* 7c07: hlt */
-[0x07] = 0xf4,
-/* 7c08: jmp 0x7c07=0x7c0a-3 */
-[0x08] = 0xeb,
-[0x09] = LOW(-3),
-/* We mov 0xdead here: set value to make debugging easier */
-[SIGNATURE_OFFSET] = LOW(0xface),
-[SIGNATURE_OFFSET + 1] = HIGH(0xface),
-/* End of boot sector marker */
-[0x1FE] = 0x55,
-[0x1FF] = 0xAA,
-};
-
 static const char *disk = "tests/acpi-test-disk.raw";
 static const char *data_dir = "tests/acpi-test-data";
 #ifdef CONFIG_IASL
@@ -739,10 +704,6 @@ static void test_smbios_structs(test_data *data)
 static void test_acpi_one(const char *params, test_data *data)
 {
 char *args;
-uint8_t signature_low;
-uint8_t signature_high;
-uint16_t signature;
-int i;
 
 args = g_strdup_printf("-net none -display none %s "
"-drive id=hd0,if=none,file=%s,format=raw "
@@ -751,24 +712,7 @@ static void test_acpi_one(const char *params, test_data 
*data)
 
 qtest_start(args);
 
-   /* Wait at most 1 minute */
-#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
-#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
-
-/* Poll until code has run and modified memory.  Once it has we know BIOS
- * initialization is done.  TODO: check that IP reached the halt
- * instruction.
- */
-for (i = 0; i < TEST_CYCLES; ++i) {
-signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
-signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
-signature = (signature_high << 8) | signature_low;
-if (signature == SIGNATURE) {
-break;
-}
-g_usleep(TEST_DELAY);
-}
-g_assert_cmphex(signature, ==, SIGNATURE);
+boot_sector_test();
 
 test_acpi_rsdp_address(data);
 

[Qemu-devel] [PATCH 3/8] virtio: add AioContext-specific function for host notifiers

2016-02-14 Thread Paolo Bonzini
This is used to register ioeventfd with a dataplane thread.

Signed-off-by: Paolo Bonzini 
---
 hw/virtio/virtio.c | 16 
 include/hw/virtio/virtio.h |  2 ++
 2 files changed, 18 insertions(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 90f2545..3a5cca4 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1785,6 +1785,22 @@ static void 
virtio_queue_host_notifier_read(EventNotifier *n)
 }
 }
 
+void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx,
+bool assign, bool set_handler)
+{
+if (assign && set_handler) {
+aio_set_event_notifier(ctx, >host_notifier, true,
+   virtio_queue_host_notifier_read);
+} else {
+aio_set_event_notifier(ctx, >host_notifier, true, NULL);
+}
+if (!assign) {
+/* Test and clear notifier before after disabling event,
+ * in case poll callback didn't have time to run. */
+virtio_queue_host_notifier_read(>host_notifier);
+}
+}
+
 void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
bool set_handler)
 {
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 108cdb0..4ce01a1 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -248,6 +248,8 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue 
*vq, bool assign,
 EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
 void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
bool set_handler);
+void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx,
+bool assign, bool set_handler);
 void virtio_queue_notify_vq(VirtQueue *vq);
 void virtio_irq(VirtQueue *vq);
 VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
-- 
1.8.3.1





[Qemu-devel] [PATCH 8/8] vring: remove

2016-02-14 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 hw/virtio/Makefile.objs   |   1 -
 hw/virtio/dataplane/Makefile.objs |   1 -
 hw/virtio/dataplane/vring.c   | 548 --
 include/hw/virtio/dataplane/vring-accessors.h |  75 
 include/hw/virtio/dataplane/vring.h   |  51 ---
 trace-events  |   3 -
 6 files changed, 679 deletions(-)
 delete mode 100644 hw/virtio/dataplane/Makefile.objs
 delete mode 100644 hw/virtio/dataplane/vring.c
 delete mode 100644 include/hw/virtio/dataplane/vring-accessors.h
 delete mode 100644 include/hw/virtio/dataplane/vring.h

diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
index 19b224a..3e2b175 100644
--- a/hw/virtio/Makefile.objs
+++ b/hw/virtio/Makefile.objs
@@ -2,7 +2,6 @@ common-obj-y += virtio-rng.o
 common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 common-obj-y += virtio-bus.o
 common-obj-y += virtio-mmio.o
-obj-$(CONFIG_VIRTIO) += dataplane/
 
 obj-y += virtio.o virtio-balloon.o 
 obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
diff --git a/hw/virtio/dataplane/Makefile.objs 
b/hw/virtio/dataplane/Makefile.objs
deleted file mode 100644
index 753a9ca..000
--- a/hw/virtio/dataplane/Makefile.objs
+++ /dev/null
@@ -1 +0,0 @@
-obj-y += vring.o
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
deleted file mode 100644
index 157e8b8..000
--- a/hw/virtio/dataplane/vring.c
+++ /dev/null
@@ -1,548 +0,0 @@
-/* Copyright 2012 Red Hat, Inc.
- * Copyright IBM, Corp. 2012
- *
- * Based on Linux 2.6.39 vhost code:
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2006 Rusty Russell IBM Corporation
- *
- * Author: Michael S. Tsirkin 
- * Stefan Hajnoczi 
- *
- * Inspiration, some code, and most witty comments come from
- * Documentation/virtual/lguest/lguest.c, by Rusty Russell
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
- */
-
-#include "qemu/osdep.h"
-#include "trace.h"
-#include "hw/hw.h"
-#include "exec/memory.h"
-#include "exec/address-spaces.h"
-#include "hw/virtio/virtio-access.h"
-#include "hw/virtio/dataplane/vring.h"
-#include "hw/virtio/dataplane/vring-accessors.h"
-#include "qemu/error-report.h"
-
-/* vring_map can be coupled with vring_unmap or (if you still have the
- * value returned in *mr) memory_region_unref.
- * Returns NULL on failure.
- * Callers that can handle a partial mapping must supply mapped_len pointer to
- * get the actual length mapped.
- * Passing mapped_len == NULL requires either a full mapping or a failure.
- */
-static void *vring_map(MemoryRegion **mr, hwaddr phys,
-   hwaddr len, hwaddr *mapped_len,
-   bool is_write)
-{
-MemoryRegionSection section = memory_region_find(get_system_memory(), 
phys, len);
-uint64_t size;
-
-if (!section.mr) {
-goto out;
-}
-
-size = int128_get64(section.size);
-assert(size);
-
-/* Passing mapped_len == NULL requires either a full mapping or a failure. 
*/
-if (!mapped_len && size < len) {
-goto out;
-}
-
-if (is_write && section.readonly) {
-goto out;
-}
-if (!memory_region_is_ram(section.mr)) {
-goto out;
-}
-
-/* Ignore regions with dirty logging, we cannot mark them dirty */
-if (memory_region_get_dirty_log_mask(section.mr)) {
-goto out;
-}
-
-if (mapped_len) {
-*mapped_len = MIN(size, len);
-}
-
-*mr = section.mr;
-return memory_region_get_ram_ptr(section.mr) + 
section.offset_within_region;
-
-out:
-memory_region_unref(section.mr);
-*mr = NULL;
-return NULL;
-}
-
-static void vring_unmap(void *buffer, bool is_write)
-{
-ram_addr_t addr;
-MemoryRegion *mr;
-
-mr = qemu_ram_addr_from_host(buffer, );
-memory_region_unref(mr);
-}
-
-/* Map the guest's vring to host memory */
-bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
-{
-struct vring *vr = >vr;
-hwaddr addr;
-hwaddr size;
-void *ptr;
-
-vring->broken = false;
-vr->num = virtio_queue_get_num(vdev, n);
-
-addr = virtio_queue_get_desc_addr(vdev, n);
-size = virtio_queue_get_desc_size(vdev, n);
-/* Map the descriptor area as read only */
-ptr = vring_map(>mr_desc, addr, size, NULL, false);
-if (!ptr) {
-error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring desc "
- "at 0x%" HWADDR_PRIx,
-  size, addr);
-goto out_err_desc;
-}
-vr->desc = ptr;
-
-addr = virtio_queue_get_avail_addr(vdev, n);
-size = virtio_queue_get_avail_size(vdev, n);
-/* Add the size of the used_event_idx */
-size += sizeof(uint16_t);
-/* Map the driver area as read only */
-ptr = vring_map(>mr_avail, addr, size, NULL, false);
-if (!ptr) {
-error_report("Failed to map 0x%" HWADDR_PRIx " byte for vring 

[Qemu-devel] [PATCH 0/8] virtio: allow migration with dataplane

2016-02-14 Thread Paolo Bonzini
Currently, dataplane threads are shut down during migration because
vring.c is not able to track dirty memory.  However, all the relevant
parts of QEMU have been made thread-safe now, so we can drop vring.c
completely.  With these patches, virtio-dataplane is now simply "virtio
with ioeventfd in a different AioContext".

Paolo Bonzini (8):
  block-migration: acquire AioContext as necessary
  vring: make vring_enable_notification return void
  virtio: add AioContext-specific function for host notifiers
  virtio: export vring_notify as virtio_should_notify
  virtio-blk: fix "disabled data plane" mode
  virtio-blk: do not use vring in dataplane
  virtio-scsi: do not use vring in dataplane
  vring: remove

 hw/block/dataplane/virtio-blk.c   | 130 +-
 hw/block/dataplane/virtio-blk.h   |   1 +
 hw/block/virtio-blk.c |  51 +--
 hw/scsi/virtio-scsi-dataplane.c   | 196 ++---
 hw/scsi/virtio-scsi.c |  52 +--
 hw/virtio/Makefile.objs   |   1 -
 hw/virtio/dataplane/Makefile.objs |   1 -
 hw/virtio/dataplane/vring.c   | 549 --
 hw/virtio/virtio.c|  20 +-
 include/hw/virtio/dataplane/vring-accessors.h |  75 
 include/hw/virtio/dataplane/vring.h   |  51 ---
 include/hw/virtio/virtio-blk.h|   4 +-
 include/hw/virtio/virtio-scsi.h   |  21 +-
 include/hw/virtio/virtio.h|   3 +
 migration/block.c |  61 ++-
 trace-events  |   3 -
 16 files changed, 134 insertions(+), 1085 deletions(-)
 delete mode 100644 hw/virtio/dataplane/Makefile.objs
 delete mode 100644 hw/virtio/dataplane/vring.c
 delete mode 100644 include/hw/virtio/dataplane/vring-accessors.h
 delete mode 100644 include/hw/virtio/dataplane/vring.h

-- 
1.8.3.1




[Qemu-devel] [PATCH 7/8] virtio-scsi: do not use vring in dataplane

2016-02-14 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 hw/scsi/virtio-scsi-dataplane.c | 196 +---
 hw/scsi/virtio-scsi.c   |  52 ++-
 include/hw/virtio/virtio-scsi.h |  21 +
 3 files changed, 35 insertions(+), 234 deletions(-)

diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 8340326..367e476 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -39,14 +39,10 @@ void virtio_scsi_set_iothread(VirtIOSCSI *s, IOThread 
*iothread)
 }
 }
 
-static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
-   VirtQueue *vq,
-   EventNotifierHandler *handler,
-   int n)
+static int virtio_scsi_vring_init(VirtIOSCSI *s, VirtQueue *vq, int n)
 {
 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-VirtIOSCSIVring *r;
 int rc;
 
 /* Set up virtqueue notify */
@@ -55,105 +51,17 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI 
*s,
 fprintf(stderr, "virtio-scsi: Failed to set host notifier (%d)\n",
 rc);
 s->dataplane_fenced = true;
-return NULL;
+return rc;
 }
 
-r = g_new(VirtIOSCSIVring, 1);
-r->host_notifier = *virtio_queue_get_host_notifier(vq);
-r->guest_notifier = *virtio_queue_get_guest_notifier(vq);
-aio_set_event_notifier(s->ctx, >host_notifier, true, handler);
-
-r->parent = s;
-
-if (!vring_setup(>vring, VIRTIO_DEVICE(s), n)) {
-fprintf(stderr, "virtio-scsi: VRing setup failed\n");
-goto fail_vring;
-}
-return r;
-
-fail_vring:
-aio_set_event_notifier(s->ctx, >host_notifier, true, NULL);
-k->set_host_notifier(qbus->parent, n, false);
-g_free(r);
-return NULL;
-}
-
-VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s,
- VirtIOSCSIVring *vring)
-{
-VirtIOSCSICommon *vs = (VirtIOSCSICommon *)s;
-VirtIOSCSIReq *req;
-
-req = vring_pop((VirtIODevice *)s, >vring,
-sizeof(VirtIOSCSIReq) + vs->cdb_size);
-if (!req) {
-return NULL;
-}
-virtio_scsi_init_req(s, NULL, req);
-req->vring = vring;
-return req;
-}
-
-void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
-{
-VirtIODevice *vdev = VIRTIO_DEVICE(req->vring->parent);
-
-vring_push(vdev, >vring->vring, >elem,
-   req->qsgl.size + req->resp_iov.size);
-
-if (vring_should_notify(vdev, >vring->vring)) {
-event_notifier_set(>vring->guest_notifier);
-}
+virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, true, true);
+return 0;
 }
 
-static void virtio_scsi_iothread_handle_ctrl(EventNotifier *notifier)
+void virtio_scsi_dataplane_notify(VirtIODevice *vdev, VirtIOSCSIReq *req)
 {
-VirtIOSCSIVring *vring = container_of(notifier,
-  VirtIOSCSIVring, host_notifier);
-VirtIOSCSI *s = VIRTIO_SCSI(vring->parent);
-VirtIOSCSIReq *req;
-
-event_notifier_test_and_clear(notifier);
-while ((req = virtio_scsi_pop_req_vring(s, vring))) {
-virtio_scsi_handle_ctrl_req(s, req);
-}
-}
-
-static void virtio_scsi_iothread_handle_event(EventNotifier *notifier)
-{
-VirtIOSCSIVring *vring = container_of(notifier,
-  VirtIOSCSIVring, host_notifier);
-VirtIOSCSI *s = vring->parent;
-VirtIODevice *vdev = VIRTIO_DEVICE(s);
-
-event_notifier_test_and_clear(notifier);
-
-if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
-return;
-}
-
-if (s->events_dropped) {
-virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
-}
-}
-
-static void virtio_scsi_iothread_handle_cmd(EventNotifier *notifier)
-{
-VirtIOSCSIVring *vring = container_of(notifier,
-  VirtIOSCSIVring, host_notifier);
-VirtIOSCSI *s = (VirtIOSCSI *)vring->parent;
-VirtIOSCSIReq *req, *next;
-QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
-
-event_notifier_test_and_clear(notifier);
-while ((req = virtio_scsi_pop_req_vring(s, vring))) {
-if (virtio_scsi_handle_cmd_req_prepare(s, req)) {
-QTAILQ_INSERT_TAIL(, req, next);
-}
-}
-
-QTAILQ_FOREACH_SAFE(req, , next, next) {
-virtio_scsi_handle_cmd_req_submit(s, req);
+if (virtio_should_notify(vdev, req->vq)) {
+event_notifier_set(virtio_queue_get_guest_notifier(req->vq));
 }
 }
 
@@ -163,46 +71,10 @@ static void virtio_scsi_clear_aio(VirtIOSCSI *s)
 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
 int i;
 
-if (s->ctrl_vring) {
-aio_set_event_notifier(s->ctx, >ctrl_vring->host_notifier,
-   true, NULL);
-}
-if (s->event_vring) {
-

[Qemu-devel] [PATCHv7 8/9] slirp: Adding IPv6 address for DNS relay

2016-02-14 Thread Samuel Thibault
From: Guillaume Subiron 

This patch adds an IPv6 address to the DNS relay. in6_equal_dns() is
developed using this Slirp attribute.
sotranslate_in/out/accept() are also updated to manage the IPv6 case so the
guest can be able to join the host using one of the Slirp addresses.

For now this only points to localhost. Further development will be needed to
automatically fetch the IPv6 address from resolv.conf, and announce this via
RDNSS.

Signed-off-by: Guillaume Subiron 
Signed-off-by: Samuel Thibault 
---
 slirp/ip6.h|  5 -
 slirp/slirp.c  |  1 +
 slirp/slirp.h  |  1 +
 slirp/socket.c | 32 
 4 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/slirp/ip6.h b/slirp/ip6.h
index 9f7623f..ded6d78 100644
--- a/slirp/ip6.h
+++ b/slirp/ip6.h
@@ -70,7 +70,10 @@ static inline bool in6_equal_mach(const struct in6_addr *a,
   || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
   && in6_equal_mach(a, >vhost_addr6, 64)))
 
-#define in6_equal_dns(a) 0
+#define in6_equal_dns(a)\
+((in6_equal_net(a, >vprefix_addr6, slirp->vprefix_len)\
+ || in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64))\
+ && in6_equal_mach(a, >vnameserver_addr6, slirp->vprefix_len))
 
 #define in6_equal_host(a)\
 (in6_equal_router(a) || in6_equal_dns(a))
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 2321c41..9e7e3a6 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -234,6 +234,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 slirp->bootp_filename = g_strdup(bootfile);
 slirp->vdhcp_startaddr = vdhcp_start;
 slirp->vnameserver_addr = vnameserver;
+inet_pton(AF_INET6, "fec0::3", >vnameserver_addr6);
 
 if (vdnssearch) {
 translate_dnssearch(slirp, vdnssearch);
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 967d93e..a830353 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -232,6 +232,7 @@ struct Slirp {
 struct in6_addr vhost_addr6;
 struct in_addr vdhcp_startaddr;
 struct in_addr vnameserver_addr;
+struct in6_addr vnameserver_addr6;
 
 struct in_addr client_ipaddr;
 char client_hostname[33];
diff --git a/slirp/socket.c b/slirp/socket.c
index d4b02c8..0661fa9 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -747,6 +747,7 @@ void sotranslate_out(struct socket *so, struct 
sockaddr_storage *addr)
 {
 Slirp *slirp = so->slirp;
 struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
 
 switch (addr->ss_family) {
 case AF_INET:
@@ -767,6 +768,19 @@ void sotranslate_out(struct socket *so, struct 
sockaddr_storage *addr)
 ntohs(sin->sin_port), inet_ntoa(sin->sin_addr)));
 break;
 
+case AF_INET6:
+if (in6_equal_net(>so_faddr6, >vprefix_addr6,
+slirp->vprefix_len)) {
+if (in6_equal(>so_faddr6, >vnameserver_addr6)) {
+/*if (get_dns_addr() < 0) {*/ /* TODO */
+sin6->sin6_addr = in6addr_loopback;
+/*}*/
+} else {
+sin6->sin6_addr = in6addr_loopback;
+}
+}
+break;
+
 default:
 break;
 }
@@ -776,6 +790,7 @@ void sotranslate_in(struct socket *so, struct 
sockaddr_storage *addr)
 {
 Slirp *slirp = so->slirp;
 struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
 
 switch (addr->ss_family) {
 case AF_INET:
@@ -792,6 +807,16 @@ void sotranslate_in(struct socket *so, struct 
sockaddr_storage *addr)
 }
 break;
 
+case AF_INET6:
+if (in6_equal_net(>so_faddr6, >vprefix_addr6,
+slirp->vprefix_len)) {
+if (in6_equal(>sin6_addr, _loopback)
+|| !in6_equal(>so_faddr6, >vhost_addr6)) {
+sin6->sin6_addr = so->so_faddr6;
+}
+}
+break;
+
 default:
 break;
 }
@@ -813,6 +838,13 @@ void sotranslate_accept(struct socket *so)
 }
 break;
 
+   case AF_INET6:
+if (in6_equal(>so_faddr6, _any) ||
+in6_equal(>so_faddr6, _loopback)) {
+   so->so_faddr6 = slirp->vhost_addr6;
+}
+break;
+
 default:
 break;
 }
-- 
2.7.0




[Qemu-devel] [PATCHv7 6/9] slirp: Reindent after refactoring

2016-02-14 Thread Samuel Thibault
From: Guillaume Subiron 

No code change.

Signed-off-by: Guillaume Subiron 
Signed-off-by: Samuel Thibault 
---
 slirp/tcp_input.c  | 92 +++---
 slirp/tcp_output.c | 29 +
 slirp/tcp_subr.c   | 50 ++---
 3 files changed, 85 insertions(+), 86 deletions(-)

diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index ceac795..fac2a24 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -258,48 +258,48 @@ tcp_input(struct mbuf *m, int iphlen, struct socket 
*inso, unsigned short af)
 
switch (af) {
case AF_INET:
-   if (iphlen > sizeof(struct ip )) {
- ip_stripoptions(m, (struct mbuf *)0);
- iphlen=sizeof(struct ip );
-   }
-   /* XXX Check if too short */
+   if (iphlen > sizeof(struct ip)) {
+   ip_stripoptions(m, (struct mbuf *)0);
+   iphlen = sizeof(struct ip);
+   }
+   /* XXX Check if too short */
 
 
-   /*
-* Save a copy of the IP header in case we want restore it
-* for sending an ICMP error message in response.
-*/
-   ip=mtod(m, struct ip *);
-   save_ip = *ip;
-   save_ip.ip_len+= iphlen;
+   /*
+* Save a copy of the IP header in case we want restore it
+* for sending an ICMP error message in response.
+*/
+   ip = mtod(m, struct ip *);
+   save_ip = *ip;
+   save_ip.ip_len += iphlen;
 
-   /*
-* Get IP and TCP header together in first mbuf.
-* Note: IP leaves IP header in first mbuf.
-*/
-   m->m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip)
-+ sizeof(struct tcphdr));
-   m->m_len += sizeof(struct tcpiphdr) - (sizeof(struct ip)
-   + sizeof(struct tcphdr));
-   ti = mtod(m, struct tcpiphdr *);
+   /*
+* Get IP and TCP header together in first mbuf.
+* Note: IP leaves IP header in first mbuf.
+*/
+   m->m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip)
++ sizeof(struct tcphdr));
+   m->m_len  += sizeof(struct tcpiphdr) - (sizeof(struct ip)
++ sizeof(struct tcphdr));
+   ti = mtod(m, struct tcpiphdr *);
 
-   /*
-* Checksum extended TCP header and data.
-*/
-   tlen = ip->ip_len;
-   tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
-   memset(>ih_mbuf, 0 , sizeof(struct mbuf_ptr));
-   memset(>ti, 0, sizeof(ti->ti));
-   ti->ti_x0 = 0;
-   ti->ti_src = save_ip.ip_src;
-   ti->ti_dst = save_ip.ip_dst;
-   ti->ti_pr = save_ip.ip_p;
-   ti->ti_len = htons((uint16_t)tlen);
-   len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
-   if(cksum(m, len)) {
- goto drop;
-   }
-   break;
+   /*
+* Checksum extended TCP header and data.
+*/
+   tlen = ip->ip_len;
+   tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
+   memset(>ih_mbuf, 0 , sizeof(struct mbuf_ptr));
+   memset(>ti, 0, sizeof(ti->ti));
+   ti->ti_x0 = 0;
+   ti->ti_src = save_ip.ip_src;
+   ti->ti_dst = save_ip.ip_dst;
+   ti->ti_pr = save_ip.ip_p;
+   ti->ti_len = htons((uint16_t)tlen);
+   len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
+   if (cksum(m, len)) {
+   goto drop;
+   }
+   break;
 
default:
g_assert_not_reached();
@@ -343,12 +343,12 @@ findso:
fhost.ss_family = af;
switch (af) {
case AF_INET:
-   lhost4 = (struct sockaddr_in *) 
-   lhost4->sin_addr = ti->ti_src;
-   lhost4->sin_port = ti->ti_sport;
-   fhost4 = (struct sockaddr_in *) 
-   fhost4->sin_addr = ti->ti_dst;
-   fhost4->sin_port = ti->ti_dport;
+   lhost4 = (struct sockaddr_in *) 
+   lhost4->sin_addr = ti->ti_src;
+   lhost4->sin_port = ti->ti_sport;
+   fhost4 = (struct sockaddr_in *) 
+   fhost4->sin_addr = ti->ti_dst;
+   fhost4->sin_port = ti->ti_dport;
break;
default:
g_assert_not_reached();
@@ -591,8 +591,8 @@ findso:
   * tcp_ctl once connected, otherwise connect
   */
  if (af == AF_INET &&
- (so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
- slirp->vnetwork_addr.s_addr) {
+(so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+slirp->vnetwork_addr.s_addr) {
if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {

[Qemu-devel] [PATCHv7 7/9] slirp: Handle IPv6 in TCP functions

2016-02-14 Thread Samuel Thibault
From: Guillaume Subiron 

This patch adds IPv6 case in TCP functions refactored by the last
patches.
This also adds IPv6 pseudo-header in tcpiphdr structure.
Finally, tcp_input() is called by ip6_input().

Signed-off-by: Guillaume Subiron 
Signed-off-by: Samuel Thibault 
---
 slirp/ip6_input.c  |  3 ++-
 slirp/tcp.h|  2 ++
 slirp/tcp_input.c  | 60 +++---
 slirp/tcp_output.c | 16 +++
 slirp/tcp_subr.c   | 30 ++-
 slirp/tcpip.h  |  9 
 6 files changed, 106 insertions(+), 14 deletions(-)

diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c
index 9ca6d32..c0b11e7 100644
--- a/slirp/ip6_input.c
+++ b/slirp/ip6_input.c
@@ -55,7 +55,8 @@ void ip6_input(struct mbuf *m)
  */
 switch (ip6->ip_nh) {
 case IPPROTO_TCP:
-icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
+NTOHS(ip6->ip_pl);
+tcp_input(m, sizeof(struct ip6), (struct socket *)NULL, AF_INET6);
 break;
 case IPPROTO_UDP:
 udp6_input(m);
diff --git a/slirp/tcp.h b/slirp/tcp.h
index 2e2b403..61befcd 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -106,6 +106,8 @@ struct tcphdr {
  */
 #undef TCP_MSS
 #defineTCP_MSS 1460
+#undef TCP6_MSS
+#define TCP6_MSS 1440
 
 #undef TCP_MAXWIN
 #defineTCP_MAXWIN  65535   /* largest value for (unscaled) window 
*/
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index fac2a24..7aad1bc 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -216,7 +216,8 @@ present:
 void
 tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 {
-   struct ip save_ip, *ip;
+   struct ip save_ip, *ip;
+   struct ip6 save_ip6, *ip6;
register struct tcpiphdr *ti;
caddr_t optp = NULL;
int optlen = 0;
@@ -230,6 +231,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, 
unsigned short af)
int ret;
struct sockaddr_storage lhost, fhost;
struct sockaddr_in *lhost4, *fhost4;
+   struct sockaddr_in6 *lhost6, *fhost6;
 struct ex_list *ex_ptr;
 Slirp *slirp;
 
@@ -256,21 +258,18 @@ tcp_input(struct mbuf *m, int iphlen, struct socket 
*inso, unsigned short af)
}
slirp = m->slirp;
 
+   ip = mtod(m, struct ip *);
+   ip6 = mtod(m, struct ip6 *);
+
switch (af) {
case AF_INET:
+   save_ip = *ip;
if (iphlen > sizeof(struct ip)) {
ip_stripoptions(m, (struct mbuf *)0);
iphlen = sizeof(struct ip);
}
/* XXX Check if too short */
 
-
-   /*
-* Save a copy of the IP header in case we want restore it
-* for sending an ICMP error message in response.
-*/
-   ip = mtod(m, struct ip *);
-   save_ip = *ip;
save_ip.ip_len += iphlen;
 
/*
@@ -295,16 +294,36 @@ tcp_input(struct mbuf *m, int iphlen, struct socket 
*inso, unsigned short af)
ti->ti_dst = save_ip.ip_dst;
ti->ti_pr = save_ip.ip_p;
ti->ti_len = htons((uint16_t)tlen);
-   len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
-   if (cksum(m, len)) {
-   goto drop;
-   }
+   break;
+
+   case AF_INET6:
+   save_ip6 = *ip6;
+   m->m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip6)
++ sizeof(struct tcphdr));
+   m->m_len  += sizeof(struct tcpiphdr) - (sizeof(struct ip6)
++ sizeof(struct tcphdr));
+   ti = mtod(m, struct tcpiphdr *);
+
+   tlen = ip6->ip_pl;
+   tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
+   memset(>ih_mbuf, 0 , sizeof(struct mbuf_ptr));
+   memset(>ti, 0, sizeof(ti->ti));
+   ti->ti_x0 = 0;
+   ti->ti_src6 = save_ip6.ip_src;
+   ti->ti_dst6 = save_ip6.ip_dst;
+   ti->ti_nh6 = save_ip6.ip_nh;
+   ti->ti_len = htons((uint16_t)tlen);
break;
 
default:
g_assert_not_reached();
}
 
+   len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
+   if (cksum(m, len)) {
+   goto drop;
+   }
+
/*
 * Check that TCP offset makes sense,
 * pull out TCP options and adjust length.  XXX
@@ -350,6 +369,14 @@ findso:
fhost4->sin_addr = ti->ti_dst;
fhost4->sin_port = ti->ti_dport;
break;
+   case AF_INET6:
+   lhost6 = (struct sockaddr_in6 *) 
+   lhost6->sin6_addr = ti->ti_src6;
+   lhost6->sin6_port = ti->ti_sport;
+   fhost6 = (struct sockaddr_in6 *) 
+   fhost6->sin6_addr = ti->ti_dst6;
+   fhost6->sin6_port = ti->ti_dport;
+   break;

Re: [Qemu-devel] [V4 4/4] hw/pci-host: Emulate AMD IO MMU

2016-02-14 Thread David kiarie
On Sun, Feb 14, 2016 at 4:02 PM, Marcel Apfelbaum
 wrote:
> On 01/18/2016 05:25 PM, David Kiarie wrote:
>>
>> Support AMD IO MMU emulation in q35 and piix chipsets
>>
>> Signed-off-by: David Kiarie 
>> ---
>>   hw/pci-host/piix.c | 11 +++
>>   hw/pci-host/q35.c  | 14 --
>>   2 files changed, 23 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
>> index b0d7e31..3ba245d 100644
>> --- a/hw/pci-host/piix.c
>> +++ b/hw/pci-host/piix.c
>> @@ -35,6 +35,7 @@
>>   #include "hw/i386/ioapic.h"
>>   #include "qapi/visitor.h"
>>   #include "qemu/error-report.h"
>> +#include "hw/i386/amd_iommu.h"
>>
>>   /*
>>* I440FX chipset data sheet.
>> @@ -297,6 +298,16 @@ static void i440fx_pcihost_realize(DeviceState *dev,
>> Error **errp)
>>
>>   sysbus_add_io(sbd, 0xcfc, >data_mem);
>>   sysbus_init_ioports(sbd, 0xcfc, 4);
>> +
>> +/* AMD IOMMU (AMD-Vi) */
>> +if (g_strcmp0(object_property_get_str(qdev_get_machine(), "iommu",
>> NULL),
>> +  "amd") == 0) {
>
>
> Hi,
>
> Minor comments, here you can use the same qdev_get_machine())->iommu as used
> below
> and the same AMD_IOMMU_STR instead of "amd".
>
> Do I understand correctly that we can have an AMD IOMMU working on an i440fx
> machine (non PCI Express)?

Well, we could say, it worked - then because I didn't have any
interrupts yet but I wont work anymore since am going to add an
interrupt with event logging.

Will resend, as soon as possible.

>
> Thanks,
> Marcel
>
>
>> +AMDIOMMUState *iommu_state;
>> +PCIDevice *iommu;
>> +iommu = pci_create_simple(s->bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
>> +iommu_state = AMD_IOMMU_DEVICE(iommu);
>> +pci_setup_iommu(s->bus, bridge_host_amd_iommu, iommu_state);
>> +}
>>   }
>>
>>   static void i440fx_realize(PCIDevice *dev, Error **errp)
>> diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
>> index 1fb4707..0c60e3c 100644
>> --- a/hw/pci-host/q35.c
>> +++ b/hw/pci-host/q35.c
>> @@ -30,6 +30,7 @@
>>   #include "hw/hw.h"
>>   #include "hw/pci-host/q35.h"
>>   #include "qapi/visitor.h"
>> +#include "hw/i386/amd_iommu.h"
>>
>>
>> /
>>* Q35 host
>> @@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
>>mch->pci_address_space, >pam_regions[i+1],
>>PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
>>   }
>> -/* Intel IOMMU (VT-d) */
>> -if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
>> +
>> +if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR) ==
>> 0) {
>> +/* Intel IOMMU (VT-d) */
>>   mch_init_dmar(mch);
>> +} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu,
>> AMD_IOMMU_STR)
>> +   == 0) {
>> +AMDIOMMUState *iommu_state;
>> +PCIDevice *iommu;
>> +PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
>> +iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
>> +iommu_state = AMD_IOMMU_DEVICE(iommu);
>> +pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
>>   }
>>   }
>>
>>
>



Re: [Qemu-devel] [PATCH 2/3] i.MX: Add the Freescale SPI Controller

2016-02-14 Thread Jean-Christophe DUBOIS

Le 14/02/2016 12:52, mar.krzeminski a écrit :

Hello,

W dniu 13.02.2016 o 17:06, Jean-Christophe Dubois pisze:

Signed-off-by: Jean-Christophe Dubois 
---
  hw/ssi/Makefile.objs |   1 +
  hw/ssi/imx_spi.c | 449 
+++

  include/hw/ssi/imx_spi.h | 104 +++
  3 files changed, 554 insertions(+)
  create mode 100644 hw/ssi/imx_spi.c
  create mode 100644 include/hw/ssi/imx_spi.h

diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
index 9555825..fcbb79e 100644
--- a/hw/ssi/Makefile.objs
+++ b/hw/ssi/Makefile.objs
@@ -4,3 +4,4 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
obj-$(CONFIG_OMAP) += omap_spi.o
+obj-$(CONFIG_IMX) += imx_spi.o
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
new file mode 100644
index 000..9f7f4fe
--- /dev/null
+++ b/hw/ssi/imx_spi.c
@@ -0,0 +1,449 @@
+/*
+ * IMX SPI Controller
+ *
+ * Copyright (c) 2016 Jean-Christophe Dubois 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 
or later.

+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw/ssi/imx_spi.h"
+#include "sysemu/sysemu.h"
+
+#ifndef DEBUG_IMX_SPI
+#define DEBUG_IMX_SPI 0
+#endif
+
+#define DPRINTF(fmt, args...) \
+do { \
+if (DEBUG_IMX_SPI) { \
+fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SPI, \
+ __func__, ##args); \
+} \
+} while (0)
+
+static char const *imx_spi_reg_name(uint32_t reg)
+{
+static char unknown[20];
+
+switch (reg) {
+case ECSPI_RXDATA:
+return  "ECSPI_RXDATA";
+case ECSPI_TXDATA:
+return  "ECSPI_TXDATA";
+case ECSPI_CONREG:
+return  "ECSPI_CONREG";
+case ECSPI_CONFIGREG:
+return  "ECSPI_CONFIGREG";
+case ECSPI_INTREG:
+return  "ECSPI_INTREG";
+case ECSPI_DMAREG:
+return  "ECSPI_DMAREG";
+case ECSPI_STATREG:
+return  "ECSPI_STATREG";
+case ECSPI_PERIODREG:
+return  "ECSPI_PERIODREG";
+case ECSPI_TESTREG:
+return  "ECSPI_TESTREG";
+case ECSPI_MSGDATA:
+return  "ECSPI_MSGDATA";
+default:
+sprintf(unknown, "%d ?", reg);
+return unknown;
+}
+}
+
+static const VMStateDescription vmstate_imx_spi = {
+.name = TYPE_IMX_SPI,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_FIFO32(tx_fifo, IMXSPIState),
+VMSTATE_FIFO32(rx_fifo, IMXSPIState),
+VMSTATE_UINT32_ARRAY(regs, IMXSPIState, ECSPI_MAX),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx_spi_txfifo_reset(IMXSPIState *s)
+{
+fifo32_reset(>tx_fifo);
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
+}
+
+static void imx_spi_rxfifo_reset(IMXSPIState *s)
+{
+fifo32_reset(>rx_fifo);
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RO;
+}
+
+static void imx_spi_update_irq(IMXSPIState *s)
+{
+int level;
+
+if (fifo32_is_empty(>rx_fifo)) {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
+} else {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RR;
+}
+
+if (fifo32_is_full(>rx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RF;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
+}
+
+if (fifo32_is_empty(>tx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TE;
+}
+
+if (fifo32_is_full(>tx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TF;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
+}
+
+level = s->regs[ECSPI_STATREG] & s->regs[ECSPI_INTREG] ? 1 : 0;
+
+if (s->previous_level != level) {
+DPRINTF("setting IRQ a level %d\n", level);
+s->previous_level = level;
+qemu_set_irq(s->irq, level);
+}
+
+DPRINTF("IRQ level is %d\n", level);
+}
+
+static uint8_t imx_spi_selected_channel(IMXSPIState *s)
+{
+return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_SELECT);
+}
+
+static uint32_t imx_spi_burst_length(IMXSPIState *s)
+{
+return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_BURST_LENGTH) 
+ 1;

+}
+
+static bool imx_spi_is_enabled(IMXSPIState *s)
+{
+return (s->regs[ECSPI_CONREG] & ECSPI_CONREG_EN) ? true : false;
+}
+
+static bool imx_spi_channel_is_master(IMXSPIState *s)
+{
+uint8_t mode = EXTRACT(s->regs[ECSPI_CONREG], 
ECSPI_CONREG_CHANNEL_MODE);

+
+return (mode & (1 << imx_spi_selected_channel(s))) ? true : false;
+}
+
+static bool imx_spi_is_multiple_master_burst(IMXSPIState *s)
+{
+uint8_t wave = EXTRACT(s->regs[ECSPI_CONFIGREG], 
ECSPI_CONFIGREG_SS_CTL);

+
+return imx_spi_channel_is_master(s) &&
+   !(s->regs[ECSPI_CONREG] 

[Qemu-devel] [PATCH 1/8] block-migration: acquire AioContext as necessary

2016-02-14 Thread Paolo Bonzini
This is needed because dataplane will run during block migration as well.

The block device migration code is quite liberal in taking the iothread
mutex.  For simplicity, keep it the same way, even though one could
actually choose between the BQL (for regular BlockDriverStates) and
the AioContext (for dataplane BlockDriverStates).  When the block layer
is made fully thread safe, aio_context_acquire shall go away altogether.

Signed-off-by: Paolo Bonzini 
---
 migration/block.c | 61 ---
 1 file changed, 49 insertions(+), 12 deletions(-)

diff --git a/migration/block.c b/migration/block.c
index a444058..6dd2327 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -60,9 +60,15 @@ typedef struct BlkMigDevState {
 int64_t cur_sector;
 int64_t cur_dirty;
 
-/* Protected by block migration lock.  */
+/* Data in the aio_bitmap is protected by block migration lock.
+ * Allocation and free happen during setup and cleanup respectively.
+ */
 unsigned long *aio_bitmap;
+
+/* Protected by block migration lock.  */
 int64_t completed_sectors;
+
+/* Protected by iothread lock / AioContext.  */
 BdrvDirtyBitmap *dirty_bitmap;
 Error *blocker;
 } BlkMigDevState;
@@ -100,7 +106,7 @@ typedef struct BlkMigState {
 int prev_progress;
 int bulk_completed;
 
-/* Lock must be taken _inside_ the iothread lock.  */
+/* Lock must be taken _inside_ the iothread lock and any AioContexts.  */
 QemuMutex lock;
 } BlkMigState;
 
@@ -264,11 +270,13 @@ static int mig_save_device_bulk(QEMUFile *f, 
BlkMigDevState *bmds)
 
 if (bmds->shared_base) {
 qemu_mutex_lock_iothread();
+aio_context_acquire(bdrv_get_aio_context(bs));
 while (cur_sector < total_sectors &&
!bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
   _sectors)) {
 cur_sector += nr_sectors;
 }
+aio_context_release(bdrv_get_aio_context(bs));
 qemu_mutex_unlock_iothread();
 }
 
@@ -302,11 +310,21 @@ static int mig_save_device_bulk(QEMUFile *f, 
BlkMigDevState *bmds)
 block_mig_state.submitted++;
 blk_mig_unlock();
 
+/* We do not know if bs is under the main thread (and thus does
+ * not acquire the AioContext when doing AIO) or rather under
+ * dataplane.  Thus acquire both the iothread mutex and the
+ * AioContext.
+ *
+ * This is ugly and will disappear when we make bdrv_* thread-safe,
+ * without the need to acquire the AioContext.
+ */
 qemu_mutex_lock_iothread();
+aio_context_acquire(bdrv_get_aio_context(bmds->bs));
 blk->aiocb = bdrv_aio_readv(bs, cur_sector, >qiov,
 nr_sectors, blk_mig_read_cb, blk);
 
 bdrv_reset_dirty_bitmap(bmds->dirty_bitmap, cur_sector, nr_sectors);
+aio_context_release(bdrv_get_aio_context(bmds->bs));
 qemu_mutex_unlock_iothread();
 
 bmds->cur_sector = cur_sector + nr_sectors;
@@ -321,8 +339,9 @@ static int set_dirty_tracking(void)
 int ret;
 
 QSIMPLEQ_FOREACH(bmds, _mig_state.bmds_list, entry) {
+/* Creating/dropping dirty bitmaps only requires the big QEMU lock.  */
 bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE,
   NULL, NULL);
 if (!bmds->dirty_bitmap) {
 ret = -errno;
 goto fail;
@@ -332,11 +352,14 @@ static int set_dirty_tracking(void)
 return ret;
 }
 
+/* Called with iothread lock taken.  */
+
 static void unset_dirty_tracking(void)
 {
 BlkMigDevState *bmds;
 
 QSIMPLEQ_FOREACH(bmds, _mig_state.bmds_list, entry) {
+/* Creating/dropping dirty bitmaps only requires the big QEMU lock.  */
 bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
 }
 }
@@ -444,7 +470,7 @@ static void blk_mig_reset_dirty_cursor(void)
 }
 }
 
-/* Called with iothread lock taken.  */
+/* Called with iothread lock and AioContext taken.  */
 
 static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
  int is_async)
@@ -527,7 +553,9 @@ static int blk_mig_save_dirty_block(QEMUFile *f, int 
is_async)
 int ret = 1;
 
 QSIMPLEQ_FOREACH(bmds, _mig_state.bmds_list, entry) {
+aio_context_acquire(bdrv_get_aio_context(bmds->bs));
 ret = mig_save_device_dirty(f, bmds, is_async);
+aio_context_release(bdrv_get_aio_context(bmds->bs));
 if (ret <= 0) {
 break;
 }
@@ -585,7 +613,9 @@ static int64_t get_remaining_dirty(void)
 int64_t dirty = 0;
 
 QSIMPLEQ_FOREACH(bmds, _mig_state.bmds_list, entry) {
+aio_context_acquire(bdrv_get_aio_context(bmds->bs));
 dirty += bdrv_get_dirty_count(bmds->dirty_bitmap);
+aio_context_release(bdrv_get_aio_context(bmds->bs));
 }
 
 return dirty << BDRV_SECTOR_BITS;
@@ -597,21 +627,28 

[Qemu-devel] [PATCH 2/8] vring: make vring_enable_notification return void

2016-02-14 Thread Paolo Bonzini
Make the API more similar to the regular virtqueue API.  This will
help when modifying the code to not use vring.c anymore.

Signed-off-by: Paolo Bonzini 
---
 hw/block/dataplane/virtio-blk.c | 3 ++-
 hw/virtio/dataplane/vring.c | 3 +--
 include/hw/virtio/dataplane/vring.h | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 0d99781..03b81bc 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -128,7 +128,8 @@ static void handle_notify(EventNotifier *e)
 /* Re-enable guest->host notifies and stop processing the vring.
  * But if the guest has snuck in more descriptors, keep processing.
  */
-if (vring_enable_notification(s->vdev, >vring)) {
+vring_enable_notification(s->vdev, >vring);
+if (!vring_more_avail(s->vdev, >vring)) {
 break;
 }
 } else { /* fatal error */
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 4308d9f..157e8b8 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -175,7 +175,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring 
*vring)
  *
  * Return true if the vring is empty, false if there are more requests.
  */
-bool vring_enable_notification(VirtIODevice *vdev, Vring *vring)
+void vring_enable_notification(VirtIODevice *vdev, Vring *vring)
 {
 if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
 vring_avail_event(>vr) = vring->vr.avail->idx;
@@ -183,7 +183,6 @@ bool vring_enable_notification(VirtIODevice *vdev, Vring 
*vring)
 vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
 }
 smp_mb(); /* ensure update is seen before reading avail_idx */
-return !vring_more_avail(vdev, vring);
 }
 
 /* This is stolen from linux/drivers/vhost/vhost.c:vhost_notify() */
diff --git a/include/hw/virtio/dataplane/vring.h 
b/include/hw/virtio/dataplane/vring.h
index e80985e..e1c2a65 100644
--- a/include/hw/virtio/dataplane/vring.h
+++ b/include/hw/virtio/dataplane/vring.h
@@ -42,7 +42,7 @@ static inline void vring_set_broken(Vring *vring)
 bool vring_setup(Vring *vring, VirtIODevice *vdev, int n);
 void vring_teardown(Vring *vring, VirtIODevice *vdev, int n);
 void vring_disable_notification(VirtIODevice *vdev, Vring *vring);
-bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
+void vring_enable_notification(VirtIODevice *vdev, Vring *vring);
 bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
 void *vring_pop(VirtIODevice *vdev, Vring *vring, size_t sz);
 void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem,
-- 
1.8.3.1





[Qemu-devel] [PATCH 6/8] virtio-blk: do not use vring in dataplane

2016-02-14 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 hw/block/dataplane/virtio-blk.c | 112 +---
 hw/block/dataplane/virtio-blk.h |   1 +
 hw/block/virtio-blk.c   |  49 +++---
 include/hw/virtio/virtio-blk.h  |   3 --
 4 files changed, 19 insertions(+), 146 deletions(-)

diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index cc521c1..36f3d2b 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -18,8 +18,6 @@
 #include "qemu/thread.h"
 #include "qemu/error-report.h"
 #include "hw/virtio/virtio-access.h"
-#include "hw/virtio/dataplane/vring.h"
-#include "hw/virtio/dataplane/vring-accessors.h"
 #include "sysemu/block-backend.h"
 #include "hw/virtio/virtio-blk.h"
 #include "virtio-blk.h"
@@ -35,7 +33,7 @@ struct VirtIOBlockDataPlane {
 VirtIOBlkConf *conf;
 
 VirtIODevice *vdev;
-Vring vring;/* virtqueue vring */
+VirtQueue *vq;  /* virtqueue vring */
 EventNotifier *guest_notifier;  /* irq */
 QEMUBH *bh; /* bh for guest notification */
 
@@ -48,94 +46,26 @@ struct VirtIOBlockDataPlane {
  */
 IOThread *iothread;
 AioContext *ctx;
-EventNotifier host_notifier;/* doorbell */
 
 /* Operation blocker on BDS */
 Error *blocker;
-void (*saved_complete_request)(struct VirtIOBlockReq *req,
-   unsigned char status);
 };
 
 /* Raise an interrupt to signal guest, if necessary */
-static void notify_guest(VirtIOBlockDataPlane *s)
+void virtio_blk_data_plane_notify(VirtIOBlockDataPlane *s)
 {
-if (!vring_should_notify(s->vdev, >vring)) {
-return;
-}
-
-event_notifier_set(s->guest_notifier);
+qemu_bh_schedule(s->bh);
 }
 
 static void notify_guest_bh(void *opaque)
 {
 VirtIOBlockDataPlane *s = opaque;
 
-notify_guest(s);
-}
-
-static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
-{
-VirtIOBlockDataPlane *s = req->dev->dataplane;
-stb_p(>in->status, status);
-
-vring_push(s->vdev, >dev->dataplane->vring, >elem, req->in_len);
-
-/* Suppress notification to guest by BH and its scheduled
- * flag because requests are completed as a batch after io
- * plug & unplug is introduced, and the BH can still be
- * executed in dataplane aio context even after it is
- * stopped, so needn't worry about notification loss with BH.
- */
-qemu_bh_schedule(s->bh);
-}
-
-static void handle_notify(EventNotifier *e)
-{
-VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
-   host_notifier);
-VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
-
-event_notifier_test_and_clear(>host_notifier);
-blk_io_plug(s->conf->conf.blk);
-for (;;) {
-MultiReqBuffer mrb = {};
-
-/* Disable guest->host notifies to avoid unnecessary vmexits */
-vring_disable_notification(s->vdev, >vring);
-
-for (;;) {
-VirtIOBlockReq *req = vring_pop(s->vdev, >vring,
-sizeof(VirtIOBlockReq));
-
-if (req == NULL) {
-break; /* no more requests */
-}
-
-virtio_blk_init_request(vblk, req);
-trace_virtio_blk_data_plane_process_request(s, req->elem.out_num,
-req->elem.in_num,
-req->elem.index);
-
-virtio_blk_handle_request(req, );
-}
-
-if (mrb.num_reqs) {
-virtio_blk_submit_multireq(s->conf->conf.blk, );
-}
-
-if (likely(!vring_more_avail(s->vdev, >vring))) { /* vring emptied 
*/
-/* Re-enable guest->host notifies and stop processing the vring.
- * But if the guest has snuck in more descriptors, keep processing.
- */
-vring_enable_notification(s->vdev, >vring);
-if (!vring_more_avail(s->vdev, >vring)) {
-break;
-}
-} else { /* fatal error */
-break;
-}
+if (!virtio_should_notify(s->vdev, s->vq)) {
+return;
 }
-blk_io_unplug(s->conf->conf.blk);
+
+event_notifier_set(s->guest_notifier);
 }
 
 static void data_plane_set_up_op_blockers(VirtIOBlockDataPlane *s)
@@ -260,7 +190,6 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
 VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
-VirtQueue *vq;
 int r;
 
 if (vblk->dataplane_started || s->starting) {
@@ -268,11 +197,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 }
 
 s->starting = true;
-
-vq = virtio_get_queue(s->vdev, 0);
-if (!vring_setup(>vring, s->vdev, 0)) {
-goto fail_vring;
-}
+

[Qemu-devel] [PATCH 5/8] virtio-blk: fix "disabled data plane" mode

2016-02-14 Thread Paolo Bonzini
In disabled mode, virtio-blk dataplane seems to be enabled, but flow
actually goes through the normal virtio path.  This patch simplifies a bit
the handling of disabled mode.  In disabled mode, virtio_blk_handle_output
might be called even if s->dataplane is not NULL.

This is a bit tricky, because the current check for s->dataplane will
always trigger, causing a continuous stream of calls to
virtio_blk_data_plane_start.  Unfortunately, these calls will not
do anything.  To fix this, set the "started" flag even in disabled
mode, and skip virtio_blk_data_plane_start if the started flag is true.
The resulting changes also prepare the code for the next patch, were
virtio-blk dataplane will reuse the same virtio_blk_handle_output function
as "regular" virtio-blk.

Because struct VirtIOBlockDataPlane is opaque in virtio-blk.c, we have
to move s->dataplane->started inside struct VirtIOBlock.

Signed-off-by: Paolo Bonzini 
---
 hw/block/dataplane/virtio-blk.c | 21 +
 hw/block/virtio-blk.c   |  2 +-
 include/hw/virtio/virtio-blk.h  |  1 +
 3 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 03b81bc..cc521c1 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -28,7 +28,6 @@
 #include "qom/object_interfaces.h"
 
 struct VirtIOBlockDataPlane {
-bool started;
 bool starting;
 bool stopping;
 bool disabled;
@@ -264,11 +263,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 VirtQueue *vq;
 int r;
 
-if (s->started || s->disabled) {
-return;
-}
-
-if (s->starting) {
+if (vblk->dataplane_started || s->starting) {
 return;
 }
 
@@ -300,7 +295,7 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 vblk->complete_request = complete_request_vring;
 
 s->starting = false;
-s->started = true;
+vblk->dataplane_started = true;
 trace_virtio_blk_data_plane_start(s);
 
 blk_set_aio_context(s->conf->conf.blk, s->ctx);
@@ -319,9 +314,10 @@ void virtio_blk_data_plane_start(VirtIOBlockDataPlane *s)
 k->set_guest_notifiers(qbus->parent, 1, false);
   fail_guest_notifiers:
 vring_teardown(>vring, s->vdev, 0);
-s->disabled = true;
   fail_vring:
+s->disabled = true;
 s->starting = false;
+vblk->dataplane_started = true;
 }
 
 /* Context: QEMU global mutex held */
@@ -331,13 +327,14 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
 VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
 
+if (!vblk->dataplane_started || s->stopping) {
+return;
+}
 
 /* Better luck next time. */
 if (s->disabled) {
 s->disabled = false;
-return;
-}
-if (!s->started || s->stopping) {
+vblk->dataplane_started = false;
 return;
 }
 s->stopping = true;
@@ -364,6 +361,6 @@ void virtio_blk_data_plane_stop(VirtIOBlockDataPlane *s)
 /* Clean up guest notifier (irq) */
 k->set_guest_notifiers(qbus->parent, 1, false);
 
-s->started = false;
+vblk->dataplane_started = false;
 s->stopping = false;
 }
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index c427698..e04c8f5 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -589,7 +589,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, 
VirtQueue *vq)
 /* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
  * dataplane here instead of waiting for .set_status().
  */
-if (s->dataplane) {
+if (s->dataplane && !s->dataplane_started) {
 virtio_blk_data_plane_start(s->dataplane);
 return;
 }
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index 199bb0e..781969d 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -56,6 +56,7 @@ typedef struct VirtIOBlock {
 /* Function to push to vq and notify guest */
 void (*complete_request)(struct VirtIOBlockReq *req, unsigned char status);
 Notifier migration_state_notifier;
+bool dataplane_started;
 struct VirtIOBlockDataPlane *dataplane;
 } VirtIOBlock;
 
-- 
1.8.3.1





[Qemu-devel] [PATCH 4/8] virtio: export vring_notify as virtio_should_notify

2016-02-14 Thread Paolo Bonzini
Virtio dataplane needs to trigger the irq manually through the
guest notifier.  Export virtio_should_notify so that it can be
used around event_notifier_set.

Signed-off-by: Paolo Bonzini 
---
 hw/virtio/virtio.c | 4 ++--
 include/hw/virtio/virtio.h | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 3a5cca4..abb97f4 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1162,7 +1162,7 @@ void virtio_irq(VirtQueue *vq)
 virtio_notify_vector(vq->vdev, vq->vector);
 }
 
-static bool vring_notify(VirtIODevice *vdev, VirtQueue *vq)
+bool virtio_should_notify(VirtIODevice *vdev, VirtQueue *vq)
 {
 uint16_t old, new;
 bool v;
@@ -1187,7 +1187,7 @@ static bool vring_notify(VirtIODevice *vdev, VirtQueue 
*vq)
 
 void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
 {
-if (!vring_notify(vdev, vq)) {
+if (!virtio_should_notify(vdev, vq)) {
 return;
 }
 
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 4ce01a1..5884228 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -162,6 +162,7 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int 
*in_bytes,
unsigned int *out_bytes,
unsigned max_in_bytes, unsigned max_out_bytes);
 
+bool virtio_should_notify(VirtIODevice *vdev, VirtQueue *vq);
 void virtio_notify(VirtIODevice *vdev, VirtQueue *vq);
 
 void virtio_save(VirtIODevice *vdev, QEMUFile *f);
-- 
1.8.3.1





[Qemu-devel] [PATCHv7 2/9] slirp: Adding ICMPv6 error sending

2016-02-14 Thread Samuel Thibault
From: Yann Bordenave 

Disambiguation : icmp_error is renamed into icmp_send_error, since it
doesn't manage errors, but only sends ICMP Error messages.

Adding icmp6_send_error to send ICMPv6 Error messages. This function is
simpler than the v4 version.
Adding some calls in various functions to send ICMP errors, when a
received packet is too big, or when its hop limit is 0.

Signed-off-by: Yann Bordenave 
Signed-off-by: Samuel Thibault 
---
 slirp/ip6_icmp.c  | 64 +++
 slirp/ip6_icmp.h  | 10 +
 slirp/ip6_input.c | 13 ++-
 slirp/ip_icmp.c   | 12 +--
 slirp/ip_icmp.h   |  4 ++--
 slirp/ip_input.c  |  8 +++
 slirp/socket.c|  4 ++--
 slirp/tcp_input.c |  2 +-
 slirp/udp.c   |  3 ++-
 9 files changed, 99 insertions(+), 21 deletions(-)

diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c
index 029d297..1cc65db 100644
--- a/slirp/ip6_icmp.c
+++ b/slirp/ip6_icmp.c
@@ -59,6 +59,70 @@ static void icmp6_send_echoreply(struct mbuf *m, Slirp 
*slirp, struct ip6 *ip,
 ip6_output(NULL, t, 0);
 }
 
+void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
+{
+Slirp *slirp = m->slirp;
+struct mbuf *t;
+struct ip6 *ip = mtod(m, struct ip6 *);
+
+char addrstr[INET6_ADDRSTRLEN];
+DEBUG_CALL("icmp_send_error");
+DEBUG_ARGS((dfd, " type = %d, code = %d\n", type, code));
+
+if (IN6_IS_ADDR_MULTICAST(>ip_src) ||
+IN6_IS_ADDR_UNSPECIFIED(>ip_src)) {
+/* TODO icmp error? */
+return;
+}
+
+t = m_get(slirp);
+
+/* IPv6 packet */
+struct ip6 *rip = mtod(t, struct ip6 *);
+rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
+rip->ip_dst = ip->ip_src;
+inet_ntop(AF_INET6, >ip_dst, addrstr, INET6_ADDRSTRLEN);
+DEBUG_ARG("target = %s", addrstr);
+
+rip->ip_nh = IPPROTO_ICMPV6;
+const int error_data_len = min(m->m_len,
+IF_MTU - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN));
+rip->ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len);
+t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
+
+/* ICMPv6 packet */
+t->m_data += sizeof(struct ip6);
+struct icmp6 *ricmp = mtod(t, struct icmp6 *);
+ricmp->icmp6_type = type;
+ricmp->icmp6_code = code;
+ricmp->icmp6_cksum = 0;
+
+switch (type) {
+case ICMP6_UNREACH:
+case ICMP6_TIMXCEED:
+ricmp->icmp6_err.unused = 0;
+break;
+case ICMP6_TOOBIG:
+ricmp->icmp6_err.mtu = htonl(IF_MTU);
+break;
+case ICMP6_PARAMPROB:
+/* TODO: Handle this case */
+break;
+default:
+g_assert_not_reached();
+break;
+}
+t->m_data += ICMP6_ERROR_MINLEN;
+memcpy(t->m_data, m->m_data, error_data_len);
+
+/* Checksum */
+t->m_data -= ICMP6_ERROR_MINLEN;
+t->m_data -= sizeof(struct ip6);
+ricmp->icmp6_cksum = ip6_cksum(t);
+
+ip6_output(NULL, t, 0);
+}
+
 /*
  * Send NDP Router Advertisement
  */
diff --git a/slirp/ip6_icmp.h b/slirp/ip6_icmp.h
index b2c40d6..9460bf8 100644
--- a/slirp/ip6_icmp.h
+++ b/slirp/ip6_icmp.h
@@ -19,6 +19,12 @@ struct icmp6_echo { /* Echo Messages */
 uint16_t seq_num;
 };
 
+union icmp6_error_body {
+uint32_t unused;
+uint32_t pointer;
+uint32_t mtu;
+};
+
 /*
  * NDP Messages
  */
@@ -82,6 +88,7 @@ struct icmp6 {
 uint8_t icmp6_code; /* type sub code */
 uint16_ticmp6_cksum;/* ones complement cksum of struct */
 union {
+union icmp6_error_body error_body;
 struct icmp6_echo echo;
 struct ndp_rs ndp_rs;
 struct ndp_ra ndp_ra;
@@ -89,6 +96,7 @@ struct icmp6 {
 struct ndp_na ndp_na;
 struct ndp_redirect ndp_redirect;
 } icmp6_body;
+#define icmp6_err icmp6_body.error_body
 #define icmp6_echo icmp6_body.echo
 #define icmp6_nrs icmp6_body.ndp_rs
 #define icmp6_nra icmp6_body.ndp_ra
@@ -98,6 +106,7 @@ struct icmp6 {
 } QEMU_PACKED;
 
 #define ICMP6_MINLEN4
+#define ICMP6_ERROR_MINLEN  8
 #define ICMP6_ECHO_MINLEN   8
 #define ICMP6_NDP_RS_MINLEN 8
 #define ICMP6_NDP_RA_MINLEN 16
@@ -197,6 +206,7 @@ struct ndpopt {
 void icmp6_init(Slirp *slirp);
 void icmp6_cleanup(Slirp *slirp);
 void icmp6_input(struct mbuf *);
+void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code);
 void ndp_send_ra(Slirp *slirp);
 void ndp_send_ns(Slirp *slirp, struct in6_addr addr);
 
diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c
index df249f1..b6a438d 100644
--- a/slirp/ip6_input.c
+++ b/slirp/ip6_input.c
@@ -39,9 +39,14 @@ void ip6_input(struct mbuf *m)
 goto bad;
 }
 
+if (ntohs(ip6->ip_pl) > IF_MTU) {
+icmp6_send_error(m, ICMP6_TOOBIG, 0);
+goto bad;
+}
+
 /* check ip_ttl for a correct ICMP reply */
 if (ip6->ip_hl == 0) {
-/*icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");*/
+icmp6_send_error(m, ICMP6_TIMXCEED, 

[Qemu-devel] [PATCHv7 4/9] slirp: Factorizing tcpiphdr structure with an union

2016-02-14 Thread Samuel Thibault
From: Guillaume Subiron 

This patch factorizes the tcpiphdr structure to put the IPv4 fields in
an union, for addition of version 6 in further patch.
Using some macros, retrocompatibility of the existing code is assured.

This patch also fixes the SLIRP_MSIZE and margin computation in various
functions, and makes them compatible with the new tcpiphdr structure,
whose size will be bigger than sizeof(struct tcphdr) + sizeof(struct ip)

Signed-off-by: Guillaume Subiron 
Signed-off-by: Samuel Thibault 
---
 slirp/if.h |  4 ++--
 slirp/mbuf.c   |  3 ++-
 slirp/slirp.c  | 15 ---
 slirp/socket.c | 13 -
 slirp/tcp_input.c  | 31 ---
 slirp/tcp_output.c | 18 +-
 slirp/tcp_subr.c   | 31 ++-
 slirp/tcpip.h  | 31 +++
 8 files changed, 102 insertions(+), 44 deletions(-)

diff --git a/slirp/if.h b/slirp/if.h
index 3327023..c7a5c57 100644
--- a/slirp/if.h
+++ b/slirp/if.h
@@ -17,7 +17,7 @@
 #define IF_MRU 1500
 #defineIF_COMP IF_AUTOCOMP /* Flags for compression */
 
-/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
-#define IF_MAXLINKHDR (2 + 14 + 40)
+/* 2 for alignment, 14 for ethernet */
+#define IF_MAXLINKHDR (2 + ETH_HLEN)
 
 #endif
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index c959758..f081c69 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -24,7 +24,8 @@
  * Find a nice value for msize
  * XXX if_maxlinkhdr already in mtu
  */
-#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6)
+#define SLIRP_MSIZE\
+(offsetof(struct mbuf, m_dat) + IF_MAXLINKHDR + TCPIPHDR_DELTA + IF_MTU)
 
 void
 m_init(Slirp *slirp)
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 5f42ada..c2c4597 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -754,15 +754,16 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int 
pkt_len)
 m = m_get(slirp);
 if (!m)
 return;
-/* Note: we add to align the IP header */
-if (M_FREEROOM(m) < pkt_len + 2) {
-m_inc(m, pkt_len + 2);
+/* Note: we add 2 to align the IP header on 4 bytes,
+ * and add the margin for the tcpiphdr overhead  */
+if (M_FREEROOM(m) < pkt_len + TCPIPHDR_DELTA + 2) {
+m_inc(m, pkt_len + TCPIPHDR_DELTA + 2);
 }
-m->m_len = pkt_len + 2;
-memcpy(m->m_data + 2, pkt, pkt_len);
+m->m_len = pkt_len + TCPIPHDR_DELTA + 2;
+memcpy(m->m_data + TCPIPHDR_DELTA + 2, pkt, pkt_len);
 
-m->m_data += 2 + ETH_HLEN;
-m->m_len -= 2 + ETH_HLEN;
+m->m_data += TCPIPHDR_DELTA + 2 + ETH_HLEN;
+m->m_len -= TCPIPHDR_DELTA + 2 + ETH_HLEN;
 
 if (proto == ETH_P_IP) {
 ip_input(m);
diff --git a/slirp/socket.c b/slirp/socket.c
index b79ddec..d4b02c8 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -483,7 +483,18 @@ sorecvfrom(struct socket *so)
  if (!m) {
  return;
  }
- m->m_data += IF_MAXLINKHDR;
+ switch (so->so_ffamily) {
+ case AF_INET:
+ m->m_data += IF_MAXLINKHDR + sizeof(struct udpiphdr);
+ break;
+ case AF_INET6:
+ m->m_data += IF_MAXLINKHDR + sizeof(struct ip6)
++ sizeof(struct udphdr);
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
 
  /*
   * XXX Shouldn't FIONREAD packets destined for port 53,
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 5f845da..26b0c8b 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -256,11 +256,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
}
slirp = m->slirp;
 
-   /*
-* Get IP and TCP header together in first mbuf.
-* Note: IP leaves IP header in first mbuf.
-*/
-   ti = mtod(m, struct tcpiphdr *);
if (iphlen > sizeof(struct ip )) {
  ip_stripoptions(m, (struct mbuf *)0);
  iphlen=sizeof(struct ip );
@@ -277,14 +272,28 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
save_ip.ip_len+= iphlen;
 
/*
+* Get IP and TCP header together in first mbuf.
+* Note: IP leaves IP header in first mbuf.
+*/
+   m->m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip)
++ sizeof(struct tcphdr));
+   m->m_len += sizeof(struct tcpiphdr) - (sizeof(struct ip)
+   + sizeof(struct tcphdr));
+   ti = mtod(m, struct tcpiphdr *);
+
+   /*
 * Checksum extended TCP header and data.
 */
-   tlen = ((struct ip *)ti)->ip_len;
-tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
-memset(>ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
-   ti->ti_x1 = 

[Qemu-devel] [PATCHv8 0/9] slirp: Adding IPv6 support to Qemu -net user mode

2016-02-14 Thread Samuel Thibault
Hello,

This is another respin of IPv6 in Qemu -net user mode.


These patches add ICMPv6, NDP, and make UDP and TCP compatible with
IPv6.


Difference with version 7 is:
- Fix overflow detection in strtol call
- Fix formatting and typos
- Use SLIRP_ prefix for header protection
- Use grand instead of srand/rand
- Use standard macros instead of defining intermediate in6_multicast and 
in6_unspecified
- Pass pointers to in6_equal* instead of structs
- Use qemu_log_mask(LOG_GUEST_ERROR) for guest errors instead of error_report()
- Use bool type
- Avoid floating point operation
- Include qemu/osdep.h in new files.
- Move code to send NA to separate function
- Fix memory leak
- Fix missing save_ip in UDPv6
- Fix zero UDP checksum
- Use unreachable assertion instead of simple breaks when the socket type is 
not v4 or v6.
- Avoid duplicate ipv4/ipv6 header save.

Here is a summary of the patches:

Guillaume Subiron (7):
  slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration
  slirp: Adding IPv6 UDP support
  slirp: Factorizing tcpiphdr structure with an union
  slirp: Generalizing and neutralizing various TCP functions before
adding IPv6 stuff
  slirp: Reindent after refactoring
  slirp: Handle IPv6 in TCP functions
  slirp: Adding IPv6 address for DNS relay

Yann Bordenave (2):
  slirp: Adding ICMPv6 error sending
  qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6
addresses

 net/net.c   |  31 
 net/slirp.c |  50 ++-
 qapi-schema.json|  40 +++--
 qemu-options.hx |  18 ++-
 slirp/Makefile.objs |   6 +-
 slirp/cksum.c   |  25 
 slirp/if.c  |   2 +-
 slirp/if.h  |   4 +-
 slirp/ip6.h | 138 ++
 slirp/ip6_icmp.c| 411 
 slirp/ip6_icmp.h| 213 +++
 slirp/ip6_input.c   |  73 ++
 slirp/ip6_output.c  |  38 +
 slirp/ip_icmp.c |  12 +-
 slirp/ip_icmp.h |   4 +-
 slirp/ip_input.c|  10 +-
 slirp/libslirp.h|   8 +-
 slirp/mbuf.c|   3 +-
 slirp/ndp_table.c   |  84 +++
 slirp/slirp.c   |  79 --
 slirp/slirp.h   |  43 +-
 slirp/socket.c  |  54 ++-
 slirp/socket.h  |  13 ++
 slirp/tcp.h |   2 +
 slirp/tcp_input.c   | 181 ---
 slirp/tcp_output.c  |  51 +--
 slirp/tcp_subr.c| 114 +++
 slirp/tcp_timer.c   |   3 +-
 slirp/tcpip.h   |  40 -
 slirp/udp.c |   3 +-
 slirp/udp.h |   5 +
 slirp/udp6.c| 156 
 32 files changed, 1754 insertions(+), 160 deletions(-)
 create mode 100644 slirp/ip6.h
 create mode 100644 slirp/ip6_icmp.c
 create mode 100644 slirp/ip6_icmp.h
 create mode 100644 slirp/ip6_input.c
 create mode 100644 slirp/ip6_output.c
 create mode 100644 slirp/ndp_table.c
 create mode 100644 slirp/udp6.c

-- 
2.7.0




[Qemu-devel] [PATCHv7 3/9] slirp: Adding IPv6 UDP support

2016-02-14 Thread Samuel Thibault
From: Guillaume Subiron 

This adds the sin6 case in the fhost and lhost unions and related macros.
It adds udp6_input() and udp6_output().
It adds the IPv6 case in sorecvfrom().
Finally, udp_input() is called by ip6_input().

Signed-off-by: Guillaume Subiron 
Signed-off-by: Samuel Thibault 
---
 slirp/Makefile.objs |   2 +-
 slirp/ip6_input.c   |   2 +-
 slirp/socket.c  |   5 ++
 slirp/socket.h  |   6 ++
 slirp/udp.h |   5 ++
 slirp/udp6.c| 156 
 6 files changed, 174 insertions(+), 2 deletions(-)
 create mode 100644 slirp/udp6.c

diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
index 4e3a289..6748e4f 100644
--- a/slirp/Makefile.objs
+++ b/slirp/Makefile.objs
@@ -1,5 +1,5 @@
 common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
ip_input.o ip_output.o dnssearch.o
 common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
-common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o \
+common-obj-y += tcp_subr.o tcp_timer.o udp.o udp6.o bootp.o tftp.o arp_table.o 
\
 ndp_table.o
diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c
index b6a438d..9ca6d32 100644
--- a/slirp/ip6_input.c
+++ b/slirp/ip6_input.c
@@ -58,7 +58,7 @@ void ip6_input(struct mbuf *m)
 icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
 break;
 case IPPROTO_UDP:
-icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
+udp6_input(m);
 break;
 case IPPROTO_ICMPV6:
 icmp6_input(m);
diff --git a/slirp/socket.c b/slirp/socket.c
index 32b1ba3..b79ddec 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -541,7 +541,12 @@ sorecvfrom(struct socket *so)
   (struct sockaddr_in *) ,
   so->so_iptos);
break;
+   case AF_INET6:
+   udp6_output(so, m, (struct sockaddr_in6 *) ,
+   (struct sockaddr_in6 *) );
+   break;
default:
+   g_assert_not_reached();
break;
}
  } /* rx error */
diff --git a/slirp/socket.h b/slirp/socket.h
index bcebce1..e9c9b05 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -34,17 +34,23 @@ struct socket {
   union {   /* foreign host */
   struct sockaddr_storage ss;
   struct sockaddr_in sin;
+  struct sockaddr_in6 sin6;
   } fhost;
 #define so_faddr fhost.sin.sin_addr
 #define so_fport fhost.sin.sin_port
+#define so_faddr6 fhost.sin6.sin6_addr
+#define so_fport6 fhost.sin6.sin6_port
 #define so_ffamily fhost.ss.ss_family
 
   union {   /* local host */
   struct sockaddr_storage ss;
   struct sockaddr_in sin;
+  struct sockaddr_in6 sin6;
   } lhost;
 #define so_laddr lhost.sin.sin_addr
 #define so_lport lhost.sin.sin_port
+#define so_laddr6 lhost.sin6.sin6_addr
+#define so_lport6 lhost.sin6.sin6_port
 #define so_lfamily lhost.ss.ss_family
 
   uint8_t  so_iptos;   /* Type of service */
diff --git a/slirp/udp.h b/slirp/udp.h
index 2f9de38..10cc780 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -83,4 +83,9 @@ struct socket * udp_listen(Slirp *, uint32_t, u_int, 
uint32_t, u_int,
 int udp_output(struct socket *so, struct mbuf *m,
 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
 int iptos);
+
+void udp6_input(register struct mbuf *);
+int udp6_output(struct socket *so, struct mbuf *m,
+struct sockaddr_in6 *saddr, struct sockaddr_in6 *daddr);
+
 #endif
diff --git a/slirp/udp6.c b/slirp/udp6.c
new file mode 100644
index 000..6c0d55f
--- /dev/null
+++ b/slirp/udp6.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron
+ */
+
+#include "slirp.h"
+#include "qemu/osdep.h"
+#include "udp.h"
+
+void udp6_input(struct mbuf *m)
+{
+Slirp *slirp = m->slirp;
+struct ip6 *ip, save_ip;
+struct udphdr *uh;
+int hlen = sizeof(struct ip6);
+int len;
+struct socket *so;
+struct sockaddr_in6 lhost;
+
+DEBUG_CALL("udp6_input");
+DEBUG_ARG("m = %lx", (long)m);
+
+if (slirp->restricted) {
+goto bad;
+}
+
+ip = mtod(m, struct ip6 *);
+m->m_len -= hlen;
+m->m_data += hlen;
+uh = mtod(m, struct udphdr *);
+m->m_len += hlen;
+m->m_data -= hlen;
+
+if (ip6_cksum(m)) {
+goto bad;
+}
+
+len = ntohs((uint16_t)uh->uh_ulen);
+
+/*
+ * Make mbuf data length reflect UDP length.
+ * If not enough data to reflect UDP length, drop.
+ */
+if (ntohs(ip->ip_pl) != len) {
+if (len > ntohs(ip->ip_pl)) {
+goto bad;
+}
+m_adj(m, len - ntohs(ip->ip_pl));
+ip->ip_pl = htons(len);
+}
+
+/*
+ * Save a copy of the IP header in case we want restore it
+ * for sending an ICMP error message in response.
+ */
+

[Qemu-devel] [PATCHv7 9/9] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses

2016-02-14 Thread Samuel Thibault
From: Yann Bordenave 

This patch adds parameters to manage some new options in the qemu -net
command.
Slirp IPv6 address, network prefix, and DNS IPv6 address can be given in
argument to the qemu command.
Defaults parameters are respectively fec0::2, fec0::, /64 and fec0::3.

Signed-off-by: Yann Bordenave 
Signed-off-by: Samuel Thibault 
---
 net/net.c| 31 +++
 net/slirp.c  | 50 --
 qapi-schema.json | 40 ++--
 qemu-options.hx  | 18 --
 slirp/libslirp.h |  8 +---
 slirp/slirp.c| 16 +---
 6 files changed, 131 insertions(+), 32 deletions(-)

diff --git a/net/net.c b/net/net.c
index c5e414f..a097971 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1060,6 +1060,37 @@ int net_client_init(QemuOpts *opts, int is_netdev, Error 
**errp)
 int ret = -1;
 
 {
+/* Parse convenience option format ip6-net=fec0::0[/64] */
+const char *ip6_net = qemu_opt_get(opts, "ip6-net");
+
+if (ip6_net) {
+char buf[strlen(ip6_net) + 1];
+
+if (get_str_sep(buf, sizeof(buf), _net, '/') < 0) {
+/* Default 64bit prefix length.  */
+qemu_opt_set(opts, "ip6-prefix", ip6_net, _abort);
+qemu_opt_set_number(opts, "ip6-prefixlen", 64, _abort);
+} else {
+/* User-specified prefix length.  */
+unsigned long len;
+int err;
+
+qemu_opt_set(opts, "ip6-prefix", buf, _abort);
+err = qemu_strtoul(ip6_net, NULL, 10, );
+
+if (err) {
+error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+  "ip6-prefix", "a number");
+} else {
+qemu_opt_set_number(opts, "ip6-prefixlen", len,
+_abort);
+}
+}
+qemu_opt_unset(opts, "ip6-net");
+}
+}
+
+{
 OptsVisitor *ov = opts_visitor_new(opts);
 
 net_visit(opts_get_visitor(ov), is_netdev, , );
diff --git a/net/slirp.c b/net/slirp.c
index 6b51fbc..076dd27 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -135,17 +135,23 @@ static NetClientInfo net_slirp_info = {
 static int net_slirp_init(NetClientState *peer, const char *model,
   const char *name, int restricted,
   const char *vnetwork, const char *vhost,
+  const char *vprefix6, int vprefix6_len,
+  const char *vhost6,
   const char *vhostname, const char *tftp_export,
   const char *bootfile, const char *vdhcp_start,
-  const char *vnameserver, const char *smb_export,
-  const char *vsmbserver, const char **dnssearch)
+  const char *vnameserver, const char *vnameserver6,
+  const char *smb_export, const char *vsmbserver,
+  const char **dnssearch)
 {
 /* default settings according to historic slirp */
 struct in_addr net  = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
 struct in_addr mask = { .s_addr = htonl(0xff00) }; /* 255.255.255.0 */
 struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
+struct in6_addr ip6_prefix;
+struct in6_addr ip6_host;
 struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
 struct in_addr dns  = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
+struct in6_addr ip6_dns;
 #ifndef _WIN32
 struct in_addr smbsrv = { .s_addr = 0 };
 #endif
@@ -213,6 +219,27 @@ static int net_slirp_init(NetClientState *peer, const char 
*model,
 return -1;
 }
 
+if (!vprefix6) {
+vprefix6 = "fec0::";
+}
+if (!inet_pton(AF_INET6, vprefix6, _prefix)) {
+return -1;
+}
+
+if (!vprefix6_len) {
+vprefix6_len = 64;
+}
+if (vprefix6_len < 0 || vprefix6_len > 128) {
+return -1;
+}
+
+if (!vhost6) {
+vhost6 = "fec0::2";
+}
+if (!inet_pton(AF_INET6, vhost6, _host)) {
+return -1;
+}
+
 if (vnameserver && !inet_aton(vnameserver, )) {
 return -1;
 }
@@ -221,6 +248,13 @@ static int net_slirp_init(NetClientState *peer, const char 
*model,
 return -1;
 }
 
+if (!vnameserver6) {
+vnameserver6 = "fec0::3";
+}
+if (!inet_pton(AF_INET6, vnameserver6, _dns)) {
+return -1;
+}
+
 if (vdhcp_start && !inet_aton(vdhcp_start, )) {
 return -1;
 }
@@ -243,8 +277,10 @@ static int net_slirp_init(NetClientState *peer, const char 
*model,
 
 s = DO_UPCAST(SlirpState, nc, nc);
 
-s->slirp = slirp_init(restricted, net, mask, host, vhostname,
- 

[Qemu-devel] [PATCHv7 1/9] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration

2016-02-14 Thread Samuel Thibault
From: Guillaume Subiron 

This patch adds the functions needed to handle IPv6 packets. ICMPv6 and
NDP headers are implemented.

Slirp is now able to send NDP Router or Neighbor Advertisement when it
receives Router or Neighbor Solicitation. Using a 64bit-sized IPv6
prefix, the guest is now able to perform stateless autoconfiguration
(SLAAC) and to compute its IPv6 address.

This patch adds an ndp_table, mainly inspired by arp_table, to keep an
NDP cache and manage network address resolution.
Slirp regularly sends NDP Neighbor Advertisement, as recommended by the
RFC, to make the guest refresh its route.

This also adds ip6_cksum() to compute ICMPv6 checksums using IPv6
pseudo-header.

Some #define ETH_* are moved upper in slirp.h to make them accessible to
other slirp/*.h

Signed-off-by: Guillaume Subiron 
Signed-off-by: Samuel Thibault 
---
 slirp/Makefile.objs |   6 +-
 slirp/cksum.c   |  25 
 slirp/if.c  |   2 +-
 slirp/ip6.h | 135 
 slirp/ip6_icmp.c| 347 
 slirp/ip6_icmp.h| 203 ++
 slirp/ip6_input.c   |  69 +++
 slirp/ip6_output.c  |  38 ++
 slirp/ndp_table.c   |  84 +
 slirp/slirp.c   |  49 +++-
 slirp/slirp.h   |  37 ++
 slirp/socket.h  |   7 ++
 12 files changed, 996 insertions(+), 6 deletions(-)
 create mode 100644 slirp/ip6.h
 create mode 100644 slirp/ip6_icmp.c
 create mode 100644 slirp/ip6_icmp.h
 create mode 100644 slirp/ip6_input.c
 create mode 100644 slirp/ip6_output.c
 create mode 100644 slirp/ndp_table.c

diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
index 2daa9dc..4e3a289 100644
--- a/slirp/Makefile.objs
+++ b/slirp/Makefile.objs
@@ -1,3 +1,5 @@
-common-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o dnssearch.o
+common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
+   ip_input.o ip_output.o dnssearch.o
 common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
-common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
+common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o \
+ndp_table.o
diff --git a/slirp/cksum.c b/slirp/cksum.c
index bc0d017..2ad0e65 100644
--- a/slirp/cksum.c
+++ b/slirp/cksum.c
@@ -138,3 +138,28 @@ cont:
REDUCE;
return (~sum & 0x);
 }
+
+int ip6_cksum(struct mbuf *m)
+{
+/* TODO: Optimize this by being able to pass the ip6_pseudohdr to cksum
+ * separately from the mbuf */
+struct ip6 save_ip, *ip = mtod(m, struct ip6 *);
+struct ip6_pseudohdr *ih = mtod(m, struct ip6_pseudohdr *);
+int sum;
+
+save_ip = *ip;
+
+ih->ih_src = save_ip.ip_src;
+ih->ih_dst = save_ip.ip_dst;
+ih->ih_pl = htonl((uint32_t)ntohs(save_ip.ip_pl));
+ih->ih_zero_hi = 0;
+ih->ih_zero_lo = 0;
+ih->ih_nh = save_ip.ip_nh;
+
+sum = cksum(m, ((int)sizeof(struct ip6_pseudohdr))
++ ntohl(ih->ih_pl));
+
+*ip = save_ip;
+
+return sum;
+}
diff --git a/slirp/if.c b/slirp/if.c
index 93d7cc0..2e21f43 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -194,7 +194,7 @@ void if_start(Slirp *slirp)
 
 /* Try to send packet unless it already expired */
 if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) {
-/* Packet is delayed due to pending ARP resolution */
+/* Packet is delayed due to pending ARP or NDP resolution */
 continue;
 }
 
diff --git a/slirp/ip6.h b/slirp/ip6.h
new file mode 100644
index 000..9f7623f
--- /dev/null
+++ b/slirp/ip6.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
+ */
+
+#ifndef SLIRP_IP6_H_
+#define SLIRP_IP6_H_
+
+#define ALLNODES_MULTICAST  { .s6_addr = \
+{ 0xff, 0x02, 0x00, 0x00,\
+0x00, 0x00, 0x00, 0x00,\
+0x00, 0x00, 0x00, 0x00,\
+0x00, 0x00, 0x00, 0x01 } }
+
+#define SOLICITED_NODE_PREFIX { .s6_addr = \
+{ 0xff, 0x02, 0x00, 0x00,\
+0x00, 0x00, 0x00, 0x00,\
+0x00, 0x00, 0x00, 0x01,\
+0xff, 0x00, 0x00, 0x00 } }
+
+#define LINKLOCAL_ADDR  { .s6_addr = \
+{ 0xfe, 0x80, 0x00, 0x00,\
+0x00, 0x00, 0x00, 0x00,\
+0x00, 0x00, 0x00, 0x00,\
+0x00, 0x00, 0x00, 0x02 } }
+
+static inline bool in6_equal(const struct in6_addr *a, const struct in6_addr 
*b)
+{
+return memcmp(a, b, sizeof(*a)) == 0;
+}
+
+static inline bool in6_equal_net(const struct in6_addr *a,
+ const struct in6_addr *b,
+ int prefix_len)
+{
+if (memcmp(a, b, 

[Qemu-devel] [PATCHv7 5/9] slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff

2016-02-14 Thread Samuel Thibault
From: Guillaume Subiron 

Basically, this patch adds some switch in various TCP functions to
prepare them for the IPv6 case.

To have something to "switch" in tcp_input() and tcp_respond(), a new
argument is used to give them the sa_family of the addresses they are
working on.

This patch does not include the entailed reindentation, to make proofread
easier. Reindentation is adressed in the following no-op patch.

Signed-off-by: Guillaume Subiron 
Signed-off-by: Samuel Thibault 
---
 slirp/ip_input.c   |  2 +-
 slirp/slirp.c  |  6 --
 slirp/slirp.h  |  5 +++--
 slirp/tcp_input.c  | 62 ++
 slirp/tcp_output.c | 14 +---
 slirp/tcp_subr.c   | 37 +---
 slirp/tcp_timer.c  |  3 ++-
 7 files changed, 99 insertions(+), 30 deletions(-)

diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 16fb2cb..12f173d 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -200,7 +200,7 @@ ip_input(struct mbuf *m)
 */
switch (ip->ip_p) {
 case IPPROTO_TCP:
-   tcp_input(m, hlen, (struct socket *)NULL);
+   tcp_input(m, hlen, (struct socket *)NULL, AF_INET);
break;
 case IPPROTO_UDP:
udp_input(m, hlen);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index c2c4597..2321c41 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -574,7 +574,8 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
 /*
  * Continue tcp_input
  */
-tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
+so->so_ffamily);
 /* continue; */
 } else {
 ret = sowrite(so);
@@ -623,7 +624,8 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
 }
 
 }
-tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
+so->so_ffamily);
 } /* SS_ISFCONNECTING */
 #endif
 }
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 15775bc..967d93e 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -349,7 +349,7 @@ void ip6_input(struct mbuf *);
 int ip6_output(struct socket *, struct mbuf *, int fast);
 
 /* tcp_input.c */
-void tcp_input(register struct mbuf *, int, struct socket *);
+void tcp_input(register struct mbuf *, int, struct socket *, unsigned short 
af);
 int tcp_mss(register struct tcpcb *, u_int);
 
 /* tcp_output.c */
@@ -360,7 +360,8 @@ void tcp_setpersist(register struct tcpcb *);
 void tcp_init(Slirp *);
 void tcp_cleanup(Slirp *);
 void tcp_template(struct tcpcb *);
-void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct 
mbuf *, tcp_seq, tcp_seq, int);
+void tcp_respond(struct tcpcb *, register struct tcpiphdr *,
+register struct mbuf *, tcp_seq, tcp_seq, int, unsigned short);
 struct tcpcb * tcp_newtcpcb(struct socket *);
 struct tcpcb * tcp_close(register struct tcpcb *);
 void tcp_sockclosed(struct tcpcb *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 26b0c8b..ceac795 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -214,7 +214,7 @@ present:
  * protocol specification dated September, 1981 very closely.
  */
 void
-tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
+tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 {
struct ip save_ip, *ip;
register struct tcpiphdr *ti;
@@ -256,6 +256,8 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
}
slirp = m->slirp;
 
+   switch (af) {
+   case AF_INET:
if (iphlen > sizeof(struct ip )) {
  ip_stripoptions(m, (struct mbuf *)0);
  iphlen=sizeof(struct ip );
@@ -297,6 +299,11 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
if(cksum(m, len)) {
  goto drop;
}
+   break;
+
+   default:
+   g_assert_not_reached();
+   }
 
/*
 * Check that TCP offset makes sense,
@@ -332,14 +339,20 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 * Locate pcb for segment.
 */
 findso:
-   lhost.ss_family = AF_INET;
+   lhost.ss_family = af;
+   fhost.ss_family = af;
+   switch (af) {
+   case AF_INET:
lhost4 = (struct sockaddr_in *) 
lhost4->sin_addr = ti->ti_src;
lhost4->sin_port = ti->ti_sport;
-   fhost.ss_family = AF_INET;
fhost4 = (struct sockaddr_in *) 
fhost4->sin_addr = ti->ti_dst;
fhost4->sin_port = ti->ti_dport;
+   break;
+   default:
+   

Re: [Qemu-devel] [V4 1/4] hw/i386: Introduce AMD IO MMU

2016-02-14 Thread David kiarie
On Thu, Feb 4, 2016 at 6:03 PM, Michael S. Tsirkin  wrote:
> On Mon, Jan 18, 2016 at 06:25:42PM +0300, David Kiarie wrote:
>> Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
>> The IO MMU does basic translation, error checking and has a
>> minimal IOTLB implementation.
>>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/i386/Makefile.objs |1 +
>>  hw/i386/amd_iommu.c   | 1409 
>> +
>>  hw/i386/amd_iommu.h   |  399 ++
>>  include/hw/pci/pci.h  |2 +
>>  4 files changed, 1811 insertions(+)
>>  create mode 100644 hw/i386/amd_iommu.c
>>  create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index b52d5b8..2f1a265 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>  obj-y += pc.o pc_piix.o pc_q35.o
>>  obj-y += pc_sysfw.o
>>  obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>  obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>  obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..20111fe
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,1409 @@
>> +/*
>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see .
>> + *
>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>
> Link to hardware spec?
>
>> + *
>> + */
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +//#define DEBUG_AMD_IOMMU
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +/* configure MMIO registers at startup/reset */
>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
>> +   uint64_t romask, uint64_t w1cmask)
>> +{
>> +stq_le_p(>mmior[addr], val);
>> +stq_le_p(>romask[addr], romask);
>> +stq_le_p(>w1cmask[addr], w1cmask);
>> +}
>> +
>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return lduw_le_p(>mmior[addr]);
>> +}
>> +
>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldl_le_p(>mmior[addr]);
>> +}
>> +
>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldq_le_p(>mmior[addr]);
>> +}
>> +
>> +/* internal write */
>> +static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr 
>> addr)
>> +{
>> +stq_le_p(>mmior[addr], val);
>> +}
>> +
>> +/* external write */
>> +static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
>> +{
>> +uint16_t romask = lduw_le_p(>romask[addr]);
>> +uint16_t w1cmask = lduw_le_p(>w1cmask[addr]);
>> +uint16_t oldval = lduw_le_p(>mmior[addr]);
>> +stw_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
>> +}
>> +
>> +static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
>> +{
>> +uint32_t romask = ldl_le_p(>romask[addr]);
>> +uint32_t w1cmask = ldl_le_p(>w1cmask[addr]);
>> +uint32_t oldval = ldl_le_p(>mmior[addr]);
>> +stl_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
>> +}
>> +
>> +static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
>> +{
>> +uint64_t romask = ldq_le_p(>romask[addr]);
>> +uint64_t w1cmask = ldq_le_p(>w1cmask[addr]);
>> +uint32_t oldval = ldq_le_p(>mmior[addr]);
>> +stq_le_p(>mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
>> +}
>> +
>> +static void amd_iommu_log_event(AMDIOMMUState *s, uint16_t *evt)
>> +{
>> +/* event logging not enabled */
>> +if (!s->evtlog_enabled || *(uint64_t *)>mmior[MMIO_STATUS]
>> +   | MMIO_STATUS_EVT_OVF) {
>
> Pls 

Re: [Qemu-devel] RFC: incremental backups: qmp-block-dirty-bitmap-diff

2016-02-14 Thread Fam Zheng
On Tue, 02/09 19:48, John Snow wrote:
> - Reading an entire drive to populate a bitmap with the understanding
> that an incremental backup is soon to follow is inefficient if the drive
> is more than just a little dirty: it may have been quicker to just
> create a new full backup and bitmap.

Above all I think this is a good idea. Just as an alternative, can we add
another sync mode for drive-backup?

(QMP) drive-backup device=d0 target=target.qcow2 format=qcow2 sync=diff \
   base=full-backup.qcow2

(the data of d0 will be compared against full-backup.qcow2 and only different
clusters will be copied to target.qcow2)

Fam



[Qemu-devel] [PATCH v3 4/8] nvdimm acpi: initialize the resource used by NVDIMM ACPI

2016-02-14 Thread Xiao Guangrong
32 bits IO port starting from 0x0a18 in guest is reserved for NVDIMM
ACPI emulation. The table, NVDIMM_DSM_MEM_FILE, will be patched into
NVDIMM ACPI binary code

OSPM uses this port to tell QEMU the final address of the DSM memory
and notify QEMU to emulate the DSM method

Signed-off-by: Xiao Guangrong 
---
 hw/acpi/Makefile.objs   |  2 +-
 hw/acpi/nvdimm.c| 35 +++
 hw/i386/acpi-build.c| 10 +-
 hw/i386/pc.c|  6 +++---
 hw/i386/pc_piix.c   |  5 +
 hw/i386/pc_q35.c|  8 +++-
 include/hw/i386/pc.h|  4 +++-
 include/hw/mem/nvdimm.h | 28 +++-
 8 files changed, 82 insertions(+), 16 deletions(-)

diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index f3ade9a..faee86c 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -2,7 +2,7 @@ common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o
 common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
 common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o cpu_hotplug_acpi_table.o
 common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o 
memory_hotplug_acpi_table.o
-common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
+obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
 common-obj-$(CONFIG_ACPI) += acpi_interface.o
 common-obj-$(CONFIG_ACPI) += bios-linker-loader.o
 common-obj-$(CONFIG_ACPI) += aml-build.o
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 49ee68e..8568b20 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -29,6 +29,7 @@
 #include "qemu/osdep.h"
 #include "hw/acpi/acpi.h"
 #include "hw/acpi/aml-build.h"
+#include "hw/nvram/fw_cfg.h"
 #include "hw/mem/nvdimm.h"
 
 static int nvdimm_plugged_device_list(Object *obj, void *opaque)
@@ -370,6 +371,40 @@ static void nvdimm_build_nfit(GSList *device_list, GArray 
*table_offsets,
 g_array_free(structures, true);
 }
 
+static uint64_t
+nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
+{
+return 0;
+}
+
+static void
+nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+}
+
+static const MemoryRegionOps nvdimm_dsm_ops = {
+.read = nvdimm_dsm_read,
+.write = nvdimm_dsm_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4,
+},
+};
+
+void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io,
+FWCfgState *fw_cfg, Object *owner)
+{
+memory_region_init_io(>io_mr, owner, _dsm_ops, state,
+  "nvdimm-acpi-io", NVDIMM_ACPI_IO_LEN);
+memory_region_add_subregion(io, NVDIMM_ACPI_IO_BASE, >io_mr);
+
+state->dsm_mem = g_array_new(false, true /* clear */, 1);
+acpi_data_push(state->dsm_mem, TARGET_PAGE_SIZE);
+fw_cfg_add_file(fw_cfg, NVDIMM_DSM_MEM_FILE, state->dsm_mem->data,
+state->dsm_mem->len);
+}
+
 #define NVDIMM_COMMON_DSM  "NCAL"
 
 static void nvdimm_build_common_dsm(Aml *dev)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 10399ec..90fc415 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -38,7 +38,6 @@
 #include "hw/loader.h"
 #include "hw/isa/isa.h"
 #include "hw/acpi/memory_hotplug.h"
-#include "hw/mem/nvdimm.h"
 #include "sysemu/tpm.h"
 #include "hw/acpi/tpm.h"
 #include "sysemu/tpm_backend.h"
@@ -2581,13 +2580,6 @@ static bool acpi_has_iommu(void)
 return intel_iommu && !ambiguous;
 }
 
-static bool acpi_has_nvdimm(void)
-{
-PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
-
-return pcms->nvdimm;
-}
-
 static
 void acpi_build(AcpiBuildTables *tables)
 {
@@ -2672,7 +2664,7 @@ void acpi_build(AcpiBuildTables *tables)
 build_dmar_q35(tables_blob, tables->linker);
 }
 
-if (acpi_has_nvdimm()) {
+if (pcms->acpi_nvdimm_state.is_enabled) {
 nvdimm_build_acpi(table_offsets, tables_blob, tables->linker);
 }
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ce185bb..8fadcc7 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1853,14 +1853,14 @@ static bool pc_machine_get_nvdimm(Object *obj, Error 
**errp)
 {
 PCMachineState *pcms = PC_MACHINE(obj);
 
-return pcms->nvdimm;
+return pcms->acpi_nvdimm_state.is_enabled;
 }
 
 static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp)
 {
 PCMachineState *pcms = PC_MACHINE(obj);
 
-pcms->nvdimm = value;
+pcms->acpi_nvdimm_state.is_enabled = value;
 }
 
 static void pc_machine_initfn(Object *obj)
@@ -1899,7 +1899,7 @@ static void pc_machine_initfn(Object *obj)
 _abort);
 
 /* nvdimm is disabled on default. */
-pcms->nvdimm = false;
+pcms->acpi_nvdimm_state.is_enabled = false;
 object_property_add_bool(obj, PC_MACHINE_NVDIMM, pc_machine_get_nvdimm,
  pc_machine_set_nvdimm, _abort);
 }
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 6f8c2cd..6a69b23 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ 

[Qemu-devel] [PATCH v3 0/8] NVDIMM ACPI: introduce the framework of QEMU emulated DSM

2016-02-14 Thread Xiao Guangrong
This patchset is against commit a407644079c86390 (net: set endianness on all
backend devices) on pci branch of Michael's git tree
and can be found at:
  https://github.com/xiaogr/qemu.git nvdimm-acpi-v3

Changelog in v3:
Changes addressing Michael's comment:
- rebase the patchset against current code

Changes addressing Igor's comment:
- rename the parameters of aml_create_field() to reflect the ACPI spec
- fix the issue that the @target operand can not be optional in
  aml_concatenate() that is also cleaned up by using build_opcode_2arg_dst()

Others:
- separate the test patches to the single set and will be posted on later 
  
These changes are based on Igor's comments:
- drop ssdt.rev2 support as the memory address allocated by BIOS/OVMF
  are always 32 bits
- support to test NVDIMM tables (NFIT and NVDIMM SSDT)
- add _CRS to report its operation region
- make AML APIs change be the separated patches

This is the second part of vNVDIMM implementation which implements the
BIOS patched dsm memory and introduces the framework that allows QEMU
to emulate DSM method

Thanks to Michael's idea, we do not reserve any memory for NVDIMM ACPI,
instead we let BIOS allocate the memory and patch the address to the
offset we want

IO port is still enabled as it plays as the way to notify QEMU and pass
the patched dsm memory address, so that IO port region, 0x0a18 - 0xa20,
is reserved and it is divided into two 32 bits ports and used to pass
the low 32 bits and high 32 bits of dsm memory address to QEMU

Thanks Igor's idea, this patchset also extends DSDT/SSDT to revision 2
to apply 64 bit operations, in order to keeping compatibility, old
version (<= 2.5) still uses revision 1. Since 64 bit operations breaks
old guests (such as windows XP), we should keep the 64 bits stuff in
the private place where common ACPI operation does not touch it

Xiao Guangrong (8):
  acpi: add aml_create_field()
  acpi: add aml_concatenate()
  acpi: allow using object as offset for OperationRegion
  nvdimm acpi: initialize the resource used by NVDIMM ACPI
  nvdimm acpi: introduce patched dsm memory
  nvdimm acpi: let qemu handle _DSM method
  nvdimm acpi: emulate dsm method
  nvdimm acpi: add _CRS

 hw/acpi/Makefile.objs   |   2 +-
 hw/acpi/aml-build.c |  28 -
 hw/acpi/nvdimm.c| 255 +++-
 hw/i386/acpi-build.c|  41 +++
 hw/i386/pc.c|   6 +-
 hw/i386/pc_piix.c   |   5 +
 hw/i386/pc_q35.c|   8 +-
 include/hw/acpi/aml-build.h |   6 +-
 include/hw/i386/pc.h|   4 +-
 include/hw/mem/nvdimm.h |  36 ++-
 10 files changed, 351 insertions(+), 40 deletions(-)

-- 
1.8.3.1




[Qemu-devel] [PATCH v3 5/8] nvdimm acpi: introduce patched dsm memory

2016-02-14 Thread Xiao Guangrong
The dsm memory is used to save the input parameters and store
the dsm result which is filled by QEMU.

The address of dsm memory is decided by bios and patched into
int32 object named "MEMA"

Signed-off-by: Xiao Guangrong 
---
 hw/acpi/nvdimm.c | 34 +-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 8568b20..bca36ae 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -29,6 +29,7 @@
 #include "qemu/osdep.h"
 #include "hw/acpi/acpi.h"
 #include "hw/acpi/aml-build.h"
+#include "hw/acpi/bios-linker-loader.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/mem/nvdimm.h"
 
@@ -406,6 +407,7 @@ void nvdimm_init_acpi_state(AcpiNVDIMMState *state, 
MemoryRegion *io,
 }
 
 #define NVDIMM_COMMON_DSM  "NCAL"
+#define NVDIMM_ACPI_MEM_ADDR   "MEMA"
 
 static void nvdimm_build_common_dsm(Aml *dev)
 {
@@ -470,7 +472,9 @@ static void nvdimm_build_nvdimm_devices(GSList 
*device_list, Aml *root_dev)
 static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
   GArray *table_data, GArray *linker)
 {
-Aml *ssdt, *sb_scope, *dev;
+Aml *ssdt, *sb_scope, *dev, *mem_addr;
+uint32_t zero_offset = 0;
+int offset;
 
 acpi_add_table(table_offsets, table_data);
 
@@ -501,9 +505,37 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray 
*table_offsets,
 
 aml_append(sb_scope, dev);
 
+/*
+ * leave it at the end of ssdt so that we can conveniently get the
+ * offset of int32 object which will be patched with the real address
+ * of the dsm memory by BIOS.
+ *
+ * 0x3200 is the magic number to let aml_int() create int32 object.
+ * It will be zeroed later to make bios_linker_loader_add_pointer()
+ * happy.
+ */
+mem_addr = aml_name_decl(NVDIMM_ACPI_MEM_ADDR, aml_int(0x3200));
+
+aml_append(sb_scope, mem_addr);
 aml_append(ssdt, sb_scope);
 /* copy AML table into ACPI tables blob and patch header there */
 g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
+
+offset = table_data->len - 4;
+
+/*
+ * zero the last 4 bytes, i.e, it is the offset of
+ * NVDIMM_ACPI_MEM_ADDR object.
+ */
+g_array_remove_range(table_data, offset, 4);
+g_array_append_vals(table_data, _offset, 4);
+
+bios_linker_loader_alloc(linker, NVDIMM_DSM_MEM_FILE, TARGET_PAGE_SIZE,
+ false /* high memory */);
+bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+   NVDIMM_DSM_MEM_FILE, table_data,
+   table_data->data + offset,
+   sizeof(uint32_t));
 build_header(linker, table_data,
 (void *)(table_data->data + table_data->len - ssdt->buf->len),
 "SSDT", ssdt->buf->len, 1, NULL, "NVDIMM");
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 6/8] nvdimm acpi: let qemu handle _DSM method

2016-02-14 Thread Xiao Guangrong
If dsm memory is successfully patched, we let qemu fully emulate
the dsm method

This patch saves _DSM input parameters into dsm memory, tell dsm
memory address to QEMU, then fetch the result from the dsm memory

Signed-off-by: Xiao Guangrong 
---
 hw/acpi/nvdimm.c | 117 ---
 1 file changed, 112 insertions(+), 5 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index bca36ae..3d9b3ab 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -372,6 +372,24 @@ static void nvdimm_build_nfit(GSList *device_list, GArray 
*table_offsets,
 g_array_free(structures, true);
 }
 
+struct NvdimmDsmIn {
+uint32_t handle;
+uint32_t revision;
+uint32_t function;
+   /* the remaining size in the page is used by arg3. */
+union {
+uint8_t arg3[0];
+};
+} QEMU_PACKED;
+typedef struct NvdimmDsmIn NvdimmDsmIn;
+
+struct NvdimmDsmOut {
+/* the size of buffer filled by QEMU. */
+uint32_t len;
+uint8_t data[0];
+} QEMU_PACKED;
+typedef struct NvdimmDsmOut NvdimmDsmOut;
+
 static uint64_t
 nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
 {
@@ -411,11 +429,18 @@ void nvdimm_init_acpi_state(AcpiNVDIMMState *state, 
MemoryRegion *io,
 
 static void nvdimm_build_common_dsm(Aml *dev)
 {
-Aml *method, *ifctx, *function;
+Aml *method, *ifctx, *function, *dsm_mem, *unpatched, *result_size;
 uint8_t byte_list[1];
 
-method = aml_method(NVDIMM_COMMON_DSM, 4, AML_NOTSERIALIZED);
+method = aml_method(NVDIMM_COMMON_DSM, 4, AML_SERIALIZED);
 function = aml_arg(2);
+dsm_mem = aml_name(NVDIMM_ACPI_MEM_ADDR);
+
+/*
+ * do not support any method if DSM memory address has not been
+ * patched.
+ */
+unpatched = aml_if(aml_equal(dsm_mem, aml_int(0x0)));
 
 /*
  * function 0 is called to inquire what functions are supported by
@@ -424,12 +449,36 @@ static void nvdimm_build_common_dsm(Aml *dev)
 ifctx = aml_if(aml_equal(function, aml_int(0)));
 byte_list[0] = 0 /* No function Supported */;
 aml_append(ifctx, aml_return(aml_buffer(1, byte_list)));
-aml_append(method, ifctx);
+aml_append(unpatched, ifctx);
 
 /* No function is supported yet. */
 byte_list[0] = 1 /* Not Supported */;
-aml_append(method, aml_return(aml_buffer(1, byte_list)));
+aml_append(unpatched, aml_return(aml_buffer(1, byte_list)));
+aml_append(method, unpatched);
+
+/*
+ * Currently no function is supported for both root device and NVDIMM
+ * devices, let's temporarily set handle to 0x0 at this time.
+ */
+aml_append(method, aml_store(aml_int(0x0), aml_name("HDLE")));
+aml_append(method, aml_store(aml_arg(1), aml_name("REVS")));
+aml_append(method, aml_store(aml_arg(2), aml_name("FUNC")));
 
+/*
+ * tell QEMU about the real address of DSM memory, then QEMU begins
+ * to emulate the method and fills the result to DSM memory.
+ */
+aml_append(method, aml_store(dsm_mem, aml_name("NTFI")));
+
+result_size = aml_local(1);
+aml_append(method, aml_store(aml_name("RLEN"), result_size));
+aml_append(method, aml_store(aml_shiftleft(result_size, aml_int(3)),
+ result_size));
+aml_append(method, aml_create_field(aml_name("ODAT"), aml_int(0),
+result_size, "OBUF"));
+aml_append(method, aml_concatenate(aml_buffer(0, NULL), aml_name("OBUF"),
+   aml_arg(6)));
+aml_append(method, aml_return(aml_arg(6)));
 aml_append(dev, method);
 }
 
@@ -472,7 +521,7 @@ static void nvdimm_build_nvdimm_devices(GSList 
*device_list, Aml *root_dev)
 static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
   GArray *table_data, GArray *linker)
 {
-Aml *ssdt, *sb_scope, *dev, *mem_addr;
+Aml *ssdt, *sb_scope, *dev, *field, *mem_addr;
 uint32_t zero_offset = 0;
 int offset;
 
@@ -498,6 +547,64 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray 
*table_offsets,
  */
 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
 
+/* map DSM memory and IO into ACPI namespace. */
+aml_append(dev, aml_operation_region("NPIO", AML_SYSTEM_IO,
+   aml_int(NVDIMM_ACPI_IO_BASE), NVDIMM_ACPI_IO_LEN));
+aml_append(dev, aml_operation_region("NRAM", AML_SYSTEM_MEMORY,
+   aml_name(NVDIMM_ACPI_MEM_ADDR), TARGET_PAGE_SIZE));
+
+/*
+ * DSM notifier:
+ * NTFI: write the address of DSM memory and notify QEMU to emulate
+ *   the access.
+ *
+ * It is the IO port so that accessing them will cause VM-exit, the
+ * control will be transferred to QEMU.
+ */
+field = aml_field("NPIO", AML_DWORD_ACC, AML_NOLOCK, AML_PRESERVE);
+aml_append(field, aml_named_field("NTFI",
+   sizeof(uint32_t) * BITS_PER_BYTE));
+aml_append(dev, field);
+
+/*
+

[Qemu-devel] [PATCH v3 3/8] acpi: allow using object as offset for OperationRegion

2016-02-14 Thread Xiao Guangrong
Extend aml_operation_region() to use object as offset

Reviewed-by: Igor Mammedov 
Signed-off-by: Xiao Guangrong 
---
 hw/acpi/aml-build.c |  4 ++--
 hw/i386/acpi-build.c| 31 ---
 include/hw/acpi/aml-build.h |  2 +-
 3 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 3362cc4..c4662f0 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -942,14 +942,14 @@ Aml *aml_package(uint8_t num_elements)
 
 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefOpRegion */
 Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
-  uint32_t offset, uint32_t len)
+  Aml *offset, uint32_t len)
 {
 Aml *var = aml_alloc();
 build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
 build_append_byte(var->buf, 0x80); /* OpRegionOp */
 build_append_namestring(var->buf, "%s", name);
 build_append_byte(var->buf, rs);
-build_append_int(var->buf, offset);
+aml_append(var, offset);
 build_append_int(var->buf, len);
 return var;
 }
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 4554eb8..10399ec 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -993,7 +993,7 @@ static void build_processor_devices(Aml *sb_scope, unsigned 
acpi_cpus,
 aml_append(sb_scope, dev);
 /* declare CPU hotplug MMIO region and PRS field to access it */
 aml_append(sb_scope, aml_operation_region(
-"PRST", AML_SYSTEM_IO, pm->cpu_hp_io_base, pm->cpu_hp_io_len));
+"PRST", AML_SYSTEM_IO, aml_int(pm->cpu_hp_io_base), 
pm->cpu_hp_io_len));
 field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
 aml_append(field, aml_named_field("PRS", 256));
 aml_append(sb_scope, field);
@@ -1078,7 +1078,7 @@ static void build_memory_devices(Aml *sb_scope, int 
nr_mem,
 
 aml_append(scope, aml_operation_region(
 MEMORY_HOTPLUG_IO_REGION, AML_SYSTEM_IO,
-io_base, io_len)
+aml_int(io_base), io_len)
 );
 
 field = aml_field(MEMORY_HOTPLUG_IO_REGION, AML_DWORD_ACC,
@@ -1192,7 +1192,8 @@ static void build_hpet_aml(Aml *table)
 aml_append(dev, aml_name_decl("_UID", zero));
 
 aml_append(dev,
-aml_operation_region("HPTM", AML_SYSTEM_MEMORY, HPET_BASE, HPET_LEN));
+aml_operation_region("HPTM", AML_SYSTEM_MEMORY, aml_int(HPET_BASE),
+ HPET_LEN));
 field = aml_field("HPTM", AML_DWORD_ACC, AML_LOCK, AML_PRESERVE);
 aml_append(field, aml_named_field("VEND", 32));
 aml_append(field, aml_named_field("PRD", 32));
@@ -1430,7 +1431,7 @@ static void build_dbg_aml(Aml *table)
 Aml *idx = aml_local(2);
 
 aml_append(scope,
-   aml_operation_region("DBG", AML_SYSTEM_IO, 0x0402, 0x01));
+   aml_operation_region("DBG", AML_SYSTEM_IO, aml_int(0x0402), 0x01));
 field = aml_field("DBG", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
 aml_append(field, aml_named_field("DBGB", 8));
 aml_append(scope, field);
@@ -1770,10 +1771,10 @@ static void build_q35_isa_bridge(Aml *table)
 
 /* ICH9 PCI to ISA irq remapping */
 aml_append(dev, aml_operation_region("PIRQ", AML_PCI_CONFIG,
- 0x60, 0x0C));
+ aml_int(0x60), 0x0C));
 
 aml_append(dev, aml_operation_region("LPCD", AML_PCI_CONFIG,
- 0x80, 0x02));
+ aml_int(0x80), 0x02));
 field = aml_field("LPCD", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE);
 aml_append(field, aml_named_field("COMA", 3));
 aml_append(field, aml_reserved_field(1));
@@ -1785,7 +1786,7 @@ static void build_q35_isa_bridge(Aml *table)
 aml_append(dev, field);
 
 aml_append(dev, aml_operation_region("LPCE", AML_PCI_CONFIG,
- 0x82, 0x02));
+ aml_int(0x82), 0x02));
 /* enable bits */
 field = aml_field("LPCE", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE);
 aml_append(field, aml_named_field("CAEN", 1));
@@ -1808,7 +1809,7 @@ static void build_piix4_pm(Aml *table)
 aml_append(dev, aml_name_decl("_ADR", aml_int(0x00010003)));
 
 aml_append(dev, aml_operation_region("P13C", AML_PCI_CONFIG,
- 0x00, 0xff));
+ aml_int(0x00), 0xff));
 aml_append(scope, dev);
 aml_append(table, scope);
 }
@@ -1825,7 +1826,7 @@ static void build_piix4_isa_bridge(Aml *table)
 
 /* PIIX PCI to ISA irq remapping */
 aml_append(dev, aml_operation_region("P40C", AML_PCI_CONFIG,
- 0x60, 0x04));
+ aml_int(0x60), 0x04));
 /* enable bits */
 field = aml_field("^PX13.P13C", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE);
 /* Offset(0x5f),, 7, 

[Qemu-devel] [PATCH v3 1/8] acpi: add aml_create_field()

2016-02-14 Thread Xiao Guangrong
It will be used by nvdimm acpi

Signed-off-by: Xiao Guangrong 
---
 hw/acpi/aml-build.c | 14 ++
 include/hw/acpi/aml-build.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 603068b..2cc3211 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -997,6 +997,20 @@ Aml *create_field_common(int opcode, Aml *srcbuf, Aml 
*index, const char *name)
 return var;
 }
 
+/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateField */
+Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits,
+  const char *name)
+{
+Aml *var = aml_alloc();
+build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
+build_append_byte(var->buf, 0x13); /* CreateFieldOp */
+aml_append(var, srcbuf);
+aml_append(var, bit_index);
+aml_append(var, num_bits);
+build_append_namestring(var->buf, "%s", name);
+return var;
+}
+
 /* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefCreateDWordField */
 Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name)
 {
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index aa29d30..8ef10ad 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -346,6 +346,8 @@ Aml *aml_mutex(const char *name, uint8_t sync_level);
 Aml *aml_acquire(Aml *mutex, uint16_t timeout);
 Aml *aml_release(Aml *mutex);
 Aml *aml_alias(const char *source_object, const char *alias_object);
+Aml *aml_create_field(Aml *srcbuf, Aml *bit_index, Aml *num_bits,
+  const char *name);
 Aml *aml_create_dword_field(Aml *srcbuf, Aml *index, const char *name);
 Aml *aml_create_qword_field(Aml *srcbuf, Aml *index, const char *name);
 Aml *aml_varpackage(uint32_t num_elements);
-- 
1.8.3.1




[Qemu-devel] [PATCH v3 8/8] nvdimm acpi: add _CRS

2016-02-14 Thread Xiao Guangrong
As Igor suggested that we can report the BIOS patched operation region
so that OSPM could see that particular range is in use and be able to
notice conflicts if it happens some day

Signed-off-by: Xiao Guangrong 
---
 hw/acpi/nvdimm.c | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index d6f067b..a6fbbee 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -566,6 +566,7 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray 
*table_offsets,
   GArray *table_data, GArray *linker)
 {
 Aml *ssdt, *sb_scope, *dev, *field, *mem_addr;
+Aml *min_addr, *max_addr, *mr32, *method, *crs;
 uint32_t zero_offset = 0;
 int offset;
 
@@ -591,6 +592,32 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray 
*table_offsets,
  */
 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0012")));
 
+/*
+ * report the dsm memory so that OSPM could see that particular range is
+ * in use and be able to notice conflicts if it happens some day.
+ */
+method = aml_method("_CRS", 0, AML_SERIALIZED);
+crs = aml_resource_template();
+aml_append(crs, aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
+ AML_MAX_FIXED, AML_CACHEABLE,
+ AML_READ_WRITE,
+ 0, 0x0, 0xFFFE, 0,
+ TARGET_PAGE_SIZE));
+aml_append(method, aml_name_decl("MR32", crs));
+mr32 = aml_name("MR32");
+aml_append(method, aml_create_dword_field(mr32, aml_int(10), "MIN"));
+aml_append(method, aml_create_dword_field(mr32, aml_int(14), "MAX"));
+
+min_addr = aml_name("MIN");
+max_addr = aml_name("MAX");
+
+aml_append(method, aml_store(aml_name(NVDIMM_ACPI_MEM_ADDR), min_addr));
+aml_append(method, aml_add(min_addr, aml_int(TARGET_PAGE_SIZE),
+   max_addr));
+aml_append(method, aml_decrement(max_addr));
+aml_append(method, aml_return(mr32));
+aml_append(dev, method);
+
 /* map DSM memory and IO into ACPI namespace. */
 aml_append(dev, aml_operation_region("NPIO", AML_SYSTEM_IO,
aml_int(NVDIMM_ACPI_IO_BASE), NVDIMM_ACPI_IO_LEN));
-- 
1.8.3.1




Re: [Qemu-devel] [PATCH 1/8] ipmi: add a realize function to the device class

2016-02-14 Thread Marcel Apfelbaum

On 02/09/2016 02:13 PM, Cédric Le Goater wrote:

This will be useful to define and use properties when the object is
instanciated.


Hi,

/s/instanciated/instantiated



Signed-off-by: Cédric Le Goater 
---
  hw/ipmi/ipmi_bmc_sim.c | 12 +---
  1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index e1ad19b8db6e..13171336f7f1 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1731,9 +1731,9 @@ static const VMStateDescription vmstate_ipmi_sim = {
  }
  };

-static void ipmi_sim_init(Object *obj)
+static void ipmi_sim_realize(DeviceState *dev, Error **errp)
  {
-IPMIBmc *b = IPMI_BMC(obj);
+IPMIBmc *b = IPMI_BMC(dev);
  unsigned int i;
  unsigned int recid;
  IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
@@ -1790,10 +1790,17 @@ static void ipmi_sim_init(Object *obj)
  vmstate_register(NULL, 0, _ipmi_sim, ibs);
  }

+static Property ipmi_sim_properties[] = {
+DEFINE_PROP_END_OF_LIST(),
+};


There is no need to add an empty property list.
You should add it in patch 5 together with the first property.

Besides that,

Reviewed-by: Marcel Apfelbaum 

Thanks,
Marcel



+
  static void ipmi_sim_class_init(ObjectClass *oc, void *data)
  {
+DeviceClass *dc = DEVICE_CLASS(oc);
  IPMIBmcClass *bk = IPMI_BMC_CLASS(oc);

+dc->realize = ipmi_sim_realize;
+dc->props = ipmi_sim_properties;
  bk->handle_command = ipmi_sim_handle_command;
  }

@@ -1801,7 +1808,6 @@ static const TypeInfo ipmi_sim_type = {
  .name  = TYPE_IPMI_BMC_SIMULATOR,
  .parent= TYPE_IPMI_BMC,
  .instance_size = sizeof(IPMIBmcSim),
-.instance_init = ipmi_sim_init,
  .class_init= ipmi_sim_class_init,
  };






[Qemu-devel] [PATCH v3 2/8] acpi: add aml_concatenate()

2016-02-14 Thread Xiao Guangrong
It will be used by nvdimm acpi

Signed-off-by: Xiao Guangrong 
---
 hw/acpi/aml-build.c | 8 
 include/hw/acpi/aml-build.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2cc3211..3362cc4 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1437,6 +1437,14 @@ Aml *aml_alias(const char *source_object, const char 
*alias_object)
 return var;
 }
 
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefConcat */
+Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
+{
+assert(target);
+return build_opcode_2arg_dst(0x73 /* ConcatOp */, source1, source2,
+ target);
+}
+
 void
 build_header(GArray *linker, GArray *table_data,
  AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 8ef10ad..735c34a 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -355,6 +355,7 @@ Aml *aml_touuid(const char *uuid);
 Aml *aml_unicode(const char *str);
 Aml *aml_derefof(Aml *arg);
 Aml *aml_sizeof(Aml *arg);
+Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
 
 void
 build_header(GArray *linker, GArray *table_data,
-- 
1.8.3.1




Re: [Qemu-devel] [PATCH v7 1/3] i386/acpi: make floppy controller object dynamic

2016-02-14 Thread Marcel Apfelbaum

On 01/26/2016 03:50 PM, Igor Mammedov wrote:

From: Roman Kagan 

Instead of statically declaring the floppy controller in DSDT, with its
_STA method depending on some obscure bit in the parent ISA bridge, add
the object dynamically to DSDT via AML API only when the controller is
present.

The _STA method is no longer necessary and is therefore dropped.  So are
the declarations of the fields indicating whether the contoller is
enabled.

Signed-off-by: Roman Kagan 
Signed-off-by: Igor Mammedov 
---
  hw/i386/acpi-build.c | 27 +++
  1 file changed, 3 insertions(+), 24 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 78758e2..2f685fb 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1231,29 +1231,10 @@ static Aml *build_fdc_device_aml(void)
  {
  Aml *dev;
  Aml *crs;
-Aml *method;
-Aml *if_ctx;
-Aml *else_ctx;
-Aml *zero = aml_int(0);
-Aml *is_present = aml_local(0);

  dev = aml_device("FDC0");
  aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));

-method = aml_method("_STA", 0, AML_NOTSERIALIZED);
-aml_append(method, aml_store(aml_name("FDEN"), is_present));
-if_ctx = aml_if(aml_equal(is_present, zero));
-{
-aml_append(if_ctx, aml_return(aml_int(0x00)));
-}
-aml_append(method, if_ctx);
-else_ctx = aml_else();
-{
-aml_append(else_ctx, aml_return(aml_int(0x0f)));
-}
-aml_append(method, else_ctx);
-aml_append(dev, method);
-
  crs = aml_resource_template();
  aml_append(crs, aml_io(AML_DECODE16, 0x03F2, 0x03F2, 0x00, 0x04));
  aml_append(crs, aml_io(AML_DECODE16, 0x03F7, 0x03F7, 0x00, 0x01));
@@ -1411,7 +1392,9 @@ static void build_isa_devices_aml(Aml *table)
  aml_append(scope, build_rtc_device_aml());
  aml_append(scope, build_kbd_device_aml());
  aml_append(scope, build_mouse_device_aml());
-aml_append(scope, build_fdc_device_aml());
+if (!!pc_find_fdc0()) {


You don't really need the double negation, right?
Anyway, I agree with the patch.

Reviewed-by: Marcel Apfelbaum 

Thanks,
Marcel


+aml_append(scope, build_fdc_device_aml());
+}
  aml_append(scope, build_lpt_device_aml());
  aml_append(scope, build_com_device_aml(1));
  aml_append(scope, build_com_device_aml(2));
@@ -1780,8 +1763,6 @@ static void build_q35_isa_bridge(Aml *table)
  aml_append(field, aml_named_field("COMB", 3));
  aml_append(field, aml_reserved_field(1));
  aml_append(field, aml_named_field("LPTD", 2));
-aml_append(field, aml_reserved_field(2));
-aml_append(field, aml_named_field("FDCD", 2));
  aml_append(dev, field);

  aml_append(dev, aml_operation_region("LPCE", AML_PCI_CONFIG,
@@ -1791,7 +1772,6 @@ static void build_q35_isa_bridge(Aml *table)
  aml_append(field, aml_named_field("CAEN", 1));
  aml_append(field, aml_named_field("CBEN", 1));
  aml_append(field, aml_named_field("LPEN", 1));
-aml_append(field, aml_named_field("FDEN", 1));
  aml_append(dev, field);

  aml_append(scope, dev);
@@ -1839,7 +1819,6 @@ static void build_piix4_isa_bridge(Aml *table)
  aml_append(field, aml_reserved_field(3));
  aml_append(field, aml_named_field("CBEN", 1));
  aml_append(dev, field);
-aml_append(dev, aml_name_decl("FDEN", aml_int(1)));

  aml_append(scope, dev);
  aml_append(table, scope);






Re: [Qemu-devel] [PATCH 2/8] ipmi: use a function to initialize the SDR table

2016-02-14 Thread Marcel Apfelbaum

On 02/09/2016 02:13 PM, Cédric Le Goater wrote:

This patch does not change anything.


Hi,

Well, it changes *something*, otherwise ... :)

Maybe "This is only a re-factoring."



 It only moves the code section

initializing the sdrs in its own routine and prepares ground for the
subsequent patches.

Signed-off-by: Cédric Le Goater 
---
  hw/ipmi/ipmi_bmc_sim.c | 49 -
  1 file changed, 28 insertions(+), 21 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 13171336f7f1..0abc9cb5de94 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1703,6 +1703,33 @@ static const uint8_t init_sdrs[] = {
  0xff, 0xff, 0x00, 0x00, 0x00
  };

+static void ipmi_sdr_init(IPMIBmcSim *ibs)
+{
+unsigned int i;
+unsigned int recid;
+
+for (i = 0;;) {



I am all for extracting the functionality in a function,
what bothers me a little is the above construct.

Maybe you can find a more "standard: approach like:

 while (recid != 0x) {
 ...
 }

Or maybe is just me.

Thanks,
Marcel


+struct ipmi_sdr_header *sdrh;
+int len;
+if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
+error_report("Problem with recid 0x%4.4x", i);
+return;
+}
+sdrh = (struct ipmi_sdr_header *) _sdrs[i];
+len = ipmi_sdr_length(sdrh);
+recid = ipmi_sdr_recid(sdrh);
+if (recid == 0x) {
+break;
+}
+if ((i + len) > sizeof(init_sdrs)) {
+error_report("Problem with recid 0x%4.4x", i);
+return;
+}
+sdr_add_entry(ibs, sdrh, len, NULL);
+i += len;
+}
+}
+
  static const VMStateDescription vmstate_ipmi_sim = {
  .name = TYPE_IPMI_BMC_SIMULATOR,
  .version_id = 1,
@@ -1735,7 +1762,6 @@ static void ipmi_sim_realize(DeviceState *dev, Error 
**errp)
  {
  IPMIBmc *b = IPMI_BMC(dev);
  unsigned int i;
-unsigned int recid;
  IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);

  qemu_mutex_init(>lock);
@@ -1752,26 +1778,7 @@ static void ipmi_sim_realize(DeviceState *dev, Error 
**errp)
  ibs->sdr.last_clear[i] = 0xff;
  }

-for (i = 0;;) {
-struct ipmi_sdr_header *sdrh;
-int len;
-if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
-error_report("Problem with recid 0x%4.4x", i);
-return;
-}
-sdrh = (struct ipmi_sdr_header *) _sdrs[i];
-len = ipmi_sdr_length(sdrh);
-recid = ipmi_sdr_recid(sdrh);
-if (recid == 0x) {
-break;
-}
-if ((i + len) > sizeof(init_sdrs)) {
-error_report("Problem with recid 0x%4.4x", i);
-return;
-}
-sdr_add_entry(ibs, sdrh, len, NULL);
-i += len;
-}
+ipmi_sdr_init(ibs);

  ibs->acpi_power_state[0] = 0;
  ibs->acpi_power_state[1] = 0;






[Qemu-devel] [PATCH v3 7/8] nvdimm acpi: emulate dsm method

2016-02-14 Thread Xiao Guangrong
Emulate dsm method after IO VM-exit

Currently, we only introduce the framework and no function is actually
supported

Signed-off-by: Xiao Guangrong 
---
 hw/acpi/aml-build.c |  2 +-
 hw/acpi/nvdimm.c| 44 
 include/hw/acpi/aml-build.h |  1 +
 include/hw/mem/nvdimm.h |  8 
 4 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index c4662f0..3e24ea5 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -227,7 +227,7 @@ static void build_extop_package(GArray *package, uint8_t op)
 build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
 }
 
-static void build_append_int_noprefix(GArray *table, uint64_t value, int size)
+void build_append_int_noprefix(GArray *table, uint64_t value, int size)
 {
 int i;
 
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 3d9b3ab..d6f067b 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -393,12 +393,56 @@ typedef struct NvdimmDsmOut NvdimmDsmOut;
 static uint64_t
 nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size)
 {
+fprintf(stderr, "BUG: we never read _DSM IO Port.\n");
 return 0;
 }
 
 static void
 nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
 {
+NvdimmDsmIn *in;
+GArray *out;
+uint32_t buf_size;
+hwaddr dsm_mem_addr = val;
+
+nvdimm_debug("dsm memory address %#lx.\n", dsm_mem_addr);
+
+/*
+ * The DSM memory is mapped to guest address space so an evil guest
+ * can change its content while we are doing DSM emulation. Avoid
+ * this by copying DSM memory to QEMU local memory.
+ */
+in = g_malloc(TARGET_PAGE_SIZE);
+cpu_physical_memory_read(dsm_mem_addr, in, TARGET_PAGE_SIZE);
+
+le32_to_cpus(>revision);
+le32_to_cpus(>function);
+le32_to_cpus(>handle);
+
+nvdimm_debug("Revision %#x Handler %#x Function %#x.\n", in->revision,
+ in->handle, in->function);
+
+out = g_array_new(false, true /* clear */, 1);
+
+/*
+ * function 0 is called to inquire what functions are supported by
+ * OSPM
+ */
+if (in->function == 0) {
+build_append_int_noprefix(out, 0 /* No function Supported */,
+  sizeof(uint8_t));
+} else {
+/* No function is supported yet. */
+build_append_int_noprefix(out, 1 /* Not Supported */,
+  sizeof(uint8_t));
+}
+
+buf_size = cpu_to_le32(out->len);
+cpu_physical_memory_write(dsm_mem_addr, _size, sizeof(buf_size));
+cpu_physical_memory_write(dsm_mem_addr + sizeof(buf_size), out->data,
+  out->len);
+g_free(in);
+g_array_free(out, true);
 }
 
 static const MemoryRegionOps nvdimm_dsm_ops = {
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 07b2d48..d828199 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -357,6 +357,7 @@ Aml *aml_derefof(Aml *arg);
 Aml *aml_sizeof(Aml *arg);
 Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
 
+void build_append_int_noprefix(GArray *table, uint64_t value, int size);
 void
 build_header(GArray *linker, GArray *table_data,
  AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 634c60b..aaa2608 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -25,6 +25,14 @@
 
 #include "hw/mem/pc-dimm.h"
 
+#define NVDIMM_DEBUG 0
+#define nvdimm_debug(fmt, ...)\
+do {  \
+if (NVDIMM_DEBUG) {   \
+fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__);  \
+} \
+} while (0)
+
 #define TYPE_NVDIMM "nvdimm"
 
 #define NVDIMM_DSM_MEM_FILE "etc/acpi/nvdimm-mem"
-- 
1.8.3.1




Re: [Qemu-devel] [PATCH 5/8] ipmi: use a file to load SDRs

2016-02-14 Thread Marcel Apfelbaum

On 02/09/2016 02:13 PM, Cédric Le Goater wrote:

The IPMI BMC simulator populates the sdr/sensor tables with a minimal
set of entries (Watchdog). But some qemu platforms might want to use
extra entries for their custom needs.

This patch modifies slighty the initializing routine to take into
account a larger set read from a file. The name of the file to use is
defined through a new 'sdr' property of the simulator device.

Signed-off-by: Cédric Le Goater 
---
  hw/ipmi/ipmi_bmc_sim.c | 19 +++
  1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index aff818cf22ab..69318eb6b556 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -27,6 +27,7 @@
  #include "qemu/timer.h"
  #include "hw/ipmi/ipmi.h"
  #include "qemu/error-report.h"
+#include "hw/loader.h"

  #define IPMI_NETFN_CHASSIS0x00

@@ -208,6 +209,7 @@ struct IPMIBmcSim {
  IPMISel sel;
  IPMISdr sdr;
  IPMISensor sensors[MAX_SENSORS];
+char *sdr_filename;

  /* Odd netfns are for responses, so we only need the even ones. */
  const IPMINetfn *netfns[MAX_NETFNS / 2];
@@ -1708,24 +1710,32 @@ static void ipmi_sdr_init(IPMIBmcSim *ibs)
  size_t sdrs_size;
  uint8_t *sdrs;

-sdrs_size = sizeof(init_sdrs);
-sdrs = init_sdrs;
+if (!ibs->sdr_filename ||
+!g_file_get_contents(ibs->sdr_filename, (gchar **) , _size,
+NULL)) {


Hi,

If the file exists but you cannot read it you may want at least to
warn the user. He may think the contents are read from the file.

Other than that and the change of the property name (as suggested in this mail 
thread

Reviewed-by: Marcel Apfelbaum 

Thanks,
Marcel



+sdrs_size = sizeof(init_sdrs);
+sdrs = init_sdrs;
+}

  for (i = 0; i < sdrs_size; i += len) {
  struct ipmi_sdr_header *sdrh;

  if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
  error_report("Problem with recid 0x%4.4x", i);
-return;
+break;
  }
  sdrh = (struct ipmi_sdr_header *) [i];
  len = ipmi_sdr_length(sdrh);
  if (i + len > sdrs_size) {
  error_report("Problem with recid 0x%4.4x", i);
-return;
+break;
  }
  sdr_add_entry(ibs, sdrh, len, NULL);
  }
+
+if (sdrs != init_sdrs) {
+g_free(sdrs);
+}
  }

  static const VMStateDescription vmstate_ipmi_sim = {
@@ -1796,6 +1806,7 @@ static void ipmi_sim_realize(DeviceState *dev, Error 
**errp)
  }

  static Property ipmi_sim_properties[] = {
+DEFINE_PROP_STRING("sdr", IPMIBmcSim, sdr_filename),
  DEFINE_PROP_END_OF_LIST(),
  };







Re: [Qemu-devel] [PATCH 7/8] ipmi: introduce an ipmi_bmc_sdr_find() API

2016-02-14 Thread Marcel Apfelbaum

On 02/09/2016 02:13 PM, Cédric Le Goater wrote:

This patch exposes a new IPMI routine to query a sdr entry from the
sdr table maintained by the IPMI BMC simulator. The API is very
similar to the internal sdr_find_entry() routine and should be used
the same way to query one or all sdrs.

A typical use would be to loop on the sdrs to build nodes of a device
tree.

Signed-off-by: Cédric Le Goater 
---
  hw/ipmi/ipmi_bmc_sim.c | 16 
  include/hw/ipmi/ipmi.h |  2 ++
  2 files changed, 18 insertions(+)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index b0754893fc08..c952219429f4 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -406,6 +406,22 @@ static int sdr_find_entry(IPMISdr *sdr, uint16_t recid,
  return 1;
  }

+int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
+  const struct ipmi_sdr_compact **sdr, uint16_t *nextrec)
+
+{
+IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
+unsigned int pos;
+
+pos = 0;
+if (sdr_find_entry(>sdr, recid, , nextrec)) {
+return -1;
+}
+
+*sdr = (const struct ipmi_sdr_compact *) >sdr.sdr[pos];
+return 0;
+}
+
  static void sel_inc_reservation(IPMISel *sel)
  {
  sel->reservation++;
diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
index 74a2b5af9613..e41321db174d 100644
--- a/include/hw/ipmi/ipmi.h
+++ b/include/hw/ipmi/ipmi.h
@@ -255,4 +255,6 @@ struct ipmi_sdr_compact {

  typedef uint8_t ipmi_sdr_compact_buffer[sizeof(struct ipmi_sdr_compact)];

+int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
+  const struct ipmi_sdr_compact **sdr, uint16_t *nextrec);


This method is not used yet. I suppose you have a work in progress
using it, I suggest to add this to your next series when it will be used.

Thanks,
Marcel


  #endif






Re: [Qemu-devel] [PATCH 8/8] ipmi: introduce an ipmi_bmc_gen_event() API

2016-02-14 Thread Marcel Apfelbaum

On 02/09/2016 02:13 PM, Cédric Le Goater wrote:

It will be used to fill the message buffer with custom events expected
by some systems. Typically, an Open PowerNV platform guest is notified
with an OEM SEL message before a shutdown or a reboot.

Signed-off-by: Cédric Le Goater 
---
  hw/ipmi/ipmi_bmc_sim.c | 24 
  include/hw/ipmi/ipmi.h |  2 ++
  2 files changed, 26 insertions(+)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index c952219429f4..cd2db03a4188 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -463,6 +463,30 @@ static int attn_irq_enabled(IPMIBmcSim *ibs)
  IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
  }

+void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log)
+{
+IPMIBmcSim *ibs = IPMI_BMC_SIMULATOR(b);
+IPMIInterface *s = ibs->parent.intf;
+IPMIInterfaceClass *k = IPMI_INTERFACE_GET_CLASS(s);
+
+if (!IPMI_BMC_EVENT_MSG_BUF_ENABLED(ibs)) {
+return;
+}
+
+if (log && IPMI_BMC_EVENT_LOG_ENABLED(ibs)) {
+sel_add_event(ibs, evt);
+}
+
+if (ibs->msg_flags & IPMI_BMC_MSG_FLAG_EVT_BUF_FULL) {
+goto out;
+}
+
+memcpy(ibs->evtbuf, evt, 16);
+ibs->msg_flags |= IPMI_BMC_MSG_FLAG_EVT_BUF_FULL;
+k->set_atn(s, 1, attn_irq_enabled(ibs));
+ out:
+return;
+}
  static void gen_event(IPMIBmcSim *ibs, unsigned int sens_num, uint8_t 
deassert,
uint8_t evd1, uint8_t evd2, uint8_t evd3)
  {
diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
index e41321db174d..178e72d72b40 100644
--- a/include/hw/ipmi/ipmi.h
+++ b/include/hw/ipmi/ipmi.h
@@ -257,4 +257,6 @@ typedef uint8_t ipmi_sdr_compact_buffer[sizeof(struct 
ipmi_sdr_compact)];

  int ipmi_bmc_sdr_find(IPMIBmc *b, uint16_t recid,
const struct ipmi_sdr_compact **sdr, uint16_t *nextrec);
+void ipmi_bmc_gen_event(IPMIBmc *b, uint8_t *evt, bool log);


Hi,

The same here, maybe you can add this function when it will be used.

Thanks,
Marcel


+
  #endif






[Qemu-devel] Collaborating on a QEMU wall poster

2016-02-14 Thread Stefan Hajnoczi
Hi,
I'm decorating my office and would like to hang up a QEMU poster.  So
I thought it would be fun to create a poster and have it printed.

The poster design is free and open.  I've chosen the following to make
collaboration easy and fit with the official QEMU logo:

License: Creative Commons Attribution 3.0
(https://creativecommons.org/licenses/by/3.0/)
File format: Inkscape SVG

Anyone who wants a copy can download the design files under Creative
Commons.  There are online printering companies who can do the
following:

Dimensions: A1 (594 x 841 mm, 23.4 x 33.1 in) or B1 (707 x 1000 mm,
27.8 x 39.4 in)
Estimated price: 15 USD, 13 EUR, 10 GBP, 95 CNY

I am working on a "QEMU architecture" poster which will show the main
internal components (TCG, UI, device emulation, etc) in a diagram.

My progress so far is just a placeholder:
https://github.com/stefanha/qemu-poster

The next step is to choose a visual theme (colors, boxes, fonts, etc)
and start arranging a nice architecture diagram.

Other poster ideas are welcome and I'd be happy to host them in my
repo.  A QEMU timeline would be cool, showing when major features and
architectures were added since the beginning (2003?).

Stefan



Re: [Qemu-devel] [PATCH 3/8] ipmi: remove the need of an ending record in the SDR table

2016-02-14 Thread Marcel Apfelbaum

On 02/09/2016 02:13 PM, Cédric Le Goater wrote:

Currently, the code initializing the sdr table relies on an ending
record with a recid of 0x. This patch changes the loop to use the
sdr size as a breaking condition.

Signed-off-by: Cédric Le Goater 
---
  hw/ipmi/ipmi_bmc_sim.c | 13 +++--
  1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 0abc9cb5de94..f219bfc7a2f3 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1699,34 +1699,27 @@ static const uint8_t init_sdrs[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
  'W',  'a',  't',  'c',  'h',  'd',  'o',  'g',
-/* End */
-0xff, 0xff, 0x00, 0x00, 0x00
  };

  static void ipmi_sdr_init(IPMIBmcSim *ibs)
  {
  unsigned int i;
-unsigned int recid;
+int len;

-for (i = 0;;) {
+for (i = 0; i < sizeof(init_sdrs); i += len) {



Hi,

This is much better, maybe you can squash it into the previous
patch, but I understand if you want to separate re-factoring and new code.

Reviewed-by: Marcel Apfelbaum 




  struct ipmi_sdr_header *sdrh;
-int len;
+
  if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
  error_report("Problem with recid 0x%4.4x", i);
  return;
  }
  sdrh = (struct ipmi_sdr_header *) _sdrs[i];
  len = ipmi_sdr_length(sdrh);
-recid = ipmi_sdr_recid(sdrh);
-if (recid == 0x) {
-break;
-}
  if ((i + len) > sizeof(init_sdrs)) {
  error_report("Problem with recid 0x%4.4x", i);
  return;
  }
  sdr_add_entry(ibs, sdrh, len, NULL);
-i += len;
  }
  }







Re: [Qemu-devel] [PATCH 4/8] ipmi: add some local variables in ipmi_sdr_init

2016-02-14 Thread Marcel Apfelbaum

On 02/09/2016 02:13 PM, Cédric Le Goater wrote:

This patch adds a couple of variables to manipulate the raw sdr
entries. The const attribute is also removed on init_sdrs. This will
ease the introduction of a sdr loader using a file.


Hi,

You could remove the const attribute when you have to, anyway

Reviewed-by: Marcel Apfelbaum 

Thanks,
Marcel




Signed-off-by: Cédric Le Goater 
---
  hw/ipmi/ipmi_bmc_sim.c | 15 ++-
  1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index f219bfc7a2f3..aff818cf22ab 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1692,7 +1692,7 @@ static void register_cmds(IPMIBmcSim *s)
  ipmi_register_netfn(s, IPMI_NETFN_STORAGE, _netfn);
  }

-static const uint8_t init_sdrs[] = {
+static uint8_t init_sdrs[] = {
  /* Watchdog device */
  0x00, 0x00, 0x51, 0x02,   35, 0x20, 0x00, 0x00,
  0x23, 0x01, 0x63, 0x00, 0x23, 0x6f, 0x0f, 0x01,
@@ -1705,17 +1705,22 @@ static void ipmi_sdr_init(IPMIBmcSim *ibs)
  {
  unsigned int i;
  int len;
+size_t sdrs_size;
+uint8_t *sdrs;

-for (i = 0; i < sizeof(init_sdrs); i += len) {
+sdrs_size = sizeof(init_sdrs);
+sdrs = init_sdrs;
+
+for (i = 0; i < sdrs_size; i += len) {
  struct ipmi_sdr_header *sdrh;

-if ((i + IPMI_SDR_HEADER_SIZE) > sizeof(init_sdrs)) {
+if (i + IPMI_SDR_HEADER_SIZE > sdrs_size) {
  error_report("Problem with recid 0x%4.4x", i);
  return;
  }
-sdrh = (struct ipmi_sdr_header *) _sdrs[i];
+sdrh = (struct ipmi_sdr_header *) [i];
  len = ipmi_sdr_length(sdrh);
-if ((i + len) > sizeof(init_sdrs)) {
+if (i + len > sdrs_size) {
  error_report("Problem with recid 0x%4.4x", i);
  return;
  }







Re: [Qemu-devel] [PATCH 6/8] ipmi: provide support for FRUs

2016-02-14 Thread Marcel Apfelbaum

On 02/09/2016 02:13 PM, Cédric Le Goater wrote:

This patch provides a simple FRU support for the BMC simulator. FRUs
are loaded from a file which name is specified in the object
properties, each entry having a fixed size, also specified in the
properties. If the file is unknown or not accessible for some reason,
a unique entry of 1024 bytes is created as a default. Just enough to
start some simulation.

Signed-off-by: Cédric Le Goater 
---
  hw/ipmi/ipmi_bmc_sim.c | 140 +
  1 file changed, 140 insertions(+)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 69318eb6b556..b0754893fc08 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -80,6 +80,9 @@
  #define IPMI_CMD_ENTER_SDR_REP_UPD_MODE   0x2A
  #define IPMI_CMD_EXIT_SDR_REP_UPD_MODE0x2B
  #define IPMI_CMD_RUN_INIT_AGENT   0x2C
+#define IPMI_CMD_GET_FRU_AREA_INFO0x10
+#define IPMI_CMD_READ_FRU_DATA0x11
+#define IPMI_CMD_WRITE_FRU_DATA   0x12
  #define IPMI_CMD_GET_SEL_INFO 0x40
  #define IPMI_CMD_GET_SEL_ALLOC_INFO   0x41
  #define IPMI_CMD_RESERVE_SEL  0x42
@@ -122,6 +125,13 @@ typedef struct IPMISdr {
  uint8_t overflow;
  } IPMISdr;

+typedef struct IPMIFru {
+char *filename;
+unsigned int nentries;
+uint16_t size;
+uint8_t *data;
+} IPMIFru;
+
  typedef struct IPMISensor {
  uint8_t status;
  uint8_t reading;
@@ -208,6 +218,7 @@ struct IPMIBmcSim {

  IPMISel sel;
  IPMISdr sdr;
+IPMIFru fru;
  IPMISensor sensors[MAX_SENSORS];
  char *sdr_filename;

@@ -1314,6 +1325,103 @@ static void get_sel_info(IPMIBmcSim *ibs,
  IPMI_ADD_RSP_DATA((ibs->sel.overflow << 7) | 0x02);
  }

+static void get_fru_area_info(IPMIBmcSim *ibs,
+ uint8_t *cmd, unsigned int cmd_len,
+ uint8_t *rsp, unsigned int *rsp_len,
+ unsigned int max_rsp_len)
+{
+uint8_t fruid;
+uint16_t fru_entry_size;
+
+IPMI_CHECK_CMD_LEN(3);


Hi,

This is little awkward for me. The cmd_len and rsp
parameters of the macro are implied.

Am I the only one this bothers?


+
+fruid = cmd[2];
+
+if (fruid >= ibs->fru.nentries) {
+rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+return;
+}
+
+fru_entry_size = ibs->fru.size;
+
+IPMI_ADD_RSP_DATA(fru_entry_size & 0xff);
+IPMI_ADD_RSP_DATA(fru_entry_size >> 8 & 0xff);
+IPMI_ADD_RSP_DATA(0x0);


Same here. By the way, do you have some spec for the above or
is an ad-hoc encoding of the fields? If yes, you could
add a reference for the spec.(This is also for the other functions in this 
patch)

Thanks,
Marcel


+}
+
+#define min(x, y) ((x) < (y) ? (x) : (y))
+#define max(x, y) ((x) > (y) ? (x) : (y))
+
+static void read_fru_data(IPMIBmcSim *ibs,
+ uint8_t *cmd, unsigned int cmd_len,
+ uint8_t *rsp, unsigned int *rsp_len,
+ unsigned int max_rsp_len)
+{
+uint8_t fruid;
+uint16_t offset;
+int i;
+uint8_t *fru_entry;
+unsigned int count;
+
+IPMI_CHECK_CMD_LEN(5);
+
+fruid = cmd[2];
+offset = (cmd[3] | cmd[4] << 8);
+
+if (fruid >= ibs->fru.nentries) {
+rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+return;
+}
+
+if (offset >= ibs->fru.size - 1) {
+rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+return;
+}
+
+fru_entry = >fru.data[fruid * ibs->fru.size];
+
+count = min(cmd[5], ibs->fru.size - offset);
+
+IPMI_ADD_RSP_DATA(count & 0xff);
+for (i = 0; i < count; i++) {
+IPMI_ADD_RSP_DATA(fru_entry[offset + i]);
+}
+}
+
+static void write_fru_data(IPMIBmcSim *ibs,
+ uint8_t *cmd, unsigned int cmd_len,
+ uint8_t *rsp, unsigned int *rsp_len,
+ unsigned int max_rsp_len)
+{
+uint8_t fruid;
+uint16_t offset;
+uint8_t *fru_entry;
+unsigned int count;
+
+IPMI_CHECK_CMD_LEN(5);
+
+fruid = cmd[2];
+offset = (cmd[3] | cmd[4] << 8);
+
+if (fruid >= ibs->fru.nentries) {
+rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+return;
+}
+
+if (offset >= ibs->fru.size - 1) {
+rsp[2] = IPMI_CC_INVALID_DATA_FIELD;
+return;
+}
+
+fru_entry = >fru.data[fruid * ibs->fru.size];
+
+count = min(cmd_len - 5, ibs->fru.size - offset);
+
+memcpy(fru_entry + offset, cmd + 5, count);
+
+IPMI_ADD_RSP_DATA(count & 0xff);
+}
+
  static void reserve_sel(IPMIBmcSim *ibs,
  uint8_t *cmd, unsigned int cmd_len,
  uint8_t *rsp, unsigned int *rsp_len,
@@ -1667,6 +1775,9 @@ static const IPMINetfn app_netfn = {
  };

  static const IPMICmdHandler storage_cmds[] = {
+[IPMI_CMD_GET_FRU_AREA_INFO] = get_fru_area_info,
+[IPMI_CMD_READ_FRU_DATA] = read_fru_data,
+[IPMI_CMD_WRITE_FRU_DATA] = write_fru_data,
  

Re: [Qemu-devel] [PATCH 2/3] i.MX: Add the Freescale SPI Controller

2016-02-14 Thread mar.krzeminski

Hello,

W dniu 13.02.2016 o 17:06, Jean-Christophe Dubois pisze:

Signed-off-by: Jean-Christophe Dubois 
---
  hw/ssi/Makefile.objs |   1 +
  hw/ssi/imx_spi.c | 449 +++
  include/hw/ssi/imx_spi.h | 104 +++
  3 files changed, 554 insertions(+)
  create mode 100644 hw/ssi/imx_spi.c
  create mode 100644 include/hw/ssi/imx_spi.h

diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs
index 9555825..fcbb79e 100644
--- a/hw/ssi/Makefile.objs
+++ b/hw/ssi/Makefile.objs
@@ -4,3 +4,4 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
  common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o
  
  obj-$(CONFIG_OMAP) += omap_spi.o

+obj-$(CONFIG_IMX) += imx_spi.o
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
new file mode 100644
index 000..9f7f4fe
--- /dev/null
+++ b/hw/ssi/imx_spi.c
@@ -0,0 +1,449 @@
+/*
+ * IMX SPI Controller
+ *
+ * Copyright (c) 2016 Jean-Christophe Dubois 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw/ssi/imx_spi.h"
+#include "sysemu/sysemu.h"
+
+#ifndef DEBUG_IMX_SPI
+#define DEBUG_IMX_SPI 0
+#endif
+
+#define DPRINTF(fmt, args...) \
+do { \
+if (DEBUG_IMX_SPI) { \
+fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SPI, \
+ __func__, ##args); \
+} \
+} while (0)
+
+static char const *imx_spi_reg_name(uint32_t reg)
+{
+static char unknown[20];
+
+switch (reg) {
+case ECSPI_RXDATA:
+return  "ECSPI_RXDATA";
+case ECSPI_TXDATA:
+return  "ECSPI_TXDATA";
+case ECSPI_CONREG:
+return  "ECSPI_CONREG";
+case ECSPI_CONFIGREG:
+return  "ECSPI_CONFIGREG";
+case ECSPI_INTREG:
+return  "ECSPI_INTREG";
+case ECSPI_DMAREG:
+return  "ECSPI_DMAREG";
+case ECSPI_STATREG:
+return  "ECSPI_STATREG";
+case ECSPI_PERIODREG:
+return  "ECSPI_PERIODREG";
+case ECSPI_TESTREG:
+return  "ECSPI_TESTREG";
+case ECSPI_MSGDATA:
+return  "ECSPI_MSGDATA";
+default:
+sprintf(unknown, "%d ?", reg);
+return unknown;
+}
+}
+
+static const VMStateDescription vmstate_imx_spi = {
+.name = TYPE_IMX_SPI,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_FIFO32(tx_fifo, IMXSPIState),
+VMSTATE_FIFO32(rx_fifo, IMXSPIState),
+VMSTATE_UINT32_ARRAY(regs, IMXSPIState, ECSPI_MAX),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx_spi_txfifo_reset(IMXSPIState *s)
+{
+fifo32_reset(>tx_fifo);
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
+}
+
+static void imx_spi_rxfifo_reset(IMXSPIState *s)
+{
+fifo32_reset(>rx_fifo);
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RO;
+}
+
+static void imx_spi_update_irq(IMXSPIState *s)
+{
+int level;
+
+if (fifo32_is_empty(>rx_fifo)) {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR;
+} else {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RR;
+}
+
+if (fifo32_is_full(>rx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RF;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF;
+}
+
+if (fifo32_is_empty(>tx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TE;
+}
+
+if (fifo32_is_full(>tx_fifo)) {
+s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TF;
+} else {
+s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF;
+}
+
+level = s->regs[ECSPI_STATREG] & s->regs[ECSPI_INTREG] ? 1 : 0;
+
+if (s->previous_level != level) {
+DPRINTF("setting IRQ a level %d\n", level);
+s->previous_level = level;
+qemu_set_irq(s->irq, level);
+}
+
+DPRINTF("IRQ level is %d\n", level);
+}
+
+static uint8_t imx_spi_selected_channel(IMXSPIState *s)
+{
+return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_SELECT);
+}
+
+static uint32_t imx_spi_burst_length(IMXSPIState *s)
+{
+return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_BURST_LENGTH) + 1;
+}
+
+static bool imx_spi_is_enabled(IMXSPIState *s)
+{
+return (s->regs[ECSPI_CONREG] & ECSPI_CONREG_EN) ? true : false;
+}
+
+static bool imx_spi_channel_is_master(IMXSPIState *s)
+{
+uint8_t mode = EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_MODE);
+
+return (mode & (1 << imx_spi_selected_channel(s))) ? true : false;
+}
+
+static bool imx_spi_is_multiple_master_burst(IMXSPIState *s)
+{
+uint8_t wave = EXTRACT(s->regs[ECSPI_CONFIGREG], ECSPI_CONFIGREG_SS_CTL);
+
+return imx_spi_channel_is_master(s) &&
+   !(s->regs[ECSPI_CONREG] & ECSPI_CONREG_SMC) &&
+   ((wave & (1 << 

  1   2   >