Re: [Qemu-devel] [PATCH] net: Move the toeplitz functions from checksum.h to net_rx_pkt.c

2018-02-26 Thread Jason Wang



On 2018年02月22日 17:04, Thomas Huth wrote:

The functions are only used in this single .c file, so there is
no need to put all this code in a header that is included from
multiple places.

Signed-off-by: Thomas Huth
---
  hw/net/net_rx_pkt.c| 44 
  include/net/checksum.h | 44 
  2 files changed, 44 insertions(+), 44 deletions(-)


Hi Thomas,

We have plan to implement RSS for virtio-net, so it looks like we'd 
better keep it in the header.


Thanks



Re: [Qemu-devel] [PATCH v3 0/7] Improvements and clean-ups related to -net

2018-02-26 Thread Jason Wang



On 2018年02月21日 18:18, Thomas Huth wrote:

"-net" is a legacy option that often causes confusion and
misconfigurations for the users, since most people are not aware
of the underlying "vlan" (i.e. hub) concept that is used for this
parameter. The prefered way of configuring your network stack is
to use "--netdev" instead, which gives you a clean 1:1 connection
between your emulated guest hardware and the host network backend.

However, there are two reasons why we could not completely deprecate
"-net" yet:

1) Convenience:
In some cases, it's more convenient to use "-net" instead of "--netdev",
e.g. if you just want to have a "tap" network connection, it's faster
to type "-net nic -net tap" instead of "--device e1000,netdev=n1
--netdev tap,id=n1".

2) On-board NICs:
Currently the "-net nic" parameter is the only way to configure on-
board NICs on certain (embedded) machines via the nd_table[] array.

So beside some generic clean-ups and removal of code that has been
marked as deprecated since QEMU 2.10 already, this patch series intro-
duces a new parameter "--nic" (in patch 7) which should be able to re-
place "-net" in the long run completely: This new convenience parameter
can be used to configure the default/on-board guest HW together with a
host network backend in a very compact way. To configure a tap backend
for the default NIC, you just have to type "--nic tap" here for example.

Note that "-net" itself is not marked as deprecated yet - that is
subject to a later patch, since it likely needs some additional
discussion first (or we might rather want to wait for some more
releases first until --nic has been properly established instead)...

v3:
- Changed the comments in qapi/net.json in patch 5/7 according
   to the suggestion from Eric. Dropped the Reviewed-bys from this
   patch since the text changed a bit now.
- Dropped the final patch 8 with the updates to qemu-doc about
   making -net less prominent. I'll resubmit that patch together
   with a patch that deprecates "-net" in a separate patch series
   instead (which will likely both need some more discussion first).

v2:
- Renamed "-n" to "--nic" (suggested by Paolo)
- Improved the QAPI comment about the removal of 'dump (suggested by Eric)
- exit(0) instead of exit(1) after showing the "-netdev help" (Eric)
- Improved the documenation for hubport a little bit (suggested by Paolo)

Thomas Huth (7):
   net: Move error reporting from net_init_client/netdev to the calling
 site
   net: List available netdevs with "-netdev help"
   net: Only show vhost-user in the help text if CONFIG_POSIX is defined
   net: Make net_client_init() static
   net: Remove the deprecated way of dumping network packets
   net: Remove the deprecated 'host_net_add' and 'host_net_remove' HMP
 commands
   net: Add a new convenience option "--nic" to configure
 default/on-board NICs

  hmp-commands.hx |  30 --
  hmp.h   |   3 -
  include/net/net.h   |   4 +-
  include/sysemu/sysemu.h |   1 +
  monitor.c   |  61 
  net/dump.c  | 102 +
  net/net.c   | 239 +++-
  qapi/net.json   |  29 ++
  qemu-doc.texi   |  16 
  qemu-options.hx |  48 +++---
  tests/test-hmp.c|   2 -
  vl.c|  10 +-
  12 files changed, 170 insertions(+), 375 deletions(-)



Applied.

Thanks



Re: [Qemu-devel] [PATCH v2 05/16] block/mirror: Convert to coroutines

2018-02-26 Thread Fam Zheng
On Mon, 01/22 23:07, Max Reitz wrote:
> @@ -101,7 +105,7 @@ static BlockErrorAction 
> mirror_error_action(MirrorBlockJob *s, bool read,
>  }
>  }
>  
> -static void mirror_iteration_done(MirrorOp *op, int ret)
> +static void coroutine_fn mirror_iteration_done(MirrorOp *op, int ret)
>  {
>  MirrorBlockJob *s = op->s;
>  struct iovec *iov;

I think we want s/qemu_coroutine_enter/aio_co_wake/ in mirror_iteration_done().
As an AIO callback before, this didn't matter, but now we are in an terminating
coroutine, so it is pointless to defer the termination, or even risky in that we
are in a aio_context_acquire/release section, but have already decremented
s->in_flight, which is fishy.

> @@ -138,9 +142,8 @@ static void mirror_iteration_done(MirrorOp *op, int ret)
>  }
>  }
>  
> -static void mirror_write_complete(void *opaque, int ret)
> +static void coroutine_fn mirror_write_complete(MirrorOp *op, int ret)
>  {
> -MirrorOp *op = opaque;
>  MirrorBlockJob *s = op->s;
>  
>  aio_context_acquire(blk_get_aio_context(s->common.blk));
> @@ -157,9 +160,8 @@ static void mirror_write_complete(void *opaque, int ret)
>  aio_context_release(blk_get_aio_context(s->common.blk));
>  }
>  
> -static void mirror_read_complete(void *opaque, int ret)
> +static void coroutine_fn mirror_read_complete(MirrorOp *op, int ret)
>  {
> -MirrorOp *op = opaque;
>  MirrorBlockJob *s = op->s;
>  
>  aio_context_acquire(blk_get_aio_context(s->common.blk));
> @@ -174,8 +176,11 @@ static void mirror_read_complete(void *opaque, int ret)
>  
>  mirror_iteration_done(op, ret);
>  } else {
> -blk_aio_pwritev(s->target, op->offset, >qiov,
> -0, mirror_write_complete, op);
> +int ret;

s/ret/ret2/ or drop the definition?
because ret is already the paramter of the function.

> +
> +ret = blk_co_pwritev(s->target, op->offset,
> + op->qiov.size, >qiov, 0);
> +mirror_write_complete(op, ret);
>  }
>  aio_context_release(blk_get_aio_context(s->common.blk));
>  }



> +static void coroutine_fn mirror_co_discard(void *opaque)
> +{
> +MirrorOp *op = opaque;
> +int ret;
> +
> +op->s->in_flight++;
> +op->s->bytes_in_flight += op->bytes;
> +*op->bytes_handled = op->bytes;
> +
> +ret = blk_co_pdiscard(op->s->target, op->offset, op->bytes);
> +mirror_write_complete(op, ret);
>  }
>  
>  static unsigned mirror_perform(MirrorBlockJob *s, int64_t offset,
> unsigned bytes, MirrorMethod mirror_method)

Doesn't mirror_perform need coroutine_fn annotation too?

>  {

Fam



Re: [Qemu-devel] [Qemu-arm] [PATCH 2/3] hw/sii9022: Add support for Silicon Image SII9022

2018-02-26 Thread Linus Walleij
On Sat, Feb 17, 2018 at 7:32 PM, Philippe Mathieu-Daudé  wrote:

> [Me]
>> +#define DEBUG_SII9022 0
>> +
>> +#define DPRINTF(fmt, ...) \
>> +do { \
>> +if (DEBUG_SII9022) { \
>> +printf("sii9022: " fmt, ## __VA_ARGS__); \
>> +} \
>> +} while (0)
>
> Can you replace DPRINTF() by trace events?

Absolutely but which ones?

I do not feel senior enough to also invent new trace events
for displays or I2C devices...

Yours,
Linus Walleij



[Qemu-devel] [PULL 1/1] virtio-gpu-3d: add support for second capability set (v4)

2018-02-26 Thread Gerd Hoffmann
From: Dave Airlie 

Due to a kernel bug we can never increase the size of capability
set 1, so introduce a new capability set in parallel, old userspace
will continue to use the old set, new userspace will start using
the new one when it detects a fixed kernel.

v2: don't use a define from virglrenderer, just probe it.
v3: fix compilation when virglrenderer disabled
v4: fix style warning, just use ?: op instead.

Signed-off-by: Dave Airlie 
Message-id: 20180223023814.24459-1-airl...@gmail.com
Signed-off-by: Gerd Hoffmann 
---
 include/hw/virtio/virtio-gpu.h  |  2 +-
 include/standard-headers/linux/virtio_gpu.h |  1 +
 hw/display/virtio-gpu-3d.c  | 15 +++
 hw/display/virtio-gpu.c |  7 ++-
 4 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 83f474ffc3..22ac3c2d0e 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -171,5 +171,5 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 void virtio_gpu_gl_block(void *opaque, bool block);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
-
+int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
 #endif
diff --git a/include/standard-headers/linux/virtio_gpu.h 
b/include/standard-headers/linux/virtio_gpu.h
index c1c8f0751d..52a830dcf8 100644
--- a/include/standard-headers/linux/virtio_gpu.h
+++ b/include/standard-headers/linux/virtio_gpu.h
@@ -260,6 +260,7 @@ struct virtio_gpu_cmd_submit {
 };
 
 #define VIRTIO_GPU_CAPSET_VIRGL 1
+#define VIRTIO_GPU_CAPSET_VIRGL2 2
 
 /* VIRTIO_GPU_CMD_GET_CAPSET_INFO */
 struct virtio_gpu_get_capset_info {
diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
index 7db84efe89..3558f38fe8 100644
--- a/hw/display/virtio-gpu-3d.c
+++ b/hw/display/virtio-gpu-3d.c
@@ -362,6 +362,11 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
 virgl_renderer_get_cap_set(resp.capset_id,
_max_version,
_max_size);
+} else if (info.capset_index == 1) {
+resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2;
+virgl_renderer_get_cap_set(resp.capset_id,
+   _max_version,
+   _max_size);
 } else {
 resp.capset_max_version = 0;
 resp.capset_max_size = 0;
@@ -635,4 +640,14 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return 0;
 }
 
+int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
+{
+uint32_t capset2_max_ver, capset2_max_size;
+virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
+  _max_ver,
+  _max_size);
+
+return capset2_max_ver ? 2 : 1;
+}
+
 #endif /* CONFIG_VIRGL */
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 6658f6c6a6..2dd3c3481a 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1215,7 +1215,12 @@ static void virtio_gpu_device_realize(DeviceState *qdev, 
Error **errp)
 /* use larger control queue in 3d mode */
 g->ctrl_vq   = virtio_add_queue(vdev, 256, virtio_gpu_handle_ctrl_cb);
 g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
-g->virtio_config.num_capsets = 1;
+
+#if defined(CONFIG_VIRGL)
+g->virtio_config.num_capsets = virtio_gpu_virgl_get_num_capsets(g);
+#else
+g->virtio_config.num_capsets = 0;
+#endif
 } else {
 g->ctrl_vq   = virtio_add_queue(vdev, 64, virtio_gpu_handle_ctrl_cb);
 g->cursor_vq = virtio_add_queue(vdev, 16, virtio_gpu_handle_cursor_cb);
-- 
2.9.3




[Qemu-devel] [PULL 0/1] Vga 20180227 patches

2018-02-26 Thread Gerd Hoffmann
The following changes since commit 0a773d55ac76c5aa89ed9187a3bc5af8c5c2a6d0:

  maintainers: Add myself as a OpenBSD maintainer (2018-02-23 12:05:07 +)

are available in the git repository at:

  git://git.kraxel.org/qemu tags/vga-20180227-pull-request

for you to fetch changes up to 5643cc94ac1cbc23e1ba6b16b6a88e1ce7b3f6a9:

  virtio-gpu-3d: add support for second capability set (v4) (2018-02-26 
13:41:34 +0100)


virtio-gpu: add support for second capability set



Dave Airlie (1):
  virtio-gpu-3d: add support for second capability set (v4)

 include/hw/virtio/virtio-gpu.h  |  2 +-
 include/standard-headers/linux/virtio_gpu.h |  1 +
 hw/display/virtio-gpu-3d.c  | 15 +++
 hw/display/virtio-gpu.c |  7 ++-
 4 files changed, 23 insertions(+), 2 deletions(-)

-- 
2.9.3




[Qemu-devel] [PATCH v8 0/2] vhost: used_memslots limit check fixes and refactoring

2018-02-26 Thread Jay Zhou
v8:
 - rebased on the master
v7:
 - rebased on the master
v2 ... v6:
 - delete the "used_memslots" global variable, and add it
   for vhost-user and vhost-kernel separately
 - refine the function, commit log
 - used_memslots refactoring

Jay Zhou (2):
  vhost: fix memslot limit check
  vhost: used_memslots refactoring

 hw/virtio/vhost-backend.c | 15 +++-
 hw/virtio/vhost-user.c| 77 ++-
 hw/virtio/vhost.c | 30 ---
 include/hw/virtio/vhost-backend.h |  6 ++-
 4 files changed, 86 insertions(+), 42 deletions(-)

--
1.8.3.1





[Qemu-devel] [PATCH v8 1/2] vhost: fix memslot limit check

2018-02-26 Thread Jay Zhou
Since used_memslots will be updated to the actual value after
registering memory listener for the first time, move the
memslots limit checking to the right place.

Reviewed-by: Igor Mammedov 
Signed-off-by: Jay Zhou 
---
 hw/virtio/vhost.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 4a44e6e..4a583a3 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1106,13 +1106,6 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 goto fail;
 }
 
-if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) {
-error_report("vhost backend memory slots limit is less"
-" than current number of present memory slots");
-r = -1;
-goto fail;
-}
-
 r = hdev->vhost_ops->vhost_set_owner(hdev);
 if (r < 0) {
 VHOST_OPS_DEBUG("vhost_set_owner failed");
@@ -1192,6 +1185,18 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
 hdev->started = false;
 memory_listener_register(>memory_listener, _space_memory);
 QLIST_INSERT_HEAD(_devices, hdev, entry);
+
+if (used_memslots > hdev->vhost_ops->vhost_backend_memslots_limit(hdev)) {
+error_report("vhost backend memory slots limit is less"
+" than current number of present memory slots");
+r = -1;
+if (busyloop_timeout) {
+goto fail_busyloop;
+} else {
+goto fail;
+}
+}
+
 return 0;
 
 fail_busyloop:
-- 
1.8.3.1





[Qemu-devel] [PATCH v8 2/2] vhost: used_memslots refactoring

2018-02-26 Thread Jay Zhou
Used_memslots is shared by vhost kernel and user, it is equal to
dev->mem->nregions, which is correct for vhost kernel, but not for
vhost user, the latter one uses memory regions that have file
descriptor. E.g. a VM has a vhost-user NIC and 8(vhost user memslot
upper limit) memory slots, it will be failed to hotplug a new DIMM
device since vhost_has_free_slot() finds no free slot left. It
should be successful if only part of memory slots have file
descriptor, so setting used memslots for vhost-user and
vhost-kernel respectively.

Signed-off-by: Igor Mammedov 
Signed-off-by: Jay Zhou 
Signed-off-by: Liuzhe 
---
 hw/virtio/vhost-backend.c | 15 +++-
 hw/virtio/vhost-user.c| 77 ++-
 hw/virtio/vhost.c | 13 +++
 include/hw/virtio/vhost-backend.h |  6 ++-
 4 files changed, 75 insertions(+), 36 deletions(-)

diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 7f09efa..59def69 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -15,6 +15,8 @@
 #include "hw/virtio/vhost-backend.h"
 #include "qemu/error-report.h"
 
+static unsigned int vhost_kernel_used_memslots;
+
 static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
  void *arg)
 {
@@ -62,6 +64,11 @@ static int vhost_kernel_memslots_limit(struct vhost_dev *dev)
 return limit;
 }
 
+static bool vhost_kernel_has_free_memslots(struct vhost_dev *dev)
+{
+return vhost_kernel_used_memslots < vhost_kernel_memslots_limit(dev);
+}
+
 static int vhost_kernel_net_set_backend(struct vhost_dev *dev,
 struct vhost_vring_file *file)
 {
@@ -233,11 +240,16 @@ static void vhost_kernel_set_iotlb_callback(struct 
vhost_dev *dev,
 qemu_set_fd_handler((uintptr_t)dev->opaque, NULL, NULL, NULL);
 }
 
+static void vhost_kernel_set_used_memslots(struct vhost_dev *dev)
+{
+vhost_kernel_used_memslots = dev->mem->nregions;
+}
+
 static const VhostOps kernel_ops = {
 .backend_type = VHOST_BACKEND_TYPE_KERNEL,
 .vhost_backend_init = vhost_kernel_init,
 .vhost_backend_cleanup = vhost_kernel_cleanup,
-.vhost_backend_memslots_limit = vhost_kernel_memslots_limit,
+.vhost_backend_has_free_memslots = vhost_kernel_has_free_memslots,
 .vhost_net_set_backend = vhost_kernel_net_set_backend,
 .vhost_scsi_set_endpoint = vhost_kernel_scsi_set_endpoint,
 .vhost_scsi_clear_endpoint = vhost_kernel_scsi_clear_endpoint,
@@ -264,6 +276,7 @@ static const VhostOps kernel_ops = {
 #endif /* CONFIG_VHOST_VSOCK */
 .vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback,
 .vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg,
+.vhost_set_used_memslots = vhost_kernel_set_used_memslots,
 };
 
 int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType 
backend_type)
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 6eb9798..f732c80 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -147,6 +147,8 @@ static VhostUserMsg m __attribute__ ((unused));
 /* The version of the protocol we support */
 #define VHOST_USER_VERSION(0x1)
 
+static bool vhost_user_free_memslots = true;
+
 struct vhost_user {
 CharBackend *chr;
 int slave_fd;
@@ -314,12 +316,43 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, 
uint64_t base,
 return 0;
 }
 
+static int vhost_user_prepare_msg(struct vhost_dev *dev, VhostUserMemory *mem,
+  int *fds)
+{
+int i, fd;
+
+vhost_user_free_memslots = true;
+for (i = 0, mem->nregions = 0; i < dev->mem->nregions; ++i) {
+struct vhost_memory_region *reg = dev->mem->regions + i;
+ram_addr_t offset;
+MemoryRegion *mr;
+
+assert((uintptr_t)reg->userspace_addr == reg->userspace_addr);
+mr = memory_region_from_host((void *)(uintptr_t)reg->userspace_addr,
+ );
+fd = memory_region_get_fd(mr);
+if (fd > 0) {
+if (mem->nregions == VHOST_MEMORY_MAX_NREGIONS) {
+vhost_user_free_memslots = false;
+return -1;
+}
+
+mem->regions[mem->nregions].userspace_addr = reg->userspace_addr;
+mem->regions[mem->nregions].memory_size = reg->memory_size;
+mem->regions[mem->nregions].guest_phys_addr = reg->guest_phys_addr;
+mem->regions[mem->nregions].mmap_offset = offset;
+fds[mem->nregions++] = fd;
+}
+}
+
+return 0;
+}
+
 static int vhost_user_set_mem_table(struct vhost_dev *dev,
 struct vhost_memory *mem)
 {
 int fds[VHOST_MEMORY_MAX_NREGIONS];
-int i, fd;
-size_t fd_num = 0;
+size_t fd_num;
 bool reply_supported = 

[Qemu-devel] [PATCH] tests/libqos: Check for valid dev pointer when looking for PCI devices

2018-02-26 Thread Thomas Huth
dev could be NULL if the PCI device can not be found due to some
reasons, so we must not dereference the pointer in this case.

Signed-off-by: Thomas Huth 
---
 tests/libqos/virtio-pci.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/tests/libqos/virtio-pci.c b/tests/libqos/virtio-pci.c
index 7ac15c0..550dede 100644
--- a/tests/libqos/virtio-pci.c
+++ b/tests/libqos/virtio-pci.c
@@ -315,7 +315,9 @@ QVirtioPCIDevice *qvirtio_pci_device_find(QPCIBus *bus, 
uint16_t device_type)
 qvirtio_pci_foreach(bus, device_type, false, 0,
 qvirtio_pci_assign_device, );
 
-dev->vdev.bus = _pci;
+if (dev) {
+dev->vdev.bus = _pci;
+}
 
 return dev;
 }
-- 
1.8.3.1




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

2018-02-26 Thread Jay Zhou
From: Gonglei 

I posted the RFC verion a few months ago for DPDK
vhost-crypto implmention, and now it's time to send
the formal version. Because we need an user space scheme
for better performance.

The vhost user crypto server side patches had been
sent to DPDK community, pls see

[RFC PATCH 0/6] lib/librte_vhost: introduce new vhost_user crypto backend
support
http://dpdk.org/ml/archives/dev/2017-November/081048.html

You also can get virtio-crypto polling mode driver from:

[PATCH v2 0/7] crypto: add virtio poll mode driver
http://dpdk.org/ml/archives/dev/2018-February/091410.html

v8:
  - make cryptodev-vhost.c complied linux independently
v7:
  - make virtio crypto enabled on non-Linux
  - fix format-string issues
  - fix error reported by clang
  - fix a typo when setting length of cipher key
  - rebased on the master
v6:
  - Fix compile error about backends/cryptodev-vhost-user.o and rebase on
the master
v5:
  - squash [PATCH v4 5/5] into previous patches [Michael]
v4:
  - "[PATCH v4 5/5] cryptodev-vhost-user: depend on CONFIG_VHOST_CRYPTO
and CONFIG_VHOST_USER" newly added to fix compilation dependency [Michael]
v3:
  - New added vhost user messages should be sent only when feature
has been successfully negotiated [Michael]
v2:
  - Fix compile error on mingw32

Gonglei (4):
  cryptodev: add vhost-user as a new cryptodev backend
  cryptodev: add vhost support
  cryptodev-vhost-user: add crypto session handler
  cryptodev-vhost-user: set the key length

 backends/Makefile.objs|   6 +
 backends/cryptodev-builtin.c  |   1 +
 backends/cryptodev-vhost-user.c   | 377 ++
 backends/cryptodev-vhost.c| 347 +++
 configure |  15 ++
 docs/interop/vhost-user.txt   |  26 +++
 hw/virtio/vhost-user.c| 104 ++
 hw/virtio/virtio-crypto.c |  70 +++
 include/hw/virtio/vhost-backend.h |   8 +
 include/hw/virtio/virtio-crypto.h |   1 +
 include/sysemu/cryptodev-vhost-user.h |  47 +
 include/sysemu/cryptodev-vhost.h  | 154 ++
 include/sysemu/cryptodev.h|   8 +
 qemu-options.hx   |  21 ++
 vl.c  |   6 +
 15 files changed, 1191 insertions(+)
 create mode 100644 backends/cryptodev-vhost-user.c
 create mode 100644 backends/cryptodev-vhost.c
 create mode 100644 include/sysemu/cryptodev-vhost-user.h
 create mode 100644 include/sysemu/cryptodev-vhost.h

--
1.8.3.1





[Qemu-devel] [PATCH v8 4/4] cryptodev-vhost-user: set the key length

2018-02-26 Thread Jay Zhou
From: Gonglei 

Signed-off-by: Gonglei 
---
 backends/cryptodev-vhost-user.c   | 4 
 include/sysemu/cryptodev-vhost-user.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c
index 9cd06c4..862d4f2 100644
--- a/backends/cryptodev-vhost-user.c
+++ b/backends/cryptodev-vhost-user.c
@@ -224,6 +224,10 @@ static void cryptodev_vhost_user_init(
  1u << VIRTIO_CRYPTO_SERVICE_MAC;
 backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
 backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
+
+backend->conf.max_size = UINT64_MAX;
+backend->conf.max_cipher_key_len = VHOST_USER_MAX_CIPHER_KEY_LEN;
+backend->conf.max_auth_key_len = VHOST_USER_MAX_AUTH_KEY_LEN;
 }
 
 static int64_t cryptodev_vhost_user_sym_create_session(
diff --git a/include/sysemu/cryptodev-vhost-user.h 
b/include/sysemu/cryptodev-vhost-user.h
index 937217b..6debf53 100644
--- a/include/sysemu/cryptodev-vhost-user.h
+++ b/include/sysemu/cryptodev-vhost-user.h
@@ -23,6 +23,9 @@
 #ifndef CRYPTODEV_VHOST_USER_H
 #define CRYPTODEV_VHOST_USER_H
 
+#define VHOST_USER_MAX_AUTH_KEY_LEN512
+#define VHOST_USER_MAX_CIPHER_KEY_LEN  64
+
 
 /**
  * cryptodev_vhost_user_get_vhost:
-- 
1.8.3.1





[Qemu-devel] [PATCH v8 3/4] cryptodev-vhost-user: add crypto session handler

2018-02-26 Thread Jay Zhou
From: Gonglei 

Introduce two vhost-user meassges: VHOST_USER_CREATE_CRYPTO_SESSION
and VHOST_USER_CLOSE_CRYPTO_SESSION. At this point, the QEMU side
support crypto operation in cryptodev host-user backend.

Signed-off-by: Gonglei 
Signed-off-by: Longpeng(Mike) 
Signed-off-by: Jay Zhou 
---
 backends/cryptodev-vhost-user.c   |  48 ++
 docs/interop/vhost-user.txt   |  26 ++
 hw/virtio/vhost-user.c| 104 ++
 include/hw/virtio/vhost-backend.h |   8 +++
 4 files changed, 175 insertions(+), 11 deletions(-)

diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c
index 151a0e6..9cd06c4 100644
--- a/backends/cryptodev-vhost-user.c
+++ b/backends/cryptodev-vhost-user.c
@@ -231,7 +231,25 @@ static int64_t cryptodev_vhost_user_sym_create_session(
CryptoDevBackendSymSessionInfo *sess_info,
uint32_t queue_index, Error **errp)
 {
-return 0;
+CryptoDevBackendClient *cc =
+   backend->conf.peers.ccs[queue_index];
+CryptoDevBackendVhost *vhost_crypto;
+uint64_t session_id = 0;
+int ret;
+
+vhost_crypto = cryptodev_vhost_user_get_vhost(cc, backend, queue_index);
+if (vhost_crypto) {
+struct vhost_dev *dev = &(vhost_crypto->dev);
+ret = dev->vhost_ops->vhost_crypto_create_session(dev,
+  sess_info,
+  _id);
+if (ret < 0) {
+return -1;
+} else {
+return session_id;
+}
+}
+return -1;
 }
 
 static int cryptodev_vhost_user_sym_close_session(
@@ -239,15 +257,23 @@ static int cryptodev_vhost_user_sym_close_session(
uint64_t session_id,
uint32_t queue_index, Error **errp)
 {
-return 0;
-}
-
-static int cryptodev_vhost_user_sym_operation(
- CryptoDevBackend *backend,
- CryptoDevBackendSymOpInfo *op_info,
- uint32_t queue_index, Error **errp)
-{
-return VIRTIO_CRYPTO_OK;
+CryptoDevBackendClient *cc =
+  backend->conf.peers.ccs[queue_index];
+CryptoDevBackendVhost *vhost_crypto;
+int ret;
+
+vhost_crypto = cryptodev_vhost_user_get_vhost(cc, backend, queue_index);
+if (vhost_crypto) {
+struct vhost_dev *dev = &(vhost_crypto->dev);
+ret = dev->vhost_ops->vhost_crypto_close_session(dev,
+ session_id);
+if (ret < 0) {
+return -1;
+} else {
+return 0;
+}
+}
+return -1;
 }
 
 static void cryptodev_vhost_user_cleanup(
@@ -326,7 +352,7 @@ cryptodev_vhost_user_class_init(ObjectClass *oc, void *data)
 bc->cleanup = cryptodev_vhost_user_cleanup;
 bc->create_session = cryptodev_vhost_user_sym_create_session;
 bc->close_session = cryptodev_vhost_user_sym_close_session;
-bc->do_sym_op = cryptodev_vhost_user_sym_operation;
+bc->do_sym_op = NULL;
 }
 
 static const TypeInfo cryptodev_vhost_user_info = {
diff --git a/docs/interop/vhost-user.txt b/docs/interop/vhost-user.txt
index 9fcf48d..cb3a759 100644
--- a/docs/interop/vhost-user.txt
+++ b/docs/interop/vhost-user.txt
@@ -368,6 +368,7 @@ Protocol features
 #define VHOST_USER_PROTOCOL_F_MTU4
 #define VHOST_USER_PROTOCOL_F_SLAVE_REQ  5
 #define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN   6
+#define VHOST_USER_PROTOCOL_F_CRYPTO_SESSION 7
 
 Master message types
 
@@ -663,6 +664,31 @@ Master message types
   field, and slaves MUST NOT accept SET_CONFIG for read-only
   configuration space fields unless the live migration bit is set.
 
+* VHOST_USER_CREATE_CRYPTO_SESSION
+
+ Id: 26
+ Equivalent ioctl: N/A
+ Master payload: crypto session description
+ Slave payload: crypto session description
+
+ Create a session for crypto operation. The server side must return the
+ session id, 0 or positive for success, negative for failure.
+ This request should be sent only when VHOST_USER_PROTOCOL_F_CRYPTO_SESSION
+ feature has been successfully negotiated.
+ It's a required feature for crypto devices.
+
+* VHOST_USER_CLOSE_CRYPTO_SESSION
+
+ Id: 27
+ Equivalent ioctl: N/A
+ Master payload: u64
+
+ Close a session for crypto operation which was previously
+ created by VHOST_USER_CREATE_CRYPTO_SESSION.
+ This request should be sent only when VHOST_USER_PROTOCOL_F_CRYPTO_SESSION
+ feature has been successfully negotiated.
+ It's a required feature for crypto devices.
+
 Slave message types
 ---
 
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 6eb9798..41ff5cf 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -17,6 +17,7 @@
 #include "sysemu/kvm.h"
 #include 

[Qemu-devel] [PATCH v8 1/4] cryptodev: add vhost-user as a new cryptodev backend

2018-02-26 Thread Jay Zhou
From: Gonglei 

Usage:
 -chardev socket,id=charcrypto0,path=/path/to/your/socket
 -object cryptodev-vhost-user,id=cryptodev0,chardev=charcrypto0
 -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0

Signed-off-by: Gonglei 
Signed-off-by: Longpeng(Mike) 
Signed-off-by: Jay Zhou 
---
 backends/Makefile.objs   |   6 +
 backends/cryptodev-vhost-user.c  | 331 +++
 backends/cryptodev-vhost.c   |  89 +++
 configure|  15 ++
 include/sysemu/cryptodev-vhost.h | 154 ++
 qemu-options.hx  |  21 +++
 vl.c |   6 +
 7 files changed, 622 insertions(+)
 create mode 100644 backends/cryptodev-vhost-user.c
 create mode 100644 backends/cryptodev-vhost.c
 create mode 100644 include/sysemu/cryptodev-vhost.h

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 67eeeba..ad7c032 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -9,4 +9,10 @@ common-obj-$(CONFIG_LINUX) += hostmem-file.o
 common-obj-y += cryptodev.o
 common-obj-y += cryptodev-builtin.o
 
+ifeq ($(CONFIG_VIRTIO),y)
+common-obj-y += cryptodev-vhost.o
+common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) += \
+cryptodev-vhost-user.o
+endif
+
 common-obj-$(CONFIG_LINUX) += hostmem-memfd.o
diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c
new file mode 100644
index 000..93c3f10
--- /dev/null
+++ b/backends/cryptodev-vhost-user.c
@@ -0,0 +1,331 @@
+/*
+ * QEMU Cryptodev backend for QEMU cipher APIs
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ *Gonglei 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
+#include "qemu/error-report.h"
+#include "standard-headers/linux/virtio_crypto.h"
+#include "sysemu/cryptodev-vhost.h"
+#include "chardev/char-fe.h"
+
+
+/**
+ * @TYPE_CRYPTODEV_BACKEND_VHOST_USER:
+ * name of backend that uses vhost user server
+ */
+#define TYPE_CRYPTODEV_BACKEND_VHOST_USER "cryptodev-vhost-user"
+
+#define CRYPTODEV_BACKEND_VHOST_USER(obj) \
+OBJECT_CHECK(CryptoDevBackendVhostUser, \
+ (obj), TYPE_CRYPTODEV_BACKEND_VHOST_USER)
+
+
+typedef struct CryptoDevBackendVhostUser {
+CryptoDevBackend parent_obj;
+
+CharBackend chr;
+char *chr_name;
+bool opened;
+CryptoDevBackendVhost *vhost_crypto[MAX_CRYPTO_QUEUE_NUM];
+} CryptoDevBackendVhostUser;
+
+static int
+cryptodev_vhost_user_running(
+ CryptoDevBackendVhost *crypto)
+{
+return crypto ? 1 : 0;
+}
+
+static void cryptodev_vhost_user_stop(int queues,
+  CryptoDevBackendVhostUser *s)
+{
+size_t i;
+
+for (i = 0; i < queues; i++) {
+if (!cryptodev_vhost_user_running(s->vhost_crypto[i])) {
+continue;
+}
+
+cryptodev_vhost_cleanup(s->vhost_crypto[i]);
+s->vhost_crypto[i] = NULL;
+}
+}
+
+static int
+cryptodev_vhost_user_start(int queues,
+ CryptoDevBackendVhostUser *s)
+{
+CryptoDevBackendVhostOptions options;
+CryptoDevBackend *b = CRYPTODEV_BACKEND(s);
+int max_queues;
+size_t i;
+
+for (i = 0; i < queues; i++) {
+if (cryptodev_vhost_user_running(s->vhost_crypto[i])) {
+continue;
+}
+
+options.opaque = >chr;
+options.backend_type = VHOST_BACKEND_TYPE_USER;
+options.cc = b->conf.peers.ccs[i];
+s->vhost_crypto[i] = cryptodev_vhost_init();
+if (!s->vhost_crypto[i]) {
+error_report("failed to init vhost_crypto for queue %zu", i);
+goto err;
+}
+
+if (i == 0) {
+max_queues =
+  cryptodev_vhost_get_max_queues(s->vhost_crypto[i]);
+if (queues > max_queues) {
+error_report("you are asking more queues than supported: %d",
+ max_queues);
+goto err;
+}
+}
+}
+
+return 0;
+
+err:
+cryptodev_vhost_user_stop(i + 1, s);
+return -1;
+}
+
+static Chardev *

[Qemu-devel] [PATCH v8 2/4] cryptodev: add vhost support

2018-02-26 Thread Jay Zhou
From: Gonglei 

Impliment the vhost-crypto's funtions, such as startup,
stop and notification etc. Introduce an enum
QCryptoCryptoDevBackendOptionsType in order to
identify the cryptodev vhost backend is vhost-user
or vhost-kernel-module (If exist).

At this point, the cryptdoev-vhost-user works.

Signed-off-by: Gonglei 
Signed-off-by: Longpeng(Mike) 
Signed-off-by: Jay Zhou 
---
 backends/cryptodev-builtin.c  |   1 +
 backends/cryptodev-vhost-user.c   |  16 +++
 backends/cryptodev-vhost.c| 258 ++
 hw/virtio/virtio-crypto.c |  70 +
 include/hw/virtio/virtio-crypto.h |   1 +
 include/sysemu/cryptodev-vhost-user.h |  44 ++
 include/sysemu/cryptodev.h|   8 ++
 7 files changed, 398 insertions(+)
 create mode 100644 include/sysemu/cryptodev-vhost-user.h

diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c
index 657c0ba..9fb0bd5 100644
--- a/backends/cryptodev-builtin.c
+++ b/backends/cryptodev-builtin.c
@@ -78,6 +78,7 @@ static void cryptodev_builtin_init(
   "cryptodev-builtin", NULL);
 cc->info_str = g_strdup_printf("cryptodev-builtin0");
 cc->queue_index = 0;
+cc->type = CRYPTODEV_BACKEND_TYPE_BUILTIN;
 backend->conf.peers.ccs[0] = cc;
 
 backend->conf.crypto_services =
diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c
index 93c3f10..151a0e6 100644
--- a/backends/cryptodev-vhost-user.c
+++ b/backends/cryptodev-vhost-user.c
@@ -29,6 +29,7 @@
 #include "standard-headers/linux/virtio_crypto.h"
 #include "sysemu/cryptodev-vhost.h"
 #include "chardev/char-fe.h"
+#include "sysemu/cryptodev-vhost-user.h"
 
 
 /**
@@ -58,6 +59,20 @@ cryptodev_vhost_user_running(
 return crypto ? 1 : 0;
 }
 
+CryptoDevBackendVhost *
+cryptodev_vhost_user_get_vhost(
+ CryptoDevBackendClient *cc,
+ CryptoDevBackend *b,
+ uint16_t queue)
+{
+CryptoDevBackendVhostUser *s =
+  CRYPTODEV_BACKEND_VHOST_USER(b);
+assert(cc->type == CRYPTODEV_BACKEND_TYPE_VHOST_USER);
+assert(queue < MAX_CRYPTO_QUEUE_NUM);
+
+return s->vhost_crypto[queue];
+}
+
 static void cryptodev_vhost_user_stop(int queues,
   CryptoDevBackendVhostUser *s)
 {
@@ -188,6 +203,7 @@ static void cryptodev_vhost_user_init(
 cc->info_str = g_strdup_printf("cryptodev-vhost-user%zu to %s ",
i, chr->label);
 cc->queue_index = i;
+cc->type = CRYPTODEV_BACKEND_TYPE_VHOST_USER;
 
 backend->conf.peers.ccs[i] = cc;
 
diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c
index 27e1c4a..8337c9a 100644
--- a/backends/cryptodev-vhost.c
+++ b/backends/cryptodev-vhost.c
@@ -23,9 +23,16 @@
  */
 
 #include "qemu/osdep.h"
+#include "hw/virtio/virtio-bus.h"
 #include "sysemu/cryptodev-vhost.h"
 
 #ifdef CONFIG_VHOST_CRYPTO
+#include "qapi/error.h"
+#include "qapi/qmp/qerror.h"
+#include "qemu/error-report.h"
+#include "hw/virtio/virtio-crypto.h"
+#include "sysemu/cryptodev-vhost-user.h"
+
 uint64_t
 cryptodev_vhost_get_max_queues(
 CryptoDevBackendVhost *crypto)
@@ -70,6 +77,228 @@ fail:
 return NULL;
 }
 
+static int
+cryptodev_vhost_start_one(CryptoDevBackendVhost *crypto,
+  VirtIODevice *dev)
+{
+int r;
+
+crypto->dev.nvqs = 1;
+crypto->dev.vqs = crypto->vqs;
+
+r = vhost_dev_enable_notifiers(>dev, dev);
+if (r < 0) {
+goto fail_notifiers;
+}
+
+r = vhost_dev_start(>dev, dev);
+if (r < 0) {
+goto fail_start;
+}
+
+return 0;
+
+fail_start:
+vhost_dev_disable_notifiers(>dev, dev);
+fail_notifiers:
+return r;
+}
+
+static void
+cryptodev_vhost_stop_one(CryptoDevBackendVhost *crypto,
+ VirtIODevice *dev)
+{
+vhost_dev_stop(>dev, dev);
+vhost_dev_disable_notifiers(>dev, dev);
+}
+
+CryptoDevBackendVhost *
+cryptodev_get_vhost(CryptoDevBackendClient *cc,
+CryptoDevBackend *b,
+uint16_t queue)
+{
+CryptoDevBackendVhost *vhost_crypto = NULL;
+
+if (!cc) {
+return NULL;
+}
+
+switch (cc->type) {
+#if defined(CONFIG_VHOST_USER) && defined(CONFIG_LINUX)
+case CRYPTODEV_BACKEND_TYPE_VHOST_USER:
+vhost_crypto = cryptodev_vhost_user_get_vhost(cc, b, queue);
+break;
+#endif
+default:
+break;
+}
+
+return vhost_crypto;
+}
+
+static void
+cryptodev_vhost_set_vq_index(CryptoDevBackendVhost *crypto,
+ int vq_index)
+{
+crypto->dev.vq_index = vq_index;
+}
+
+static int
+vhost_set_vring_enable(CryptoDevBackendClient *cc,
+CryptoDevBackend *b,
+

[Qemu-devel] [Bug 1750899] Re: Mouse cursor sometimes can't pass the invisible border on the right side of the screen

2018-02-26 Thread Michael Akushsky
** Also affects: gentoo
   Importance: Undecided
   Status: New

** No longer affects: gentoo

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1750899

Title:
  Mouse cursor sometimes can't pass the invisible border on the right
  side of the screen

Status in QEMU:
  New

Bug description:
  I'm using qemu 2.11 on Gentoo Linux, with configured GPU passthrough (Radeon 
RX580) to the guest Windows 10.
  This configuration is alive for last 4 years, this time I changed a lot qemu, 
linux kernel and windows versions, changed GPU and always all was working as 
expected. I always used standard PS/2 mouse emulation and that was enough for 
me.

  Now, I bought two new monitors, instead of old one, and setup them as
  one logical monitor, using technology called Eyefinity - it's a part
  of standard Radeon software. Now Windows thinks, that I have one
  monitor with resolution 2160x1920 (I bought Dell monitors with a thin
  borders and use them in portrait mode).

  Windows uses it without any problems, but mouse become crazy - sometimes (~3 
times from each 5) I can't move cursor to the right border of the screen, it 
looks like the invisible vertical border. I spent really huge amount of time to 
understand, which component is the root of problem and found, that it's really 
a mouse. I tried all possible variants (standard, tablet, virtio-mouse-pci, 
virtio-tablet-pci), and found, that in both mouse variants bug is reproducing, 
and in both tablet variants - cursor stuck near all real borders and corners, 
so it's not a variant too.
  The only working variant becomes passing real USB port to my VM and insert 
second mouse to this port. So, now it's working, but I have two mice on my 
working place, which doesn't seems very useful.

  Here is my command line:

  QEMU_AUDIO_DRV=pa QEMU_PA_SAMPLES=4096 qemu-system-x86_64 -enable-kvm -M q35 
-m 12168 -cpu host,kvm=off -smp 4,sockets=1,cores=4 \
  -bios /usr/share/qemu/bios.bin -rtc base=localtime -vga none -device 
secondary-vga \
  -drive 
id=virtiocd,if=none,format=raw,file=/home/akushsky/virtio-win-0.1.141.iso \
  -device driver=ide-cd,bus=ide.1,drive=virtiocd \
  -device 
ioh3420,bus=pcie.0,addr=1c.0,multifunction=on,port=1,chassis=1,id=root.1 \
  -device 
vfio-pci,host=05:00.0,bus=root.1,addr=00.0,multifunction=on,romfile=/opt/kvm/images/Sapphire.RX580.8192.170320_1.bin,x-vga=on
 \
  -device virtio-scsi-pci,id=scsi \
  -drive 
file=/dev/sdb,id=disk,format=raw,if=none,discard=on,cache=none,aio=native,detect-zeroes=unmap
 -device scsi-hd,drive=disk,id=scsi0 \
  -device ich9-intel-hda,bus=pcie.0,addr=1b.0,id=sound0 -device 
hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 \
  -usb -usbdevice host:046d:c52b

  All in all, I checked on Windows 7 and Windows 10, and on qemu 2.10
  and 2.11 - bug is always reproducible.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1750899/+subscriptions



[Qemu-devel] [PATCH 11/16] translate-all: add page_collection assertions

2018-02-26 Thread Emilio G. Cota
The appended adds assertions to make sure we do not longjmp with page
locks held. Some notes:

- user-mode has nothing to check, since page_locks are !user-mode only.

- The checks only apply to page collections, since these have relatively
  complex callers.

- Some simple page_lock/unlock callers have been left unchecked --
  namely page_lock_tb, tb_phys_invalidate and tb_link_page.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/cpu-exec.c  |  1 +
 accel/tcg/translate-all.c | 22 ++
 include/exec/exec-all.h   |  8 
 3 files changed, 31 insertions(+)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 8c68727..7c83887 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -271,6 +271,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
 tcg_debug_assert(!have_mmap_lock());
 #endif
 tb_lock_reset();
+assert_page_collection_locked(false);
 }
 
 if (in_exclusive_region) {
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 07527d5..82832ef 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -605,6 +605,24 @@ void page_collection_unlock(struct page_collection *set)
 { }
 #else /* !CONFIG_USER_ONLY */
 
+#ifdef CONFIG_DEBUG_TCG
+static __thread bool page_collection_locked;
+
+void assert_page_collection_locked(bool val)
+{
+tcg_debug_assert(page_collection_locked == val);
+}
+
+static inline void set_page_collection_locked(bool val)
+{
+page_collection_locked = val;
+}
+#else
+static inline void set_page_collection_locked(bool val)
+{
+}
+#endif /* !CONFIG_DEBUG_TCG */
+
 static inline void page_lock(PageDesc *pd)
 {
 qemu_spin_lock(>lock);
@@ -677,6 +695,7 @@ static void do_page_entry_lock(struct page_entry *pe)
 page_lock(pe->pd);
 g_assert(!pe->locked);
 pe->locked = true;
+set_page_collection_locked(true);
 }
 
 static gboolean page_entry_lock(gpointer key, gpointer value, gpointer data)
@@ -769,6 +788,7 @@ page_collection_lock(tb_page_addr_t start, tb_page_addr_t 
end)
 set->tree = g_tree_new_full(tb_page_addr_cmp, NULL, NULL,
 page_entry_destroy);
 set->max = NULL;
+assert_page_collection_locked(false);
 
  retry:
 g_tree_foreach(set->tree, page_entry_lock, NULL);
@@ -787,6 +807,7 @@ page_collection_lock(tb_page_addr_t start, tb_page_addr_t 
end)
  page_trylock_add(set, tb->page_addr[1]))) {
 /* drop all locks, and reacquire in order */
 g_tree_foreach(set->tree, page_entry_unlock, NULL);
+set_page_collection_locked(false);
 goto retry;
 }
 }
@@ -799,6 +820,7 @@ void page_collection_unlock(struct page_collection *set)
 /* entries are unlocked and freed via page_entry_destroy */
 g_tree_destroy(set->tree);
 g_free(set);
+set_page_collection_locked(false);
 }
 
 #endif /* !CONFIG_USER_ONLY */
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index aeaa127..7911e69 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -431,6 +431,14 @@ void tb_lock(void);
 void tb_unlock(void);
 void tb_lock_reset(void);
 
+#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_DEBUG_TCG)
+void assert_page_collection_locked(bool val);
+#else
+static inline void assert_page_collection_locked(bool val)
+{
+}
+#endif
+
 #if !defined(CONFIG_USER_ONLY)
 
 struct MemoryRegion *iotlb_to_region(CPUState *cpu,
-- 
2.7.4




[Qemu-devel] [PATCH 16/16] tcg: remove tb_lock

2018-02-26 Thread Emilio G. Cota
Use mmap_lock in user-mode to protect TCG state and the page
descriptors.
In !user-mode, each vCPU has its own TCG state, so no locks
needed. Per-page locks are used to protect the page descriptors.

Per-TB locks are used in both modes to protect TB jumps.

Some notes:

- tb_lock is removed from notdirty_mem_write by passing a
  locked page_collection to tb_invalidate_phys_page_fast.

- tcg_tb_lookup/remove/insert/etc have their own internal lock(s),
  so there is no need to further serialize access to them.

- do_tb_flush is run in a safe async context, meaning no other
  vCPU threads are running. Therefore acquiring mmap_lock there
  is just to please tools such as thread sanitizer.

- Not visible in the diff, but tb_invalidate_phys_page already
  has an assert_memory_lock.

- cpu_io_recompile is !user-only, so no mmap_lock there.

- Added mmap_unlock()'s before all siglongjmp's that could
  be called in user-mode while mmap_lock is held.
  + Added an assert for !have_mmap_lock() after returning from
the longjmp in cpu_exec, just like we do in cpu_exec_step_atomic.

Performance numbers before/after:

Host: AMD Opteron(tm) Processor 6376

 ubuntu 17.04 ppc64 bootup+shutdown time

  700 +-+--++--++---+*--+-+
  |++  ++   +   *B|
  | before ***B***** *|
  |tb lock removal ###D### ***|
  600 +-+   *** +-+
  |   ** #|
  |*B*  #D|
  | *** * ##  |
  500 +-+***   ###  +-+
  | * ***   ###   |
  |*B*  # ##  |
  |  ** *  #D#|
  400 +-+  **## +-+
  |  **   ### |
  |**   ##|
  |  ** # ##  |
  300 +-+  *   B*  #D#  +-+
  |B ***###   |
  |*   **     |
  | *   ***  ###  |
  200 +-+   B  *B #D#   +-+
  | #B* *   ## #  |
  | #*##  |
  |+ D##D# ++   ++|
  100 +-+--++--++---++--+-+
   18  16  Guest CPUs   48   64
  png: https://imgur.com/HwmBHXe

  debian jessie aarch64 bootup+shutdown time

  90 +-+--+-+-++++--+-+
 |+ + ++++|
 | before ***B***B|
  80 +tb lock removal ###D###  **D  +-+
 |   **###|
 | **##   |
  70 +-+ ** #   +-+
 | ** ##  |
 |   **  #|
  60 +-+   *B  ##   +-+
 |   **  ##   |
 |***  #D |
  50 +-+   ***   ## +-+
 | * **   ### |
 |   **B*  ###|
  40 +-+   # ## +-+
 |    #D# |
 | ***B**  ###|
  30 +-+B***B** +-+
 |B *   * # ###   |
 | B   ###D#  |
  20 +-+   D  ##D## +-+
 |  D#|
 |+ + ++++|
  10 +-+--+-+-++++--+-+
  1 8 16  Guest CPUs48   64
  png: https://imgur.com/iGpGFtv

The gains are high for 4-8 CPUs. Beyond that point, however, unrelated
lock contention significantly hurts scalability.


[Qemu-devel] [PATCH 14/16] cputlb: remove tb_lock from tlb_flush functions

2018-02-26 Thread Emilio G. Cota
The acquisition of tb_lock was added when the async tlb_flush
was introduced in e3b9ca810 ("cputlb: introduce tlb_flush_* async work.")

tb_lock was there to allow us to do memset() on the tb_jmp_cache's.
However, since f3ced3c5928 ("tcg: consistently access cpu->tb_jmp_cache
atomically") all accesses to tb_jmp_cache are atomic, so tb_lock
is not needed here. Get rid of it.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/cputlb.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 0543903..f5c3a09 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -125,8 +125,6 @@ static void tlb_flush_nocheck(CPUState *cpu)
 atomic_set(>tlb_flush_count, env->tlb_flush_count + 1);
 tlb_debug("(count: %zu)\n", tlb_flush_count());
 
-tb_lock();
-
 memset(env->tlb_table, -1, sizeof(env->tlb_table));
 memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table));
 cpu_tb_jmp_cache_clear(cpu);
@@ -135,8 +133,6 @@ static void tlb_flush_nocheck(CPUState *cpu)
 env->tlb_flush_addr = -1;
 env->tlb_flush_mask = 0;
 
-tb_unlock();
-
 atomic_mb_set(>pending_tlb_flush, 0);
 }
 
@@ -180,8 +176,6 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, 
run_on_cpu_data data)
 
 assert_cpu_is_self(cpu);
 
-tb_lock();
-
 tlb_debug("start: mmu_idx:0x%04lx\n", mmu_idx_bitmask);
 
 for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
@@ -197,8 +191,6 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, 
run_on_cpu_data data)
 cpu_tb_jmp_cache_clear(cpu);
 
 tlb_debug("done\n");
-
-tb_unlock();
 }
 
 void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap)
-- 
2.7.4




[Qemu-devel] [PATCH 12/16] translate-all: discard TB when tb_link_page returns an existing matching TB

2018-02-26 Thread Emilio G. Cota
Use the recently-gained QHT feature of returning the matching TB if it
already exists. This allows us to get rid of the lookup we perform
right after acquiring tb_lock.

Suggested-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 accel/tcg/cpu-exec.c  | 14 ++
 accel/tcg/translate-all.c | 47 ++-
 2 files changed, 40 insertions(+), 21 deletions(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 7c83887..8aed38c 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -243,10 +243,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
 if (tb == NULL) {
 mmap_lock();
 tb_lock();
-tb = tb_htable_lookup(cpu, pc, cs_base, flags, cf_mask);
-if (likely(tb == NULL)) {
-tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
-}
+tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
 tb_unlock();
 mmap_unlock();
 }
@@ -396,14 +393,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
 tb_lock();
 acquired_tb_lock = true;
 
-/* There's a chance that our desired tb has been translated while
- * taking the locks so we check again inside the lock.
- */
-tb = tb_htable_lookup(cpu, pc, cs_base, flags, cf_mask);
-if (likely(tb == NULL)) {
-/* if no translated code available, then translate it now */
-tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask);
-}
+tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask);
 
 mmap_unlock();
 /* We add the TB in the virtual pc hash table for the fast lookup */
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 82832ef..dbe6c12 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1503,12 +1503,16 @@ static inline void tb_page_add(PageDesc *p, 
TranslationBlock *tb,
  * (-1) to indicate that only one page contains the TB.
  *
  * Called with mmap_lock held for user-mode emulation.
+ *
+ * Returns @tb or an existing TB that matches @tb.
  */
-static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
- tb_page_addr_t phys_page2)
+static TranslationBlock *
+tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
+ tb_page_addr_t phys_page2)
 {
 PageDesc *p;
 PageDesc *p2 = NULL;
+void *existing_tb;
 uint32_t h;
 
 assert_memory_lock();
@@ -1516,6 +1520,11 @@ static void tb_link_page(TranslationBlock *tb, 
tb_page_addr_t phys_pc,
 /*
  * Add the TB to the page list.
  * To avoid deadlock, acquire first the lock of the lower-addressed page.
+ * We keep the locks held until after inserting the TB in the hash table,
+ * so that if the insertion fails we know for sure that the TBs are still
+ * in the page descriptors.
+ * Note that inserting into the hash table first isn't an option, since
+ * we can only insert TBs that are fully initialized.
  */
 p = page_find_alloc(phys_pc >> TARGET_PAGE_BITS, 1);
 if (likely(phys_page2 == -1)) {
@@ -1535,21 +1544,33 @@ static void tb_link_page(TranslationBlock *tb, 
tb_page_addr_t phys_pc,
 tb_page_add(p2, tb, 1, phys_page2);
 }
 
+/* add in the hash table */
+h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK,
+ tb->trace_vcpu_dstate);
+existing_tb = qht_insert(_ctx.htable, tb, h);
+
+/* remove TB from the page(s) if we couldn't insert it */
+if (unlikely(existing_tb)) {
+tb_page_remove(p, tb);
+invalidate_page_bitmap(p);
+if (p2) {
+tb_page_remove(p2, tb);
+invalidate_page_bitmap(p2);
+}
+tb = existing_tb;
+}
+
 if (p2) {
 page_unlock(p2);
 }
 page_unlock(p);
 
-/* add in the hash table */
-h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK,
- tb->trace_vcpu_dstate);
-qht_insert(_ctx.htable, tb, h);
-
 #ifdef CONFIG_USER_ONLY
 if (DEBUG_TB_CHECK_GATE) {
 tb_page_check();
 }
 #endif
+return tb;
 }
 
 /* Called with mmap_lock held for user mode emulation.  */
@@ -1558,7 +1579,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
   uint32_t flags, int cflags)
 {
 CPUArchState *env = cpu->env_ptr;
-TranslationBlock *tb;
+TranslationBlock *tb, *existing_tb;
 tb_page_addr_t phys_pc, phys_page2;
 target_ulong virt_page2;
 tcg_insn_unit *gen_code_buf;
@@ -1706,7 +1727,15 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
  * memory barrier is required before tb_link_page() makes the TB visible
  * through the physical hash table and physical page list.
  */
-tb_link_page(tb, phys_pc, phys_page2);
+existing_tb = tb_link_page(tb, phys_pc, phys_page2);
+/* if the TB 

[Qemu-devel] [PATCH 13/16] translate-all: protect TB jumps with a per-destination-TB lock

2018-02-26 Thread Emilio G. Cota
This applies to both user-mode and !user-mode emulation.

Instead of relying on a global lock, protect the list of incoming
jumps with tb->jmp_lock. This lock also protects tb->cflags,
so update all tb->cflags readers outside tb->jmp_lock to use
atomic reads via tb_cflags().

In order to find the destination TB (and therefore its jmp_lock)
from the origin TB, we introduce tb->jmp_dest[].

I considered not using a linked list of jumps, which simplifies
code and makes the struct smaller. However, it unnecessarily increases
memory usage, which results in a performance decrease. See for
instance these numbers booting+shutting down debian-arm:
  Time (s)  Rel. err (%)  Abs. err (s)  Rel. slowdown (%)
--
 before  20.88  0.74  0.154512 0.
 after   20.81  0.38  0.079078-0.33524904
 GTree   21.02  0.28  0.058856 0.67049808
 GHashTable + xxhash 21.63  1.08  0.233604  3.5919540

Using a hash table or a binary tree to keep track of the jumps
doesn't really pay off, not only due to the increased memory usage,
but also because most TBs have only 0 or 1 jumps to them. The maximum
number of jumps when booting debian-arm that I measured is 35, but
as we can see in the histogram below a TB with that many incoming jumps
is extremely rare; the average TB has 0.80 incoming jumps.

n_jumps: 379208; avg jumps/tb: 0.801099
dist: [0.0,1.0)|▄█▁▁▁ ▁▁ ▁▁▁  ▁▁▁ ▁|[34.0,35.0]

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/cpu-exec.c|  41 +-
 accel/tcg/translate-all.c   | 118 
 docs/devel/multi-thread-tcg.txt |   6 +-
 include/exec/exec-all.h |  33 +++
 4 files changed, 123 insertions(+), 75 deletions(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 8aed38c..20dad1b 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -350,28 +350,43 @@ void tb_set_jmp_target(TranslationBlock *tb, int n, 
uintptr_t addr)
 }
 }
 
-/* Called with tb_lock held.  */
 static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
 {
+uintptr_t old;
+
 assert(n < ARRAY_SIZE(tb->jmp_list_next));
-if (tb->jmp_list_next[n]) {
-/* Another thread has already done this while we were
- * outside of the lock; nothing to do in this case */
-return;
+qemu_spin_lock(_next->jmp_lock);
+
+/* make sure the destination TB is valid */
+if (tb_next->cflags & CF_INVALID) {
+goto out_unlock_next;
+}
+/* Atomically claim the jump destination slot only if it was NULL */
+old = atomic_cmpxchg(>jmp_dest[n], (uintptr_t)NULL, 
(uintptr_t)tb_next);
+if (old) {
+goto out_unlock_next;
 }
+
+/* patch the native jump address */
+tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc.ptr);
+
+/* add in TB jmp list */
+tb->jmp_list_next[n] = tb_next->jmp_list_head;
+tb_next->jmp_list_head = (uintptr_t)tb | n;
+
+qemu_spin_unlock(_next->jmp_lock);
+
 qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
"Linking TBs %p [" TARGET_FMT_lx
"] index %d -> %p [" TARGET_FMT_lx "]\n",
tb->tc.ptr, tb->pc, n,
tb_next->tc.ptr, tb_next->pc);
+return;
 
-/* patch the native jump address */
-tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc.ptr);
-
-/* add in TB jmp circular list */
-tb->jmp_list_next[n] = tb_next->jmp_list_first;
-tb_next->jmp_list_first = (uintptr_t)tb | n;
+ out_unlock_next:
+qemu_spin_unlock(_next->jmp_lock);
+return;
 }
 
 static inline TranslationBlock *tb_find(CPUState *cpu,
@@ -414,9 +429,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
 tb_lock();
 acquired_tb_lock = true;
 }
-if (!(tb->cflags & CF_INVALID)) {
-tb_add_jump(last_tb, tb_exit, tb);
-}
+tb_add_jump(last_tb, tb_exit, tb);
 }
 if (acquired_tb_lock) {
 tb_unlock();
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index dbe6c12..9ab6477 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -173,6 +173,9 @@ struct page_collection {
 #define PAGE_FOR_EACH_TB(pagedesc, tb, n)   \
 TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next)
 
+#define TB_FOR_EACH_JMP(head_tb, tb, n) \
+TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_next)
+
 /* In system mode we want L1_MAP to be based on ram offsets,
while in user mode we want it to be based on virtual addresses.  */
 #if !defined(CONFIG_USER_ONLY)
@@ -390,7 +393,7 @@ static int 

[Qemu-devel] [PATCH 05/16] translate-all: iterate over TBs in a page with PAGE_FOR_EACH_TB

2018-02-26 Thread Emilio G. Cota
This commit does several things, but to avoid churn I merged them all
into the same commit. To wit:

- Use uintptr_t instead of TranslationBlock * for the list of TBs in a page.
  Just like we did in (c37e6d7e "tcg: Use uintptr_t type for
  jmp_list_{next|first} fields of TB"), the rationale is the same: these
  are tagged pointers, not pointers. So use a more appropriate type.

- Only check the least significant bit of the tagged pointers. Masking
  with 3/~3 is unnecessary and confusing.

- Introduce the TB_FOR_EACH_TAGGED macro, and use it to define
  PAGE_FOR_EACH_TB, which improves readability.

- Update tb_page_remove to use PAGE_FOR_EACH_TB. In case there
  is a bug and we attempt to remove a TB that is not in the list, instead
  of segfaulting (since the list is NULL-terminated) we will reach
  g_assert_not_reached().

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/translate-all.c | 65 +++
 include/exec/exec-all.h   |  2 +-
 2 files changed, 33 insertions(+), 34 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 20ad3fc..06aa905 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -103,7 +103,7 @@
 
 typedef struct PageDesc {
 /* list of TBs intersecting this ram page */
-TranslationBlock *first_tb;
+uintptr_t first_tb;
 #ifdef CONFIG_SOFTMMU
 /* in order to optimize self modifying code, we count the number
of lookups we do to a given page to use a bitmap */
@@ -114,6 +114,18 @@ typedef struct PageDesc {
 #endif
 } PageDesc;
 
+/* list iterators for lists of tagged pointers in TranslationBlock */
+#define TB_FOR_EACH_TAGGED(head, tb, n, field)  \
+for (n = (head) & 1,\
+ tb = (TranslationBlock *)((head) & ~1);\
+ tb;\
+ tb = (TranslationBlock *)tb->field[n], \
+ n = (uintptr_t)tb & 1, \
+ tb = (TranslationBlock *)((uintptr_t)tb & ~1))
+
+#define PAGE_FOR_EACH_TB(pagedesc, tb, n)   \
+TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next)
+
 /* In system mode we want L1_MAP to be based on ram offsets,
while in user mode we want it to be based on virtual addresses.  */
 #if !defined(CONFIG_USER_ONLY)
@@ -818,7 +830,7 @@ static void page_flush_tb_1(int level, void **lp)
 PageDesc *pd = *lp;
 
 for (i = 0; i < V_L2_SIZE; ++i) {
-pd[i].first_tb = NULL;
+pd[i].first_tb = (uintptr_t)NULL;
 invalidate_page_bitmap(pd + i);
 }
 } else {
@@ -946,21 +958,21 @@ static void tb_page_check(void)
 
 #endif /* CONFIG_USER_ONLY */
 
-static inline void tb_page_remove(TranslationBlock **ptb, TranslationBlock *tb)
+static inline void tb_page_remove(PageDesc *pd, TranslationBlock *tb)
 {
 TranslationBlock *tb1;
+uintptr_t *pprev;
 unsigned int n1;
 
-for (;;) {
-tb1 = *ptb;
-n1 = (uintptr_t)tb1 & 3;
-tb1 = (TranslationBlock *)((uintptr_t)tb1 & ~3);
+pprev = >first_tb;
+PAGE_FOR_EACH_TB(pd, tb1, n1) {
 if (tb1 == tb) {
-*ptb = tb1->page_next[n1];
-break;
+*pprev = tb1->page_next[n1];
+return;
 }
-ptb = >page_next[n1];
+pprev = >page_next[n1];
 }
+g_assert_not_reached();
 }
 
 /* remove the TB from a list of TBs jumping to the n-th jump target of the TB 
*/
@@ -1048,12 +1060,12 @@ void tb_phys_invalidate(TranslationBlock *tb, 
tb_page_addr_t page_addr)
 /* remove the TB from the page list */
 if (tb->page_addr[0] != page_addr) {
 p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS);
-tb_page_remove(>first_tb, tb);
+tb_page_remove(p, tb);
 invalidate_page_bitmap(p);
 }
 if (tb->page_addr[1] != -1 && tb->page_addr[1] != page_addr) {
 p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS);
-tb_page_remove(>first_tb, tb);
+tb_page_remove(p, tb);
 invalidate_page_bitmap(p);
 }
 
@@ -1084,10 +1096,7 @@ static void build_page_bitmap(PageDesc *p)
 
 p->code_bitmap = bitmap_new(TARGET_PAGE_SIZE);
 
-tb = p->first_tb;
-while (tb != NULL) {
-n = (uintptr_t)tb & 3;
-tb = (TranslationBlock *)((uintptr_t)tb & ~3);
+PAGE_FOR_EACH_TB(p, tb, n) {
 /* NOTE: this is subtle as a TB may span two physical pages */
 if (n == 0) {
 /* NOTE: tb_end may be after the end of the page, but
@@ -1102,7 +,6 @@ static void build_page_bitmap(PageDesc *p)
 tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
 }
 bitmap_set(p->code_bitmap, tb_start, tb_end - tb_start);
-tb = tb->page_next[n];
 }
 }
 #endif
@@ -1125,9 +1133,9 @@ static inline void tb_alloc_page(TranslationBlock *tb,
 p = 

[Qemu-devel] [PATCH 10/16] translate-all: use per-page locking in !user-mode

2018-02-26 Thread Emilio G. Cota
Groundwork for supporting parallel TCG generation.

Instead of using a global lock (tb_lock) to protect changes
to pages, use fine-grained, per-page locks in !user-mode.
User-mode stays with mmap_lock.

Sometimes changes need to happen atomically on more than one
page (e.g. when a TB that spans across two pages is
added/invalidated, or when a range of pages is invalidated).
We therefore introduce struct page_collection, which helps
us keep track of a set of pages that have been locked in
the appropriate locking order (i.e. by ascending page index).

This commit first introduces the structs and the function helpers,
to then convert the calling code to use per-page locking. Note
that tb_lock is not removed yet.

While at it, rename tb_alloc_page to tb_page_add, which pairs with
tb_page_remove.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/translate-all.c | 432 +-
 accel/tcg/translate-all.h |   3 +
 include/exec/exec-all.h   |   3 +-
 3 files changed, 396 insertions(+), 42 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 4cb03f1..07527d5 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -112,8 +112,55 @@ typedef struct PageDesc {
 #else
 unsigned long flags;
 #endif
+#ifndef CONFIG_USER_ONLY
+QemuSpin lock;
+#endif
 } PageDesc;
 
+/**
+ * struct page_entry - page descriptor entry
+ * @pd: pointer to the  PageDesc of the page this entry represents
+ * @index:  page index of the page
+ * @locked: whether the page is locked
+ *
+ * This struct helps us keep track of the locked state of a page, without
+ * bloating  PageDesc.
+ *
+ * A page lock protects accesses to all fields of  PageDesc.
+ *
+ * See also:  page_collection.
+ */
+struct page_entry {
+PageDesc *pd;
+tb_page_addr_t index;
+bool locked;
+};
+
+/**
+ * struct page_collection - tracks a set of pages (i.e.  page_entry's)
+ * @tree:   Binary search tree (BST) of the pages, with key == page index
+ * @max:Pointer to the page in @tree with the highest page index
+ *
+ * To avoid deadlock we lock pages in ascending order of page index.
+ * When operating on a set of pages, we need to keep track of them so that
+ * we can lock them in order and also unlock them later. For this we collect
+ * pages (i.e.  page_entry's) in a binary search @tree. Given that the
+ * @tree implementation we use does not provide an O(1) operation to obtain the
+ * highest-ranked element, we use @max to keep track of the inserted page
+ * with the highest index. This is valuable because if a page is not in
+ * the tree and its index is higher than @max's, then we can lock it
+ * without breaking the locking order rule.
+ *
+ * Note on naming: 'struct page_set' would be shorter, but we already have a 
few
+ * page_set_*() helpers, so page_collection is used instead to avoid confusion.
+ *
+ * See also: page_collection_lock().
+ */
+struct page_collection {
+GTree *tree;
+struct page_entry *max;
+};
+
 /* list iterators for lists of tagged pointers in TranslationBlock */
 #define TB_FOR_EACH_TAGGED(head, tb, n, field)  \
 for (n = (head) & 1,\
@@ -510,6 +557,15 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int 
alloc)
 return NULL;
 }
 pd = g_new0(PageDesc, V_L2_SIZE);
+#ifndef CONFIG_USER_ONLY
+{
+int i;
+
+for (i = 0; i < V_L2_SIZE; i++) {
+qemu_spin_init([i].lock);
+}
+}
+#endif
 existing = atomic_cmpxchg(lp, NULL, pd);
 if (unlikely(existing)) {
 g_free(pd);
@@ -525,6 +581,228 @@ static inline PageDesc *page_find(tb_page_addr_t index)
 return page_find_alloc(index, 0);
 }
 
+/* In user-mode page locks aren't used; mmap_lock is enough */
+#ifdef CONFIG_USER_ONLY
+static inline void page_lock(PageDesc *pd)
+{ }
+
+static inline void page_unlock(PageDesc *pd)
+{ }
+
+static inline void page_lock_tb(const TranslationBlock *tb)
+{ }
+
+static inline void page_unlock_tb(const TranslationBlock *tb)
+{ }
+
+struct page_collection *
+page_collection_lock(tb_page_addr_t start, tb_page_addr_t end)
+{
+return NULL;
+}
+
+void page_collection_unlock(struct page_collection *set)
+{ }
+#else /* !CONFIG_USER_ONLY */
+
+static inline void page_lock(PageDesc *pd)
+{
+qemu_spin_lock(>lock);
+}
+
+static inline void page_unlock(PageDesc *pd)
+{
+qemu_spin_unlock(>lock);
+}
+
+/* lock the page(s) of a TB in the correct acquisition order */
+static inline void page_lock_tb(const TranslationBlock *tb)
+{
+if (likely(tb->page_addr[1] == -1)) {
+page_lock(page_find(tb->page_addr[0] >> TARGET_PAGE_BITS));
+return;
+}
+if (tb->page_addr[0] < tb->page_addr[1]) {
+page_lock(page_find(tb->page_addr[0] >> TARGET_PAGE_BITS));
+page_lock(page_find(tb->page_addr[1] >> TARGET_PAGE_BITS));
+} else {

[Qemu-devel] [PATCH 06/16] translate-all: make l1_map lockless

2018-02-26 Thread Emilio G. Cota
Groundwork for supporting parallel TCG generation.

We never remove entries from the radix tree, so we can use cmpxchg
to implement lockless insertions.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/translate-all.c   | 24 ++--
 docs/devel/multi-thread-tcg.txt |  4 ++--
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 06aa905..f2bfa71 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -472,20 +472,12 @@ static void page_init(void)
 #endif
 }
 
-/* If alloc=1:
- * Called with tb_lock held for system emulation.
- * Called with mmap_lock held for user-mode emulation.
- */
 static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
 {
 PageDesc *pd;
 void **lp;
 int i;
 
-if (alloc) {
-assert_memory_lock();
-}
-
 /* Level 1.  Always allocated.  */
 lp = l1_map + ((index >> v_l1_shift) & (v_l1_size - 1));
 
@@ -494,11 +486,17 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, 
int alloc)
 void **p = atomic_rcu_read(lp);
 
 if (p == NULL) {
+void *existing;
+
 if (!alloc) {
 return NULL;
 }
 p = g_new0(void *, V_L2_SIZE);
-atomic_rcu_set(lp, p);
+existing = atomic_cmpxchg(lp, NULL, p);
+if (unlikely(existing)) {
+g_free(p);
+p = existing;
+}
 }
 
 lp = p + ((index >> (i * V_L2_BITS)) & (V_L2_SIZE - 1));
@@ -506,11 +504,17 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, 
int alloc)
 
 pd = atomic_rcu_read(lp);
 if (pd == NULL) {
+void *existing;
+
 if (!alloc) {
 return NULL;
 }
 pd = g_new0(PageDesc, V_L2_SIZE);
-atomic_rcu_set(lp, pd);
+existing = atomic_cmpxchg(lp, NULL, pd);
+if (unlikely(existing)) {
+g_free(pd);
+pd = existing;
+}
 }
 
 return pd + (index & (V_L2_SIZE - 1));
diff --git a/docs/devel/multi-thread-tcg.txt b/docs/devel/multi-thread-tcg.txt
index a99b456..faf8918 100644
--- a/docs/devel/multi-thread-tcg.txt
+++ b/docs/devel/multi-thread-tcg.txt
@@ -134,8 +134,8 @@ tb_set_jmp_target() code. Modification to the linked lists 
that allow
 searching for linked pages are done under the protect of the
 tb_lock().
 
-The global page table is protected by the tb_lock() in system-mode and
-mmap_lock() in linux-user mode.
+The global page table is a lockless radix tree; cmpxchg is used
+to atomically insert new elements.
 
 The lookup caches are updated atomically and the lookup hash uses QHT
 which is designed for concurrent safe lookup.
-- 
2.7.4




[Qemu-devel] [PATCH 03/16] tcg: track TBs with per-region BST's

2018-02-26 Thread Emilio G. Cota
This paves the way for enabling scalable parallel generation of TCG code.

Instead of tracking TBs with a single binary search tree (BST), use a
BST for each TCG region, protecting it with a lock. This is as scalable
as it gets, since each TCG thread operates on a separate region.

The core of this change is the introduction of struct tcg_region_tree,
which contains a pointer to a GTree and an associated lock to serialize
accesses to it. We then allocate an array of tcg_region_tree's, adding
the appropriate padding to avoid false sharing based on
qemu_dcache_linesize.

Given a tc_ptr, we first find the corresponding region_tree. This
is done by special-casing the first and last regions first, since they
might be of size != region.size; otherwise we just divide the offset
by region.stride. I was worried about this division (several dozen
cycles of latency), but profiling shows that this is not a fast path.
Note that region.stride is not required to be a power of two; it
is only required to be a multiple of the host's page size.

Note that with this design we can also provide consistent snapshots
about all region trees at once; for instance, tcg_tb_foreach
acquires/releases all region_tree locks before/after iterating over them.
For this reason we now drop tb_lock in dump_exec_info().

As an alternative I considered implementing a concurrent BST, but this
can be tricky to get right, offers no consistent snapshots of the BST,
and performance and scalability-wise I don't think it could ever beat
having separate GTrees, given that our workload is insert-mostly (all
concurrent BST designs I've seen focus, understandably, on making
lookups fast, which comes at the expense of convoluted, non-wait-free
insertions/removals).

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/cpu-exec.c  |   2 +-
 accel/tcg/translate-all.c | 101 
 include/exec/exec-all.h   |   1 -
 include/exec/tb-context.h |   1 -
 tcg/tcg.c | 191 ++
 tcg/tcg.h |   6 ++
 6 files changed, 213 insertions(+), 89 deletions(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index ec57564..8c68727 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -222,7 +222,7 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles,
 
 tb_lock();
 tb_phys_invalidate(tb, -1);
-tb_remove(tb);
+tcg_tb_remove(tb);
 tb_unlock();
 }
 #endif
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 1cf10f8..3a51d49 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -205,8 +205,6 @@ void tb_lock_reset(void)
 }
 }
 
-static TranslationBlock *tb_find_pc(uintptr_t tc_ptr);
-
 void cpu_gen_init(void)
 {
 tcg_context_init(_init_ctx);
@@ -375,13 +373,13 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc)
 
 if (check_offset < tcg_init_ctx.code_gen_buffer_size) {
 tb_lock();
-tb = tb_find_pc(host_pc);
+tb = tcg_tb_lookup(host_pc);
 if (tb) {
 cpu_restore_state_from_tb(cpu, tb, host_pc);
 if (tb->cflags & CF_NOCACHE) {
 /* one-shot translation, invalidate it immediately */
 tb_phys_invalidate(tb, -1);
-tb_remove(tb);
+tcg_tb_remove(tb);
 }
 r = true;
 }
@@ -731,48 +729,6 @@ static inline void *alloc_code_gen_buffer(void)
 }
 #endif /* USE_STATIC_CODE_GEN_BUFFER, WIN32, POSIX */
 
-/* compare a pointer @ptr and a tb_tc @s */
-static int ptr_cmp_tb_tc(const void *ptr, const struct tb_tc *s)
-{
-if (ptr >= s->ptr + s->size) {
-return 1;
-} else if (ptr < s->ptr) {
-return -1;
-}
-return 0;
-}
-
-static gint tb_tc_cmp(gconstpointer ap, gconstpointer bp)
-{
-const struct tb_tc *a = ap;
-const struct tb_tc *b = bp;
-
-/*
- * When both sizes are set, we know this isn't a lookup.
- * This is the most likely case: every TB must be inserted; lookups
- * are a lot less frequent.
- */
-if (likely(a->size && b->size)) {
-if (a->ptr > b->ptr) {
-return 1;
-} else if (a->ptr < b->ptr) {
-return -1;
-}
-/* a->ptr == b->ptr should happen only on deletions */
-g_assert(a->size == b->size);
-return 0;
-}
-/*
- * All lookups have either .size field set to 0.
- * From the glib sources we see that @ap is always the lookup key. However
- * the docs provide no guarantee, so we just mark this case as likely.
- */
-if (likely(a->size == 0)) {
-return ptr_cmp_tb_tc(a->ptr, b);
-}
-return ptr_cmp_tb_tc(b->ptr, a);
-}
-
 static inline void code_gen_alloc(size_t tb_size)
 {
 tcg_ctx->code_gen_buffer_size = size_code_gen_buffer(tb_size);
@@ -781,7 +737,6 @@ static inline void code_gen_alloc(size_t tb_size)
 fprintf(stderr, "Could not allocate dynamic 

[Qemu-devel] [PATCH 15/16] translate-all: remove tb_lock mention from cpu_restore_state_from_tb

2018-02-26 Thread Emilio G. Cota
tb_lock was needed when the function did retranslation. However,
since fca8a500d519 ("tcg: Save insn data and use it in
cpu_restore_state_from_tb") we don't do retranslation.

Get rid of the comment.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/translate-all.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 9ab6477..ee49d03 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -357,9 +357,7 @@ static int encode_search(TranslationBlock *tb, uint8_t 
*block)
 return p - block;
 }
 
-/* The cpu state corresponding to 'searched_pc' is restored.
- * Called with tb_lock held.
- */
+/* The cpu state corresponding to 'searched_pc' is restored */
 static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
  uintptr_t searched_pc)
 {
-- 
2.7.4




[Qemu-devel] [PATCH 02/16] qht: return existing entry when qht_insert fails

2018-02-26 Thread Emilio G. Cota
The meaning of "existing" is now changed to "matches in hash and
ht->cmp result". This is saner than just checking the pointer value.

Note that we now return NULL on insertion success, or the existing
pointer on failure. We can do this because NULL pointers are not
allowed to be inserted in QHT.

Suggested-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 include/qemu/qht.h |  7 ---
 tests/qht-bench.c  |  4 ++--
 tests/test-qht.c   |  5 -
 util/qht.c | 17 +
 4 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/include/qemu/qht.h b/include/qemu/qht.h
index dd512bf..c320cb6 100644
--- a/include/qemu/qht.h
+++ b/include/qemu/qht.h
@@ -77,10 +77,11 @@ void qht_destroy(struct qht *ht);
  * In case of successful operation, smp_wmb() is implied before the pointer is
  * inserted into the hash table.
  *
- * Returns true on success.
- * Returns false if the @p-@hash pair already exists in the hash table.
+ * On success, returns NULL.
+ * On failure, returns the pointer from an entry that is equivalent (i.e.
+ * ht->cmp matches and the hash is the same) to @p-@h.
  */
-bool qht_insert(struct qht *ht, void *p, uint32_t hash);
+void *qht_insert(struct qht *ht, void *p, uint32_t hash);
 
 /**
  * qht_lookup_custom - Look up a pointer using a custom comparison function.
diff --git a/tests/qht-bench.c b/tests/qht-bench.c
index c94ac25..2f88400 100644
--- a/tests/qht-bench.c
+++ b/tests/qht-bench.c
@@ -163,7 +163,7 @@ static void do_rw(struct thread_info *info)
 bool written = false;
 
 if (qht_lookup(, p, hash) == NULL) {
-written = qht_insert(, p, hash);
+written = !qht_insert(, p, hash);
 }
 if (written) {
 stats->in++;
@@ -322,7 +322,7 @@ static void htable_init(void)
 r = xorshift64star(r);
 p = [r & (init_range - 1)];
 hash = h(*p);
-if (qht_insert(, p, hash)) {
+if (qht_insert(, p, hash) == NULL) {
 break;
 }
 retries++;
diff --git a/tests/test-qht.c b/tests/test-qht.c
index f8f2886..7164ae4 100644
--- a/tests/test-qht.c
+++ b/tests/test-qht.c
@@ -27,11 +27,14 @@ static void insert(int a, int b)
 
 for (i = a; i < b; i++) {
 uint32_t hash;
+void *existing;
 
 arr[i] = i;
 hash = i;
 
-qht_insert(, [i], hash);
+g_assert_true(!qht_insert(, [i], hash));
+existing = qht_insert(, [i], hash);
+g_assert_true(existing == [i]);
 }
 }
 
diff --git a/util/qht.c b/util/qht.c
index dcb3ee1..f9f49a9 100644
--- a/util/qht.c
+++ b/util/qht.c
@@ -511,9 +511,9 @@ void *qht_lookup(struct qht *ht, const void *userp, 
uint32_t hash)
 }
 
 /* call with head->lock held */
-static bool qht_insert__locked(struct qht *ht, struct qht_map *map,
-   struct qht_bucket *head, void *p, uint32_t hash,
-   bool *needs_resize)
+static void *qht_insert__locked(struct qht *ht, struct qht_map *map,
+struct qht_bucket *head, void *p, uint32_t 
hash,
+bool *needs_resize)
 {
 struct qht_bucket *b = head;
 struct qht_bucket *prev = NULL;
@@ -523,8 +523,9 @@ static bool qht_insert__locked(struct qht *ht, struct 
qht_map *map,
 do {
 for (i = 0; i < QHT_BUCKET_ENTRIES; i++) {
 if (b->pointers[i]) {
-if (unlikely(b->pointers[i] == p)) {
-return false;
+if (unlikely(b->hashes[i] == hash &&
+ ht->cmp(b->pointers[i], p))) {
+return b->pointers[i];
 }
 } else {
 goto found;
@@ -553,7 +554,7 @@ static bool qht_insert__locked(struct qht *ht, struct 
qht_map *map,
 atomic_set(>hashes[i], hash);
 atomic_set(>pointers[i], p);
 seqlock_write_end(>sequence);
-return true;
+return NULL;
 }
 
 static __attribute__((noinline)) void qht_grow_maybe(struct qht *ht)
@@ -577,12 +578,12 @@ static __attribute__((noinline)) void 
qht_grow_maybe(struct qht *ht)
 qemu_mutex_unlock(>lock);
 }
 
-bool qht_insert(struct qht *ht, void *p, uint32_t hash)
+void *qht_insert(struct qht *ht, void *p, uint32_t hash)
 {
 struct qht_bucket *b;
 struct qht_map *map;
 bool needs_resize = false;
-bool ret;
+void *ret;
 
 /* NULL pointers are not supported */
 qht_debug_assert(p);
-- 
2.7.4




[Qemu-devel] [PATCH 01/16] qht: require a default comparison function

2018-02-26 Thread Emilio G. Cota
qht_lookup now uses the default cmp function. qht_lookup_custom is defined
to retain the old behaviour, that is a cmp function is explicitly provided.

qht_insert will gain use of the default cmp in the next patch.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/cpu-exec.c  |  4 ++--
 accel/tcg/translate-all.c | 16 +++-
 include/qemu/qht.h| 23 +++
 tests/qht-bench.c | 14 +++---
 tests/test-qht.c  | 15 ++-
 util/qht.c| 14 +++---
 6 files changed, 64 insertions(+), 22 deletions(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 280200f..ec57564 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -293,7 +293,7 @@ struct tb_desc {
 uint32_t trace_vcpu_dstate;
 };
 
-static bool tb_cmp(const void *p, const void *d)
+static bool tb_lookup_cmp(const void *p, const void *d)
 {
 const TranslationBlock *tb = p;
 const struct tb_desc *desc = d;
@@ -338,7 +338,7 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, 
target_ulong pc,
 phys_pc = get_page_addr_code(desc.env, pc);
 desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
 h = tb_hash_func(phys_pc, pc, flags, cf_mask, *cpu->trace_dstate);
-return qht_lookup(_ctx.htable, tb_cmp, , h);
+return qht_lookup_custom(_ctx.htable, tb_lookup_cmp, , h);
 }
 
 void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 67795cd..1cf10f8 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -785,11 +785,25 @@ static inline void code_gen_alloc(size_t tb_size)
 qemu_mutex_init(_ctx.tb_lock);
 }
 
+static bool tb_cmp(const void *ap, const void *bp)
+{
+const TranslationBlock *a = ap;
+const TranslationBlock *b = bp;
+
+return a->pc == b->pc &&
+a->cs_base == b->cs_base &&
+a->flags == b->flags &&
+(tb_cflags(a) & CF_HASH_MASK) == (tb_cflags(b) & CF_HASH_MASK) &&
+a->trace_vcpu_dstate == b->trace_vcpu_dstate &&
+a->page_addr[0] == b->page_addr[0] &&
+a->page_addr[1] == b->page_addr[1];
+}
+
 static void tb_htable_init(void)
 {
 unsigned int mode = QHT_MODE_AUTO_RESIZE;
 
-qht_init(_ctx.htable, CODE_GEN_HTABLE_SIZE, mode);
+qht_init(_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode);
 }
 
 /* Must be called before using the QEMU cpus. 'tb_size' is the size
diff --git a/include/qemu/qht.h b/include/qemu/qht.h
index 531aa95..dd512bf 100644
--- a/include/qemu/qht.h
+++ b/include/qemu/qht.h
@@ -11,8 +11,11 @@
 #include "qemu/thread.h"
 #include "qemu/qdist.h"
 
+typedef bool (*qht_cmp_func_t)(const void *a, const void *b);
+
 struct qht {
 struct qht_map *map;
+qht_cmp_func_t cmp;
 QemuMutex lock; /* serializes setters of ht->map */
 unsigned int mode;
 };
@@ -47,10 +50,12 @@ typedef void (*qht_iter_func_t)(struct qht *ht, void *p, 
uint32_t h, void *up);
 /**
  * qht_init - Initialize a QHT
  * @ht: QHT to be initialized
+ * @cmp: default comparison function. Cannot be NULL.
  * @n_elems: number of entries the hash table should be optimized for.
  * @mode: bitmask with OR'ed QHT_MODE_*
  */
-void qht_init(struct qht *ht, size_t n_elems, unsigned int mode);
+void qht_init(struct qht *ht, qht_cmp_func_t cmp, size_t n_elems,
+  unsigned int mode);
 
 /**
  * qht_destroy - destroy a previously initialized QHT
@@ -78,7 +83,7 @@ void qht_destroy(struct qht *ht);
 bool qht_insert(struct qht *ht, void *p, uint32_t hash);
 
 /**
- * qht_lookup - Look up a pointer in a QHT
+ * qht_lookup_custom - Look up a pointer using a custom comparison function.
  * @ht: QHT to be looked up
  * @func: function to compare existing pointers against @userp
  * @userp: pointer to pass to @func
@@ -94,8 +99,18 @@ bool qht_insert(struct qht *ht, void *p, uint32_t hash);
  * Returns the corresponding pointer when a match is found.
  * Returns NULL otherwise.
  */
-void *qht_lookup(struct qht *ht, qht_lookup_func_t func, const void *userp,
- uint32_t hash);
+void *qht_lookup_custom(struct qht *ht, qht_lookup_func_t func,
+const void *userp, uint32_t hash);
+
+/**
+ * qht_lookup - Look up a pointer in a QHT
+ * @ht: QHT to be looked up
+ * @userp: pointer to pass to @func
+ * @hash: hash of the pointer to be looked up
+ *
+ * Calls qht_lookup_custom() using @ht's default comparison function.
+ */
+void *qht_lookup(struct qht *ht, const void *userp, uint32_t hash);
 
 /**
  * qht_remove - remove a pointer from the hash table
diff --git a/tests/qht-bench.c b/tests/qht-bench.c
index 4cabdfd..c94ac25 100644
--- a/tests/qht-bench.c
+++ b/tests/qht-bench.c
@@ -93,10 +93,10 @@ static void usage_complete(int argc, char *argv[])
 exit(-1);
 }
 
-static bool is_equal(const void *obj, const void *userp)
+static bool is_equal(const void *ap, const void *bp)
 {
-const long *a = obj;
-const long *b = userp;

[Qemu-devel] [PATCH 04/16] tcg: move tb_ctx.tb_phys_invalidate_count to tcg_ctx

2018-02-26 Thread Emilio G. Cota
Thereby making it per-TCGContext. Once we remove tb_lock, this will
avoid an atomic increment every time a TB is invalidated.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/translate-all.c |  5 +++--
 include/exec/tb-context.h |  1 -
 tcg/tcg.c | 14 ++
 tcg/tcg.h |  3 +++
 4 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 3a51d49..20ad3fc 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1072,7 +1072,8 @@ void tb_phys_invalidate(TranslationBlock *tb, 
tb_page_addr_t page_addr)
 /* suppress any remaining jumps to this TB */
 tb_jmp_unlink(tb);
 
-tb_ctx.tb_phys_invalidate_count++;
+atomic_set(_ctx->tb_phys_invalidate_count,
+   tcg_ctx->tb_phys_invalidate_count + 1);
 }
 
 #ifdef CONFIG_SOFTMMU
@@ -1862,7 +1863,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
 cpu_fprintf(f, "\nStatistics:\n");
 cpu_fprintf(f, "TB flush count  %u\n",
 atomic_read(_ctx.tb_flush_count));
-cpu_fprintf(f, "TB invalidate count %d\n", 
tb_ctx.tb_phys_invalidate_count);
+cpu_fprintf(f, "TB invalidate count %zu\n", 
tcg_tb_phys_invalidate_count());
 cpu_fprintf(f, "TLB flush count %zu\n", tlb_flush_count());
 tcg_dump_info(f, cpu_fprintf);
 }
diff --git a/include/exec/tb-context.h b/include/exec/tb-context.h
index d8472c8..8c9b49c 100644
--- a/include/exec/tb-context.h
+++ b/include/exec/tb-context.h
@@ -37,7 +37,6 @@ struct TBContext {
 
 /* statistics */
 unsigned tb_flush_count;
-int tb_phys_invalidate_count;
 };
 
 extern TBContext tb_ctx;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index b471708..a7b596e 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -791,6 +791,20 @@ size_t tcg_code_capacity(void)
 return capacity;
 }
 
+size_t tcg_tb_phys_invalidate_count(void)
+{
+unsigned int n_ctxs = atomic_read(_tcg_ctxs);
+unsigned int i;
+size_t total = 0;
+
+for (i = 0; i < n_ctxs; i++) {
+const TCGContext *s = atomic_read(_ctxs[i]);
+
+total += atomic_read(>tb_phys_invalidate_count);
+}
+return total;
+}
+
 /* pool based memory allocation */
 void *tcg_malloc_internal(TCGContext *s, int size)
 {
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 8bf29cc..9dd9448 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -694,6 +694,8 @@ struct TCGContext {
 /* Threshold to flush the translated code buffer.  */
 void *code_gen_highwater;
 
+size_t tb_phys_invalidate_count;
+
 /* Track which vCPU triggers events */
 CPUState *cpu;  /* *_trans */
 
@@ -852,6 +854,7 @@ size_t tcg_code_capacity(void);
 
 void tcg_tb_insert(TranslationBlock *tb);
 void tcg_tb_remove(TranslationBlock *tb);
+size_t tcg_tb_phys_invalidate_count(void);
 TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr);
 void tcg_tb_foreach(GTraverseFunc func, gpointer user_data);
 size_t tcg_nb_tbs(void);
-- 
2.7.4




[Qemu-devel] [PATCH 09/16] translate-all: move tb_invalidate_phys_page_range up in the file

2018-02-26 Thread Emilio G. Cota
This greatly simplifies next commit's diff.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/translate-all.c | 77 ---
 1 file changed, 39 insertions(+), 38 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index a98e182..4cb03f1 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1371,44 +1371,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
 
 /*
  * Invalidate all TBs which intersect with the target physical address range
- * [start;end[. NOTE: start and end may refer to *different* physical pages.
- * 'is_cpu_write_access' should be true if called from a real cpu write
- * access: the virtual CPU will exit the current TB if code is modified inside
- * this TB.
- *
- * Called with mmap_lock held for user-mode emulation, grabs tb_lock
- * Called with tb_lock held for system-mode emulation
- */
-static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t 
end)
-{
-tb_page_addr_t next;
-
-for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- start < end;
- start = next, next += TARGET_PAGE_SIZE) {
-tb_page_addr_t bound = MIN(next, end);
-
-tb_invalidate_phys_page_range(start, bound, 0);
-}
-}
-
-#ifdef CONFIG_SOFTMMU
-void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
-{
-assert_tb_locked();
-tb_invalidate_phys_range_1(start, end);
-}
-#else
-void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
-{
-assert_memory_lock();
-tb_lock();
-tb_invalidate_phys_range_1(start, end);
-tb_unlock();
-}
-#endif
-/*
- * Invalidate all TBs which intersect with the target physical address range
  * [start;end[. NOTE: start and end must refer to the *same* physical page.
  * 'is_cpu_write_access' should be true if called from a real cpu write
  * access: the virtual CPU will exit the current TB if code is modified inside
@@ -1505,6 +1467,45 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, 
tb_page_addr_t end,
 #endif
 }
 
+/*
+ * Invalidate all TBs which intersect with the target physical address range
+ * [start;end[. NOTE: start and end may refer to *different* physical pages.
+ * 'is_cpu_write_access' should be true if called from a real cpu write
+ * access: the virtual CPU will exit the current TB if code is modified inside
+ * this TB.
+ *
+ * Called with mmap_lock held for user-mode emulation, grabs tb_lock
+ * Called with tb_lock held for system-mode emulation
+ */
+static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t 
end)
+{
+tb_page_addr_t next;
+
+for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+ start < end;
+ start = next, next += TARGET_PAGE_SIZE) {
+tb_page_addr_t bound = MIN(next, end);
+
+tb_invalidate_phys_page_range(start, bound, 0);
+}
+}
+
+#ifdef CONFIG_SOFTMMU
+void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
+{
+assert_tb_locked();
+tb_invalidate_phys_range_1(start, end);
+}
+#else
+void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end)
+{
+assert_memory_lock();
+tb_lock();
+tb_invalidate_phys_range_1(start, end);
+tb_unlock();
+}
+#endif
+
 #ifdef CONFIG_SOFTMMU
 /* len must be <= 8 and start must be a multiple of len.
  * Called via softmmu_template.h when code areas are written to with
-- 
2.7.4




[Qemu-devel] [PATCH 08/16] translate-all: work page-by-page in tb_invalidate_phys_range_1

2018-02-26 Thread Emilio G. Cota
So that we pass a same-page range to tb_invalidate_phys_page_range,
instead of always passing an end address that could be on a different
page.

As discussed with Peter Maydell on the list [1], tb_invalidate_phys_page_range
doesn't actually do much with 'end', which explains why we have never
hit a bug despite going against what the comment on top of
tb_invalidate_phys_page_range requires:

> * Invalidate all TBs which intersect with the target physical address range
> * [start;end[. NOTE: start and end must refer to the *same* physical page.

The appended honours the comment, which avoids confusion.

While at it, rework the loop into a for loop, which is less error prone
(e.g. "continue" won't result in an infinite loop).

[1] https://lists.gnu.org/archive/html/qemu-devel/2017-07/msg09165.html

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/translate-all.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 816419a..a98e182 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -1381,10 +1381,14 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
  */
 static void tb_invalidate_phys_range_1(tb_page_addr_t start, tb_page_addr_t 
end)
 {
-while (start < end) {
-tb_invalidate_phys_page_range(start, end, 0);
-start &= TARGET_PAGE_MASK;
-start += TARGET_PAGE_SIZE;
+tb_page_addr_t next;
+
+for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+ start < end;
+ start = next, next += TARGET_PAGE_SIZE) {
+tb_page_addr_t bound = MIN(next, end);
+
+tb_invalidate_phys_page_range(start, bound, 0);
 }
 }
 
-- 
2.7.4




[Qemu-devel] [PATCH 00/16] tcg: tb_lock removal redux v1

2018-02-26 Thread Emilio G. Cota
With this set we finally remove tb_lock. The performance gains
when booting a guest are compelling at low core counts. However,
beyond 8 cores performance doesn't improve due to unrelated
contention--see results in the last patch of the series
("tcg: remove tb_lock").

I have another series that greatly reduces this other contention by
using per-CPU locks instead of the BQL to keep track of a subset
of CPUState. But that series is pretty large so let's deal with
this first.

You can fetch the patches from:
  https://github.com/cota/qemu/tree/tb-lock-removal-redux-v1

Thanks,

Emilio




[Qemu-devel] [PATCH 07/16] translate-all: remove hole in PageDesc

2018-02-26 Thread Emilio G. Cota
Groundwork for supporting parallel TCG generation.

Move the hole to the end of the struct, so that a u32
field can be added there without bloating the struct.

Signed-off-by: Emilio G. Cota 
---
 accel/tcg/translate-all.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index f2bfa71..816419a 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -107,8 +107,8 @@ typedef struct PageDesc {
 #ifdef CONFIG_SOFTMMU
 /* in order to optimize self modifying code, we count the number
of lookups we do to a given page to use a bitmap */
-unsigned int code_write_count;
 unsigned long *code_bitmap;
+unsigned int code_write_count;
 #else
 unsigned long flags;
 #endif
-- 
2.7.4




Re: [Qemu-devel] [RFC] exec: eliminate ram naming issue as migration

2018-02-26 Thread Tan, Jianfeng


> -Original Message-
> From: Paolo Bonzini [mailto:pbonz...@redhat.com]
> Sent: Monday, February 26, 2018 10:43 PM
> To: Igor Mammedov; Tan, Jianfeng
> Cc: Jason Wang; Maxime Coquelin; qemu-devel@nongnu.org; Michael S .
> Tsirkin
> Subject: Re: [Qemu-devel] [RFC] exec: eliminate ram naming issue as
> migration
> 
> On 26/02/2018 13:55, Igor Mammedov wrote:
> >>> So how about just adding a new option --mem-share to decide if that's a
> >>> private memory or shared memory? That seems much straightforward
> way
> > Above options are legacy (which we can't remove for compat reasons),
> > their replacement is 'memory-backend-file' backend which has all of
> > the above including 'share' property.
> 
> More precisely, we have added "-object memory-backend-file" to avoid
> proliferation of options related to memory.  Besides unifying the cases
> of 1 and >1 NUMA node, using -object also has the advantage of
> supporting memory hotplug.
> 
> You wrote "I find adding a backend for nonnuma pc RAM is roundabout way"
> but basically the command line says "this VM has only one NUMA node,
> backed by this memory object" which is a precise description of what the
> VM memory looks like.
> 
> > So just add 'memdev' property to machine and reuse memory-backend-file
> > with it instead of duplicating functionality in the legacy code.
> 
> That would however also have a different RAMBlock id, effectively
> producing the same output as "-numa node,memdev=...".

Is it possible that we force that RAMBlock id to be "pc.ram"?

> 
> I think this should be solved at the libvirt level.  Libvirt should
> write in the migration XML cookie whether the VM is using -object or
> -mem-path to declare its memory, and newly-started VMs should always use
> -object.  This won't fix the problem for VMs that are already running,
> but it will fix it the next time they are started.

In this case, we return to the start point :-)

Thanks,
Jianfeng


Re: [Qemu-devel] [RFC] exec: eliminate ram naming issue as migration

2018-02-26 Thread Tan, Jianfeng


> -Original Message-
> From: Igor Mammedov [mailto:imamm...@redhat.com]
> Sent: Monday, February 26, 2018 8:56 PM
> To: Tan, Jianfeng
> Cc: Paolo Bonzini; Jason Wang; Maxime Coquelin; qemu-devel@nongnu.org;
> Michael S . Tsirkin
> Subject: Re: [Qemu-devel] [RFC] exec: eliminate ram naming issue as
> migration
> 
> On Sat, 24 Feb 2018 03:11:30 +
> "Tan, Jianfeng"  wrote:
> 
> > > -Original Message-
> > > From: Tan, Jianfeng
> > > Sent: Saturday, February 24, 2018 11:08 AM
> > > To: 'Igor Mammedov'
> > > Cc: Paolo Bonzini; Jason Wang; Maxime Coquelin; qemu-
> de...@nongnu.org;
> > > Michael S . Tsirkin
> > > Subject: RE: [Qemu-devel] [RFC] exec: eliminate ram naming issue as
> > > migration
> > >
> > > Hi Igor and all,
> > >
> > > > -Original Message-
> > > > From: Igor Mammedov [mailto:imamm...@redhat.com]
> > > > Sent: Thursday, February 8, 2018 7:30 PM
> > > > To: Tan, Jianfeng
> > > > Cc: Paolo Bonzini; Jason Wang; Maxime Coquelin; qemu-
> > > de...@nongnu.org;
> > > > Michael S . Tsirkin
> > > > Subject: Re: [Qemu-devel] [RFC] exec: eliminate ram naming issue as
> > > > migration
> > > >
> > > [...]
> > > > > > It could be solved by adding memdev option to machine,
> > > > > > which would allow to specify backend object. And then on
> > > > > > top make -mem-path alias new option to clean thing up.
> > > > >
> > > > > Do you mean?
> > > > >
> > > > > src vm: -m xG
> > > > > dst vm: -m xG,memdev=pc.ram -object memory-backend-
> > > file,id=pc.ram,size=xG,mem-path=xxx,share=on ...
> > > > Yep, I've meant something like it
> > > >
> > > > src vm: -m xG,memdev=SHARED_RAM -object memory-backend-
> > > file,id=SHARED_RAM,size=xG,mem-path=xxx,share=on
> > > > dst vm: -m xG,memdev=SHARED_RAM -object memory-backend-
> > > file,id=SHARED_RAM,size=xG,mem-path=xxx,share=on
> > >
> > > After a second thought, I find adding a backend for nonnuma pc RAM is
> > > roundabout way.
> > >
> > > And we actually have an existing way to add a file-backed RAM: commit
> > > c902760fb25f ("Add option to use file backed guest memory"). Basically,
> this
> > > commit adds two options, --mem-path and --mem-prealloc, without
> specify
> > > a backend explicitly.
> > >
> > > So how about just adding a new option --mem-share to decide if that's a
> > > private memory or shared memory? That seems much straightforward
> way
> Above options are legacy (which we can't remove for compat reasons),
> their replacement is 'memory-backend-file' backend which has all of
> the above including 'share' property.

OK, such options are legacy. I've no idea of that. Thanks! That makes sense.

> 
> So just add 'memdev' property to machine and reuse memory-backend-file
> with it instead of duplicating functionality in the legacy code.

To "-m" or "-machine"?




Re: [Qemu-devel] Windows balloon driver PFN issue

2018-02-26 Thread Peter Xu
On Mon, Feb 26, 2018 at 10:54:11AM +0200, Gal Hammer wrote:
> Hi Peter,
> 
> On Fri, Feb 2, 2018 at 12:11 PM, Peter Xu  wrote:
> > On Thu, Feb 01, 2018 at 02:48:20PM +0200, Michael S. Tsirkin wrote:
> >
> > [...]
> >
> >> > > > > PFN is GPA>>12.  Do you have more than 1<<44 bytes of memory in 
> >> > > > > this VM then?
> >> > > >
> >> > > > No.  But isn't it still not good to drop the page at offset zero (and
> >> > > > drop it NNN times)?
> >> > >
> >> > > Absolutely - looks like a bug. I just don't know why does this happen.
> >> >
> >> > IMHO if we are using a PFN array like this:
> >> >
> >> >u64 pfn_array[];
> >> >
> >> > In the windows guest driver, then we'll see this (as mentioned
> >> > above).  But for sure this is wild guess of mine.
> >>
> >> I don't see code like this anywhere in the windows balloon
> >> driver. It's here:
> >> https://github.com/virtio-win/kvm-guest-drivers-windows.git
> >
> > Thanks for the pointer.  I had a quick glance, the PFN array is
> > defined as:
> >
> > PPFN_NUMBER pfns_table;
> >
> > But I don't know what's sizeof(PPFN_NUMBER). :(
> 
> sizeof(PPFN_NUMBER) = sizeof(void*)
> 
> PFN_NUMBER is of an unsigned long type. Although it doesn't matter, as
> a pointer to it is always the same size, 4 bytes in a 32-bit CPU and 8
> bytes in 64-bit one.

Ah, it's not really PPFN_NUMBER that matters, it should be
PFN_NUMBER.  This is how the PFNs are copied in windows driver:

RtlCopyMemory(ctx->pfns_table, MmGetMdlPfnArray(pPageMdl),
ctx->num_pfns * sizeof(PFN_NUMBER));

I don't know these APIs, but it looks like MmGetMdlPfnArray() is
returning an PFN_NUMBER array.

And I don't know how the balloon spec says, but in QEMU it's always
using uint32_t as PFN.  See virtio_balloon_handle_output():

while (iov_to_buf(elem->out_sg, elem->out_num, offset, , 4) == 4)

So I guess only if sizeof(PFN_NUMBER)==4 is true on both 32/64 bits
platforms of windows, otherwise there might be a problem.

Thanks,

-- 
Peter Xu



Re: [Qemu-devel] [PATCH v2 1/2] xilinx_spips: Enable only two slaves when reading/writing with stripe

2018-02-26 Thread Alistair Francis
On Fri, Feb 23, 2018 at 3:22 PM, Francisco Iglesias
 wrote:
> Assert only the lower cs on bus 0 and upper cs on bus 1 when both buses and
> chip selects are enabled (e.g reading/writing with stripe).
>
> Signed-off-by: Francisco Iglesias 

Reviewed-by: Alistair Francis 
Tested-by: Alistair Francis 

Alistair

> ---
>  hw/ssi/xilinx_spips.c | 41 +
>  1 file changed, 37 insertions(+), 4 deletions(-)
>
> diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
> index 8af36ca3d4..0cb484ecf4 100644
> --- a/hw/ssi/xilinx_spips.c
> +++ b/hw/ssi/xilinx_spips.c
> @@ -223,7 +223,7 @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int 
> field)
>  {
>  int i;
>
> -for (i = 0; i < s->num_cs; i++) {
> +for (i = 0; i < s->num_cs * s->num_busses; i++) {
>  bool old_state = s->cs_lines_state[i];
>  bool new_state = field & (1 << i);
>
> @@ -234,7 +234,7 @@ static void xilinx_spips_update_cs(XilinxSPIPS *s, int 
> field)
>  }
>  qemu_set_irq(s->cs_lines[i], !new_state);
>  }
> -if (!(field & ((1 << s->num_cs) - 1))) {
> +if (!(field & ((1 << (s->num_cs * s->num_busses)) - 1))) {
>  s->snoop_state = SNOOP_CHECKING;
>  s->cmd_dummies = 0;
>  s->link_state = 1;
> @@ -248,7 +248,40 @@ static void 
> xlnx_zynqmp_qspips_update_cs_lines(XlnxZynqMPQSPIPS *s)
>  {
>  if (s->regs[R_GQSPI_GF_SNAPSHOT]) {
>  int field = ARRAY_FIELD_EX32(s->regs, GQSPI_GF_SNAPSHOT, 
> CHIP_SELECT);
> -xilinx_spips_update_cs(XILINX_SPIPS(s), field);
> +bool upper_cs_sel = field & (1 << 1);
> +bool lower_cs_sel = field & 1;
> +bool bus0_enabled;
> +bool bus1_enabled;
> +uint8_t buses;
> +int cs = 0;
> +
> +buses = ARRAY_FIELD_EX32(s->regs, GQSPI_GF_SNAPSHOT, 
> DATA_BUS_SELECT);
> +bus0_enabled = buses & 1;
> +bus1_enabled = buses & (1 << 1);
> +
> +if (bus0_enabled && bus1_enabled) {
> +if (lower_cs_sel) {
> +cs |= 1;
> +}
> +if (upper_cs_sel) {
> +cs |= 1 << 3;
> +}
> +} else if (bus0_enabled) {
> +if (lower_cs_sel) {
> +cs |= 1;
> +}
> +if (upper_cs_sel) {
> +cs |= 1 << 1;
> +}
> +} else if (bus1_enabled) {
> +if (lower_cs_sel) {
> +cs |= 1 << 2;
> +}
> +if (upper_cs_sel) {
> +cs |= 1 << 3;
> +}
> +}
> +xilinx_spips_update_cs(XILINX_SPIPS(s), cs);
>  }
>  }
>
> @@ -260,7 +293,7 @@ static void xilinx_spips_update_cs_lines(XilinxSPIPS *s)
>  if (num_effective_busses(s) == 2) {
>  /* Single bit chip-select for qspi */
>  field &= 0x1;
> -field |= field << 1;
> +field |= field << 3;
>  /* Dual stack U-Page */
>  } else if (s->regs[R_LQSPI_CFG] & LQSPI_CFG_TWO_MEM &&
> s->regs[R_LQSPI_STS] & LQSPI_CFG_U_PAGE) {
> --
> 2.11.0
>
>



Re: [Qemu-devel] [PATCH v4 03/11] sdcard: add a trace event for command responses

2018-02-26 Thread Alistair Francis
On Thu, Feb 15, 2018 at 2:05 PM, Philippe Mathieu-Daudé  wrote:
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/sd/sd.c | 27 ---
>  hw/sd/trace-events |  1 +
>  2 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/hw/sd/sd.c b/hw/sd/sd.c
> index 72e9b47e34..8f72cde534 100644
> --- a/hw/sd/sd.c
> +++ b/hw/sd/sd.c
> @@ -153,6 +153,27 @@ static const char *sd_state_name(enum SDCardStates state)
>  return state_name[state];
>  }
>
> +static const char *sd_response_name(sd_rsp_type_t rsp)
> +{
> +static const char *response_name[] = {
> +[sd_r0] = "RESP#0 (no response)",
> +[sd_r1] = "RESP#1 (normal cmd)",
> +[sd_r2_i]   = "RESP#2 (CID reg)",
> +[sd_r2_s]   = "RESP#2 (CSD reg)",
> +[sd_r3] = "RESP#3 (OCR reg)",
> +[sd_r6] = "RESP#6 (RCA)",
> +[sd_r7] = "RESP#7 (operating voltage)",
> +};
> +if (rsp == sd_illegal) {
> +return "ILLEGAL RESP";
> +}
> +if (rsp == sd_r1b) {
> +rsp = sd_r1;
> +}
> +assert(rsp <= ARRAY_SIZE(response_name));
> +return response_name[rsp];
> +}
> +
>  static uint8_t sd_get_dat_lines(SDState *sd)
>  {
>  return sd->enable ? sd->dat_lines : 0;
> @@ -1596,10 +1617,12 @@ send_response:
>
>  case sd_r0:
>  case sd_illegal:
> -default:
>  rsplen = 0;
>  break;
> +default:
> +g_assert_not_reached();
>  }
> +trace_sdcard_response(sd_response_name(rtype), rsplen);
>
>  if (rtype != sd_illegal) {
>  /* Clear the "clear on valid command" status bits now we've
> @@ -1616,8 +1639,6 @@ send_response:
>  DPRINTF(" %02x", response[i]);
>  }
>  DPRINTF(" state %d\n", sd->state);
> -} else {
> -DPRINTF("No response %d\n", sd->state);
>  }
>  #endif
>
> diff --git a/hw/sd/trace-events b/hw/sd/trace-events
> index 75dac5a2cd..b2aa19ec0d 100644
> --- a/hw/sd/trace-events
> +++ b/hw/sd/trace-events
> @@ -26,6 +26,7 @@ sdhci_capareg(const char *desc, uint16_t val) "%s: %u"
>  # hw/sd/sd.c
>  sdcard_normal_command(uint8_t cmd, uint32_t arg, const char *state) "CMD%d 
> arg 0x%08x (state %s)"
>  sdcard_app_command(uint8_t acmd, uint32_t arg) "ACMD%d arg 0x%08x"
> +sdcard_response(const char *rspdesc, int rsplen) "%s (sz:%d)"
>  sdcard_read_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 0x%x"
>  sdcard_write_block(uint64_t addr, uint32_t len) "addr 0x%" PRIx64 " size 
> 0x%x"
>
> --
> 2.16.1
>
>



[Qemu-devel] [PATCH v2 resend] block/mirror: change the semantic of 'force' of block-job-cancel

2018-02-26 Thread Liang Li
When doing drive mirror to a low speed shared storage, if there was heavy
BLK IO write workload in VM after the 'ready' event, drive mirror block job
can't be canceled immediately, it would keep running until the heavy BLK IO
workload stopped in the VM.

Libvirt depends on the current block-job-cancel semantics, which is that
when used without a flag after the 'ready' event, the command blocks
until data is in sync.  However, these semantics are awkward in other
situations, for example, people may use drive mirror for realtime
backups while still wanting to use block live migration.  Libvirt cannot
start a block live migration while another drive mirror is in progress,
but the user would rather abandon the backup attempt as broken and
proceed with the live migration than be stuck waiting for the current
drive mirror backup to finish.

The drive-mirror command already includes a 'force' flag, which libvirt
does not use, although it documented the flag as only being useful to
quit a job which is paused.  However, since quitting a paused job has
the same effect as abandoning a backup in a non-paused job (namely, the
destination file is not in sync, and the command completes immediately),
we can just improve the documentation to make the force flag obviously
useful.

Cc: Paolo Bonzini 
Cc: Jeff Cody 
Cc: Kevin Wolf 
Cc: Max Reitz 
Cc: Eric Blake 
Cc: John Snow 
Reported-by: Huaitong Han 
Signed-off-by: Huaitong Han 
Signed-off-by: Liang Li 
---
 block/mirror.c| 10 --
 blockdev.c|  4 ++--
 blockjob.c| 12 +++-
 hmp-commands.hx   |  3 ++-
 include/block/blockjob.h  |  9 -
 qapi/block-core.json  |  5 +++--
 tests/test-blockjob-txn.c |  8 
 7 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index c9badc1..9190b1c 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -869,11 +869,8 @@ static void coroutine_fn mirror_run(void *opaque)
 
 ret = 0;
 trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
-if (!s->synced) {
-block_job_sleep_ns(>common, delay_ns);
-if (block_job_is_cancelled(>common)) {
-break;
-}
+if (block_job_is_cancelled(>common) && s->common.force) {
+break;
 } else if (!should_complete) {
 delay_ns = (s->in_flight == 0 && cnt == 0 ? SLICE_TIME : 0);
 block_job_sleep_ns(>common, delay_ns);
@@ -887,7 +884,8 @@ immediate_exit:
  * or it was cancelled prematurely so that we do not guarantee that
  * the target is a copy of the source.
  */
-assert(ret < 0 || (!s->synced && block_job_is_cancelled(>common)));
+assert(ret < 0 || ((s->common.force || !s->synced) &&
+   block_job_is_cancelled(>common)));
 assert(need_drain);
 mirror_wait_for_all_io(s);
 }
diff --git a/blockdev.c b/blockdev.c
index 8e977ee..039f156 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -145,7 +145,7 @@ void blockdev_mark_auto_del(BlockBackend *blk)
 aio_context_acquire(aio_context);
 
 if (bs->job) {
-block_job_cancel(bs->job);
+block_job_cancel(bs->job, false);
 }
 
 aio_context_release(aio_context);
@@ -3802,7 +3802,7 @@ void qmp_block_job_cancel(const char *device,
 }
 
 trace_qmp_block_job_cancel(job);
-block_job_cancel(job);
+block_job_cancel(job, force);
 out:
 aio_context_release(aio_context);
 }
diff --git a/blockjob.c b/blockjob.c
index f5cea84..9b0b1a4 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -365,7 +365,7 @@ static void block_job_completed_single(BlockJob *job)
 block_job_unref(job);
 }
 
-static void block_job_cancel_async(BlockJob *job)
+static void block_job_cancel_async(BlockJob *job, bool force)
 {
 if (job->iostatus != BLOCK_DEVICE_IO_STATUS_OK) {
 block_job_iostatus_reset(job);
@@ -376,6 +376,8 @@ static void block_job_cancel_async(BlockJob *job)
 job->pause_count--;
 }
 job->cancelled = true;
+/* To prevent 'force == false' overriding a previous 'force == true' */
+job->force |= force;
 }
 
 static int block_job_finish_sync(BlockJob *job,
@@ -437,7 +439,7 @@ static void block_job_completed_txn_abort(BlockJob *job)
  * on the caller, so leave it. */
 QLIST_FOREACH(other_job, >jobs, txn_list) {
 if (other_job != job) {
-block_job_cancel_async(other_job);
+block_job_cancel_async(other_job, false);
 }
 }
 while (!QLIST_EMPTY(>jobs)) {
@@ -542,10 +544,10 @@ void block_job_user_resume(BlockJob *job)
 }
 }
 
-void block_job_cancel(BlockJob *job)
+void block_job_cancel(BlockJob *job, bool force)
 {
 if 

[Qemu-devel] QEMU Status Update

2018-02-26 Thread Michael Clark
Hi Folks,

Just a quick update regarding the process of submitting the RISC-V QEMU port 
upstream for inclusion in the QEMU 2.12 release this coming April.

We’ve just submitted our first pull request after receiving positive feedback 
from the v6 patch series submitted last week. We recently contacted 
contributors in response to feedback from Red Hat, to relicense the code as 
GPLv2+ which is the main change in this most recent v7 patch series:

- http://lists.nongnu.org/archive/html/qemu-devel/2018-02/msg06489.html
- http://lists.nongnu.org/archive/html/qemu-devel/2018-02/msg05778.html
- http://lists.nongnu.org/archive/html/qemu-devel/2018-02/msg06132.html

I’d also like to take this opportunity to point out the riscv-qemu wiki where 
we have moved some of the documentation for the port:

- https://github.com/riscv/riscv-qemu/wiki

We no longer have a custom README.md in the repo given the code-base is now 
based on upstream QEMU. I’ve added wiki links to SiFive’s freedom-u-sdk which 
creates build recipes to create qemu and a bootable buildroot-based linux image 
that will run on the freedom U series VC707 FPGA, SiFive’s new HiFive Unleashed 
board and of course riscv-qemu. I’ve also added links to the Fedora RISC-V 
Architecture page and the Debian RISC-V Architecture page which have additional 
links to RISC-V Linux packages and root images.

With the current version of riscv-qemu we are able to run Privileged ISA v1.9.1 
riscv-linux/bbl, on the spike_v1.9.1 machine, Privileged ISA v1.10 
riscv-linux/bbl on the spike_v1.10 and virt machines, HiFive1 binaries on the 
sifive_e300 machine and we have working MTTCG-enabled SMP on the virt machine 
thanks to work done by Stefan O’Rear and Richard Henderson on thread-safe 
atomics.

There is still a lot of future development work that we can switch our 
attention to once the port is upstream. This is a non-exhaustive list, just to 
give you an idea of future work that needs to be done:

- Allow on-the-fly ‘misa’ changes, perhaps with translation cache flushing
- Currently the misa flag is read-only
- Support the rules being discussed for enabling and disabling misa C flag
- Currently QEMU allows instruction fetches on half-word (16-bit) 
boundaries when C is disabled
- Disable MMU when misa S flag is not set
- Currently QEMU allows configuring of the MMU on the E-series machine
- This works because E-series code does not touch the satp register
- Add vendor specific cpu models such as ’sifive-e31’, ’sifive-e51’, 
’sifive-u54’, etc
- Currently we have ‘generic-imacs’, ‘generic-imafdcsu’, etc
- Improve device support
- FIFO and interrupt mode support for the SiFive UART along with Linux 
driver
- PCI host (GPEX) for the ‘virt’ machine to enable virtio-pci
- SPI and GPIO devices for the SiFive boards
- Add generic GPIO based power-off and reset
- Implement HTIF queuing and fix 32-bit support
- Privileged ISA v1.10 and v1.11
- Add support for TSR, TW and TVM flags (priv v1.10)
- Add Hypervisor support (draft priv v1.11)

Thanks to everyone who helped with patch review, testing, patches and pull 
requests. I’d also like to give special thanks to Sagar who did a huge amount 
of the original work on the port. 

Note: I’m explicitly cross-posting as this email is relevant to both the RISC-V 
software development community and the QEMU development community.

Regards,
Michael.


Re: [Qemu-devel] [PATCH v2 3/3] virtio-balloon: add a timer to limit the free page report waiting time

2018-02-26 Thread Michael S. Tsirkin
On Mon, Feb 26, 2018 at 12:35:31PM +0800, Wei Wang wrote:
> On 02/09/2018 08:15 PM, Dr. David Alan Gilbert wrote:
> > * Wei Wang (wei.w.w...@intel.com) wrote:
> > > This patch adds a timer to limit the time that host waits for the free
> > > page hints reported by the guest. Users can specify the time in ms via
> > > "free-page-wait-time" command line option. If a user doesn't specify a
> > > time, host waits till the guest finishes reporting all the free page
> > > hints. The policy (wait for all the free page hints to be reported or
> > > use a time limit) is determined by the orchestration layer.
> > That's kind of a get-out; but there's at least two problems:
> > a) With a timeout of 0 (the default) we might hang forever waiting
> >for the guest; broken guests are just too common, we can't do
> >that.
> > b) Even if we were going to do that, you'd have to make sure that
> >migrate_cancel provided a way out.
> > c) How does that work during a savevm snapshot or when the guest is
> >stopped?
> > d) OK, the timer gives us some safety (except c); but how does the
> >orchestration layer ever come up with a 'safe' value for it?
> >Unless we can suggest a safe value that the orchestration layer
> >can use, or a way they can work it out, then they just wont use
> >it.
> > 
> 
> Hi Dave,
> 
> Sorry for my late response. Please see below:
> 
> a) I think people would just kill the guest if it is broken.

There's no way to know whether it's broken.

> We can also
> change the default timeout value, for example 1 second, which is enough for
> the free page reporting.

There's no way to know whether it's enough.

> b) How about changing it this way: if timeout happens, host sends a stop
> command to the guest, and makes virtio_balloon_poll_free_page_hints()
> "return" immediately (without getting the guest's acknowledge). The "return"
> basically goes back to the migration_thread function:
> while (s->state == MIGRATION_STATUS_ACTIVE ||
>s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE) {
> ...
> }
> 
> migration_cancel sets the state to MIGRATION_CANCELLING, so it will stop the
> migration process.
> 
> c) This optimization needs the guest to report. If the guest is stopped, it
> wouldn't work. How about adding a check of "RUN_STATE" before going into the
> optimization?
> 
> d) Yes. Normally it is faster to wait for the guest to report all the free
> pages. Probably, we can just hardcode a value (e.g. 1s) for now (instead of
> making it configurable by users), this is used to handle the case that the
> guest is broken. What would you think?
> 
> Best,
> Wei

I think all this is premature optimization. It is not at all clear that
anything is gained by delaying migration. Just ask for hints and start
sending pages immediately.  If guest tells us a page is free before it's
sent, we can skip sending it.  OTOH if migration is taking less time to
complete than it takes for guest to respond, then we are better off just
ignoring the hint.

-- 
MST



[Qemu-devel] [PULL] RISC-V QEMU Port Submission

2018-02-26 Thread Michael Clark
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

The following changes since commit 0a773d55ac76c5aa89ed9187a3bc5af8c5c2a6d0:

  maintainers: Add myself as a OpenBSD maintainer (2018-02-23 12:05:07 +)

are available in the git repository at:

  https://github.com/riscv/riscv-qemu.git tags/riscv-qemu-upstream-v7

for you to fetch changes up to 170a9d412ca1eb3b7ae6f6c1ff86dcbdff0fd7a8:

  RISC-V Build Infrastructure (2018-02-27 11:09:43 +1300)

- 
QEMU RISC-V Emulation Support (RV64GC, RV32GC)

With this reelase we have contacted all contributors and have received
agreement to re-license their work as GPLv2+. This release also updates
linux-user/riscv/termbits.h which should fix S390 builds. The spike_v1.9
machine has been renamed to spike_v1.9.1 to match the privileged ISA
version and spike_v1.10 has been made the default machine. All substantial
work in this series has been reviewed or acknowledged and subsequent to
submitting this series we will be submitting signed a pull request.

The git tree for the v7 patch series tree (squashed and rebased):

- - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v7

The git tree for the v1-v6 patch series with review commit history:

- - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v6
- - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v5
- - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v4
- - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v3
- - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v2
- - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v1

*** Known Issues ***

- - Disassembler has some checkpatch warnings for the sake of code brevity
- - scripts/qemu-binfmt-conf.sh has checkpatch warnings due to line length
- - PMP (Physical Memory Protection) is as-of-yet unused and needs testing

*** Changelog ***

v7

- - Make spike_v1.10 the default machine
- - Rename spike_v1.9 to spike_v1.9.1 to match privileged spec version
- - Remove empty target/riscv/trace-events file
- - Monitor ROM 32-bit reset code needs to be target endian
- - Add TARGET_TIOCGPTPEER to linux-user/riscv/termbits.h
- - Add -initrd support to the virt board
- - Fix naming in spike machine interface header
- - Update copyright notice on RISC-V Spike machines
- - Update copyright notice on RISC-V HTIF Console device
- - Change CPU Core and translator to GPLv2+
- - Change RISC-V Disassembler to GPLv2+
- - Change SiFive Test Finisher to GPLv2+
- - Change SiFive CLINT to GPLv2+
- - Change SiFive PRCI to GPLv2+
- - Change SiFive PLIC to GPLv2+
- - Change RISC-V spike machines to GPLv2+
- - Change RISC-V virt machine to GPLv2+
- - Change SiFive E300 machine to GPLv2+
- - Change SiFive U500 machine to GPLv2+
- - Change RISC-V Hart Array to GPLv2+
- - Change RISC-V HTIF device to GPLv2+
- - Change SiFiveUART device to GPLv2+

v6

- - Drop IEEE 754-201x minimumNumber/maximumNumber for fmin/fmax
- - Remove some unnecessary commented debug statements
- - Change RISCV_CPU_TYPE_NAME to use riscv-cpu suffix
- - Define all CPU variants for linux-user
- - qemu_log calls require trailing \n
- - Replace PLIC printfs with qemu_log
- - Tear out unused HTIF code and eliminate shouting debug messages
- - Fix illegal instruction when sfence.vma is passed (rs2) arguments
- - Make updates to PTE accessed and dirty bits atomic
- - Only require atomic PTE updates on MTTCG enabled guests
- - Page fault if accessed or dirty bits can't be updated
- - Fix get_physical_address PTE reads and writes on riscv32
- - Remove erroneous comments from the PLIC
- - Default enable MTTCG
- - Make WFI less conservative
- - Unify local interrupt handling
- - Expunge HTIF interrupts
- - Always access mstatus.mip under a lock
- - Don't implement rdtime/rdtimeh in system mode (bbl emulates them)
- - Implement insreth/cycleh for rv32 and always enable user-mode counters
- - Add GDB stub support for reading and writing CSRs
- - Rename ENABLE_CHARDEV #ifdef from HTIF code
- - Replace bad HTIF ELF code with load_elf symbol callback
- - Convert chained if else fault handlers to switch statements
- - Use RISCV exception codes for linux-user page faults

v5

- - Implement NaN-boxing for flw, set high order bits to 1
- - Use float_muladd_negate_* flags to floatXX_muladd
- - Use IEEE 754-201x minimumNumber/maximumNumber for fmin/fmax
- - Fix TARGET_NR_syscalls
- - Update linux-user/riscv/syscall_nr.h
- - Fix FENCE.I, needs to terminate translation block
- - Adjust unusual convention for interruptno >= 0

v4

- - Add @riscv: since 2.12 to CpuInfoArch
- - Remove misleading little-endian comment from load_kernel
- - Rename cpu-model property to cpu-type
- - Drop some unnecessary inline function attributes
- - Don't allow GDB to set value of x0 register
- - Remove unnecessary empty property lists
- - Add Test Finisher device to implement poweroff in virt machine
- - Implement priv ISA v1.10 trap and sret/mret xPIE/xIE behavior
- - 

Re: [Qemu-devel] [PATCH v7 00/23] RISC-V QEMU Port Submission

2018-02-26 Thread no-reply
Hi,

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

Message-id: 1519683480-33201-1-git-send-email-...@sifive.com
Subject: [Qemu-devel] [PATCH v7 00/23] RISC-V QEMU Port Submission
Type: series

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

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

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

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

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

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag] patchew/1519683480-33201-1-git-send-email-...@sifive.com 
-> patchew/1519683480-33201-1-git-send-email-...@sifive.com
Submodule 'capstone' (git://git.qemu.org/capstone.git) registered for path 
'capstone'
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Submodule 'roms/QemuMacDrivers' (git://git.qemu.org/QemuMacDrivers.git) 
registered for path 'roms/QemuMacDrivers'
Submodule 'roms/SLOF' (git://git.qemu-project.org/SLOF.git) registered for path 
'roms/SLOF'
Submodule 'roms/ipxe' (git://git.qemu-project.org/ipxe.git) registered for path 
'roms/ipxe'
Submodule 'roms/openbios' (git://git.qemu-project.org/openbios.git) registered 
for path 'roms/openbios'
Submodule 'roms/openhackware' (git://git.qemu-project.org/openhackware.git) 
registered for path 'roms/openhackware'
Submodule 'roms/qemu-palcode' (git://github.com/rth7680/qemu-palcode.git) 
registered for path 'roms/qemu-palcode'
Submodule 'roms/seabios' (git://git.qemu-project.org/seabios.git/) registered 
for path 'roms/seabios'
Submodule 'roms/seabios-hppa' (git://github.com/hdeller/seabios-hppa.git) 
registered for path 'roms/seabios-hppa'
Submodule 'roms/sgabios' (git://git.qemu-project.org/sgabios.git) registered 
for path 'roms/sgabios'
Submodule 'roms/skiboot' (git://git.qemu.org/skiboot.git) registered for path 
'roms/skiboot'
Submodule 'roms/u-boot' (git://git.qemu-project.org/u-boot.git) registered for 
path 'roms/u-boot'
Submodule 'roms/vgabios' (git://git.qemu-project.org/vgabios.git/) registered 
for path 'roms/vgabios'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered 
for path 'ui/keycodemapdb'
Cloning into 'capstone'...
Submodule path 'capstone': checked out 
'22ead3e0bfdb87516656453336160e0a37b066bf'
Cloning into 'dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
Cloning into 'roms/QemuMacDrivers'...
Submodule path 'roms/QemuMacDrivers': checked out 
'd4e7d7ac663fcb55f1b93575445fcbca372f17a7'
Cloning into 'roms/SLOF'...
Submodule path 'roms/SLOF': checked out 
'fa981320a1e0968d6fc1b8de319723ff8212b337'
Cloning into 'roms/ipxe'...
Submodule path 'roms/ipxe': checked out 
'0600d3ae94f93efd10fc6b3c7420a9557a3a1670'
Cloning into 'roms/openbios'...
Submodule path 'roms/openbios': checked out 
'54d959d97fb331708767b2fd4a878efd2bbc41bb'
Cloning into 'roms/openhackware'...
Submodule path 'roms/openhackware': checked out 
'c559da7c8eec5e45ef1f67978827af6f0b9546f5'
Cloning into 'roms/qemu-palcode'...
Submodule path 'roms/qemu-palcode': checked out 
'f3c7e44c70254975df2a00af39701eafbac4d471'
Cloning into 'roms/seabios'...
Submodule path 'roms/seabios': checked out 
'63451fca13c75870e1703eb3e20584d91179aebc'
Cloning into 'roms/seabios-hppa'...
Submodule path 'roms/seabios-hppa': checked out 
'649e6202b8d65d46c69f542b1380f840fbe8ab13'
Cloning into 'roms/sgabios'...
Submodule path 'roms/sgabios': checked out 
'cbaee52287e5f32373181cff50a00b6c4ac9015a'
Cloning into 'roms/skiboot'...
Submodule path 'roms/skiboot': checked out 
'e0ee24c27a172bcf482f6f2bc905e6211c134bcc'
Cloning into 'roms/u-boot'...
Submodule path 'roms/u-boot': checked out 
'd85ca029f257b53a96da6c2fb421e78a003a9943'
Cloning into 'roms/vgabios'...
Submodule path 'roms/vgabios': checked out 
'19ea12c230ded95928ecaef0db47a82231c2e485'
Cloning into 'ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out 
'6b3d716e2b6472eb7189d3220552280ef3d832ce'
Switched to a new branch 'test'
7e16956 RISC-V Build Infrastructure
d5fc9fa SiFive Freedom U500 RISC-V Machine
0dd0d08 SiFive Freedom E300 RISC-V Machine
6a7084c SiFive RISC-V PRCI Block
bd70435 SiFive RISC-V UART Device
2c8fd79 RISC-V VirtIO Machine
e6f9b74 SiFive RISC-V Test Finisher
70c3ed0 RISC-V Spike Machines
802248e SiFive RISC-V PLIC Block
946a5c4 SiFive RISC-V CLINT Block
e4277c8 RISC-V HART Array
daa1c5a RISC-V HTIF Console
9fa1bfa Add symbol table callback interface to load_elf
c0a6b9d RISC-V Linux User Emulation
effb082 RISC-V Physical Memory Protection
f5f5047 RISC-V TCG Code Generation
e31eba4 RISC-V GDB Stub
d826084 RISC-V FPU Support
18ed15b 

Re: [Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file

2018-02-26 Thread Eric Blake

On 02/26/2018 04:57 PM, Eric Blake wrote:

Commit f0df84c6 added watchdog-set-action in the main qapi-schema.json,
but it belongs better in qapi/run-state.json alongside the definition
of WatchdogAction.


I'm adding:

The command was written prior to commit 0e201d34 creating the latter 
file, even though it was merged after.




Signed-off-by: Eric Blake 
---

Based on my review of 24/29, I'm inserting this patch right before
rebasing that one onto master.

  qapi-schema.json| 9 -
  qapi/run-state.json | 9 +
  2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 05cc58e121e..93912e804ab 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3180,12 +3180,3 @@
  # Since: 2.9
  ##
  { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
-
-##
-# @watchdog-set-action:
-#
-# Set watchdog action
-#
-# Since: 2.11
-##
-{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
diff --git a/qapi/run-state.json b/qapi/run-state.json
index bca46a8785f..3924357fef4 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -283,6 +283,15 @@
'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
  'inject-nmi' ] }

+##
+# @watchdog-set-action:
+#
+# Set watchdog action
+#
+# Since: 2.11
+##
+{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
  ##
  # @GUEST_PANICKED:
  #



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



Re: [Qemu-devel] [PATCH v7 00/23] RISC-V QEMU Port Submission

2018-02-26 Thread Eric Blake

On 02/26/2018 04:24 PM, Michael Clark wrote:

I've pushed a signed tag which includes the cover letter for the pull
request.

https://github.com/riscv/riscv-qemu/releases/tag/riscv-qemu-upstream-v7

Apologies. I'm not exactly sure how to format a pull request email.


I use:

$ git request-pull origin repo $TAG | xclip
$ git send-email --confirm=always --annotate \
   --subject-prefix=PULL origin

then paste in the generated cover letter to the templated 00/NN.

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



Re: [Qemu-devel] [PATCH v7 23/23] RISC-V Build Infrastructure

2018-02-26 Thread Eric Blake

On 02/26/2018 04:18 PM, Michael Clark wrote:

This adds RISC-V into the build system enabling the following targets:

- riscv32-softmmu
- riscv64-softmmu
- riscv32-linux-user
- riscv64-linux-user

This adds defaults configs for RISC-V, enables the build for the RISC-V
CPU core, hardware, and Linux User Emulation. The 'qemu-binfmt-conf.sh'
script is updated to add the RISC-V ELF magic.

Expected checkpatch errors for consistency reasons:

ERROR: line over 90 characters
FILE: scripts/qemu-binfmt-conf.sh

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---



+++ b/qapi-schema.json



  ##
  # @CpuInfo:
@@ -452,6 +454,7 @@
  'ppc': 'CpuInfoPPC',
  'mips': 'CpuInfoMIPS',
  'tricore': 'CpuInfoTricore',
+'riscv': 'CpuInfoRISCV',
  'other': 'CpuInfoOther' } }


Hmm - we're trying to deprecate CpuInfo in parallel, in favor of the new 
query-cpus-fast.  CpuInfoRISCV will be useless once that happens, but it 
doesn't invalidate your pull request.


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



[Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file

2018-02-26 Thread Eric Blake
Commit f0df84c6 added watchdog-set-action in the main qapi-schema.json,
but it belongs better in qapi/run-state.json alongside the definition
of WatchdogAction.

Signed-off-by: Eric Blake 
---

Based on my review of 24/29, I'm inserting this patch right before
rebasing that one onto master.

 qapi-schema.json| 9 -
 qapi/run-state.json | 9 +
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 05cc58e121e..93912e804ab 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3180,12 +3180,3 @@
 # Since: 2.9
 ##
 { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
-
-##
-# @watchdog-set-action:
-#
-# Set watchdog action
-#
-# Since: 2.11
-##
-{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
diff --git a/qapi/run-state.json b/qapi/run-state.json
index bca46a8785f..3924357fef4 100644
--- a/qapi/run-state.json
+++ b/qapi/run-state.json
@@ -283,6 +283,15 @@
   'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
 'inject-nmi' ] }

+##
+# @watchdog-set-action:
+#
+# Set watchdog action
+#
+# Since: 2.11
+##
+{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
+
 ##
 # @GUEST_PANICKED:
 #
-- 
2.14.3




Re: [Qemu-devel] [PULL v2 1/6] tpm: Set the flags of the CMD_INIT command to 0

2018-02-26 Thread Stefan Berger

Michael, can you please apply this patch to stable?

git cherry-pick 302705876

Regards,
   Stefan



The flags of the CMD_INIT control channel command were not
initialized properly. Fix this and set to 0.

Signed-off-by: Stefan Berger 
Reviewed-by: Marc-André Lureau 
---
  hw/tpm/tpm_emulator.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
index 35c78de..532d3e3 100644
--- a/hw/tpm/tpm_emulator.c
+++ b/hw/tpm/tpm_emulator.c
@@ -320,7 +320,9 @@ static int tpm_emulator_set_buffer_size(TPMBackend *tb,
  static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
  {
  TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-ptm_init init;
+ptm_init init = {
+.u.req.init_flags = 0,
+};
  ptm_res res;
  
  if (buffersize != 0 &&






Re: [Qemu-devel] [PATCH v7 00/23] RISC-V QEMU Port Submission

2018-02-26 Thread no-reply
Hi,

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

Type: series
Message-id: 1519683480-33201-1-git-send-email-...@sifive.com
Subject: [Qemu-devel] [PATCH v7 00/23] RISC-V QEMU Port Submission

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

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

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

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

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

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]   
patchew/1519683480-33201-1-git-send-email-...@sifive.com -> 
patchew/1519683480-33201-1-git-send-email-...@sifive.com
Switched to a new branch 'test'
7e169569e5 RISC-V Build Infrastructure
d5fc9fad62 SiFive Freedom U500 RISC-V Machine
0dd0d088c4 SiFive Freedom E300 RISC-V Machine
6a7084c579 SiFive RISC-V PRCI Block
bd70435ab8 SiFive RISC-V UART Device
2c8fd79433 RISC-V VirtIO Machine
e6f9b7412f SiFive RISC-V Test Finisher
70c3ed0d5d RISC-V Spike Machines
802248e514 SiFive RISC-V PLIC Block
946a5c4ef9 SiFive RISC-V CLINT Block
e4277c8e18 RISC-V HART Array
daa1c5aadd RISC-V HTIF Console
9fa1bfa6ac Add symbol table callback interface to load_elf
c0a6b9d7d8 RISC-V Linux User Emulation
effb082340 RISC-V Physical Memory Protection
f5f5047c0c RISC-V TCG Code Generation
e31eba4767 RISC-V GDB Stub
d826084744 RISC-V FPU Support
18ed15b8a6 RISC-V CPU Helpers
1648526a98 RISC-V Disassembler
8a7023fd44 RISC-V CPU Core Definition
4c792ca31a RISC-V ELF Machine Definition
7f71438dec RISC-V Maintainers

=== OUTPUT BEGIN ===
Checking PATCH 1/23: RISC-V Maintainers...
Checking PATCH 2/23: RISC-V ELF Machine Definition...
Checking PATCH 3/23: RISC-V CPU Core Definition...
Checking PATCH 4/23: RISC-V Disassembler...
WARNING: line over 80 characters
#649: FILE: disas/riscv.c:597:
+static const rvc_constraint rvcc_jalr[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, 
rvc_end };

ERROR: line over 90 characters
#650: FILE: disas/riscv.c:598:
+static const rvc_constraint rvcc_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, 
rvc_imm_eq_zero, rvc_end };

WARNING: line over 80 characters
#680: FILE: disas/riscv.c:628:
+static const rvc_constraint rvcc_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, 
rvc_end };

WARNING: line over 80 characters
#681: FILE: disas/riscv.c:629:
+static const rvc_constraint rvcc_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, 
rvc_end };

WARNING: line over 80 characters
#682: FILE: disas/riscv.c:630:
+static const rvc_constraint rvcc_rdcycle[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc00, rvc_end };

WARNING: line over 80 characters
#683: FILE: disas/riscv.c:631:
+static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, 
rvc_end };

ERROR: line over 90 characters
#684: FILE: disas/riscv.c:632:
+static const rvc_constraint rvcc_rdinstret[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc02, rvc_end };

ERROR: line over 90 characters
#685: FILE: disas/riscv.c:633:
+static const rvc_constraint rvcc_rdcycleh[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc80, rvc_end };

WARNING: line over 80 characters
#686: FILE: disas/riscv.c:634:
+static const rvc_constraint rvcc_rdtimeh[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc81, rvc_end };

ERROR: line over 90 characters
#687: FILE: disas/riscv.c:635:
+static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0xc80, rvc_end };

WARNING: line over 80 characters
#688: FILE: disas/riscv.c:636:
+static const rvc_constraint rvcc_frcsr[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x003, 
rvc_end };

WARNING: line over 80 characters
#689: FILE: disas/riscv.c:637:
+static const rvc_constraint rvcc_frrm[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x002, 
rvc_end };

WARNING: line over 80 characters
#690: FILE: disas/riscv.c:638:
+static const rvc_constraint rvcc_frflags[] = { rvc_rs1_eq_x0, 
rvc_csr_eq_0x001, rvc_end };

ERROR: line over 90 characters
#1089: FILE: disas/riscv.c:1037:
+{ "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, 
rv_op_addi, rv_op_addi },

WARNING: line over 80 characters
#1090: FILE: disas/riscv.c:1038:
+{ "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, 
rv_op_fld, 0 },

WARNING: line over 80 characters
#1091: FILE: disas/riscv.c:1039:
+{ "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, 
rv_op_lw },

WARNING: line over 80 characters
#1093: FILE: disas/riscv.c:1041:
+{ "c.fsd", rv_codec_cs_sd, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, 
rv_op_fsd, 0 },

WARNING: line over 80 characters
#1094: FILE: disas/riscv.c:1042:
+{ "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, 
rv_op_sw },

WARNING: line over 80 characters

Re: [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module

2018-02-26 Thread Eric Blake

On 02/23/2018 11:41 AM, Markus Armbruster wrote:



+++ b/Makefile
@@ -92,10 +92,70 @@ include $(SRC_PATH)/rules.mak
   GENERATED_FILES = qemu-version.h config-host.h qemu-options.def
   GENERATED_FILES += qapi-builtin-types.h qapi-builtin-types.c
   GENERATED_FILES += qapi-types.h qapi-types.c
+GENERATED_FILES += qapi/qapi-types-block-core.h qapi/qapi-types-block-core.c


For the makefile, I'd suggest using an intermediate list of module
names, and then using make string operations to expand it into larger
lists, to cut down on the repetition.  Something like (untested):

QAPI_MODULES = block-core block char common ...
GENERATED_FILES += $(addprefix qapi/qapi-types-,$(addsuffix
.c,$(QAPI_MODULES))
GENERATED_FILES += $(addprefix qapi/qapi-types-,$(addsuffix
.h,$(QAPI_MODULES))


I did it the stupid way to save time.  Improvements welcome :)




+++ b/Makefile.objs
@@ -3,8 +3,56 @@
   stub-obj-y = stubs/ crypto/
   util-obj-y = util/ qobject/ qapi/
   util-obj-y += qapi-builtin-types.o
+util-obj-y += qapi-types.o
+util-obj-y += qapi/qapi-types-block-core.o


Perhaps this can also exploit make text manipulation?

Otherwise looks good.


Thanks!


At this point, I'll take your patch as-is, and worry about improvements 
as followups.


Reviewed-by: Eric Blake 

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



Re: [Qemu-devel] [PATCH v7 00/23] RISC-V QEMU Port Submission

2018-02-26 Thread Michael Clark
I've pushed a signed tag which includes the cover letter for the pull
request.

https://github.com/riscv/riscv-qemu/releases/tag/riscv-qemu-upstream-v7

Apologies. I'm not exactly sure how to format a pull request email.

On Tue, Feb 27, 2018 at 11:17 AM, Michael Clark  wrote:

> QEMU RISC-V Emulation Support (RV64GC, RV32GC)
>
> With this reelase we have contacted all contributors and have received
> agreement to re-license their work as GPLv2+. This release also updates
> linux-user/riscv/termbits.h which should fix S390 builds. The spike_v1.9
> machine has been renamed to spike_v1.9.1 to match the privileged ISA
> version and spike_v1.10 has been made the default machine. All substantial
> work in this series has been reviewed or acknowledged and subsequent to
> submitting this series we will be submitting signed a pull request.
>
> The git tree for the v7 patch series tree (squashed and rebased):
>
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v7
>
> The git tree for the v1-v6 patch series with review commit history:
>
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v6
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v5
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v4
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v3
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v2
> - https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v1
>
> *** Known Issues ***
>
> - Disassembler has some checkpatch warnings for the sake of code brevity
> - scripts/qemu-binfmt-conf.sh has checkpatch warnings due to line length
> - PMP (Physical Memory Protection) is as-of-yet unused and needs testing
>
> *** Changelog ***
>
> v7
>
> - Make spike_v1.10 the default machine
> - Rename spike_v1.9 to spike_v1.9.1 to match privileged spec version
> - Remove empty target/riscv/trace-events file
> - Monitor ROM 32-bit reset code needs to be target endian
> - Add TARGET_TIOCGPTPEER to linux-user/riscv/termbits.h
> - Add -initrd support to the virt board
> - Fix naming in spike machine interface header
> - Update copyright notice on RISC-V Spike machines
> - Update copyright notice on RISC-V HTIF Console device
> - Change CPU Core and translator to GPLv2+
> - Change RISC-V Disassembler to GPLv2+
> - Change SiFive Test Finisher to GPLv2+
> - Change SiFive CLINT to GPLv2+
> - Change SiFive PRCI to GPLv2+
> - Change SiFive PLIC to GPLv2+
> - Change RISC-V spike machines to GPLv2+
> - Change RISC-V virt machine to GPLv2+
> - Change SiFive E300 machine to GPLv2+
> - Change SiFive U500 machine to GPLv2+
> - Change RISC-V Hart Array to GPLv2+
> - Change RISC-V HTIF device to GPLv2+
> - Change SiFiveUART device to GPLv2+
>
> v6
>
> - Drop IEEE 754-201x minimumNumber/maximumNumber for fmin/fmax
> - Remove some unnecessary commented debug statements
> - Change RISCV_CPU_TYPE_NAME to use riscv-cpu suffix
> - Define all CPU variants for linux-user
> - qemu_log calls require trailing \n
> - Replace PLIC printfs with qemu_log
> - Tear out unused HTIF code and eliminate shouting debug messages
> - Fix illegal instruction when sfence.vma is passed (rs2) arguments
> - Make updates to PTE accessed and dirty bits atomic
> - Only require atomic PTE updates on MTTCG enabled guests
> - Page fault if accessed or dirty bits can't be updated
> - Fix get_physical_address PTE reads and writes on riscv32
> - Remove erroneous comments from the PLIC
> - Default enable MTTCG
> - Make WFI less conservative
> - Unify local interrupt handling
> - Expunge HTIF interrupts
> - Always access mstatus.mip under a lock
> - Don't implement rdtime/rdtimeh in system mode (bbl emulates them)
> - Implement insreth/cycleh for rv32 and always enable user-mode counters
> - Add GDB stub support for reading and writing CSRs
> - Rename ENABLE_CHARDEV #ifdef from HTIF code
> - Replace bad HTIF ELF code with load_elf symbol callback
> - Convert chained if else fault handlers to switch statements
> - Use RISCV exception codes for linux-user page faults
>
> v5
>
> - Implement NaN-boxing for flw, set high order bits to 1
> - Use float_muladd_negate_* flags to floatXX_muladd
> - Use IEEE 754-201x minimumNumber/maximumNumber for fmin/fmax
> - Fix TARGET_NR_syscalls
> - Update linux-user/riscv/syscall_nr.h
> - Fix FENCE.I, needs to terminate translation block
> - Adjust unusual convention for interruptno >= 0
>
> v4
>
> - Add @riscv: since 2.12 to CpuInfoArch
> - Remove misleading little-endian comment from load_kernel
> - Rename cpu-model property to cpu-type
> - Drop some unnecessary inline function attributes
> - Don't allow GDB to set value of x0 register
> - Remove unnecessary empty property lists
> - Add Test Finisher device to implement poweroff in virt machine
> - Implement priv ISA v1.10 trap and sret/mret xPIE/xIE behavior
> - Store fflags data in fp_status
> - Purge runtime users of helper_raise_exception
> - Fix validate_csr
> - Tidy gen_jalr
> - Tidy immediate shifts
> - Add 

[Qemu-devel] [PATCH v7 23/23] RISC-V Build Infrastructure

2018-02-26 Thread Michael Clark
This adds RISC-V into the build system enabling the following targets:

- riscv32-softmmu
- riscv64-softmmu
- riscv32-linux-user
- riscv64-linux-user

This adds defaults configs for RISC-V, enables the build for the RISC-V
CPU core, hardware, and Linux User Emulation. The 'qemu-binfmt-conf.sh'
script is updated to add the RISC-V ELF magic.

Expected checkpatch errors for consistency reasons:

ERROR: line over 90 characters
FILE: scripts/qemu-binfmt-conf.sh

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 arch_init.c|  2 ++
 configure  | 13 +
 cpus.c |  6 ++
 default-configs/riscv32-linux-user.mak |  1 +
 default-configs/riscv32-softmmu.mak|  4 
 default-configs/riscv64-linux-user.mak |  1 +
 default-configs/riscv64-softmmu.mak|  4 
 hw/riscv/Makefile.objs | 12 
 include/sysemu/arch_init.h |  1 +
 qapi-schema.json   | 16 +++-
 scripts/qemu-binfmt-conf.sh| 13 -
 target/riscv/Makefile.objs |  1 +
 12 files changed, 72 insertions(+), 2 deletions(-)
 create mode 100644 default-configs/riscv32-linux-user.mak
 create mode 100644 default-configs/riscv32-softmmu.mak
 create mode 100644 default-configs/riscv64-linux-user.mak
 create mode 100644 default-configs/riscv64-softmmu.mak
 create mode 100644 hw/riscv/Makefile.objs
 create mode 100644 target/riscv/Makefile.objs

diff --git a/arch_init.c b/arch_init.c
index 4c36f2b..e157619 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -71,6 +71,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_OPENRISC
 #elif defined(TARGET_PPC)
 #define QEMU_ARCH QEMU_ARCH_PPC
+#elif defined(TARGET_RISCV)
+#define QEMU_ARCH QEMU_ARCH_RISCV
 #elif defined(TARGET_S390X)
 #define QEMU_ARCH QEMU_ARCH_S390X
 #elif defined(TARGET_SH4)
diff --git a/configure b/configure
index 39f3a43..bada290 100755
--- a/configure
+++ b/configure
@@ -6786,6 +6786,16 @@ case "$target_name" in
 echo "TARGET_ABI32=y" >> $config_target_mak
 gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml 
power-spe.xml power-vsx.xml"
   ;;
+  riscv32)
+TARGET_BASE_ARCH=riscv
+TARGET_ABI_DIR=riscv
+mttcg=yes
+  ;;
+  riscv64)
+TARGET_BASE_ARCH=riscv
+TARGET_ABI_DIR=riscv
+mttcg=yes
+  ;;
   sh4|sh4eb)
 TARGET_ARCH=sh4
 bflt="yes"
@@ -6955,6 +6965,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
   ppc*)
 disas_config "PPC"
   ;;
+  riscv)
+disas_config "RISCV"
+  ;;
   s390*)
 disas_config "S390"
   ;;
diff --git a/cpus.c b/cpus.c
index f298b65..91424ba 100644
--- a/cpus.c
+++ b/cpus.c
@@ -2094,6 +2094,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 #elif defined(TARGET_SPARC)
 SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
 CPUSPARCState *env = _cpu->env;
+#elif defined(TARGET_RISCV)
+RISCVCPU *riscv_cpu = RISCV_CPU(cpu);
+CPURISCVState *env = _cpu->env;
 #elif defined(TARGET_MIPS)
 MIPSCPU *mips_cpu = MIPS_CPU(cpu);
 CPUMIPSState *env = _cpu->env;
@@ -2127,6 +2130,9 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 #elif defined(TARGET_TRICORE)
 info->value->arch = CPU_INFO_ARCH_TRICORE;
 info->value->u.tricore.PC = env->PC;
+#elif defined(TARGET_RISCV)
+info->value->arch = CPU_INFO_ARCH_RISCV;
+info->value->u.riscv.pc = env->pc;
 #else
 info->value->arch = CPU_INFO_ARCH_OTHER;
 #endif
diff --git a/default-configs/riscv32-linux-user.mak 
b/default-configs/riscv32-linux-user.mak
new file mode 100644
index 000..865b362
--- /dev/null
+++ b/default-configs/riscv32-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for riscv-linux-user
diff --git a/default-configs/riscv32-softmmu.mak 
b/default-configs/riscv32-softmmu.mak
new file mode 100644
index 000..f9e7421
--- /dev/null
+++ b/default-configs/riscv32-softmmu.mak
@@ -0,0 +1,4 @@
+# Default configuration for riscv-softmmu
+
+CONFIG_SERIAL=y
+CONFIG_VIRTIO=y
diff --git a/default-configs/riscv64-linux-user.mak 
b/default-configs/riscv64-linux-user.mak
new file mode 100644
index 000..865b362
--- /dev/null
+++ b/default-configs/riscv64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for riscv-linux-user
diff --git a/default-configs/riscv64-softmmu.mak 
b/default-configs/riscv64-softmmu.mak
new file mode 100644
index 000..f9e7421
--- /dev/null
+++ b/default-configs/riscv64-softmmu.mak
@@ -0,0 +1,4 @@
+# Default configuration for riscv-softmmu
+
+CONFIG_SERIAL=y
+CONFIG_VIRTIO=y
diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs
new file mode 100644
index 000..23f684b
--- /dev/null
+++ b/hw/riscv/Makefile.objs
@@ -0,0 +1,12 @@
+obj-y += riscv_htif.o
+obj-y += riscv_hart.o
+obj-y += sifive_e300.o
+obj-y += sifive_clint.o
+obj-y += sifive_prci.o
+obj-y += sifive_plic.o
+obj-y += sifive_test.o
+obj-y += sifive_u500.o
+obj-y 

[Qemu-devel] [PATCH v7 22/23] SiFive Freedom U500 RISC-V Machine

2018-02-26 Thread Michael Clark
This provides a RISC-V Board compatible with the the SiFive U500 SDK.
The following machine is implemented:

- 'sifive_u500'; CLINT, PLIC, UART, device-tree

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_u500.c | 341 +
 include/hw/riscv/sifive_u500.h |  63 
 2 files changed, 404 insertions(+)
 create mode 100644 hw/riscv/sifive_u500.c
 create mode 100644 include/hw/riscv/sifive_u500.h

diff --git a/hw/riscv/sifive_u500.c b/hw/riscv/sifive_u500.c
new file mode 100644
index 000..89a1d6b
--- /dev/null
+++ b/hw/riscv/sifive_u500.c
@@ -0,0 +1,341 @@
+/*
+ * QEMU RISC-V Board Compatible with SiFive U500 SDK
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides a RISC-V Board compatible with the the SiFive U500 SDK
+ *
+ * 0) UART
+ * 1) CLINT (Core Level Interruptor)
+ * 2) PLIC (Platform Level Interrupt Controller)
+ *
+ * This board currently uses a hardcoded devicetree that indicates one hart.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/sifive_uart.h"
+#include "hw/riscv/sifive_prci.h"
+#include "hw/riscv/sifive_u500.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/device_tree.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} sifive_u500_memmap[] = {
+[SIFIVE_U500_DEBUG] ={0x0,  0x100 },
+[SIFIVE_U500_MROM] = { 0x1000, 0x2000 },
+[SIFIVE_U500_CLINT] ={  0x200,0x1 },
+[SIFIVE_U500_PLIC] = {  0xc00,  0x400 },
+[SIFIVE_U500_UART0] ={ 0x10013000, 0x1000 },
+[SIFIVE_U500_UART1] ={ 0x10023000, 0x1000 },
+[SIFIVE_U500_DRAM] = { 0x8000,0x0 },
+};
+
+static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
+{
+int i;
+for (i = 0; i < (len >> 2); i++) {
+stl_phys(_space_memory, pa + (i << 2), rom[i]);
+}
+}
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ _entry, NULL, _high,
+ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void create_fdt(SiFiveU500State *s, const struct MemmapEntry *memmap,
+uint64_t mem_size, const char *cmdline)
+{
+void *fdt;
+int cpu;
+uint32_t *cells;
+char *nodename;
+uint32_t plic_phandle;
+
+fdt = s->fdt = create_device_tree(>fdt_size);
+if (!fdt) {
+error_report("create_device_tree() failed");
+exit(1);
+}
+
+qemu_fdt_setprop_string(fdt, "/", "model", "ucbbar,spike-bare,qemu");
+qemu_fdt_setprop_string(fdt, "/", "compatible", "ucbbar,spike-bare-dev");
+qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+
+qemu_fdt_add_subnode(fdt, "/soc");
+qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
+qemu_fdt_setprop_string(fdt, "/soc", "compatible", 
"ucbbar,spike-bare-soc");
+qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
+
+nodename = g_strdup_printf("/memory@%lx",
+(long)memmap[SIFIVE_U500_DRAM].base);
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop_cells(fdt, nodename, "reg",
+memmap[SIFIVE_U500_DRAM].base >> 32, memmap[SIFIVE_U500_DRAM].base,
+mem_size >> 32, mem_size);
+qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
+g_free(nodename);
+
+qemu_fdt_add_subnode(fdt, "/cpus");
+qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 

[Qemu-devel] [PATCH v7 19/23] SiFive RISC-V UART Device

2018-02-26 Thread Michael Clark
QEMU model of the UART on the SiFive E300 and U500 series SOCs.
BBL supports the SiFive UART for early console access via the SBI
(Supervisor Binary Interface) and the linux kernel SBI console.

The SiFive UART implements the pre qom legacy interface consistent
with the 16550a UART in 'hw/char/serial.c'.

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_uart.c | 176 +
 include/hw/riscv/sifive_uart.h |  71 +
 2 files changed, 247 insertions(+)
 create mode 100644 hw/riscv/sifive_uart.c
 create mode 100644 include/hw/riscv/sifive_uart.h

diff --git a/hw/riscv/sifive_uart.c b/hw/riscv/sifive_uart.c
new file mode 100644
index 000..b0c3798
--- /dev/null
+++ b/hw/riscv/sifive_uart.c
@@ -0,0 +1,176 @@
+/*
+ * QEMU model of the UART on the SiFive E300 and U500 series SOCs.
+ *
+ * Copyright (c) 2016 Stefan O'Rear
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "chardev/char.h"
+#include "chardev/char-fe.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_uart.h"
+
+/*
+ * Not yet implemented:
+ *
+ * Transmit FIFO using "qemu/fifo8.h"
+ * SIFIVE_UART_IE_TXWM interrupts
+ * SIFIVE_UART_IE_RXWM interrupts must honor fifo watermark
+ * Rx FIFO watermark interrupt trigger threshold
+ * Tx FIFO watermark interrupt trigger threshold.
+ */
+
+static void update_irq(SiFiveUARTState *s)
+{
+int cond = 0;
+if ((s->ie & SIFIVE_UART_IE_RXWM) && s->rx_fifo_len) {
+cond = 1;
+}
+if (cond) {
+qemu_irq_raise(s->irq);
+} else {
+qemu_irq_lower(s->irq);
+}
+}
+
+static uint64_t
+uart_read(void *opaque, hwaddr addr, unsigned int size)
+{
+SiFiveUARTState *s = opaque;
+unsigned char r;
+switch (addr) {
+case SIFIVE_UART_RXFIFO:
+if (s->rx_fifo_len) {
+r = s->rx_fifo[0];
+memmove(s->rx_fifo, s->rx_fifo + 1, s->rx_fifo_len - 1);
+s->rx_fifo_len--;
+qemu_chr_fe_accept_input(>chr);
+update_irq(s);
+return r;
+}
+return 0x8000;
+
+case SIFIVE_UART_TXFIFO:
+return 0; /* Should check tx fifo */
+case SIFIVE_UART_IE:
+return s->ie;
+case SIFIVE_UART_IP:
+return s->rx_fifo_len ? SIFIVE_UART_IP_RXWM : 0;
+case SIFIVE_UART_TXCTRL:
+return s->txctrl;
+case SIFIVE_UART_RXCTRL:
+return s->rxctrl;
+case SIFIVE_UART_DIV:
+return s->div;
+}
+
+hw_error("%s: bad read: addr=0x%x\n",
+__func__, (int)addr);
+return 0;
+}
+
+static void
+uart_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+SiFiveUARTState *s = opaque;
+uint32_t value = val64;
+unsigned char ch = value;
+
+switch (addr) {
+case SIFIVE_UART_TXFIFO:
+qemu_chr_fe_write(>chr, , 1);
+return;
+case SIFIVE_UART_IE:
+s->ie = val64;
+update_irq(s);
+return;
+case SIFIVE_UART_TXCTRL:
+s->txctrl = val64;
+return;
+case SIFIVE_UART_RXCTRL:
+s->rxctrl = val64;
+return;
+case SIFIVE_UART_DIV:
+s->div = val64;
+return;
+}
+hw_error("%s: bad write: addr=0x%x v=0x%x\n",
+__func__, (int)addr, (int)value);
+}
+
+static const MemoryRegionOps uart_ops = {
+.read = uart_read,
+.write = uart_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+};
+
+static void uart_rx(void *opaque, const uint8_t *buf, int size)
+{
+SiFiveUARTState *s = opaque;
+
+/* Got a byte.  */
+if (s->rx_fifo_len >= sizeof(s->rx_fifo)) {
+printf("WARNING: UART dropped char.\n");
+return;
+}
+s->rx_fifo[s->rx_fifo_len++] = *buf;
+
+update_irq(s);
+}
+
+static int uart_can_rx(void *opaque)
+{
+SiFiveUARTState *s = opaque;
+
+return s->rx_fifo_len < sizeof(s->rx_fifo);
+}
+
+static void uart_event(void *opaque, int event)
+{
+}
+
+static int uart_be_change(void *opaque)
+{
+SiFiveUARTState *s = opaque;
+
+qemu_chr_fe_set_handlers(>chr, uart_can_rx, uart_rx, uart_event,
+uart_be_change, s, NULL, true);
+
+return 0;
+}
+
+/*
+ * Create UART device.
+ */

[Qemu-devel] [PATCH v7 16/23] RISC-V Spike Machines

2018-02-26 Thread Michael Clark
RISC-V machines compatble with Spike aka riscv-isa-sim, the RISC-V
Instruction Set Simulator. The following machines are implemented:

- 'spike_v1.9'; HTIF console, config-string, Privileged ISA Version 1.9.1
- 'spike_v1.10'; HTIF console, device-tree, Privileged ISA Version 1.10

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/spike_v1_09.c   | 202 ++
 hw/riscv/spike_v1_10.c   | 277 +++
 include/hw/riscv/spike.h |  45 
 3 files changed, 524 insertions(+)
 create mode 100644 hw/riscv/spike_v1_09.c
 create mode 100644 hw/riscv/spike_v1_10.c
 create mode 100644 include/hw/riscv/spike.h

diff --git a/hw/riscv/spike_v1_09.c b/hw/riscv/spike_v1_09.c
new file mode 100644
index 000..2c75a8a
--- /dev/null
+++ b/hw/riscv/spike_v1_09.c
@@ -0,0 +1,202 @@
+/*
+ * QEMU RISC-V Spike Board
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * This provides a RISC-V Board with the following devices:
+ *
+ * 0) HTIF Console and Poweroff
+ * 1) CLINT (Timer and IPI)
+ *
+ * This board currently uses a hardcoded devicetree that indicates one hart.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_htif.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/spike.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} spike_memmap[] = {
+[SPIKE_MROM] = { 0x1000, 0x2000 },
+[SPIKE_CLINT] ={  0x200,0x1 },
+[SPIKE_DRAM] = { 0x8000,0x0 },
+};
+
+static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
+{
+int i;
+for (i = 0; i < (len >> 2); i++) {
+stl_phys(_space_memory, pa + (i << 2), rom[i]);
+}
+}
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf_ram_sym(kernel_filename, identity_translate, NULL,
+_entry, NULL, _high, 0, ELF_MACHINE, 1, 0,
+NULL, true, htif_symbol_callback) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void riscv_spike_board_init(MachineState *machine)
+{
+const struct MemmapEntry *memmap = spike_memmap;
+
+SpikeState *s = g_new0(SpikeState, 1);
+MemoryRegion *system_memory = get_system_memory();
+MemoryRegion *main_mem = g_new(MemoryRegion, 1);
+MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
+
+/* Initialize SOC */
+object_initialize(>soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY);
+object_property_add_child(OBJECT(machine), "soc", OBJECT(>soc),
+  _abort);
+object_property_set_str(OBJECT(>soc), TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_09,
+"cpu-type", _abort);
+object_property_set_int(OBJECT(>soc), smp_cpus, "num-harts",
+_abort);
+object_property_set_bool(OBJECT(>soc), true, "realized",
+_abort);
+
+/* register system main memory (actual RAM) */
+memory_region_init_ram(main_mem, NULL, "riscv.spike.ram",
+   machine->ram_size, _fatal);
+memory_region_add_subregion(system_memory, DRAM_BASE, main_mem);
+
+/* boot rom */
+memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom",
+   0x4, _fatal);
+memory_region_add_subregion(system_memory, 0x0, boot_rom);
+
+if (machine->kernel_filename) {
+load_kernel(machine->kernel_filename);
+}
+
+uint32_t reset_vec[8] = {
+0x297 + memmap[SPIKE_DRAM].base - memmap[SPIKE_MROM].base, /* lui */
+0x00028067,   /* jump to DRAM_BASE */
+0x,   /* reserved */
+memmap[SPIKE_MROM].base + 

[Qemu-devel] [PATCH v7 18/23] RISC-V VirtIO Machine

2018-02-26 Thread Michael Clark
RISC-V machine with device-tree, 16550a UART and VirtIO MMIO.
The following machine is implemented:

- 'virt'; CLINT, PLIC, 16550A UART, VirtIO MMIO, device-tree

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/virt.c | 420 
 include/hw/riscv/virt.h |  68 
 2 files changed, 488 insertions(+)
 create mode 100644 hw/riscv/virt.c
 create mode 100644 include/hw/riscv/virt.h

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
new file mode 100644
index 000..62351fb
--- /dev/null
+++ b/hw/riscv/virt.c
@@ -0,0 +1,420 @@
+/*
+ * QEMU RISC-V VirtIO Board
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * RISC-V machine with 16550a UART and VirtIO MMIO
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_htif.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/sifive_test.h"
+#include "hw/riscv/virt.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "sysemu/device_tree.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} virt_memmap[] = {
+[VIRT_DEBUG] ={0x0,  0x100 },
+[VIRT_MROM] = { 0x1000, 0x2000 },
+[VIRT_TEST] = { 0x4000, 0x1000 },
+[VIRT_CLINT] ={  0x200,0x1 },
+[VIRT_PLIC] = {  0xc00,  0x400 },
+[VIRT_UART0] ={ 0x1000,  0x100 },
+[VIRT_VIRTIO] =   { 0x10001000, 0x1000 },
+[VIRT_DRAM] = { 0x8000,0x0 },
+};
+
+static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
+{
+int i;
+for (i = 0; i < (len >> 2); i++) {
+stl_phys(_space_memory, pa + (i << 2), rom[i]);
+}
+}
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ _entry, NULL, _high,
+ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static hwaddr load_initrd(const char *filename, uint64_t mem_size,
+  uint64_t kernel_entry, hwaddr *start)
+{
+int size;
+
+/* We want to put the initrd far enough into RAM that when the
+ * kernel is uncompressed it will not clobber the initrd. However
+ * on boards without much RAM we must ensure that we still leave
+ * enough room for a decent sized initrd, and on boards with large
+ * amounts of RAM we must avoid the initrd being so far up in RAM
+ * that it is outside lowmem and inaccessible to the kernel.
+ * So for boards with less  than 256MB of RAM we put the initrd
+ * halfway into RAM, and for boards with 256MB of RAM or more we put
+ * the initrd at 128MB.
+ */
+*start = kernel_entry + MIN(mem_size / 2, 128 * 1024 * 1024);
+
+size = load_ramdisk(filename, *start, mem_size - *start);
+if (size == -1) {
+size = load_image_targphys(filename, *start, mem_size - *start);
+if (size == -1) {
+  error_report("qemu: could not load ramdisk '%s'", filename);
+  exit(1);
+}
+}
+return *start + size;
+}
+
+static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
+uint64_t mem_size, const char *cmdline)
+{
+void *fdt;
+int cpu;
+uint32_t *cells;
+char *nodename;
+uint32_t plic_phandle, phandle = 1;
+int i;
+
+fdt = s->fdt = create_device_tree(>fdt_size);
+if (!fdt) {
+error_report("create_device_tree() failed");
+exit(1);
+}
+
+qemu_fdt_setprop_string(fdt, "/", "model", "riscv-virtio,qemu");
+qemu_fdt_setprop_string(fdt, "/", "compatible", "riscv-virtio");
+qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
+qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+

[Qemu-devel] [PATCH v7 17/23] SiFive RISC-V Test Finisher

2018-02-26 Thread Michael Clark
Test finisher memory mapped device used to exit simulation.

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_test.c | 93 ++
 include/hw/riscv/sifive_test.h | 42 +++
 2 files changed, 135 insertions(+)
 create mode 100644 hw/riscv/sifive_test.c
 create mode 100644 include/hw/riscv/sifive_test.h

diff --git a/hw/riscv/sifive_test.c b/hw/riscv/sifive_test.c
new file mode 100644
index 000..8abd2cd
--- /dev/null
+++ b/hw/riscv/sifive_test.c
@@ -0,0 +1,93 @@
+/*
+ * QEMU SiFive Test Finisher
+ *
+ * Copyright (c) 2018 SiFive, Inc.
+ *
+ * Test finisher memory mapped device used to exit simulation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_test.h"
+
+static uint64_t sifive_test_read(void *opaque, hwaddr addr, unsigned int size)
+{
+return 0;
+}
+
+static void sifive_test_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+if (addr == 0) {
+int status = val64 & 0x;
+int code = (val64 >> 16) & 0x;
+switch (status) {
+case FINISHER_FAIL:
+exit(code);
+case FINISHER_PASS:
+exit(0);
+default:
+break;
+}
+}
+hw_error("%s: write: addr=0x%x val=0x%016" PRIx64 "\n",
+__func__, (int)addr, val64);
+}
+
+static const MemoryRegionOps sifive_test_ops = {
+.read = sifive_test_read,
+.write = sifive_test_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+};
+
+static void sifive_test_init(Object *obj)
+{
+SiFiveTestState *s = SIFIVE_TEST(obj);
+
+memory_region_init_io(>mmio, obj, _test_ops, s,
+  TYPE_SIFIVE_TEST, 0x1000);
+sysbus_init_mmio(SYS_BUS_DEVICE(obj), >mmio);
+}
+
+static const TypeInfo sifive_test_info = {
+.name  = TYPE_SIFIVE_TEST,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(SiFiveTestState),
+.instance_init = sifive_test_init,
+};
+
+static void sifive_test_register_types(void)
+{
+type_register_static(_test_info);
+}
+
+type_init(sifive_test_register_types)
+
+
+/*
+ * Create Test device.
+ */
+DeviceState *sifive_test_create(hwaddr addr)
+{
+DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_TEST);
+qdev_init_nofail(dev);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+return dev;
+}
diff --git a/include/hw/riscv/sifive_test.h b/include/hw/riscv/sifive_test.h
new file mode 100644
index 000..71d4c9f
--- /dev/null
+++ b/include/hw/riscv/sifive_test.h
@@ -0,0 +1,42 @@
+/*
+ * QEMU Test Finisher interface
+ *
+ * Copyright (c) 2018 SiFive, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#ifndef HW_SIFIVE_TEST_H
+#define HW_SIFIVE_TEST_H
+
+#define TYPE_SIFIVE_TEST "riscv.sifive.test"
+
+#define SIFIVE_TEST(obj) \
+OBJECT_CHECK(SiFiveTestState, (obj), TYPE_SIFIVE_TEST)
+
+typedef struct SiFiveTestState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+MemoryRegion mmio;
+} SiFiveTestState;
+
+enum {
+FINISHER_FAIL = 0x,
+FINISHER_PASS = 0x
+};
+
+DeviceState *sifive_test_create(hwaddr addr);
+
+#endif
-- 
2.7.0




[Qemu-devel] [PATCH v7 21/23] SiFive Freedom E300 RISC-V Machine

2018-02-26 Thread Michael Clark
This provides a RISC-V Board compatible with the the SiFive E300 SDK.
The following machine is implemented:

- 'sifive_e300'; CLINT, PLIC, UART, AON, GPIO, QSPI, PWM

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_e300.c | 236 +
 include/hw/riscv/sifive_e300.h |  73 +
 2 files changed, 309 insertions(+)
 create mode 100644 hw/riscv/sifive_e300.c
 create mode 100644 include/hw/riscv/sifive_e300.h

diff --git a/hw/riscv/sifive_e300.c b/hw/riscv/sifive_e300.c
new file mode 100644
index 000..a55d2ab
--- /dev/null
+++ b/hw/riscv/sifive_e300.c
@@ -0,0 +1,236 @@
+/*
+ * QEMU RISC-V Board Compatible with SiFive E300 SDK
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Provides a board compatible with the bsp in the SiFive E300 SDK:
+ *
+ * 0) UART
+ * 1) CLINT (Core Level Interruptor)
+ * 2) PLIC (Platform Level Interrupt Controller)
+ * 3) PRCI (Power, Reset, Clock, Interrupt)
+ * 4) Registers emulated as RAM: AON, GPIO, QSPI, PWM
+ * 5) Flash memory emulated as RAM
+ *
+ * The Mask ROM reset vector jumps to the flash payload at 0x2040_.
+ * The OTP ROM and Flash boot code will be emulated in a future version.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/sifive_plic.h"
+#include "hw/riscv/sifive_clint.h"
+#include "hw/riscv/sifive_prci.h"
+#include "hw/riscv/sifive_uart.h"
+#include "hw/riscv/sifive_e300.h"
+#include "chardev/char.h"
+#include "sysemu/arch_init.h"
+#include "exec/address-spaces.h"
+#include "elf.h"
+
+static const struct MemmapEntry {
+hwaddr base;
+hwaddr size;
+} sifive_e300_memmap[] = {
+[SIFIVE_E300_DEBUG] ={0x0,  0x100 },
+[SIFIVE_E300_MROM] = { 0x1000, 0x2000 },
+[SIFIVE_E300_OTP] =  {0x2, 0x2000 },
+[SIFIVE_E300_CLINT] ={  0x200,0x1 },
+[SIFIVE_E300_PLIC] = {  0xc00,  0x400 },
+[SIFIVE_E300_AON] =  { 0x1000, 0x8000 },
+[SIFIVE_E300_PRCI] = { 0x10008000, 0x8000 },
+[SIFIVE_E300_OTP_CTRL] = { 0x1001, 0x1000 },
+[SIFIVE_E300_GPIO0] ={ 0x10012000, 0x1000 },
+[SIFIVE_E300_UART0] ={ 0x10013000, 0x1000 },
+[SIFIVE_E300_QSPI0] ={ 0x10014000, 0x1000 },
+[SIFIVE_E300_PWM0] = { 0x10015000, 0x1000 },
+[SIFIVE_E300_UART1] ={ 0x10023000, 0x1000 },
+[SIFIVE_E300_QSPI1] ={ 0x10024000, 0x1000 },
+[SIFIVE_E300_PWM1] = { 0x10025000, 0x1000 },
+[SIFIVE_E300_QSPI2] ={ 0x10034000, 0x1000 },
+[SIFIVE_E300_PWM2] = { 0x10035000, 0x1000 },
+[SIFIVE_E300_XIP] =  { 0x2000, 0x2000 },
+[SIFIVE_E300_DTIM] = { 0x8000, 0x4000 }
+};
+
+static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len)
+{
+int i;
+for (i = 0; i < (len >> 2); i++) {
+stl_phys(_space_memory, pa + (i << 2), rom[i]);
+}
+}
+
+static uint64_t identity_translate(void *opaque, uint64_t addr)
+{
+return addr;
+}
+
+static uint64_t load_kernel(const char *kernel_filename)
+{
+uint64_t kernel_entry, kernel_high;
+
+if (load_elf(kernel_filename, identity_translate, NULL,
+ _entry, NULL, _high,
+ 0, ELF_MACHINE, 1, 0) < 0) {
+error_report("qemu: could not load kernel '%s'", kernel_filename);
+exit(1);
+}
+return kernel_entry;
+}
+
+static void sifive_mmio_emulate(MemoryRegion *parent, const char *name,
+ uintptr_t offset, uintptr_t length)
+{
+MemoryRegion *mock_mmio = g_new(MemoryRegion, 1);
+memory_region_init_ram(mock_mmio, NULL, name, length, _fatal);
+memory_region_add_subregion(parent, offset, mock_mmio);
+}
+
+static void riscv_sifive_e300_init(MachineState *machine)
+{
+const struct MemmapEntry *memmap = sifive_e300_memmap;
+
+SiFiveE300State *s = g_new0(SiFiveE300State, 1);
+MemoryRegion *sys_mem = get_system_memory();
+MemoryRegion *main_mem = g_new(MemoryRegion, 1);
+MemoryRegion *mask_rom = 

[Qemu-devel] [PATCH v7 14/23] SiFive RISC-V CLINT Block

2018-02-26 Thread Michael Clark
The CLINT (Core Local Interruptor) device provides real-time clock, timer
and interprocessor interrupts based on SiFive's CLINT specification.

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_clint.c | 254 
 include/hw/riscv/sifive_clint.h |  50 
 2 files changed, 304 insertions(+)
 create mode 100644 hw/riscv/sifive_clint.c
 create mode 100644 include/hw/riscv/sifive_clint.h

diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c
new file mode 100644
index 000..4893453
--- /dev/null
+++ b/hw/riscv/sifive_clint.c
@@ -0,0 +1,254 @@
+/*
+ * SiFive CLINT (Core Local Interruptor)
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides real-time clock, timer and interprocessor interrupts.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_clint.h"
+#include "qemu/timer.h"
+
+/* See: riscv-pk/machine/sbi_entry.S and arch/riscv/kernel/time.c */
+#define TIMER_FREQ (10 * 1000 * 1000)
+
+static uint64_t cpu_riscv_read_rtc(void)
+{
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), TIMER_FREQ,
+NANOSECONDS_PER_SECOND);
+}
+
+/*
+ * Called when timecmp is written to update the QEMU timer or immediately
+ * trigger timer interrupt if mtimecmp <= current timer value.
+ */
+static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value)
+{
+uint64_t next;
+uint64_t diff;
+
+uint64_t rtc_r = cpu_riscv_read_rtc();
+
+cpu->env.timecmp = value;
+if (cpu->env.timecmp <= rtc_r) {
+/* if we're setting an MTIMECMP value in the "past",
+   immediately raise the timer interrupt */
+riscv_set_local_interrupt(cpu, MIP_MTIP, 1);
+return;
+}
+
+/* otherwise, set up the future timer interrupt */
+riscv_set_local_interrupt(cpu, MIP_MTIP, 0);
+diff = cpu->env.timecmp - rtc_r;
+/* back to ns (note args switched in muldiv64) */
+next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+muldiv64(diff, NANOSECONDS_PER_SECOND, TIMER_FREQ);
+timer_mod(cpu->env.timer, next);
+}
+
+/*
+ * Callback used when the timer set using timer_mod expires.
+ * Should raise the timer interrupt line
+ */
+static void sifive_clint_timer_cb(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+riscv_set_local_interrupt(cpu, MIP_MTIP, 1);
+}
+
+/* CPU wants to read rtc or timecmp register */
+static uint64_t sifive_clint_read(void *opaque, hwaddr addr, unsigned size)
+{
+SiFiveCLINTState *clint = opaque;
+if (addr >= clint->sip_base &&
+addr < clint->sip_base + (clint->num_harts << 2)) {
+size_t hartid = (addr - clint->sip_base) >> 2;
+CPUState *cpu = qemu_get_cpu(hartid);
+CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
+if (!env) {
+error_report("clint: invalid timecmp hartid: %zu", hartid);
+} else if ((addr & 0x3) == 0) {
+return (env->mip & MIP_MSIP) > 0;
+} else {
+error_report("clint: invalid read: %08x", (uint32_t)addr);
+return 0;
+}
+} else if (addr >= clint->timecmp_base &&
+addr < clint->timecmp_base + (clint->num_harts << 3)) {
+size_t hartid = (addr - clint->timecmp_base) >> 3;
+CPUState *cpu = qemu_get_cpu(hartid);
+CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
+if (!env) {
+error_report("clint: invalid timecmp hartid: %zu", hartid);
+} else if ((addr & 0x7) == 0) {
+/* timecmp_lo */
+uint64_t timecmp = env->timecmp;
+return timecmp & 0x;
+} else if ((addr & 0x7) == 4) {
+/* timecmp_hi */
+uint64_t timecmp = env->timecmp;
+return (timecmp >> 32) & 0x;
+} else {
+error_report("clint: invalid read: %08x", (uint32_t)addr);
+return 0;
+}
+} else if (addr == clint->time_base) {
+/* time_lo */
+return cpu_riscv_read_rtc() & 0x;
+} else if (addr == clint->time_base + 4) {
+/* time_hi */
+return (cpu_riscv_read_rtc() >> 32) & 0x;
+}
+
+

[Qemu-devel] [PATCH v7 20/23] SiFive RISC-V PRCI Block

2018-02-26 Thread Michael Clark
Simple model of the PRCI  (Power, Reset, Clock, Interrupt) to emulate
register reads made by the SDK BSP.

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_prci.c | 89 ++
 include/hw/riscv/sifive_prci.h | 37 ++
 2 files changed, 126 insertions(+)
 create mode 100644 hw/riscv/sifive_prci.c
 create mode 100644 include/hw/riscv/sifive_prci.h

diff --git a/hw/riscv/sifive_prci.c b/hw/riscv/sifive_prci.c
new file mode 100644
index 000..0910ea3
--- /dev/null
+++ b/hw/riscv/sifive_prci.c
@@ -0,0 +1,89 @@
+/*
+ * QEMU SiFive PRCI (Power, Reset, Clock, Interrupt)
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Simple model of the PRCI to emulate register reads made by the SDK BSP
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_prci.h"
+
+/* currently implements enough to mock freedom-e-sdk BSP clock programming */
+
+static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size)
+{
+if (addr == 0 /* PRCI_HFROSCCFG */) {
+return 1 << 31; /* ROSC_RDY */
+}
+if (addr == 8 /* PRCI_PLLCFG*/) {
+return 1 << 31; /* PLL_LOCK */
+}
+hw_error("%s: read: addr=0x%x\n", __func__, (int)addr);
+return 0;
+}
+
+static void sifive_prci_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+/* discard writes */
+}
+
+static const MemoryRegionOps sifive_prci_ops = {
+.read = sifive_prci_read,
+.write = sifive_prci_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 4
+}
+};
+
+static void sifive_prci_init(Object *obj)
+{
+SiFivePRCIState *s = SIFIVE_PRCI(obj);
+
+memory_region_init_io(>mmio, obj, _prci_ops, s,
+  TYPE_SIFIVE_PRCI, 0x8000);
+sysbus_init_mmio(SYS_BUS_DEVICE(obj), >mmio);
+}
+
+static const TypeInfo sifive_prci_info = {
+.name  = TYPE_SIFIVE_PRCI,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(SiFivePRCIState),
+.instance_init = sifive_prci_init,
+};
+
+static void sifive_prci_register_types(void)
+{
+type_register_static(_prci_info);
+}
+
+type_init(sifive_prci_register_types)
+
+
+/*
+ * Create PRCI device.
+ */
+DeviceState *sifive_prci_create(hwaddr addr)
+{
+DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_PRCI);
+qdev_init_nofail(dev);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
+return dev;
+}
diff --git a/include/hw/riscv/sifive_prci.h b/include/hw/riscv/sifive_prci.h
new file mode 100644
index 000..b6f4c48
--- /dev/null
+++ b/include/hw/riscv/sifive_prci.h
@@ -0,0 +1,37 @@
+/*
+ * QEMU SiFive PRCI (Power, Reset, Clock, Interrupt) interface
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#ifndef HW_SIFIVE_PRCI_H
+#define HW_SIFIVE_PRCI_H
+
+#define TYPE_SIFIVE_PRCI "riscv.sifive.prci"
+
+#define SIFIVE_PRCI(obj) \
+OBJECT_CHECK(SiFivePRCIState, (obj), TYPE_SIFIVE_PRCI)
+
+typedef struct SiFivePRCIState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+MemoryRegion mmio;
+} SiFivePRCIState;
+
+DeviceState *sifive_prci_create(hwaddr addr);
+
+#endif
-- 
2.7.0




[Qemu-devel] [PATCH v7 08/23] RISC-V TCG Code Generation

2018-02-26 Thread Michael Clark
TCG code generation for the RV32IMAFDC and RV64IMAFDC. The QEMU
RISC-V code generator has complete coverage for the Base ISA v2.2,
Privileged ISA v1.9.1 and Privileged ISA v1.10:

- RISC-V Instruction Set Manual Volume I: User-Level ISA Version 2.2
- RISC-V Instruction Set Manual Volume II: Privileged ISA Version 1.9.1
- RISC-V Instruction Set Manual Volume II: Privileged ISA Version 1.10

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 target/riscv/instmap.h   |  364 +
 target/riscv/translate.c | 1974 ++
 2 files changed, 2338 insertions(+)
 create mode 100644 target/riscv/instmap.h
 create mode 100644 target/riscv/translate.c

diff --git a/target/riscv/instmap.h b/target/riscv/instmap.h
new file mode 100644
index 000..58baa1b
--- /dev/null
+++ b/target/riscv/instmap.h
@@ -0,0 +1,364 @@
+/*
+ * RISC-V emulation for qemu: Instruction decode helpers
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#define MASK_OP_MAJOR(op)  (op & 0x7F)
+enum {
+/* rv32i, rv64i, rv32m */
+OPC_RISC_LUI= (0x37),
+OPC_RISC_AUIPC  = (0x17),
+OPC_RISC_JAL= (0x6F),
+OPC_RISC_JALR   = (0x67),
+OPC_RISC_BRANCH = (0x63),
+OPC_RISC_LOAD   = (0x03),
+OPC_RISC_STORE  = (0x23),
+OPC_RISC_ARITH_IMM  = (0x13),
+OPC_RISC_ARITH  = (0x33),
+OPC_RISC_FENCE  = (0x0F),
+OPC_RISC_SYSTEM = (0x73),
+
+/* rv64i, rv64m */
+OPC_RISC_ARITH_IMM_W = (0x1B),
+OPC_RISC_ARITH_W = (0x3B),
+
+/* rv32a, rv64a */
+OPC_RISC_ATOMIC = (0x2F),
+
+/* floating point */
+OPC_RISC_FP_LOAD = (0x7),
+OPC_RISC_FP_STORE = (0x27),
+
+OPC_RISC_FMADD = (0x43),
+OPC_RISC_FMSUB = (0x47),
+OPC_RISC_FNMSUB = (0x4B),
+OPC_RISC_FNMADD = (0x4F),
+
+OPC_RISC_FP_ARITH = (0x53),
+};
+
+#define MASK_OP_ARITH(op)   (MASK_OP_MAJOR(op) | (op & ((0x7 << 12) | \
+(0x7F << 25
+enum {
+OPC_RISC_ADD   = OPC_RISC_ARITH | (0x0 << 12) | (0x00 << 25),
+OPC_RISC_SUB   = OPC_RISC_ARITH | (0x0 << 12) | (0x20 << 25),
+OPC_RISC_SLL   = OPC_RISC_ARITH | (0x1 << 12) | (0x00 << 25),
+OPC_RISC_SLT   = OPC_RISC_ARITH | (0x2 << 12) | (0x00 << 25),
+OPC_RISC_SLTU  = OPC_RISC_ARITH | (0x3 << 12) | (0x00 << 25),
+OPC_RISC_XOR   = OPC_RISC_ARITH | (0x4 << 12) | (0x00 << 25),
+OPC_RISC_SRL   = OPC_RISC_ARITH | (0x5 << 12) | (0x00 << 25),
+OPC_RISC_SRA   = OPC_RISC_ARITH | (0x5 << 12) | (0x20 << 25),
+OPC_RISC_OR= OPC_RISC_ARITH | (0x6 << 12) | (0x00 << 25),
+OPC_RISC_AND   = OPC_RISC_ARITH | (0x7 << 12) | (0x00 << 25),
+
+/* RV64M */
+OPC_RISC_MUL= OPC_RISC_ARITH | (0x0 << 12) | (0x01 << 25),
+OPC_RISC_MULH   = OPC_RISC_ARITH | (0x1 << 12) | (0x01 << 25),
+OPC_RISC_MULHSU = OPC_RISC_ARITH | (0x2 << 12) | (0x01 << 25),
+OPC_RISC_MULHU  = OPC_RISC_ARITH | (0x3 << 12) | (0x01 << 25),
+
+OPC_RISC_DIV= OPC_RISC_ARITH | (0x4 << 12) | (0x01 << 25),
+OPC_RISC_DIVU   = OPC_RISC_ARITH | (0x5 << 12) | (0x01 << 25),
+OPC_RISC_REM= OPC_RISC_ARITH | (0x6 << 12) | (0x01 << 25),
+OPC_RISC_REMU   = OPC_RISC_ARITH | (0x7 << 12) | (0x01 << 25),
+};
+
+
+#define MASK_OP_ARITH_IMM(op)   (MASK_OP_MAJOR(op) | (op & (0x7 << 12)))
+enum {
+OPC_RISC_ADDI   = OPC_RISC_ARITH_IMM | (0x0 << 12),
+OPC_RISC_SLTI   = OPC_RISC_ARITH_IMM | (0x2 << 12),
+OPC_RISC_SLTIU  = OPC_RISC_ARITH_IMM | (0x3 << 12),
+OPC_RISC_XORI   = OPC_RISC_ARITH_IMM | (0x4 << 12),
+OPC_RISC_ORI= OPC_RISC_ARITH_IMM | (0x6 << 12),
+OPC_RISC_ANDI   = OPC_RISC_ARITH_IMM | (0x7 << 12),
+OPC_RISC_SLLI   = OPC_RISC_ARITH_IMM | (0x1 << 12), /* additional part of
+   IMM */
+OPC_RISC_SHIFT_RIGHT_I = OPC_RISC_ARITH_IMM | (0x5 << 12) /* SRAI, SRLI */
+};
+
+#define MASK_OP_BRANCH(op) (MASK_OP_MAJOR(op) | (op & (0x7 << 12)))
+enum {
+OPC_RISC_BEQ  = OPC_RISC_BRANCH  | (0x0  << 12),
+OPC_RISC_BNE  = OPC_RISC_BRANCH  | (0x1  << 12),
+OPC_RISC_BLT  = OPC_RISC_BRANCH  | (0x4  << 12),
+OPC_RISC_BGE  = OPC_RISC_BRANCH  | (0x5  << 12),
+OPC_RISC_BLTU = OPC_RISC_BRANCH  | (0x6  << 12),
+OPC_RISC_BGEU = OPC_RISC_BRANCH  | (0x7  << 12)
+};
+
+enum {
+OPC_RISC_ADDIW   = 

[Qemu-devel] [PATCH v7 10/23] RISC-V Linux User Emulation

2018-02-26 Thread Michael Clark
Implementation of linux user emulation for RISC-V.

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 linux-user/elfload.c  |  22 +++
 linux-user/main.c |  99 +
 linux-user/riscv/syscall_nr.h | 287 ++
 linux-user/riscv/target_cpu.h |  18 +++
 linux-user/riscv/target_signal.h  |  23 +++
 linux-user/riscv/target_structs.h |  46 ++
 linux-user/riscv/target_syscall.h |  56 
 linux-user/riscv/termbits.h   | 222 +
 linux-user/signal.c   | 203 ++-
 linux-user/syscall.c  |   2 +
 linux-user/syscall_defs.h |  13 +-
 target/riscv/cpu_user.h   |  13 ++
 12 files changed, 998 insertions(+), 6 deletions(-)
 create mode 100644 linux-user/riscv/syscall_nr.h
 create mode 100644 linux-user/riscv/target_cpu.h
 create mode 100644 linux-user/riscv/target_signal.h
 create mode 100644 linux-user/riscv/target_structs.h
 create mode 100644 linux-user/riscv/target_syscall.h
 create mode 100644 linux-user/riscv/termbits.h
 create mode 100644 target/riscv/cpu_user.h

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 8bb9a2c..0277091 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1291,6 +1291,28 @@ static inline void init_thread(struct target_pt_regs 
*regs,
 
 #endif /* TARGET_TILEGX */
 
+#ifdef TARGET_RISCV
+
+#define ELF_START_MMAP 0x8000
+#define ELF_ARCH  EM_RISCV
+
+#ifdef TARGET_RISCV32
+#define ELF_CLASS ELFCLASS32
+#else
+#define ELF_CLASS ELFCLASS64
+#endif
+
+static inline void init_thread(struct target_pt_regs *regs,
+   struct image_info *infop)
+{
+regs->sepc = infop->entry;
+regs->sp = infop->start_stack;
+}
+
+#define ELF_EXEC_PAGESIZE 4096
+
+#endif /* TARGET_RISCV */
+
 #ifdef TARGET_HPPA
 
 #define ELF_START_MMAP  0x8000
diff --git a/linux-user/main.c b/linux-user/main.c
index fd79006..b27890a 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3652,6 +3652,100 @@ void cpu_loop(CPUTLGState *env)
 
 #endif
 
+#ifdef TARGET_RISCV
+
+void cpu_loop(CPURISCVState *env)
+{
+CPUState *cs = CPU(riscv_env_get_cpu(env));
+int trapnr, signum, sigcode;
+target_ulong sigaddr;
+target_ulong ret;
+
+for (;;) {
+cpu_exec_start(cs);
+trapnr = cpu_exec(cs);
+cpu_exec_end(cs);
+process_queued_cpu_work(cs);
+
+signum = 0;
+sigcode = 0;
+sigaddr = 0;
+
+switch (trapnr) {
+case EXCP_INTERRUPT:
+/* just indicate that signals should be handled asap */
+break;
+case EXCP_ATOMIC:
+cpu_exec_step_atomic(cs);
+break;
+case RISCV_EXCP_U_ECALL:
+env->pc += 4;
+if (env->gpr[xA7] == TARGET_NR_arch_specific_syscall + 15) {
+/* riscv_flush_icache_syscall is a no-op in QEMU as
+   self-modifying code is automatically detected */
+ret = 0;
+} else {
+ret = do_syscall(env,
+ env->gpr[xA7],
+ env->gpr[xA0],
+ env->gpr[xA1],
+ env->gpr[xA2],
+ env->gpr[xA3],
+ env->gpr[xA4],
+ env->gpr[xA5],
+ 0, 0);
+}
+if (ret == -TARGET_ERESTARTSYS) {
+env->pc -= 4;
+} else if (ret != -TARGET_QEMU_ESIGRETURN) {
+env->gpr[xA0] = ret;
+}
+if (cs->singlestep_enabled) {
+goto gdbstep;
+}
+break;
+case RISCV_EXCP_ILLEGAL_INST:
+signum = TARGET_SIGILL;
+sigcode = TARGET_ILL_ILLOPC;
+break;
+case RISCV_EXCP_BREAKPOINT:
+signum = TARGET_SIGTRAP;
+sigcode = TARGET_TRAP_BRKPT;
+sigaddr = env->pc;
+break;
+case RISCV_EXCP_INST_PAGE_FAULT:
+case RISCV_EXCP_LOAD_PAGE_FAULT:
+case RISCV_EXCP_STORE_PAGE_FAULT:
+signum = TARGET_SIGSEGV;
+sigcode = TARGET_SEGV_MAPERR;
+break;
+case EXCP_DEBUG:
+gdbstep:
+signum = gdb_handlesig(cs, TARGET_SIGTRAP);
+sigcode = TARGET_TRAP_BRKPT;
+break;
+default:
+EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
+ trapnr);
+exit(EXIT_FAILURE);
+}
+
+if (signum) {
+target_siginfo_t info = {
+.si_signo = signum,
+.si_errno = 0,
+.si_code = sigcode,
+._sifields._sigfault._addr = sigaddr
+};
+

[Qemu-devel] [PATCH v7 09/23] RISC-V Physical Memory Protection

2018-02-26 Thread Michael Clark
Implements the physical memory protection extension as specified in
Privileged ISA Version 1.10.

PMP (Physical Memory Protection) is as-of-yet unused and needs testing.
The SiFive verification team have PMP test cases that will be run.

Nothing currently depends on PMP support. It would be preferable to keep
the code in-tree for folk that are interested in RISC-V PMP support.

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 target/riscv/pmp.c | 380 +
 target/riscv/pmp.h |  64 +
 2 files changed, 444 insertions(+)
 create mode 100644 target/riscv/pmp.c
 create mode 100644 target/riscv/pmp.h

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
new file mode 100644
index 000..f432f3b
--- /dev/null
+++ b/target/riscv/pmp.c
@@ -0,0 +1,380 @@
+/*
+ * QEMU RISC-V PMP (Physical Memory Protection)
+ *
+ * Author: Daire McNamara, daire.mcnam...@emdalo.com
+ * Ivan Griffin, ivan.grif...@emdalo.com
+ *
+ * This provides a RISC-V Physical Memory Protection implementation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+/*
+ * PMP (Physical Memory Protection) is as-of-yet unused and needs testing.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "qemu-common.h"
+
+#ifndef CONFIG_USER_ONLY
+
+#define RISCV_DEBUG_PMP 0
+#define PMP_DEBUG(fmt, ...)
\
+do {   
\
+if (RISCV_DEBUG_PMP) { 
\
+qemu_log_mask(LOG_TRACE, "%s: " fmt "\n", __func__, 
##__VA_ARGS__);\
+}  
\
+} while (0)
+
+static void pmp_write_cfg(CPURISCVState *env, uint32_t addr_index,
+uint8_t val);
+static uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t addr_index);
+static void pmp_update_rule(CPURISCVState *env, uint32_t pmp_index);
+
+/*
+ * Accessor method to extract address matching type 'a field' from cfg reg
+ */
+static inline uint8_t pmp_get_a_field(uint8_t cfg)
+{
+uint8_t a = cfg >> 3;
+return a & 0x3;
+}
+
+/*
+ * Check whether a PMP is locked or not.
+ */
+static inline int pmp_is_locked(CPURISCVState *env, uint32_t pmp_index)
+{
+
+if (env->pmp_state.pmp[pmp_index].cfg_reg & PMP_LOCK) {
+return 1;
+}
+
+/* Top PMP has no 'next' to check */
+if ((pmp_index + 1u) >= MAX_RISCV_PMPS) {
+return 0;
+}
+
+/* In TOR mode, need to check the lock bit of the next pmp
+ * (if there is a next)
+ */
+const uint8_t a_field =
+pmp_get_a_field(env->pmp_state.pmp[pmp_index + 1].cfg_reg);
+if ((env->pmp_state.pmp[pmp_index + 1u].cfg_reg & PMP_LOCK) &&
+ (PMP_AMATCH_TOR == a_field)) {
+return 1;
+}
+
+return 0;
+}
+
+/*
+ * Count the number of active rules.
+ */
+static inline uint32_t pmp_get_num_rules(CPURISCVState *env)
+{
+ return env->pmp_state.num_rules;
+}
+
+/*
+ * Accessor to get the cfg reg for a specific PMP/HART
+ */
+static inline uint8_t pmp_read_cfg(CPURISCVState *env, uint32_t pmp_index)
+{
+if (pmp_index < MAX_RISCV_PMPS) {
+return env->pmp_state.pmp[pmp_index].cfg_reg;
+}
+
+return 0;
+}
+
+
+/*
+ * Accessor to set the cfg reg for a specific PMP/HART
+ * Bounds checks and relevant lock bit.
+ */
+static void pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
+{
+if (pmp_index < MAX_RISCV_PMPS) {
+if (!pmp_is_locked(env, pmp_index)) {
+env->pmp_state.pmp[pmp_index].cfg_reg = val;
+pmp_update_rule(env, pmp_index);
+} else {
+PMP_DEBUG("ignoring write - locked");
+}
+} else {
+PMP_DEBUG("ignoring write - out of bounds");
+}
+}
+
+static void pmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong 
*ea)
+{
+/*
+   ...aaa0   8-byte NAPOT range
+   ...aa01   16-byte NAPOT range
+   ...a011   32-byte NAPOT range
+   ...
+   aa01...   2^XLEN-byte NAPOT range
+   a011...   2^(XLEN+1)-byte NAPOT range
+   0111...   2^(XLEN+2)-byte NAPOT range
+   ...   Reserved
+*/
+if (a == -1) {
+*sa = 0u;
+*ea = -1;
+

[Qemu-devel] [PATCH v7 15/23] SiFive RISC-V PLIC Block

2018-02-26 Thread Michael Clark
The PLIC (Platform Level Interrupt Controller) device provides a
parameterizable interrupt controller based on SiFive's PLIC specification.

Acked-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/sifive_plic.c | 505 +
 include/hw/riscv/sifive_plic.h |  85 +++
 2 files changed, 590 insertions(+)
 create mode 100644 hw/riscv/sifive_plic.c
 create mode 100644 include/hw/riscv/sifive_plic.h

diff --git a/hw/riscv/sifive_plic.c b/hw/riscv/sifive_plic.c
new file mode 100644
index 000..874de2e
--- /dev/null
+++ b/hw/riscv/sifive_plic.c
@@ -0,0 +1,505 @@
+/*
+ * SiFive PLIC (Platform Level Interrupt Controller)
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * This provides a parameterizable interrupt controller based on SiFive's PLIC.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_plic.h"
+
+#define RISCV_DEBUG_PLIC 0
+
+static PLICMode char_to_mode(char c)
+{
+switch (c) {
+case 'U': return PLICMode_U;
+case 'S': return PLICMode_S;
+case 'H': return PLICMode_H;
+case 'M': return PLICMode_M;
+default:
+error_report("plic: invalid mode '%c'", c);
+exit(1);
+}
+}
+
+static char mode_to_char(PLICMode m)
+{
+switch (m) {
+case PLICMode_U: return 'U';
+case PLICMode_S: return 'S';
+case PLICMode_H: return 'H';
+case PLICMode_M: return 'M';
+default: return '?';
+}
+}
+
+static void sifive_plic_print_state(SiFivePLICState *plic)
+{
+int i;
+int addrid;
+
+/* pending */
+qemu_log("pending   : ");
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+qemu_log("%08x", plic->pending[i]);
+}
+qemu_log("\n");
+
+/* pending */
+qemu_log("claimed   : ");
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+qemu_log("%08x", plic->claimed[i]);
+}
+qemu_log("\n");
+
+for (addrid = 0; addrid < plic->num_addrs; addrid++) {
+qemu_log("hart%d-%c enable: ",
+plic->addr_config[addrid].hartid,
+mode_to_char(plic->addr_config[addrid].mode));
+for (i = plic->bitfield_words - 1; i >= 0; i--) {
+qemu_log("%08x", plic->enable[addrid * plic->bitfield_words + i]);
+}
+qemu_log("\n");
+}
+}
+
+static
+void sifive_plic_set_pending(SiFivePLICState *plic, int irq, bool pending)
+{
+qemu_mutex_lock(>lock);
+uint32_t word = irq >> 5;
+if (pending) {
+plic->pending[word] |= (1 << (irq & 31));
+} else {
+plic->pending[word] &= ~(1 << (irq & 31));
+}
+qemu_mutex_unlock(>lock);
+}
+
+static
+void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool claimed)
+{
+qemu_mutex_lock(>lock);
+uint32_t word = irq >> 5;
+if (claimed) {
+plic->claimed[word] |= (1 << (irq & 31));
+} else {
+plic->claimed[word] &= ~(1 << (irq & 31));
+}
+qemu_mutex_unlock(>lock);
+}
+
+static
+int sifive_plic_num_irqs_pending(SiFivePLICState *plic, uint32_t addrid)
+{
+int i, j, count = 0;
+for (i = 0; i < plic->bitfield_words; i++) {
+uint32_t pending_enabled_not_claimed =
+(plic->pending[i] & ~plic->claimed[i]) &
+plic->enable[addrid * plic->bitfield_words + i];
+if (!pending_enabled_not_claimed) {
+continue;
+}
+for (j = 0; j < 32; j++) {
+int irq = (i << 5) + j;
+uint32_t prio = plic->source_priority[irq];
+int enabled = pending_enabled_not_claimed & (1 << j);
+if (enabled && prio > plic->target_priority[addrid]) {
+count++;
+}
+}
+}
+return count;
+}
+
+static void sifive_plic_update(SiFivePLICState *plic)
+{
+int addrid;
+
+/* raise irq on harts where this irq is enabled */
+for (addrid = 0; addrid < plic->num_addrs; addrid++) {
+uint32_t hartid = plic->addr_config[addrid].hartid;
+PLICMode mode = plic->addr_config[addrid].mode;
+CPUState *cpu = qemu_get_cpu(hartid);
+CPURISCVState *env = cpu ? cpu->env_ptr : NULL;
+if (!env) {
+continue;
+}
+int level = sifive_plic_num_irqs_pending(plic, 

[Qemu-devel] [PATCH v7 11/23] Add symbol table callback interface to load_elf

2018-02-26 Thread Michael Clark
The RISC-V HTIF (Host Target Interface) console device requires access
to the symbol table to locate the 'tohost' and 'fromhost' symbols.

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/core/loader.c | 18 --
 include/hw/elf_ops.h | 34 +-
 include/hw/loader.h  | 17 -
 3 files changed, 53 insertions(+), 16 deletions(-)

diff --git a/hw/core/loader.c b/hw/core/loader.c
index 91669d6..80b69ea 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -450,6 +450,20 @@ int load_elf_ram(const char *filename,
  int clear_lsb, int data_swab, AddressSpace *as,
  bool load_rom)
 {
+return load_elf_ram_sym(filename, translate_fn, translate_opaque,
+pentry, lowaddr, highaddr, big_endian,
+elf_machine, clear_lsb, data_swab, as,
+load_rom, NULL);
+}
+
+/* return < 0 if error, otherwise the number of bytes loaded in memory */
+int load_elf_ram_sym(const char *filename,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque, uint64_t *pentry,
+ uint64_t *lowaddr, uint64_t *highaddr, int big_endian,
+ int elf_machine, int clear_lsb, int data_swab,
+ AddressSpace *as, bool load_rom, symbol_fn_t sym_cb)
+{
 int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
 uint8_t e_ident[EI_NIDENT];
 
@@ -488,11 +502,11 @@ int load_elf_ram(const char *filename,
 if (e_ident[EI_CLASS] == ELFCLASS64) {
 ret = load_elf64(filename, fd, translate_fn, translate_opaque, 
must_swab,
  pentry, lowaddr, highaddr, elf_machine, clear_lsb,
- data_swab, as, load_rom);
+ data_swab, as, load_rom, sym_cb);
 } else {
 ret = load_elf32(filename, fd, translate_fn, translate_opaque, 
must_swab,
  pentry, lowaddr, highaddr, elf_machine, clear_lsb,
- data_swab, as, load_rom);
+ data_swab, as, load_rom, sym_cb);
 }
 
  fail:
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index d192e7e..b6e19e3 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -105,7 +105,7 @@ static int glue(symcmp, SZ)(const void *s0, const void *s1)
 }
 
 static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
-  int clear_lsb)
+  int clear_lsb, symbol_fn_t sym_cb)
 {
 struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
 struct elf_sym *syms = NULL;
@@ -133,10 +133,26 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, 
int fd, int must_swab,
 
 nsyms = symtab->sh_size / sizeof(struct elf_sym);
 
+/* String table */
+if (symtab->sh_link >= ehdr->e_shnum) {
+goto fail;
+}
+strtab = _table[symtab->sh_link];
+
+str = load_at(fd, strtab->sh_offset, strtab->sh_size);
+if (!str) {
+goto fail;
+}
+
 i = 0;
 while (i < nsyms) {
-if (must_swab)
+if (must_swab) {
 glue(bswap_sym, SZ)([i]);
+}
+if (sym_cb) {
+sym_cb(str + syms[i].st_name, syms[i].st_info,
+   syms[i].st_value, syms[i].st_size);
+}
 /* We are only interested in function symbols.
Throw everything else away.  */
 if (syms[i].st_shndx == SHN_UNDEF ||
@@ -163,15 +179,6 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int 
fd, int must_swab,
 }
 }
 
-/* String table */
-if (symtab->sh_link >= ehdr->e_shnum)
-goto fail;
-strtab = _table[symtab->sh_link];
-
-str = load_at(fd, strtab->sh_offset, strtab->sh_size);
-if (!str)
-goto fail;
-
 /* Commit */
 s = g_malloc0(sizeof(*s));
 s->lookup_symbol = glue(lookup_symbol, SZ);
@@ -264,7 +271,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
   int must_swab, uint64_t *pentry,
   uint64_t *lowaddr, uint64_t *highaddr,
   int elf_machine, int clear_lsb, int data_swab,
-  AddressSpace *as, bool load_rom)
+  AddressSpace *as, bool load_rom,
+  symbol_fn_t sym_cb)
 {
 struct elfhdr ehdr;
 struct elf_phdr *phdr = NULL, *ph;
@@ -329,7 +337,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
 if (pentry)
*pentry = (uint64_t)(elf_sword)ehdr.e_entry;
 
-glue(load_symbols, SZ)(, fd, must_swab, clear_lsb);
+glue(load_symbols, SZ)(, fd, must_swab, clear_lsb, sym_cb);
 
 size = ehdr.e_phnum * sizeof(phdr[0]);
 if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff) {
diff --git 

[Qemu-devel] [PATCH v7 12/23] RISC-V HTIF Console

2018-02-26 Thread Michael Clark
HTIF (Host Target Interface) provides console emulation for QEMU. HTIF
allows identical copies of BBL (Berkeley Boot Loader) and linux to run
on both Spike and QEMU. BBL provides HTIF console access via the
SBI (Supervisor Binary Interface) and the linux kernel SBI console.

The HTIT chardev implements the pre qom legacy interface consistent
with the 16550a UART in 'hw/char/serial.c'.

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/riscv_htif.c | 258 ++
 include/hw/riscv/riscv_htif.h |  61 ++
 2 files changed, 319 insertions(+)
 create mode 100644 hw/riscv/riscv_htif.c
 create mode 100644 include/hw/riscv/riscv_htif.h

diff --git a/hw/riscv/riscv_htif.c b/hw/riscv/riscv_htif.c
new file mode 100644
index 000..3e17f30
--- /dev/null
+++ b/hw/riscv/riscv_htif.c
@@ -0,0 +1,258 @@
+/*
+ * QEMU RISC-V Host Target Interface (HTIF) Emulation
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * This provides HTIF device emulation for QEMU. At the moment this allows
+ * for identical copies of bbl/linux to run on both spike and QEMU.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "hw/sysbus.h"
+#include "hw/char/serial.h"
+#include "chardev/char.h"
+#include "chardev/char-fe.h"
+#include "hw/riscv/riscv_htif.h"
+#include "qemu/timer.h"
+#include "exec/address-spaces.h"
+#include "qemu/error-report.h"
+
+#define RISCV_DEBUG_HTIF 0
+#define HTIF_DEBUG(fmt, ...)   
\
+do {   
\
+if (RISCV_DEBUG_HTIF) {
\
+qemu_log_mask(LOG_TRACE, "%s: " fmt "\n", __func__, 
##__VA_ARGS__);\
+}  
\
+} while (0)
+
+static uint64_t fromhost_addr, tohost_addr;
+
+void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
+uint64_t st_size)
+{
+if (strcmp("fromhost", st_name) == 0) {
+fromhost_addr = st_value;
+if (st_size != 8) {
+error_report("HTIF fromhost must be 8 bytes");
+exit(1);
+}
+} else if (strcmp("tohost", st_name) == 0) {
+tohost_addr = st_value;
+if (st_size != 8) {
+error_report("HTIF tohost must be 8 bytes");
+exit(1);
+}
+}
+}
+
+/*
+ * Called by the char dev to see if HTIF is ready to accept input.
+ */
+static int htif_can_recv(void *opaque)
+{
+return 1;
+}
+
+/*
+ * Called by the char dev to supply input to HTIF console.
+ * We assume that we will receive one character at a time.
+ */
+static void htif_recv(void *opaque, const uint8_t *buf, int size)
+{
+HTIFState *htifstate = opaque;
+
+if (size != 1) {
+return;
+}
+
+/* TODO - we need to check whether mfromhost is zero which indicates
+  the device is ready to receive. The current implementation
+  will drop characters */
+
+uint64_t val_written = htifstate->pending_read;
+uint64_t resp = 0x100 | *buf;
+
+htifstate->env->mfromhost = (val_written >> 48 << 48) | (resp << 16 >> 16);
+}
+
+/*
+ * Called by the char dev to supply special events to the HTIF console.
+ * Not used for HTIF.
+ */
+static void htif_event(void *opaque, int event)
+{
+
+}
+
+static int htif_be_change(void *opaque)
+{
+HTIFState *s = opaque;
+
+qemu_chr_fe_set_handlers(>chr, htif_can_recv, htif_recv, htif_event,
+htif_be_change, s, NULL, true);
+
+return 0;
+}
+
+static void htif_handle_tohost_write(HTIFState *htifstate, uint64_t 
val_written)
+{
+uint8_t device = val_written >> 56;
+uint8_t cmd = val_written >> 48;
+uint64_t payload = val_written & 0xULL;
+int resp = 0;
+
+HTIF_DEBUG("mtohost write: device: %d cmd: %d what: %02" PRIx64
+" -payload: %016" PRIx64 "\n", device, cmd, payload & 0xFF, payload);
+
+/*
+ * Currently, there is a fixed mapping of devices:
+ * 0: riscv-tests Pass/Fail Reporting Only (no syscall proxy)
+ * 1: Console
+ */
+if (unlikely(device == 0x0)) {
+/* frontend syscall 

[Qemu-devel] [PATCH v7 13/23] RISC-V HART Array

2018-02-26 Thread Michael Clark
Holds the state of a heterogenous array of RISC-V hardware threads.

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 hw/riscv/riscv_hart.c | 89 +++
 include/hw/riscv/riscv_hart.h | 39 +++
 2 files changed, 128 insertions(+)
 create mode 100644 hw/riscv/riscv_hart.c
 create mode 100644 include/hw/riscv/riscv_hart.h

diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c
new file mode 100644
index 000..14e3c18
--- /dev/null
+++ b/hw/riscv/riscv_hart.c
@@ -0,0 +1,89 @@
+/*
+ * QEMU RISCV Hart Array
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous array of RISC-V harts
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/riscv_hart.h"
+
+static Property riscv_harts_props[] = {
+DEFINE_PROP_UINT32("num-harts", RISCVHartArrayState, num_harts, 1),
+DEFINE_PROP_STRING("cpu-type", RISCVHartArrayState, cpu_type),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void riscv_harts_cpu_reset(void *opaque)
+{
+RISCVCPU *cpu = opaque;
+cpu_reset(CPU(cpu));
+}
+
+static void riscv_harts_realize(DeviceState *dev, Error **errp)
+{
+RISCVHartArrayState *s = RISCV_HART_ARRAY(dev);
+Error *err = NULL;
+int n;
+
+s->harts = g_new0(RISCVCPU, s->num_harts);
+
+for (n = 0; n < s->num_harts; n++) {
+
+object_initialize(>harts[n], sizeof(RISCVCPU), s->cpu_type);
+s->harts[n].env.mhartid = n;
+object_property_add_child(OBJECT(s), "harts[*]", OBJECT(>harts[n]),
+  _abort);
+qemu_register_reset(riscv_harts_cpu_reset, >harts[n]);
+object_property_set_bool(OBJECT(>harts[n]), true,
+ "realized", );
+if (err) {
+error_propagate(errp, err);
+return;
+}
+}
+}
+
+static void riscv_harts_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->props = riscv_harts_props;
+dc->realize = riscv_harts_realize;
+}
+
+static void riscv_harts_init(Object *obj)
+{
+/* RISCVHartArrayState *s = SIFIVE_COREPLEX(obj); */
+}
+
+static const TypeInfo riscv_harts_info = {
+.name  = TYPE_RISCV_HART_ARRAY,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(RISCVHartArrayState),
+.instance_init = riscv_harts_init,
+.class_init= riscv_harts_class_init,
+};
+
+static void riscv_harts_register_types(void)
+{
+type_register_static(_harts_info);
+}
+
+type_init(riscv_harts_register_types)
diff --git a/include/hw/riscv/riscv_hart.h b/include/hw/riscv/riscv_hart.h
new file mode 100644
index 000..0671d88
--- /dev/null
+++ b/include/hw/riscv/riscv_hart.h
@@ -0,0 +1,39 @@
+/*
+ * QEMU RISC-V Hart Array interface
+ *
+ * Copyright (c) 2017 SiFive, Inc.
+ *
+ * Holds the state of a heterogenous array of RISC-V harts
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#ifndef HW_RISCV_HART_H
+#define HW_RISCV_HART_H
+
+#define TYPE_RISCV_HART_ARRAY "riscv.hart_array"
+
+#define RISCV_HART_ARRAY(obj) \
+OBJECT_CHECK(RISCVHartArrayState, (obj), TYPE_RISCV_HART_ARRAY)
+
+typedef struct RISCVHartArrayState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+uint32_t num_harts;
+char *cpu_type;
+RISCVCPU *harts;
+} RISCVHartArrayState;
+
+#endif
-- 
2.7.0




[Qemu-devel] [PATCH v7 05/23] RISC-V CPU Helpers

2018-02-26 Thread Michael Clark
Privileged control and status register helpers and page fault handling.

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 target/riscv/helper.c| 503 
 target/riscv/helper.h|  78 ++
 target/riscv/op_helper.c | 655 +++
 3 files changed, 1236 insertions(+)
 create mode 100644 target/riscv/helper.c
 create mode 100644 target/riscv/helper.h
 create mode 100644 target/riscv/op_helper.c

diff --git a/target/riscv/helper.c b/target/riscv/helper.c
new file mode 100644
index 000..c472582
--- /dev/null
+++ b/target/riscv/helper.c
@@ -0,0 +1,503 @@
+/*
+ * RISC-V emulation helpers for qemu.
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "tcg-op.h"
+
+#define RISCV_DEBUG_INTERRUPT 0
+
+int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
+{
+#ifdef CONFIG_USER_ONLY
+return 0;
+#else
+return env->priv;
+#endif
+}
+
+#ifndef CONFIG_USER_ONLY
+/*
+ * Return RISC-V IRQ number if an interrupt should be taken, else -1.
+ * Used in cpu-exec.c
+ *
+ * Adapted from Spike's processor_t::take_interrupt()
+ */
+static int riscv_cpu_hw_interrupts_pending(CPURISCVState *env)
+{
+target_ulong pending_interrupts = atomic_read(>mip) & env->mie;
+
+target_ulong mie = get_field(env->mstatus, MSTATUS_MIE);
+target_ulong m_enabled = env->priv < PRV_M || (env->priv == PRV_M && mie);
+target_ulong enabled_interrupts = pending_interrupts &
+  ~env->mideleg & -m_enabled;
+
+target_ulong sie = get_field(env->mstatus, MSTATUS_SIE);
+target_ulong s_enabled = env->priv < PRV_S || (env->priv == PRV_S && sie);
+enabled_interrupts |= pending_interrupts & env->mideleg &
+  -s_enabled;
+
+if (enabled_interrupts) {
+return ctz64(enabled_interrupts); /* since non-zero */
+} else {
+return EXCP_NONE; /* indicates no pending interrupt */
+}
+}
+#endif
+
+bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+#if !defined(CONFIG_USER_ONLY)
+if (interrupt_request & CPU_INTERRUPT_HARD) {
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = >env;
+int interruptno = riscv_cpu_hw_interrupts_pending(env);
+if (interruptno >= 0) {
+cs->exception_index = RISCV_EXCP_INT_FLAG | interruptno;
+riscv_cpu_do_interrupt(cs);
+return true;
+}
+}
+#endif
+return false;
+}
+
+#if !defined(CONFIG_USER_ONLY)
+
+/* get_physical_address - get the physical address for this virtual address
+ *
+ * Do a page table walk to obtain the physical address corresponding to a
+ * virtual address. Returns 0 if the translation was successful
+ *
+ * Adapted from Spike's mmu_t::translate and mmu_t::walk
+ *
+ */
+static int get_physical_address(CPURISCVState *env, hwaddr *physical,
+int *prot, target_ulong addr,
+int access_type, int mmu_idx)
+{
+/* NOTE: the env->pc value visible here will not be
+ * correct, but the value visible to the exception handler
+ * (riscv_cpu_do_interrupt) is correct */
+
+int mode = mmu_idx;
+
+if (mode == PRV_M && access_type != MMU_INST_FETCH) {
+if (get_field(env->mstatus, MSTATUS_MPRV)) {
+mode = get_field(env->mstatus, MSTATUS_MPP);
+}
+}
+
+if (mode == PRV_M) {
+*physical = addr;
+*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+return TRANSLATE_SUCCESS;
+}
+
+*prot = 0;
+
+target_ulong base;
+int levels, ptidxbits, ptesize, vm, sum;
+int mxr = get_field(env->mstatus, MSTATUS_MXR);
+
+if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+base = get_field(env->satp, SATP_PPN) << PGSHIFT;
+sum = get_field(env->mstatus, MSTATUS_SUM);
+vm = get_field(env->satp, SATP_MODE);
+switch (vm) {
+case VM_1_10_SV32:
+  levels = 2; ptidxbits = 10; ptesize = 4; break;
+case VM_1_10_SV39:
+  levels = 3; ptidxbits = 9; ptesize = 8; break;
+case VM_1_10_SV48:
+  levels = 4; 

[Qemu-devel] [PATCH v7 06/23] RISC-V FPU Support

2018-02-26 Thread Michael Clark
Helper routines for FPU instructions and NaN definitions.

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 fpu/softfloat-specialize.h |   7 +-
 target/riscv/fpu_helper.c  | 373 +
 2 files changed, 377 insertions(+), 3 deletions(-)
 create mode 100644 target/riscv/fpu_helper.c

diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index e81ca00..e2844d0 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -114,7 +114,8 @@ float32 float32_default_nan(float_status *status)
 #if defined(TARGET_SPARC) || defined(TARGET_M68K)
 return const_float32(0x7FFF);
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
-  defined(TARGET_XTENSA) || defined(TARGET_S390X) || 
defined(TARGET_TRICORE)
+  defined(TARGET_XTENSA) || defined(TARGET_S390X) || \
+  defined(TARGET_TRICORE) || defined(TARGET_RISCV)
 return const_float32(0x7FC0);
 #elif defined(TARGET_HPPA)
 return const_float32(0x7FA0);
@@ -139,7 +140,7 @@ float64 float64_default_nan(float_status *status)
 #if defined(TARGET_SPARC) || defined(TARGET_M68K)
 return const_float64(LIT64(0x7FFF));
 #elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
-  defined(TARGET_S390X)
+  defined(TARGET_S390X) || defined(TARGET_RISCV)
 return const_float64(LIT64(0x7FF8));
 #elif defined(TARGET_HPPA)
 return const_float64(LIT64(0x7FF4));
@@ -189,7 +190,7 @@ float128 float128_default_nan(float_status *status)
 r.high = LIT64(0x7FFF7FFF);
 } else {
 r.low = LIT64(0x);
-#if defined(TARGET_S390X) || defined(TARGET_PPC)
+#if defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_RISCV)
 r.high = LIT64(0x7FFF8000);
 #else
 r.high = LIT64(0x8000);
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
new file mode 100644
index 000..abbadea
--- /dev/null
+++ b/target/riscv/fpu_helper.c
@@ -0,0 +1,373 @@
+/*
+ * RISC-V FPU Emulation Helpers for QEMU.
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/exec-all.h"
+#include "exec/helper-proto.h"
+
+target_ulong cpu_riscv_get_fflags(CPURISCVState *env)
+{
+int soft = get_float_exception_flags(>fp_status);
+target_ulong hard = 0;
+
+hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0;
+hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0;
+hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0;
+hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0;
+hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0;
+
+return hard;
+}
+
+void cpu_riscv_set_fflags(CPURISCVState *env, target_ulong hard)
+{
+int soft = 0;
+
+soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0;
+soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0;
+soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0;
+soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0;
+soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0;
+
+set_float_exception_flags(soft, >fp_status);
+}
+
+void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
+{
+int softrm;
+
+if (rm == 7) {
+rm = env->frm;
+}
+switch (rm) {
+case 0:
+softrm = float_round_nearest_even;
+break;
+case 1:
+softrm = float_round_to_zero;
+break;
+case 2:
+softrm = float_round_down;
+break;
+case 3:
+softrm = float_round_up;
+break;
+case 4:
+softrm = float_round_ties_away;
+break;
+default:
+do_raise_exception_err(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+}
+
+set_float_rounding_mode(softrm, >fp_status);
+}
+
+uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+uint64_t frs3)
+{
+return float32_muladd(frs1, frs2, frs3, 0, >fp_status);
+}
+
+uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
+uint64_t frs3)
+{
+return float64_muladd(frs1, frs2, frs3, 0, >fp_status);
+}
+
+uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t 

[Qemu-devel] [PATCH v7 04/23] RISC-V Disassembler

2018-02-26 Thread Michael Clark
The RISC-V disassembler has no dependencies outside of the 'disas'
directory so it can be applied independently. The majority of the
disassembler is machine-generated from instruction set metadata:

- https://github.com/michaeljclark/riscv-meta

Expected checkpatch errors for consistency and brevity reasons:

ERROR: line over 90 characters
ERROR: trailing statements should be on next line
ERROR: space prohibited between function name and open parenthesis '('

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 disas.c |2 +
 disas/Makefile.objs |1 +
 disas/riscv.c   | 3048 +++
 include/disas/bfd.h |2 +
 4 files changed, 3053 insertions(+)
 create mode 100644 disas/riscv.c

diff --git a/disas.c b/disas.c
index d4ad108..5325b7e 100644
--- a/disas.c
+++ b/disas.c
@@ -522,6 +522,8 @@ void disas(FILE *out, void *code, unsigned long size)
 # ifdef _ARCH_PPC64
 s.info.cap_mode = CS_MODE_64;
 # endif
+#elif defined(__riscv__)
+print_insn = print_insn_riscv;
 #elif defined(__aarch64__) && defined(CONFIG_ARM_A64_DIS)
 print_insn = print_insn_arm_a64;
 s.info.cap_arch = CS_ARCH_ARM64;
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index 53556f8..213be2f 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -17,6 +17,7 @@ common-obj-$(CONFIG_MIPS_DIS) += mips.o
 common-obj-$(CONFIG_NIOS2_DIS) += nios2.o
 common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
 common-obj-$(CONFIG_PPC_DIS) += ppc.o
+common-obj-$(CONFIG_RISCV_DIS) += riscv.o
 common-obj-$(CONFIG_S390_DIS) += s390.o
 common-obj-$(CONFIG_SH4_DIS) += sh4.o
 common-obj-$(CONFIG_SPARC_DIS) += sparc.o
diff --git a/disas/riscv.c b/disas/riscv.c
new file mode 100644
index 000..3c17501
--- /dev/null
+++ b/disas/riscv.c
@@ -0,0 +1,3048 @@
+/*
+ * QEMU RISC-V Disassembler
+ *
+ * Copyright (c) 2016-2017 Michael Clark 
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "disas/bfd.h"
+
+
+/* types */
+
+typedef uint64_t rv_inst;
+typedef uint16_t rv_opcode;
+
+/* enums */
+
+typedef enum {
+rv32,
+rv64,
+rv128
+} rv_isa;
+
+typedef enum {
+rv_rm_rne = 0,
+rv_rm_rtz = 1,
+rv_rm_rdn = 2,
+rv_rm_rup = 3,
+rv_rm_rmm = 4,
+rv_rm_dyn = 7,
+} rv_rm;
+
+typedef enum {
+rv_fence_i = 8,
+rv_fence_o = 4,
+rv_fence_r = 2,
+rv_fence_w = 1,
+} rv_fence;
+
+typedef enum {
+rv_ireg_zero,
+rv_ireg_ra,
+rv_ireg_sp,
+rv_ireg_gp,
+rv_ireg_tp,
+rv_ireg_t0,
+rv_ireg_t1,
+rv_ireg_t2,
+rv_ireg_s0,
+rv_ireg_s1,
+rv_ireg_a0,
+rv_ireg_a1,
+rv_ireg_a2,
+rv_ireg_a3,
+rv_ireg_a4,
+rv_ireg_a5,
+rv_ireg_a6,
+rv_ireg_a7,
+rv_ireg_s2,
+rv_ireg_s3,
+rv_ireg_s4,
+rv_ireg_s5,
+rv_ireg_s6,
+rv_ireg_s7,
+rv_ireg_s8,
+rv_ireg_s9,
+rv_ireg_s10,
+rv_ireg_s11,
+rv_ireg_t3,
+rv_ireg_t4,
+rv_ireg_t5,
+rv_ireg_t6,
+} rv_ireg;
+
+typedef enum {
+rvc_end,
+rvc_simm_6,
+rvc_imm_6,
+rvc_imm_7,
+rvc_imm_8,
+rvc_imm_9,
+rvc_imm_10,
+rvc_imm_12,
+rvc_imm_18,
+rvc_imm_nz,
+rvc_imm_x2,
+rvc_imm_x4,
+rvc_imm_x8,
+rvc_imm_x16,
+rvc_rd_b3,
+rvc_rs1_b3,
+rvc_rs2_b3,
+rvc_rd_eq_rs1,
+rvc_rd_eq_ra,
+rvc_rd_eq_sp,
+rvc_rd_eq_x0,
+rvc_rs1_eq_sp,
+rvc_rs1_eq_x0,
+rvc_rs2_eq_x0,
+rvc_rd_ne_x0_x2,
+rvc_rd_ne_x0,
+rvc_rs1_ne_x0,
+rvc_rs2_ne_x0,
+rvc_rs2_eq_rs1,
+rvc_rs1_eq_ra,
+rvc_imm_eq_zero,
+rvc_imm_eq_n1,
+rvc_imm_eq_p1,
+rvc_csr_eq_0x001,
+rvc_csr_eq_0x002,
+rvc_csr_eq_0x003,
+rvc_csr_eq_0xc00,
+rvc_csr_eq_0xc01,
+rvc_csr_eq_0xc02,
+rvc_csr_eq_0xc80,
+rvc_csr_eq_0xc81,
+rvc_csr_eq_0xc82,
+} rvc_constraint;
+
+typedef enum {
+rv_codec_illegal,
+rv_codec_none,
+rv_codec_u,
+rv_codec_uj,
+rv_codec_i,
+rv_codec_i_sh5,
+rv_codec_i_sh6,
+rv_codec_i_sh7,
+rv_codec_i_csr,
+rv_codec_s,
+rv_codec_sb,
+rv_codec_r,
+rv_codec_r_m,
+rv_codec_r4_m,
+rv_codec_r_a,
+rv_codec_r_l,
+rv_codec_r_f,
+rv_codec_cb,
+rv_codec_cb_imm,
+rv_codec_cb_sh5,
+rv_codec_cb_sh6,
+rv_codec_ci,
+rv_codec_ci_sh5,
+  

[Qemu-devel] [PATCH v7 07/23] RISC-V GDB Stub

2018-02-26 Thread Michael Clark
GDB Register read and write routines.

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 target/riscv/gdbstub.c | 62 ++
 1 file changed, 62 insertions(+)
 create mode 100644 target/riscv/gdbstub.c

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
new file mode 100644
index 000..4f919b6
--- /dev/null
+++ b/target/riscv/gdbstub.c
@@ -0,0 +1,62 @@
+/*
+ * RISC-V GDB Server Stub
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+#include "cpu.h"
+
+int riscv_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = >env;
+
+if (n < 32) {
+return gdb_get_regl(mem_buf, env->gpr[n]);
+} else if (n == 32) {
+return gdb_get_regl(mem_buf, env->pc);
+} else if (n < 65) {
+return gdb_get_reg64(mem_buf, env->fpr[n - 33]);
+} else if (n < 4096 + 65) {
+return gdb_get_regl(mem_buf, csr_read_helper(env, n - 65));
+}
+return 0;
+}
+
+int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = >env;
+
+if (n == 0) {
+/* discard writes to x0 */
+return sizeof(target_ulong);
+} else if (n < 32) {
+env->gpr[n] = ldtul_p(mem_buf);
+return sizeof(target_ulong);
+} else if (n == 32) {
+env->pc = ldtul_p(mem_buf);
+return sizeof(target_ulong);
+} else if (n < 65) {
+env->fpr[n - 33] = ldq_p(mem_buf); /* always 64-bit */
+return sizeof(uint64_t);
+} else if (n < 4096 + 65) {
+csr_write_helper(env, ldtul_p(mem_buf), n - 65);
+}
+return 0;
+}
-- 
2.7.0




[Qemu-devel] [PATCH v7 01/23] RISC-V Maintainers

2018-02-26 Thread Michael Clark
Add Michael Clark, Palmer Dabbelt, Sagar Karandikar and Bastian
Koppelmann as RISC-V Maintainers.

Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Signed-off-by: Michael Clark 
---
 MAINTAINERS | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index a334a25..858ab51 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -233,6 +233,17 @@ F: hw/ppc/
 F: include/hw/ppc/
 F: disas/ppc.c
 
+RISC-V
+M: Michael Clark 
+M: Palmer Dabbelt 
+M: Sagar Karandikar 
+M: Bastian Koppelmann 
+S: Maintained
+F: target/riscv/
+F: hw/riscv/
+F: include/hw/riscv/
+F: disas/riscv.c
+
 S390
 M: Richard Henderson 
 M: Alexander Graf 
-- 
2.7.0




[Qemu-devel] [PATCH v7 00/23] RISC-V QEMU Port Submission

2018-02-26 Thread Michael Clark
QEMU RISC-V Emulation Support (RV64GC, RV32GC)

With this reelase we have contacted all contributors and have received
agreement to re-license their work as GPLv2+. This release also updates
linux-user/riscv/termbits.h which should fix S390 builds. The spike_v1.9
machine has been renamed to spike_v1.9.1 to match the privileged ISA
version and spike_v1.10 has been made the default machine. All substantial
work in this series has been reviewed or acknowledged and subsequent to
submitting this series we will be submitting signed a pull request.

The git tree for the v7 patch series tree (squashed and rebased):

- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v7

The git tree for the v1-v6 patch series with review commit history:

- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v6
- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v5
- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v4
- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v3
- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v2
- https://github.com/riscv/riscv-qemu/tree/qemu-upstream-v1

*** Known Issues ***

- Disassembler has some checkpatch warnings for the sake of code brevity
- scripts/qemu-binfmt-conf.sh has checkpatch warnings due to line length
- PMP (Physical Memory Protection) is as-of-yet unused and needs testing

*** Changelog ***

v7

- Make spike_v1.10 the default machine
- Rename spike_v1.9 to spike_v1.9.1 to match privileged spec version
- Remove empty target/riscv/trace-events file
- Monitor ROM 32-bit reset code needs to be target endian
- Add TARGET_TIOCGPTPEER to linux-user/riscv/termbits.h
- Add -initrd support to the virt board
- Fix naming in spike machine interface header
- Update copyright notice on RISC-V Spike machines
- Update copyright notice on RISC-V HTIF Console device
- Change CPU Core and translator to GPLv2+
- Change RISC-V Disassembler to GPLv2+
- Change SiFive Test Finisher to GPLv2+
- Change SiFive CLINT to GPLv2+
- Change SiFive PRCI to GPLv2+
- Change SiFive PLIC to GPLv2+
- Change RISC-V spike machines to GPLv2+
- Change RISC-V virt machine to GPLv2+
- Change SiFive E300 machine to GPLv2+
- Change SiFive U500 machine to GPLv2+
- Change RISC-V Hart Array to GPLv2+
- Change RISC-V HTIF device to GPLv2+
- Change SiFiveUART device to GPLv2+

v6

- Drop IEEE 754-201x minimumNumber/maximumNumber for fmin/fmax
- Remove some unnecessary commented debug statements
- Change RISCV_CPU_TYPE_NAME to use riscv-cpu suffix
- Define all CPU variants for linux-user
- qemu_log calls require trailing \n
- Replace PLIC printfs with qemu_log
- Tear out unused HTIF code and eliminate shouting debug messages
- Fix illegal instruction when sfence.vma is passed (rs2) arguments
- Make updates to PTE accessed and dirty bits atomic
- Only require atomic PTE updates on MTTCG enabled guests
- Page fault if accessed or dirty bits can't be updated
- Fix get_physical_address PTE reads and writes on riscv32
- Remove erroneous comments from the PLIC
- Default enable MTTCG
- Make WFI less conservative
- Unify local interrupt handling
- Expunge HTIF interrupts
- Always access mstatus.mip under a lock
- Don't implement rdtime/rdtimeh in system mode (bbl emulates them)
- Implement insreth/cycleh for rv32 and always enable user-mode counters
- Add GDB stub support for reading and writing CSRs
- Rename ENABLE_CHARDEV #ifdef from HTIF code
- Replace bad HTIF ELF code with load_elf symbol callback
- Convert chained if else fault handlers to switch statements
- Use RISCV exception codes for linux-user page faults

v5

- Implement NaN-boxing for flw, set high order bits to 1
- Use float_muladd_negate_* flags to floatXX_muladd
- Use IEEE 754-201x minimumNumber/maximumNumber for fmin/fmax
- Fix TARGET_NR_syscalls
- Update linux-user/riscv/syscall_nr.h
- Fix FENCE.I, needs to terminate translation block
- Adjust unusual convention for interruptno >= 0

v4

- Add @riscv: since 2.12 to CpuInfoArch
- Remove misleading little-endian comment from load_kernel
- Rename cpu-model property to cpu-type
- Drop some unnecessary inline function attributes
- Don't allow GDB to set value of x0 register
- Remove unnecessary empty property lists
- Add Test Finisher device to implement poweroff in virt machine
- Implement priv ISA v1.10 trap and sret/mret xPIE/xIE behavior
- Store fflags data in fp_status
- Purge runtime users of helper_raise_exception
- Fix validate_csr
- Tidy gen_jalr
- Tidy immediate shifts
- Add gen_exception_inst_addr_mis
- Add gen_exception_debug
- Add gen_exception_illegal
- Tidy helper_fclass_*
- Split rounding mode setting to a new function
- Enforce MSTATUS_FS via TB flags
- Implement acquire/release barrier semantics
- Use atomic operations as required
- Fix FENCE and FENCE_I
- Remove commented code from spike machines
- PAGE_WRITE permissions can be set on loads if page is already dirty
- The result of format conversion on an NaN must be a quiet NaN
- Add missing process_queued_cpu_work to riscv 

[Qemu-devel] [PATCH v7 02/23] RISC-V ELF Machine Definition

2018-02-26 Thread Michael Clark
Define RISC-V ELF machine EM_RISCV 243

Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
Signed-off-by: Michael Clark 
---
 include/elf.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/elf.h b/include/elf.h
index e8a515c..8e457fc 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -112,6 +112,8 @@ typedef int64_t  Elf64_Sxword;
 
 #define EM_UNICORE32110 /* UniCore32 */
 
+#define EM_RISCV243 /* RISC-V */
+
 /*
  * This is an interim value that we will use until the committee comes
  * up with a final number.
-- 
2.7.0




[Qemu-devel] [PATCH v7 03/23] RISC-V CPU Core Definition

2018-02-26 Thread Michael Clark
Add CPU state header, CPU definitions and initialization routines

Reviewed-by: Richard Henderson 
Signed-off-by: Michael Clark 
---
 target/riscv/cpu.c  | 390 +
 target/riscv/cpu.h  | 275 
 target/riscv/cpu_bits.h | 416 
 3 files changed, 1081 insertions(+)
 create mode 100644 target/riscv/cpu.c
 create mode 100644 target/riscv/cpu.h
 create mode 100644 target/riscv/cpu_bits.h

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
new file mode 100644
index 000..47ebdb2
--- /dev/null
+++ b/target/riscv/cpu.c
@@ -0,0 +1,390 @@
+/*
+ * QEMU RISC-V CPU
+ *
+ * Copyright (c) 2016-2017 Sagar Karandikar, sag...@eecs.berkeley.edu
+ * Copyright (c) 2017-2018 SiFive, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+
+/* RISC-V CPU definitions */
+
+const char * const riscv_int_regnames[] = {
+  "zero", "ra  ", "sp  ", "gp  ", "tp  ", "t0  ", "t1  ", "t2  ",
+  "s0  ", "s1  ", "a0  ", "a1  ", "a2  ", "a3  ", "a4  ", "a5  ",
+  "a6  ", "a7  ", "s2  ", "s3  ", "s4  ", "s5  ", "s6  ", "s7  ",
+  "s8  ", "s9  ", "s10 ", "s11 ", "t3  ", "t4  ", "t5  ", "t6  "
+};
+
+const char * const riscv_fpr_regnames[] = {
+  "ft0 ", "ft1 ", "ft2 ", "ft3 ", "ft4 ", "ft5 ", "ft6 ",  "ft7 ",
+  "fs0 ", "fs1 ", "fa0 ", "fa1 ", "fa2 ", "fa3 ", "fa4 ",  "fa5 ",
+  "fa6 ", "fa7 ", "fs2 ", "fs3 ", "fs4 ", "fs5 ", "fs6 ",  "fs7 ",
+  "fs8 ", "fs9 ", "fs10", "fs11", "ft8 ", "ft9 ", "ft10",  "ft11"
+};
+
+const char * const riscv_excp_names[] = {
+"misaligned_fetch",
+"fault_fetch",
+"illegal_instruction",
+"breakpoint",
+"misaligned_load",
+"fault_load",
+"misaligned_store",
+"fault_store",
+"user_ecall",
+"supervisor_ecall",
+"hypervisor_ecall",
+"machine_ecall",
+"exec_page_fault",
+"load_page_fault",
+"reserved",
+"store_page_fault"
+};
+
+const char * const riscv_intr_names[] = {
+"u_software",
+"s_software",
+"h_software",
+"m_software",
+"u_timer",
+"s_timer",
+"h_timer",
+"m_timer",
+"u_external",
+"s_external",
+"h_external",
+"m_external",
+"coprocessor",
+"host"
+};
+
+typedef struct RISCVCPUInfo {
+const char *name;
+void (*initfn)(Object *obj);
+} RISCVCPUInfo;
+
+static void riscv_any_cpu_init(Object *obj)
+{
+CPURISCVState *env = _CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVU;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+
+static void riscv_imafdcsu_priv1_9_cpu_init(Object *obj)
+{
+CPURISCVState *env = _CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_09_1;
+}
+
+static void riscv_imafdcsu_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = _CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+
+static void riscv_imacu_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = _CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVC | RVU;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+
+static void riscv_imac_priv1_10_cpu_init(Object *obj)
+{
+CPURISCVState *env = _CPU(obj)->env;
+env->misa = RVXLEN | RVI | RVM | RVA | RVC;
+env->user_ver = USER_VERSION_2_02_0;
+env->priv_ver = PRIV_VERSION_1_10_0;
+}
+
+static const RISCVCPUInfo riscv_cpus[] = {
+{ TYPE_RISCV_CPU_ANY,riscv_any_cpu_init },
+{ TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_09, riscv_imafdcsu_priv1_9_cpu_init },
+{ TYPE_RISCV_CPU_IMAFDCSU_PRIV_1_10, riscv_imafdcsu_priv1_10_cpu_init },
+{ TYPE_RISCV_CPU_IMACU_PRIV_1_10,riscv_imacu_priv1_10_cpu_init },
+{ TYPE_RISCV_CPU_IMAC_PRIV_1_10, riscv_imac_priv1_10_cpu_init },
+{ NULL, NULL }
+};
+
+static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
+{
+ObjectClass *oc;
+char *typename;
+char **cpuname;
+
+cpuname = g_strsplit(cpu_model, ",", 1);

[Qemu-devel] [Bug 1428958] Re: random IO errors / data corruption in VMs (created and executed via virt-manager)

2018-02-26 Thread Thomas Huth
Closing according to comment #2.

** Changed in: qemu
   Status: New => Fix Released

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1428958

Title:
  random IO errors / data corruption in VMs (created and executed via
  virt-manager)

Status in QEMU:
  Fix Released

Bug description:
  I have recurring problems with VM installation and usage - data on VM disk 
gets corrupted at some point and it causes all sorts of problems - sometimes I 
cannot even install base system, other times some .so files are corrupt after 
isntallation, etc - totally random.
  I use virt-manager to create and run VMs. I have also tried creating VMs via 
virt-install, result is identical.
  If I use VirtualBox I have no such problems.
  My OS is Fedora 20 upgraded to 21, qemu and libvirt are installed from Fedora 
official repos.

  Here's an example qemu command-line:
  /usr/bin/qemu-system-x86_64
  -machine accel=kvm
  -name fuel
  -S
  -machine pc-i440fx-2.1,accel=kvm,usb=off
  -cpu 
SandyBridge,+invpcid,+erms,+bmi2,+smep,+avx2,+bmi1,+fsgsbase,+abm,+pdpe1gb,+rdrand,+f16c,+osxsave,+movbe,+pcid,+pdcm,+xtpr,+fma,+tm2,+est,+smx,+vmx,+ds_cpl,+monitor,+dtes64,+pbe,+tm,+ht,+ss,+acpi,+ds,+vme
  -m 3142
  -realtime mlock=off
  -smp 2,sockets=2,cores=1,threads=1
  -uuid 27693a46-7a50-4a3c-bcaf-bf061ba469ed
  -no-user-config
  -nodefaults
  -chardev 
socket,id=charmonitor,path=/var/lib/libvirt/qemu/fuel.monitor,server,nowait
  -mon chardev=charmonitor,id=monitor,mode=control
  -rtc base=utc,driftfix=slew
  -global kvm-pit.lost_tick_policy=discard
  -no-hpet
  -no-shutdown
  -boot menu=on,strict=on
  -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x6.0x7
  -device 
ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x6
  -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x6.0x1
  -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x6.0x2
  -device lsi,id=scsi0,bus=pci.0,addr=0xa
  -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x7
  -drive 
file=/home/virtual-disks/fuel.vdi,if=none,id=drive-virtio-disk0,format=vdi
  -device 
virtio-blk-pci,scsi=off,bus=pci.0,addr=0x8,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1
  -drive 
file=/home/dsutyagin/Downloads/iso/MirantisOpenStack-6.0.iso,if=none,id=drive-scsi0-0-0,readonly=on,format=raw
  -device 
scsi-cd,bus=scsi0.0,scsi-id=0,drive=drive-scsi0-0-0,id=scsi0-0-0,bootindex=2
  -netdev tap,fd=23,id=hostnet0,vhost=on,vhostfd=24
  -device 
virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:0d:42:2d,bus=pci.0,addr=0x3
  -netdev tap,fd=25,id=hostnet1,vhost=on,vhostfd=26
  -device 
virtio-net-pci,netdev=hostnet1,id=net1,mac=52:54:00:a4:8c:ef,bus=pci.0,addr=0x4
  -chardev pty,id=charserial0
  -device isa-serial,chardev=charserial0,id=serial0
  -chardev 
socket,id=charchannel0,path=/var/lib/libvirt/qemu/channel/target/fuel.org.qemu.guest_agent.0,server,nowait
  -device 
virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=org.qemu.guest_agent.0
  -chardev spicevmc,id=charchannel1,name=vdagent
  -device 
virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel1,id=channel1,name=com.redhat.spice.0
  -device usb-tablet,id=input0
  -spice port=5900,addr=127.0.0.1,disable-ticketing,seamless-migration=on
  -device 
qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,bus=pci.0,addr=0x2
  -device intel-hda,id=sound0,bus=pci.0,addr=0x5 -device 
hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0
  -chardev spicevmc,id=charredir0,name=usbredir
  -device usb-redir,chardev=charredir0,id=redir0
  -chardev spicevmc,id=charredir1,name=usbredir
  -device usb-redir,chardev=charredir1,id=redir1
  -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x9
  -msg timestamp=on

  If this is not a bug, I'd be happy if you help me fix this problem. I
  am sorry if this is not the proper place to post such a problem.

  qemu-system-x86_64 --version
  QEMU emulator version 2.1.3 (qemu-2.1.3-2.fc21), Copyright (c) 2003-2008 
Fabrice Bellard

  qemu-kvm --version
  QEMU emulator version 2.1.3 (qemu-2.1.3-2.fc21), Copyright (c) 2003-2008 
Fabrice Bellard

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1428958/+subscriptions



[Qemu-devel] [Bug 1429034] Re: qemu abort in qemu_coroutine_enter when multi-thread writing

2018-02-26 Thread Thomas Huth
Triaging old bug tickets... can you still reproduce this issue with the
latest version of QEMU? Or could we close this ticket nowadays?

** Changed in: qemu
   Status: New => Incomplete

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1429034

Title:
  qemu abort in qemu_coroutine_enter when multi-thread writing

Status in QEMU:
  Incomplete

Bug description:
  qemu release version: 2.2.0
  platform: x86_64

  qemu would be aborted when there are two threads to write two seperate
  qcow2 files.

  call stack:

  #0 0x75e18989 __GI_raise(sig=sig@entry=6) 
(../nptl/sysdeps/unix/sysv/linux/raise.c:56)
  #1 0x75e1a098 __GI_abort() (abort.c:90)
  #2 0x7728c034 qemu_coroutine_enter(co=0x7fffe0004800, opaque=0x0) 
(qemu-coroutine.c:117)
  #3 0x7727df39 bdrv_co_io_em_complete(opaque=0x77fd6ae0, ret=0) 
(block.c:4847)
  #4 0x77270314 thread_pool_completion_bh(opaque=0x7fffe0006ad0) 
(thread-pool.c:187)
  #5 0x7726f873 aio_bh_poll(ctx=0x7fffe0001d00) (async.c:82)
  #6 0x7728340b aio_dispatch(ctx=0x7fffe0001d00) (aio-posix.c:137)
  #7 0x772837b0 aio_poll(ctx=0x7fffe0001d00, blocking=true) 
(aio-posix.c:248)
  #8 ?? 0x772795a8 in bdrv_prwv_co (bs=0x7fffdc0021c0, 
offset=12071639552, qiov=0x7fffe67fa590, is_write=true, flags=(unknown: 0)) 
(block.c:2703)
  #9 ?? 0x7727966a in bdrv_rw_co (bs=0x7fffdc0021c0, 
sector_num=23577421, buf=0x7fffe4629250 
"\234\b\335Ǽ\254\213q\301\366\315=\005oI\301\245=\373\004+2?H\212\025\035+\262\274C;X\301FaP\324\335\061ҝ\316=\347\335\020\365\003goɿ\214\312S=\v2]\373\363C\311\341\334\r5k\346k\204\332\023\264\315陌\230\203J\222u\214\066",
 nb_sectors=128, is_write=true, flags=(unknown: 0)) (block.c:2726)
  #10 0x77279758bdrv_write(bs=0x7fffdc0021c0, sector_num=23577421, 
buf=0x7fffe4629250 
"\234\b\335Ǽ\254\213q\301\366\315=\005oI\301\245=\373\004+2?H\212\025\035+\262\274C;X\301FaP\324\335\061ҝ\316=\347\335\020\365\003goɿ\214\312S=\v2]\373\363C\311\341\334\r5k\346k\204\332\023\264\315陌\230\203J\222u\214\066",
 nb_sectors=128) (block.c:2760)

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1429034/+subscriptions



[Qemu-devel] [Bug 1432103] Re: error in x86 executable segment permission check

2018-02-26 Thread Thomas Huth
Triaging old bug tickets... can you still reproduce this issue with the
latest version of QEMU? Or could we close this ticket nowadays? Can you
provide a binary to reproduce this issue?

** Changed in: qemu
   Status: New => Incomplete

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1432103

Title:
  error in x86 executable segment permission check

Status in QEMU:
  Incomplete

Bug description:
  When the code segment register (%cs) selects an executable segment
  with no read permission, mov instructions that read from the segment
  via %cs prefix can still succeed without causing a general protection
  error.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1432103/+subscriptions



Re: [Qemu-devel] [PATCH v4 0/7] vfio: add display support

2018-02-26 Thread Alex Williamson
On Mon, 26 Feb 2018 09:35:51 +0100
Gerd Hoffmann  wrote:

> On Fri, Feb 23, 2018 at 10:05:17AM +0100, Gerd Hoffmann wrote:
> > > Hi Gerd,
> > > 
> > > It's a little bit concerning that the only way we can test the
> > > region-based display support is with proprietary drivers that nobody
> > > but NVIDIA has at this point.  Have you considered adding region-based
> > > display support to the mdev sample tty driver?  I know it sounds
> > > ridiculous for a serial device to have a display, but the vfio display
> > > region support isn't really tied to the functionality of the base mdev
> > > device.  We could have it simply display a static test pattern, just so
> > > we can test the end to end code path without a dependency on a closed
> > > vendor driver.  
> > 
> > Hmm, have to think about that.  Some way to change the display content
> > would be nice as you can see whenever display updates are working then.  
> 
> https://www.kraxel.org/cgit/linux/log/?h=vfio-sample-display
> 
> Comes with host mdev driver and guest framebuffer driver.

Awesome!



[Qemu-devel] [PATCH v2] ppc: Fix size of ppc64 xer register

2018-02-26 Thread Michael Matz
The normal gdb definition of the XER registers is only 32 bit,
and that's what the current version of power64-core.xml also
says (seems copied from gdb's).  But qemu's idea of the XER register
is target_ulong (in CPUPPCState, ppc_gdb_register_len and
ppc_cpu_gdb_read_register)

That mismatch leads to the following message when attaching
with gdb:

  Truncated register 32 in remote 'g' packet

(and following on that qemu stops responding).  The simple fix is
to say the truth in the .xml file.  But the better fix is to
actually make it 32bit on the wire, as old gdbs don't support
XML files for describing registers.  Also the XER state in qemu
doesn't seem to use the high 32 bits, so sending it off to gdb
doesn't seem worthwhile.

[v2: fix formatting in moved line and adjust others]

Signed-off-by: Michael Matz 
---
 target/ppc/gdbstub.c | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 7a33813..688749d 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -33,14 +33,14 @@ static int ppc_gdb_register_len_apple(int n)
 return 8;
 case 64 ... 95:
 return 16;
-case 64+32: /* nip */
-case 65+32: /* msr */
-case 67+32: /* lr */
-case 68+32: /* ctr */
-case 69+32: /* xer */
-case 70+32: /* fpscr */
+case 64 + 32: /* nip */
+case 65 + 32: /* msr */
+case 67 + 32: /* lr */
+case 68 + 32: /* ctr */
+case 70 + 32: /* fpscr */
 return 8;
-case 66+32: /* cr */
+case 66 + 32: /* cr */
+case 69 + 32: /* xer */
 return 4;
 default:
 return 0;
@@ -61,6 +61,8 @@ static int ppc_gdb_register_len(int n)
 return 8;
 case 66:
 /* cr */
+case 69:
+/* xer */
 return 4;
 case 64:
 /* nip */
@@ -70,8 +72,6 @@ static int ppc_gdb_register_len(int n)
 /* lr */
 case 68:
 /* ctr */
-case 69:
-/* xer */
 return sizeof(target_ulong);
 case 70:
 /* fpscr */
@@ -152,7 +152,7 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 gdb_get_regl(mem_buf, env->ctr);
 break;
 case 69:
-gdb_get_regl(mem_buf, env->xer);
+gdb_get_reg32(mem_buf, env->xer);
 break;
 case 70:
 gdb_get_reg32(mem_buf, env->fpscr);
@@ -208,7 +208,7 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t 
*mem_buf, int n)
 gdb_get_reg64(mem_buf, env->ctr);
 break;
 case 69 + 32:
-gdb_get_reg64(mem_buf, env->xer);
+gdb_get_reg32(mem_buf, env->xer);
 break;
 case 70 + 32:
 gdb_get_reg64(mem_buf, env->fpscr);
@@ -259,7 +259,7 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 env->ctr = ldtul_p(mem_buf);
 break;
 case 69:
-env->xer = ldtul_p(mem_buf);
+env->xer = ldl_p(mem_buf);
 break;
 case 70:
 /* fpscr */
@@ -309,7 +309,7 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t 
*mem_buf, int n)
 env->ctr = ldq_p(mem_buf);
 break;
 case 69 + 32:
-env->xer = ldq_p(mem_buf);
+env->xer = ldl_p(mem_buf);
 break;
 case 70 + 32:
 /* fpscr */
-- 
1.8.1.4




Re: [Qemu-devel] intel-iommu and vhost: Do we need 'device-iotlb' and 'ats'?

2018-02-26 Thread Jintack Lim
Hi Eric,

On Mon, Feb 26, 2018 at 5:14 AM, Auger Eric  wrote:
> Hi Jintack,
>
> On 21/02/18 05:03, Jintack Lim wrote:
>> Hi,
>>
>> I'm using vhost with the virtual intel-iommu, and this page[1] shows
>> the QEMU command line example.
>>
>> qemu-system-x86_64 -M q35,accel=kvm,kernel-irqchip=split -m 2G \
>>-device intel-iommu,intremap=on,device-iotlb=on \
>>-device ioh3420,id=pcie.1,chassis=1 \
>>-device
>> virtio-net-pci,bus=pcie.1,netdev=net0,disable-legacy=on,disable-modern=off,iommu_platform=on,ats=on
>> \
>>-netdev tap,id=net0,vhostforce \
>>$IMAGE_PATH
>>
>> I wonder what's the impact of using device-iotlb and ats options as
>> they are described necessary.
>>
>> In my understanding, vhost in the kernel only looks at
>> VIRTIO_F_IOMMU_PLATFORM, and when it is set, vhost uses a
>> device-iotlb. In addition, vhost and QEMU communicate using vhost_msg
>> basically to cache mappings correctly in the vhost, so I wonder what's
>> the role of ats in this case.
>>
>> A related question is that if we use SMMU emulation[2] on ARM without
>> those options, does vhost cache mappings as if it has a device-iotlb?
>> (I guess this is the case.)
> vsmmuv3 emulation code does not support ATS at the moment. vhost support
> is something different. As Peter explained it comes with the capability
> of the virtio device to register unmap notifiers. Those notifiers get
> called each time there are TLB invalidation commands. That way the
> in-kernel vhost cache can be invalidated. vhost support was there until
> vsmmuv3 v7. With latest versions, I removed it to help reviewers
> concentrate on the root functionality. However I will send it to you
> based on v9.

Thanks, Eric. I'm happy to take a look at those patches!

Thanks,
Jintack

>
> Thanks
>
> Eric
>>
>> I'm pretty new to QEMU code, so I might be missing something. Can
>> somebody shed some light on it?
>>
>> [1] https://wiki.qemu.org/Features/VT-d
>> [2] http://lists.nongnu.org/archive/html/qemu-devel/2018-02/msg04736.html
>>
>> Thanks,
>> Jintack
>>
>>
>




Re: [Qemu-devel] [PATCH v3 24/29] vhost-user: Add VHOST_USER_POSTCOPY_END message

2018-02-26 Thread Michael S. Tsirkin
On Fri, Feb 16, 2018 at 01:16:20PM +, Dr. David Alan Gilbert (git) wrote:
> From: "Dr. David Alan Gilbert" 
> 
> This message is sent just before the end of postcopy to get the
> client to stop using userfault since we wont respond to any more
> requests.  It should close userfaultfd so that any other pages
> get mapped to the backing file automatically by the kernel, since
> at this point we know we've received everything.
> 
> Signed-off-by: Dr. David Alan Gilbert 
> Reviewed-by: Peter Xu 
> ---
>  contrib/libvhost-user/libvhost-user.c | 23 +++
>  contrib/libvhost-user/libvhost-user.h |  1 +
>  docs/interop/vhost-user.txt   |  8 
>  hw/virtio/vhost-user.c|  1 +
>  4 files changed, 33 insertions(+)
> 
> diff --git a/contrib/libvhost-user/libvhost-user.c 
> b/contrib/libvhost-user/libvhost-user.c
> index 1b224af706..1f988ab787 100644
> --- a/contrib/libvhost-user/libvhost-user.c
> +++ b/contrib/libvhost-user/libvhost-user.c
> @@ -99,6 +99,7 @@ vu_request_to_string(unsigned int req)
>  REQ(VHOST_USER_SET_CONFIG),
>  REQ(VHOST_USER_POSTCOPY_ADVISE),
>  REQ(VHOST_USER_POSTCOPY_LISTEN),
> +REQ(VHOST_USER_POSTCOPY_END),
>  REQ(VHOST_USER_MAX),
>  };
>  #undef REQ
> @@ -1095,6 +1096,26 @@ vu_set_postcopy_listen(VuDev *dev, VhostUserMsg *vmsg)
>  vmsg->payload.u64 = 0; /* Success */
>  return true;
>  }
> +
> +static bool
> +vu_set_postcopy_end(VuDev *dev, VhostUserMsg *vmsg)
> +{
> +DPRINT("%s: Entry\n", __func__);
> +dev->postcopy_listening = false;
> +if (dev->postcopy_ufd > 0) {
> +close(dev->postcopy_ufd);
> +dev->postcopy_ufd = -1;
> +DPRINT("%s: Done close\n", __func__);
> +}
> +
> +vmsg->fd_num = 0;
> +vmsg->payload.u64 = 0;
> +vmsg->size = sizeof(vmsg->payload.u64);
> +vmsg->flags = VHOST_USER_VERSION |  VHOST_USER_REPLY_MASK;
> +DPRINT("%s: exit\n", __func__);
> +return true;
> +}
> +
>  static bool
>  vu_process_message(VuDev *dev, VhostUserMsg *vmsg)
>  {
> @@ -1170,6 +1191,8 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg)
>  return vu_set_postcopy_advise(dev, vmsg);
>  case VHOST_USER_POSTCOPY_LISTEN:
>  return vu_set_postcopy_listen(dev, vmsg);
> +case VHOST_USER_POSTCOPY_END:
> +return vu_set_postcopy_end(dev, vmsg);
>  default:
>  vmsg_close_fds(vmsg);
>  vu_panic(dev, "Unhandled request: %d", vmsg->request);
> diff --git a/contrib/libvhost-user/libvhost-user.h 
> b/contrib/libvhost-user/libvhost-user.h
> index fcba53c3c3..9696b89f6e 100644
> --- a/contrib/libvhost-user/libvhost-user.h
> +++ b/contrib/libvhost-user/libvhost-user.h
> @@ -84,6 +84,7 @@ typedef enum VhostUserRequest {
>  VHOST_USER_SET_CONFIG = 25,
>  VHOST_USER_POSTCOPY_ADVISE  = 26,
>  VHOST_USER_POSTCOPY_LISTEN  = 27,
> +VHOST_USER_POSTCOPY_END = 28,
>  VHOST_USER_MAX
>  } VhostUserRequest;
>  
> diff --git a/docs/interop/vhost-user.txt b/docs/interop/vhost-user.txt
> index 5bbcab2cc4..4bf7d8ef99 100644
> --- a/docs/interop/vhost-user.txt
> +++ b/docs/interop/vhost-user.txt
> @@ -697,6 +697,14 @@ Master message types
>  
>Master advises slave that a transition to postcopy mode has happened.
>  
> + * VHOST_USER_POSTCOPY_END
> +  Id: 28
> +  Slave payload: u64
> +
> +  Master advises that postcopy migration has now completed.  The
> +  slave must disable the userfaultfd. The response is an acknowledgement
> +  only.
> +
>  Slave message types
>  ---
>  

Which protocol feature enables this message?

> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index 74807091a0..cf7923b25f 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -78,6 +78,7 @@ typedef enum VhostUserRequest {
>  VHOST_USER_SET_CONFIG = 25,
>  VHOST_USER_POSTCOPY_ADVISE  = 26,
>  VHOST_USER_POSTCOPY_LISTEN  = 27,
> +VHOST_USER_POSTCOPY_END = 28,
>  VHOST_USER_MAX
>  } VhostUserRequest;
>  
> -- 
> 2.14.3



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

2018-02-26 Thread no-reply
Hi,

This series failed docker-mingw@fedora build test. Please find the testing 
commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

Type: series
Message-id: cover.1519647019.git.arei.gong...@huawei.com
Subject: [Qemu-devel] [PATCH v7 0/4] cryptodev: add vhost support

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=8
time make docker-test-mingw@fedora
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
a368ba01f8 cryptodev-vhost-user: set the key length
4aac6fd873 cryptodev-vhost-user: add crypto session handler
85f349bef6 cryptodev: add vhost support
25ff6207f4 cryptodev: add vhost-user as a new cryptodev backend

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-oyp3nbz5/src/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
  BUILD   fedora
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-oyp3nbz5/src'
  GEN 
/var/tmp/patchew-tester-tmp-oyp3nbz5/src/docker-src.2018-02-26-15.23.04.24302/qemu.tar
Cloning into 
'/var/tmp/patchew-tester-tmp-oyp3nbz5/src/docker-src.2018-02-26-15.23.04.24302/qemu.tar.vroot'...
done.
Your branch is up-to-date with 'origin/test'.
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into 
'/var/tmp/patchew-tester-tmp-oyp3nbz5/src/docker-src.2018-02-26-15.23.04.24302/qemu.tar.vroot/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered 
for path 'ui/keycodemapdb'
Cloning into 
'/var/tmp/patchew-tester-tmp-oyp3nbz5/src/docker-src.2018-02-26-15.23.04.24302/qemu.tar.vroot/ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out 
'6b3d716e2b6472eb7189d3220552280ef3d832ce'
  COPYRUNNER
RUN test-mingw in qemu:fedora 
Packages installed:
PyYAML-3.12-5.fc27.x86_64
SDL-devel-1.2.15-29.fc27.x86_64
bc-1.07.1-3.fc27.x86_64
bison-3.0.4-8.fc27.x86_64
bzip2-1.0.6-24.fc27.x86_64
ccache-3.3.5-1.fc27.x86_64
clang-5.0.1-1.fc27.x86_64
findutils-4.6.0-14.fc27.x86_64
flex-2.6.1-5.fc27.x86_64
gcc-7.3.1-2.fc27.x86_64
gcc-c++-7.3.1-2.fc27.x86_64
gettext-0.19.8.1-12.fc27.x86_64
git-2.14.3-2.fc27.x86_64
glib2-devel-2.54.3-2.fc27.x86_64
hostname-3.18-4.fc27.x86_64
libaio-devel-0.3.110-9.fc27.x86_64
libasan-7.3.1-2.fc27.x86_64
libfdt-devel-1.4.6-1.fc27.x86_64
libubsan-7.3.1-2.fc27.x86_64
make-4.2.1-4.fc27.x86_64
mingw32-SDL-1.2.15-9.fc27.noarch
mingw32-bzip2-1.0.6-9.fc27.noarch
mingw32-curl-7.54.1-2.fc27.noarch
mingw32-glib2-2.54.1-1.fc27.noarch
mingw32-gmp-6.1.2-2.fc27.noarch
mingw32-gnutls-3.5.13-2.fc27.noarch
mingw32-gtk2-2.24.31-4.fc27.noarch
mingw32-gtk3-3.22.16-1.fc27.noarch
mingw32-libjpeg-turbo-1.5.1-3.fc27.noarch
mingw32-libpng-1.6.29-2.fc27.noarch
mingw32-libssh2-1.8.0-3.fc27.noarch
mingw32-libtasn1-4.13-1.fc27.noarch
mingw32-nettle-3.3-3.fc27.noarch
mingw32-pixman-0.34.0-3.fc27.noarch
mingw32-pkg-config-0.28-9.fc27.x86_64
mingw64-SDL-1.2.15-9.fc27.noarch
mingw64-bzip2-1.0.6-9.fc27.noarch
mingw64-curl-7.54.1-2.fc27.noarch
mingw64-glib2-2.54.1-1.fc27.noarch
mingw64-gmp-6.1.2-2.fc27.noarch
mingw64-gnutls-3.5.13-2.fc27.noarch
mingw64-gtk2-2.24.31-4.fc27.noarch
mingw64-gtk3-3.22.16-1.fc27.noarch
mingw64-libjpeg-turbo-1.5.1-3.fc27.noarch
mingw64-libpng-1.6.29-2.fc27.noarch
mingw64-libssh2-1.8.0-3.fc27.noarch
mingw64-libtasn1-4.13-1.fc27.noarch
mingw64-nettle-3.3-3.fc27.noarch
mingw64-pixman-0.34.0-3.fc27.noarch
mingw64-pkg-config-0.28-9.fc27.x86_64
nettle-devel-3.4-1.fc27.x86_64
perl-5.26.1-402.fc27.x86_64
pixman-devel-0.34.0-4.fc27.x86_64
python3-3.6.2-13.fc27.x86_64
sparse-0.5.1-2.fc27.x86_64
tar-1.29-7.fc27.x86_64
which-2.21-4.fc27.x86_64
zlib-devel-1.2.11-4.fc27.x86_64

Environment variables:
TARGET_LIST=
PACKAGES=ccache gettext git tar PyYAML sparse flex bison python3 bzip2 hostname 
glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel gcc gcc-c++ 
clang make perl which bc findutils libaio-devel nettle-devel libasan 
libubsan mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL 
mingw32-pkg-config mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle 
mingw32-libtasn1 mingw32-libjpeg-turbo mingw32-libpng mingw32-curl 
mingw32-libssh2 mingw32-bzip2 mingw64-pixman mingw64-glib2 mingw64-gmp 
mingw64-SDL mingw64-pkg-config mingw64-gtk2 mingw64-gtk3 mingw64-gnutls 
mingw64-nettle mingw64-libtasn1 mingw64-libjpeg-turbo mingw64-libpng 
mingw64-curl mingw64-libssh2 mingw64-bzip2
J=8
V=
HOSTNAME=a488d2c23dbf
DEBUG=
SHOW_ENV=1
PWD=/
HOME=/root
CCACHE_DIR=/var/tmp/ccache
DISTTAG=f27container
QEMU_CONFIGURE_OPTS=--python=/usr/bin/python3
FGC=f27
TEST_DIR=/tmp/qemu-test
SHLVL=1
FEATURES=mingw clang pyyaml asan dtc

Re: [Qemu-devel] [PATCH] HMP: Initialize err before using

2018-02-26 Thread Dr. David Alan Gilbert
* Zhangjixiang (jixiang_zh...@h3c.com) wrote:
> From 295640e6f4aa83b843e245bb1af9995be37de84d Mon Sep 17 00:00:00 2001
> From: zhangjixiang 
> Date: Sun, 25 Feb 2018 09:47:51 +0800
> Subject: [PATCH] HMP: Initialize err before using
> 
> When bdrv_snapshot_delete return fail, the errp will not be
> assigned a valid value in error_propagate as errp didn't be
> initialized in hmp_delvm, then error_reportf_err will use an
> uninitialized value(call by hmp_delvm), and qemu crash.
> 
> Signed-off-by: zhangjixiang 
> ---
> hmp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hmp.c b/hmp.c
> index 7870d6a300..4a4da004e9 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -1340,7 +1340,7 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
> void hmp_delvm(Monitor *mon, const QDict *qdict)
> {
>  BlockDriverState *bs;
> -Error *err;
> +Error *err = NULL;
>  const char *name = qdict_get_str(qdict, "name");
>  if (bdrv_all_delete_snapshot(name, , ) < 0) {

OK, that looks right; and that bug seems to have been around for a
while; thank you:

Reviewed-by: Dr. David Alan Gilbert 

(I think the headers on the mail look a bit broken; it's probably best
to use git send-email  when possible).

Dave

> --
> 2.11.0
> -
> 本邮件及其附件含有新华三技术有限公司的保密信息,仅限于发送给上面地址中列出
> 的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、
> 或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本
> 邮件!
> This e-mail and its attachments contain confidential information from New 
> H3C, which is
> intended only for the person or entity whose address is listed above. Any use 
> of the
> information contained herein in any way (including, but not limited to, total 
> or partial
> disclosure, reproduction, or dissemination) by persons other than the intended
> recipient(s) is prohibited. If you receive this e-mail in error, please 
> notify the sender
> by phone or email immediately and delete it!
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



Re: [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators

2018-02-26 Thread Eric Blake

On 02/23/2018 11:20 AM, Markus Armbruster wrote:

Eric Blake  writes:


On 02/11/2018 03:35 AM, Markus Armbruster wrote:

Whenever qapi-schema.json changes, we run six programs eleven times to
update eleven files.  Similar for qga/qapi-schema.json.  This is
silly.  Replace the six programs by a single program that spits out
all eleven files.

The programs become modules in new Python package qapi, along with the
helper library.  This requires moving them to scripts/qapi/.

Signed-off-by: Markus Armbruster 
Reviewed-by: Marc-André Lureau 
---



+++ b/docs/devel/qapi-code-gen.txt



   @@ -1302,23 +1296,22 @@ Example:
   }
 const char *const example_QAPIEvent_lookup[] = {
-[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
+
+[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
   [EXAMPLE_QAPI_EVENT__MAX] = NULL,
   };


Looks like our generated code indentation has slightly regressed from
what we would write by hand, but it's still okay for generated code
(and the commit message in 5/29 did call that out)


I'd prefer to have this tidied up.


Actually, we currently output with good indentation, but with different 
text altogether:


const QEnumLookup example_QAPIEvent_lookup = {
.array = (const char *const[]) {
[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
},
.size = EXAMPLE_QAPI_EVENT__MAX
};

I'm fixing that up as part of prepping this series for PULL.



+def gen_commands(schema, output_dir, prefix):
+blurb = ' * Schema-defined QAPI/QMP commands'


We discussed whether to make the assignment to blurb be a one-liner in
an earlier patch, but I'm also fine with the churn you have over the
course of the series.


I ran out of time, and decided to leave this one as is.


It wasn't too difficult (although the ripple effects hit 3 other 
patches), so I did this as well.


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



Re: [Qemu-devel] [qemu-s390x] [PULL-for-s390x 06/14] s390-ccw: parse and set boot menu options

2018-02-26 Thread Collin L. Walling

On 02/26/2018 02:29 PM, Collin L. Walling wrote:

On 02/26/2018 01:48 PM, Cornelia Huck wrote:

On Mon, 26 Feb 2018 11:42:29 +0100
Thomas Huth  wrote:

[...]


  3 files changed, 66 insertions(+), 4 deletions(-)
+static void s390_ipl_set_boot_menu(S390IPLState *ipl)
+{
+    QemuOptsList *plist = qemu_find_opts("boot-opts");
+    QemuOpts *opts = QTAILQ_FIRST(>head);
+    uint8_t *flags = >qipl.qipl_flags;
+    uint32_t *timeout = >qipl.boot_menu_timeout;
+    const char *tmp;
+    unsigned long splash_time = 0;
+
+    if (!get_boot_device(0)) {
+    if (boot_menu) {
+    error_report("boot menu requires a bootindex to be 
specified for "

+ "the IPL device.");
+    }
+    return;
+    }
+
+    switch (ipl->iplb.pbt) {
+    case S390_IPL_TYPE_CCW:
+    break;
+    default:
+    error_report("boot menu is not supported for this device 
type.");

If I specify both a bootindex for a device and a -kernel parameter, I
get this error message. Looks a tad odd, but not sure how to avoid it.


Hmm... perhaps an additional check if no IPLB, then skip trying to set
any boot menu data?


[...]




Something like:

    if (!ipl->iplb.len) {
    return;
    }

placed just below the if (!get_boot_device(0)) chunk fixed it for me.If 
no IPLB was set,
then the IPLB fields should just all be zeros.  Why not just check if 
the length is 0 to

determine that we did not set an IPLB at all?

also:

    if (!ipl->iplb.len) {
        if (boot_menu) {
            error_report("boot menu requires an IPLB to function");
        }
    return;
    }

if you think an error message is needed (use a better message, mine is 
not helpful but I
just wanted to demonstrate that the if (boot_menu) check should be 
nested first).


Thanks for reporting this.  Seems to be a few cases that I missed on my end.

--
- Collin L Walling



Re: [Qemu-devel] [qemu-s390x] [PULL-for-s390x 06/14] s390-ccw: parse and set boot menu options

2018-02-26 Thread Collin L. Walling

On 02/26/2018 01:48 PM, Cornelia Huck wrote:

On Mon, 26 Feb 2018 11:42:29 +0100
Thomas Huth  wrote:


From: "Collin L. Walling" 

Set boot menu options for an s390 guest and store them in
the iplb. These options are set via the QEMU command line
option:

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

or via the libvirt domain xml:

 
   
 

Where X represents some positive integer representing
milliseconds.

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

Signed-off-by: Collin L. Walling 
Reviewed-by: Janosch Frank 
Reviewed-by: Thomas Huth 
Signed-off-by: Thomas Huth 
---
  hw/s390x/ipl.c  | 52 +
  hw/s390x/ipl.h  |  9 +++--
  pc-bios/s390-ccw/iplb.h |  9 +++--

Updating the header, but it is not consumed in the bios?


  3 files changed, 66 insertions(+), 4 deletions(-)
+static void s390_ipl_set_boot_menu(S390IPLState *ipl)
+{
+QemuOptsList *plist = qemu_find_opts("boot-opts");
+QemuOpts *opts = QTAILQ_FIRST(>head);
+uint8_t *flags = >qipl.qipl_flags;
+uint32_t *timeout = >qipl.boot_menu_timeout;
+const char *tmp;
+unsigned long splash_time = 0;
+
+if (!get_boot_device(0)) {
+if (boot_menu) {
+error_report("boot menu requires a bootindex to be specified for "
+ "the IPL device.");
+}
+return;
+}
+
+switch (ipl->iplb.pbt) {
+case S390_IPL_TYPE_CCW:
+break;
+default:
+error_report("boot menu is not supported for this device type.");

If I specify both a bootindex for a device and a -kernel parameter, I
get this error message. Looks a tad odd, but not sure how to avoid it.


Hmm... perhaps an additional check if no IPLB, then skip trying to set
any boot menu data?


[...]



--
- Collin L Walling




Re: [Qemu-devel] [PULL-for-s390x 06/14] s390-ccw: parse and set boot menu options

2018-02-26 Thread Cornelia Huck
On Mon, 26 Feb 2018 11:42:29 +0100
Thomas Huth  wrote:

> From: "Collin L. Walling" 
> 
> Set boot menu options for an s390 guest and store them in
> the iplb. These options are set via the QEMU command line
> option:
> 
> -boot menu=on|off[,splash-time=X]
> 
> or via the libvirt domain xml:
> 
> 
>   
> 
> 
> Where X represents some positive integer representing
> milliseconds.
> 
> Any value set for loadparm will override all boot menu options.
> If loadparm=PROMPT, then the menu will be enabled without a
> timeout.
> 
> Signed-off-by: Collin L. Walling 
> Reviewed-by: Janosch Frank 
> Reviewed-by: Thomas Huth 
> Signed-off-by: Thomas Huth 
> ---
>  hw/s390x/ipl.c  | 52 
> +
>  hw/s390x/ipl.h  |  9 +++--
>  pc-bios/s390-ccw/iplb.h |  9 +++--

Updating the header, but it is not consumed in the bios?

>  3 files changed, 66 insertions(+), 4 deletions(-)

> +static void s390_ipl_set_boot_menu(S390IPLState *ipl)
> +{
> +QemuOptsList *plist = qemu_find_opts("boot-opts");
> +QemuOpts *opts = QTAILQ_FIRST(>head);
> +uint8_t *flags = >qipl.qipl_flags;
> +uint32_t *timeout = >qipl.boot_menu_timeout;
> +const char *tmp;
> +unsigned long splash_time = 0;
> +
> +if (!get_boot_device(0)) {
> +if (boot_menu) {
> +error_report("boot menu requires a bootindex to be specified for 
> "
> + "the IPL device.");
> +}
> +return;
> +}
> +
> +switch (ipl->iplb.pbt) {
> +case S390_IPL_TYPE_CCW:
> +break;
> +default:
> +error_report("boot menu is not supported for this device type.");

If I specify both a bootindex for a device and a -kernel parameter, I
get this error message. Looks a tad odd, but not sure how to avoid it.

Also, error_report() should not use trailing punctuation, but we can
fix that up with a follow-on patch.

> +return;
> +}
> +
> +if (!boot_menu) {
> +return;
> +}
> +
> +*flags |= QIPL_FLAG_BM_OPTS_CMD;
> +
> +tmp = qemu_opt_get(opts, "splash-time");
> +
> +if (tmp && qemu_strtoul(tmp, NULL, 10, _time)) {
> +error_report("splash-time is invalid, forcing it to 0.");
> +*timeout = 0;
> +return;
> +}
> +
> +if (splash_time > 0x) {
> +error_report("splash-time is too large, forcing it to max value.");
> +*timeout = 0x;
> +return;
> +}
> +
> +*timeout = cpu_to_be32(splash_time);
> +}
> +



Re: [Qemu-devel] [PATCH V5 2/4] tests/migration: Convert the boot block compilation script into Makefile

2018-02-26 Thread Wei Huang


On 02/26/2018 12:01 PM, Dr. David Alan Gilbert wrote:
> * Wei Huang (w...@redhat.com) wrote:
>> The x86 boot block header currently is generated with a shell script.
>> To better support other CPUs (e.g. aarch64), we convert the script
>> into Makefile. This allows us to 1) support cross-compilation easily,
>> and 2) avoid creating a script file for every architecture.
>>
>> Signed-off-by: Wei Huang 
> 
> But what happens if you're on a system that doesn't have the cross
> compilers?  I found it's too easy to get stuck with it trying
> to rebuild the header when there's no need.

I think it is fine. If no cross compiler is present, NNN_cross_prefix
won't find anything. So it ends up with using the gcc tools on host
systems. Obviously the compilation will fail. This should become the
problem to solve for whoever wants to do cross-compile. For us, we have
done our part because the .h files have been provided.

> 
> Dave
> 
>> ---
>>  tests/migration/Makefile | 36 
>> 
>>  tests/migration/rebuild-x86-bootblock.sh | 33 -
>>  tests/migration/x86-a-b-bootblock.h  |  2 +-
>>  tests/migration/x86-a-b-bootblock.s  |  5 ++---
>>  4 files changed, 39 insertions(+), 37 deletions(-)
>>  create mode 100644 tests/migration/Makefile
>>  delete mode 100755 tests/migration/rebuild-x86-bootblock.sh
>>
>> diff --git a/tests/migration/Makefile b/tests/migration/Makefile
>> new file mode 100644
>> index 00..8fbedaa8b8
>> --- /dev/null
>> +++ b/tests/migration/Makefile
>> @@ -0,0 +1,36 @@
>> +#
>> +# Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
>> +#
>> +# Authors:
>> +#   Dave Gilbert 
>> +#
>> +# This work is licensed under the terms of the GNU GPL, version 2 or later.
>> +# See the COPYING file in the top-level directory.
>> +#
>> +export __note
>> +override define __note
>> +/* This file is automatically generated from
>> + * tests/migration/$<, edit that and then run
>> + * "make $@" inside tests/migration to update,
>> + * and then remember to send both in your patch submission.
>> + */
>> +endef
>> +
>> +all: x86-a-b-bootblock.h
>> +# Dummy command so that make thinks it has done something
>> +@true
>> +
>> +SRC_PATH=../..
>> +include $(SRC_PATH)/rules.mak
>> +
>> +x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
>> +
>> +x86-a-b-bootblock.h: x86-a-b-bootblock.s
>> +$(x86_64_cross_prefix)as --32 -march=i486 $< -o x86.o
>> +$(x86_64_cross_prefix)objcopy -O binary x86.o x86.boot
>> +dd if=x86.boot of=x86.bootsect bs=256 count=2 skip=124
>> +echo "$$__note" > $@
>> +xxd -i x86.bootsect | sed -e 's/.*int.*//' >> $@
>> +
>> +clean:
>> +rm -f *.bootsect *.boot *.o
>> diff --git a/tests/migration/rebuild-x86-bootblock.sh 
>> b/tests/migration/rebuild-x86-bootblock.sh
>> deleted file mode 100755
>> index 86cec5d284..00
>> --- a/tests/migration/rebuild-x86-bootblock.sh
>> +++ /dev/null
>> @@ -1,33 +0,0 @@
>> -#!/bin/sh
>> -# Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
>> -# This work is licensed under the terms of the GNU GPL, version 2 or later.
>> -# See the COPYING file in the top-level directory.
>> -#
>> -# Author: dgilb...@redhat.com
>> -
>> -ASMFILE=$PWD/tests/migration/x86-a-b-bootblock.s
>> -HEADER=$PWD/tests/migration/x86-a-b-bootblock.h
>> -
>> -if [ ! -e "$ASMFILE" ]
>> -then
>> -  echo "Couldn't find $ASMFILE" >&2
>> -  exit 1
>> -fi
>> -
>> -ASM_WORK_DIR=$(mktemp -d --tmpdir X86BB.XX)
>> -cd "$ASM_WORK_DIR" &&
>> -as --32 -march=i486 "$ASMFILE" -o x86.o &&
>> -objcopy -O binary x86.o x86.boot &&
>> -dd if=x86.boot of=x86.bootsect bs=256 count=2 skip=124 &&
>> -xxd -i x86.bootsect |
>> -sed -e 's/.*int.*//' > x86.hex &&
>> -cat - x86.hex < "$HEADER"
>> -/* This file is automatically generated from
>> - * tests/migration/x86-a-b-bootblock.s, edit that and then run
>> - * tests/migration/rebuild-x86-bootblock.sh to update,
>> - * and then remember to send both in your patch submission.
>> - */
>> -HERE
>> -
>> -rm x86.hex x86.bootsect x86.boot x86.o
>> -cd .. && rmdir "$ASM_WORK_DIR"
>> diff --git a/tests/migration/x86-a-b-bootblock.h 
>> b/tests/migration/x86-a-b-bootblock.h
>> index 78a151fe2a..9e8e2e028b 100644
>> --- a/tests/migration/x86-a-b-bootblock.h
>> +++ b/tests/migration/x86-a-b-bootblock.h
>> @@ -1,6 +1,6 @@
>>  /* This file is automatically generated from
>>   * tests/migration/x86-a-b-bootblock.s, edit that and then run
>> - * tests/migration/rebuild-x86-bootblock.sh to update,
>> + * "make x86-a-b-bootblock.h" inside tests/migration to update,
>>   * and then remember to send both in your patch submission.
>>   */
>>  unsigned char x86_bootsect[] = {
>> diff --git a/tests/migration/x86-a-b-bootblock.s 
>> b/tests/migration/x86-a-b-bootblock.s
>> index b1642641a7..98dbfab084 100644
>> --- a/tests/migration/x86-a-b-bootblock.s
>> +++ b/tests/migration/x86-a-b-bootblock.s
>> @@ -3,9 +3,8 @@
>>  #  

Re: [Qemu-devel] [PATCH V4 3/3] tests: Add migration test for aarch64

2018-02-26 Thread Wei Huang


On 02/26/2018 03:03 AM, Andrew Jones wrote:
> On Fri, Feb 23, 2018 at 04:13:08PM -0600, Wei Huang wrote:
>>
>>
>> On 02/22/2018 03:00 AM, Andrew Jones wrote:
>>> On Wed, Feb 21, 2018 at 10:44:17PM -0600, Wei Huang wrote:
 This patch adds migration test support for aarch64. The test code, which
 implements the same functionality as x86, is booted as a kernel in qemu.
 Here are the design choices we make for aarch64:

  * We choose this -kernel approach because aarch64 QEMU doesn't provide a
built-in fw like x86 does. So instead of relying on a boot loader, we
use -kernel approach for aarch64.
  * The serial output is sent to PL011 directly.
  * The physical memory base for mach-virt machine is 0x4000. We change
the start_address and end_address for aarch64.

 In addition to providing the binary, this patch also includes the source
 code and the build script in tests/migration/. So users can change the
 source and/or re-compile the binary as they wish.

 Signed-off-by: Wei Huang 
 ---
  tests/Makefile.include   |  1 +
  tests/migration-test.c   | 47 +---
  tests/migration/Makefile | 12 +-
  tests/migration/aarch64-a-b-kernel.S | 71 
 
  tests/migration/aarch64-a-b-kernel.h | 19 ++
  tests/migration/migration-test.h |  5 +++
  6 files changed, 147 insertions(+), 8 deletions(-)
  create mode 100644 tests/migration/aarch64-a-b-kernel.S
  create mode 100644 tests/migration/aarch64-a-b-kernel.h

 diff --git a/tests/Makefile.include b/tests/Makefile.include
 index a1bcbffe12..df9f64438f 100644
 --- a/tests/Makefile.include
 +++ b/tests/Makefile.include
 @@ -372,6 +372,7 @@ check-qtest-arm-y += tests/sdhci-test$(EXESUF)
  check-qtest-aarch64-y = tests/numa-test$(EXESUF)
  check-qtest-aarch64-y += tests/sdhci-test$(EXESUF)
  check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF)
 +check-qtest-aarch64-y += tests/migration-test$(EXESUF)
  
  check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
  
 diff --git a/tests/migration-test.c b/tests/migration-test.c
 index e2e06ed337..a4f6732a59 100644
 --- a/tests/migration-test.c
 +++ b/tests/migration-test.c
 @@ -11,6 +11,7 @@
   */
  
  #include "qemu/osdep.h"
 +#include 
  
  #include "libqtest.h"
  #include "qapi/qmp/qdict.h"
 @@ -23,8 +24,8 @@
  
  #include "migration/migration-test.h"
  
 -const unsigned start_address = TEST_MEM_START;
 -const unsigned end_address = TEST_MEM_END;
 +unsigned start_address = TEST_MEM_START;
 +unsigned end_address = TEST_MEM_END;
  bool got_stop;
  
  #if defined(__linux__)
 @@ -81,12 +82,13 @@ static const char *tmpfs;
   * outputting a 'B' every so often if it's still running.
   */
  #include "tests/migration/x86-a-b-bootblock.h"
 +#include "tests/migration/aarch64-a-b-kernel.h"
  
 -static void init_bootfile_x86(const char *bootpath)
 +static void init_bootfile(const char *bootpath, void *content)
  {
  FILE *bootfile = fopen(bootpath, "wb");
  
 -g_assert_cmpint(fwrite(x86_bootsect, 512, 1, bootfile), ==, 1);
 +g_assert_cmpint(fwrite(content, 512, 1, bootfile), ==, 1);
  fclose(bootfile);
  }
  
 @@ -393,7 +395,7 @@ static void test_migrate_start(QTestState **from, 
 QTestState **to,
  got_stop = false;
  
  if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
 -init_bootfile_x86(bootpath);
 +init_bootfile(bootpath, x86_bootsect);
  cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
" -name source,debug-threads=on"
" -serial file:%s/src_serial"
 @@ -422,6 +424,39 @@ static void test_migrate_start(QTestState **from, 
 QTestState **to,
" -serial file:%s/dest_serial"
" -incoming %s",
accel, tmpfs, uri);
 +} else if (strcmp(arch, "aarch64") == 0) {
 +const char *cpu;
 +const char *gic_ver;
 +struct utsname utsname;
 +
 +/* kvm and tcg need different cpu and gic-version configs */
 +if (access("/dev/kvm", F_OK) == 0 && uname() == 0 &&
 +strcmp(utsname.machine, "aarch64") == 0) {
 +accel = "kvm";
 +cpu = "host";
 +gic_ver = "host";
 +} else {
 +accel = "tcg";
 +cpu = "cortex-a57";
 +gic_ver = "2";
 +}
 +
 +init_bootfile(bootpath, aarch64_kernel);
 +

[Qemu-devel] [PATCH V6 1/4] rules: Move cross compilation auto detection functions to rules.mak

2018-02-26 Thread Wei Huang
This patch moves the auto detection functions for cross compilation from
roms/Makefile to rules.mak. So the functions can be shared among Makefiles
in QEMU.

Signed-off-by: Wei Huang 
Reviewed-by: Andrew Jones 
---
 roms/Makefile | 24 +++-
 rules.mak | 15 +++
 2 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/roms/Makefile b/roms/Makefile
index b5e5a69e91..e972c65333 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -21,23 +21,6 @@ pxe-rom-virtio   efi-rom-virtio   : DID := 1000
 pxe-rom-vmxnet3  efi-rom-vmxnet3  : VID := 15ad
 pxe-rom-vmxnet3  efi-rom-vmxnet3  : DID := 07b0
 
-#
-# cross compiler auto detection
-#
-path := $(subst :, ,$(PATH))
-system := $(shell uname -s | tr "A-Z" "a-z")
-
-# first find cross binutils in path
-find-cross-ld = $(firstword $(wildcard $(patsubst 
%,%/$(1)-*$(system)*-ld,$(path
-# then check we have cross gcc too
-find-cross-gcc = $(firstword $(wildcard $(patsubst %ld,%gcc,$(call 
find-cross-ld,$(1)
-# finally strip off path + toolname so we get the prefix
-find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1
-
-powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
-powerpc_cross_prefix := $(call find-cross-prefix,powerpc)
-x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
-
 # tag our seabios builds
 SEABIOS_EXTRAVERSION="-prebuilt.qemu-project.org"
 
@@ -66,6 +49,13 @@ default:
@echo "  skiboot-- update skiboot.lid"
@echo "  u-boot.e500-- update u-boot.e500"
 
+SRC_PATH=..
+include $(SRC_PATH)/rules.mak
+
+powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
+powerpc_cross_prefix := $(call find-cross-prefix,powerpc)
+x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
+
 bios: build-seabios-config-seabios-128k build-seabios-config-seabios-256k
cp seabios/builds/seabios-128k/bios.bin ../pc-bios/bios.bin
cp seabios/builds/seabios-256k/bios.bin ../pc-bios/bios-256k.bin
diff --git a/rules.mak b/rules.mak
index 6e943335f3..ef8adee3f8 100644
--- a/rules.mak
+++ b/rules.mak
@@ -62,6 +62,21 @@ expand-objs = $(strip $(sort $(filter %.o,$1)) \
   $(foreach o,$(filter %.mo,$1),$($o-objs)) \
   $(filter-out %.o %.mo,$1))
 
+# Cross compilation auto detection. Use find-cross-prefix to detect the
+# target archtecture's prefix, and then append it to the build tool or pass
+# it to CROSS_COMPILE directly. Here is one example:
+#  x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
+#  $(x86_64_cross_prefix)gcc -c test.c -o test.o
+#  make -C testdir CROSS_COMPILE=$(x86_64_cross_prefix)
+cross-search-path := $(subst :, ,$(PATH))
+cross-host-system := $(shell uname -s | tr "A-Z" "a-z")
+
+find-cross-ld = $(firstword $(wildcard $(patsubst \
+%,%/$(1)-*$(cross-host-system)*-ld,$(cross-search-path
+find-cross-gcc = $(firstword $(wildcard \
+$(patsubst %ld,%gcc,$(call find-cross-ld,$(1)
+find-cross-prefix = $(subst gcc,,$(notdir $(call find-cross-gcc,$(1
+
 %.o: %.c
$(call quiet-command,$(CC) $(QEMU_LOCAL_INCLUDES) $(QEMU_INCLUDES) \
   $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) \
-- 
2.14.3




[Qemu-devel] [PATCH V6 3/4] tests/migration: Add migration-test header file

2018-02-26 Thread Wei Huang
This patch moves the settings related migration-test from the
migration-test.c file to a seperate header file. It also renames the
x86-a-b-bootblock.s file extension from .s to .S, allowing gcc
pre-processor to include the C-style header file correctly.

Signed-off-by: Wei Huang 
Reviewed-by: Andrew Jones 
---
 tests/migration-test.c | 28 +++---
 tests/migration/Makefile   |  4 ++--
 tests/migration/migration-test.h   | 18 ++
 .../{x86-a-b-bootblock.s => x86-a-b-bootblock.S}   |  7 +++---
 tests/migration/x86-a-b-bootblock.h|  2 +-
 5 files changed, 39 insertions(+), 20 deletions(-)
 create mode 100644 tests/migration/migration-test.h
 rename tests/migration/{x86-a-b-bootblock.s => x86-a-b-bootblock.S} (94%)

diff --git a/tests/migration-test.c b/tests/migration-test.c
index 74f9361bdd..c88b7e7a19 100644
--- a/tests/migration-test.c
+++ b/tests/migration-test.c
@@ -21,10 +21,10 @@
 #include "sysemu/sysemu.h"
 #include "hw/nvram/chrp_nvram.h"
 
-#define MIN_NVRAM_SIZE 8192 /* from spapr_nvram.c */
+#include "migration/migration-test.h"
 
-const unsigned start_address = 1024 * 1024;
-const unsigned end_address = 100 * 1024 * 1024;
+const unsigned start_address = TEST_MEM_START;
+const unsigned end_address = TEST_MEM_END;
 bool got_stop;
 
 #if defined(__linux__)
@@ -77,8 +77,8 @@ static bool ufd_version_check(void)
 
 static const char *tmpfs;
 
-/* A simple PC boot sector that modifies memory (1-100MB) quickly
- * outputting a 'B' every so often if it's still running.
+/* The boot file modifies memory area in [start_address, end_address)
+ * repeatedly. It outputs a 'B' at a fixed rate while it's still running.
  */
 #include "tests/migration/x86-a-b-bootblock.h"
 
@@ -104,9 +104,8 @@ static void init_bootfile_ppc(const char *bootpath)
 memcpy(header->name, "common", 6);
 chrp_nvram_finish_partition(header, MIN_NVRAM_SIZE);
 
-/* FW_MAX_SIZE is 4MB, but slof.bin is only 900KB,
- * so let's modify memory between 1MB and 100MB
- * to do like PC bootsector
+/* FW_MAX_SIZE is 4MB, but slof.bin is only 900KB. So it is OK to modify
+ * memory between start_address and end_address like PC bootsector does.
  */
 
 sprintf(buf + 16,
@@ -263,11 +262,11 @@ static void wait_for_migration_pass(QTestState *who)
 static void check_guests_ram(QTestState *who)
 {
 /* Our ASM test will have been incrementing one byte from each page from
- * 1MB to <100MB in order.
- * This gives us a constraint that any page's byte should be equal or less
- * than the previous pages byte (mod 256); and they should all be equal
- * except for one transition at the point where we meet the incrementer.
- * (We're running this with the guest stopped).
+ * start_address to < end_address in order. This gives us a constraint
+ * that any page's byte should be equal or less than the previous pages
+ * byte (mod 256); and they should all be equal except for one transition
+ * at the point where we meet the incrementer. (We're running this with
+ * the guest stopped).
  */
 unsigned address;
 uint8_t first_byte;
@@ -278,7 +277,8 @@ static void check_guests_ram(QTestState *who)
 qtest_memread(who, start_address, _byte, 1);
 last_byte = first_byte;
 
-for (address = start_address + 4096; address < end_address; address += 
4096)
+for (address = start_address + TEST_MEM_PAGE_SIZE; address < end_address;
+ address += TEST_MEM_PAGE_SIZE)
 {
 uint8_t b;
 qtest_memread(who, address, , 1);
diff --git a/tests/migration/Makefile b/tests/migration/Makefile
index 8fbedaa8b8..013b8d1f44 100644
--- a/tests/migration/Makefile
+++ b/tests/migration/Makefile
@@ -25,8 +25,8 @@ include $(SRC_PATH)/rules.mak
 
 x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
 
-x86-a-b-bootblock.h: x86-a-b-bootblock.s
-   $(x86_64_cross_prefix)as --32 -march=i486 $< -o x86.o
+x86-a-b-bootblock.h: x86-a-b-bootblock.S
+   $(x86_64_cross_prefix)gcc -m32 -march=i486 -c $< -o x86.o
$(x86_64_cross_prefix)objcopy -O binary x86.o x86.boot
dd if=x86.boot of=x86.bootsect bs=256 count=2 skip=124
echo "$$__note" > $@
diff --git a/tests/migration/migration-test.h b/tests/migration/migration-test.h
new file mode 100644
index 00..48b59b3281
--- /dev/null
+++ b/tests/migration/migration-test.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018 Red Hat, Inc. and/or its affiliates
+ *
+ * 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_MIGRATION_H_
+#define _TEST_MIGRATION_H_
+
+/* Common */
+#define TEST_MEM_START  (1 * 1024 * 1024)
+#define TEST_MEM_END(100 * 1024 * 1024)
+#define TEST_MEM_PAGE_SIZE  4096
+
+/* PPC */
+#define MIN_NVRAM_SIZE 8192 /* from spapr_nvram.c */
+

[Qemu-devel] [PATCH V6 4/4] tests: Add migration test for aarch64

2018-02-26 Thread Wei Huang
This patch adds migration test support for aarch64. The test code, which
implements the same functionality as x86, is booted as a kernel in qemu.
Here are the design choices we make for aarch64:

 * We choose this -kernel approach because aarch64 QEMU doesn't provide a
   built-in fw like x86 does. So instead of relying on a boot loader, we
   use -kernel approach for aarch64.
 * The serial output is sent to PL011 directly.
 * The physical memory base for mach-virt machine is 0x4000. We change
   the start_address and end_address for aarch64.

In addition to providing the binary, this patch also includes the source
code and the build script in tests/migration/. So users can change the
source and/or re-compile the binary as they wish.

Signed-off-by: Wei Huang 
---
 tests/Makefile.include   |  1 +
 tests/migration-test.c   | 46 +++---
 tests/migration/Makefile | 12 +-
 tests/migration/aarch64-a-b-kernel.S | 75 
 tests/migration/aarch64-a-b-kernel.h | 19 +
 tests/migration/migration-test.h |  9 +
 6 files changed, 154 insertions(+), 8 deletions(-)
 create mode 100644 tests/migration/aarch64-a-b-kernel.S
 create mode 100644 tests/migration/aarch64-a-b-kernel.h

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 577eb573a2..538173866c 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -372,6 +372,7 @@ check-qtest-arm-y += tests/sdhci-test$(EXESUF)
 check-qtest-aarch64-y = tests/numa-test$(EXESUF)
 check-qtest-aarch64-y += tests/sdhci-test$(EXESUF)
 check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF)
+check-qtest-aarch64-y += tests/migration-test$(EXESUF)
 
 check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
 
diff --git a/tests/migration-test.c b/tests/migration-test.c
index c88b7e7a19..9cc98445b0 100644
--- a/tests/migration-test.c
+++ b/tests/migration-test.c
@@ -11,6 +11,7 @@
  */
 
 #include "qemu/osdep.h"
+#include 
 
 #include "libqtest.h"
 #include "qapi/qmp/qdict.h"
@@ -23,8 +24,8 @@
 
 #include "migration/migration-test.h"
 
-const unsigned start_address = TEST_MEM_START;
-const unsigned end_address = TEST_MEM_END;
+unsigned start_address = TEST_MEM_START;
+unsigned end_address = TEST_MEM_END;
 bool got_stop;
 
 #if defined(__linux__)
@@ -81,12 +82,13 @@ static const char *tmpfs;
  * repeatedly. It outputs a 'B' at a fixed rate while it's still running.
  */
 #include "tests/migration/x86-a-b-bootblock.h"
+#include "tests/migration/aarch64-a-b-kernel.h"
 
-static void init_bootfile_x86(const char *bootpath)
+static void init_bootfile(const char *bootpath, void *content)
 {
 FILE *bootfile = fopen(bootpath, "wb");
 
-g_assert_cmpint(fwrite(x86_bootsect, 512, 1, bootfile), ==, 1);
+g_assert_cmpint(fwrite(content, 512, 1, bootfile), ==, 1);
 fclose(bootfile);
 }
 
@@ -392,7 +394,7 @@ static void test_migrate_start(QTestState **from, 
QTestState **to,
 got_stop = false;
 
 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
-init_bootfile_x86(bootpath);
+init_bootfile(bootpath, x86_bootsect);
 cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
   " -name source,debug-threads=on"
   " -serial file:%s/src_serial"
@@ -421,6 +423,38 @@ static void test_migrate_start(QTestState **from, 
QTestState **to,
   " -serial file:%s/dest_serial"
   " -incoming %s",
   accel, tmpfs, uri);
+} else if (strcmp(arch, "aarch64") == 0) {
+const char *cpu;
+const char *gic_ver;
+struct utsname utsname;
+
+/* kvm and tcg need different cpu and gic-version configs */
+if (access("/dev/kvm", F_OK) == 0 && uname() == 0 &&
+strcmp(utsname.machine, "aarch64") == 0) {
+accel = "kvm";
+cpu = "host";
+gic_ver = "host";
+} else {
+accel = "tcg";
+cpu = "cortex-a57";
+gic_ver = "2";
+}
+
+init_bootfile(bootpath, aarch64_kernel);
+cmd_src = g_strdup_printf("-machine virt,accel=%s,gic-version=%s "
+  "-name vmsource,debug-threads=on -cpu %s "
+  "-m 150M -serial file:%s/src_serial "
+  "-kernel %s ",
+  accel, gic_ver, cpu, tmpfs, bootpath);
+cmd_dst = g_strdup_printf("-machine virt,accel=%s,gic-version=%s "
+  "-name vmdest,debug-threads=on -cpu %s "
+  "-m 150M -serial file:%s/dest_serial "
+  "-kernel %s "
+  "-incoming %s ",
+  accel, gic_ver, cpu, tmpfs, bootpath, uri);
+
+start_address = 

[Qemu-devel] [PATCH V6 0/4] tests: Add migration test for aarch64

2018-02-26 Thread Wei Huang
This patchset adds a migration test for aarch64. It leverages
Dave Gilbert's recent patch "tests/migration: Add source to PC boot block"
to create a new test case for aarch64.

V5->V6:
 * Add Reviewed-by to patch 1-3
 * Add more design notes in patch 4 (aarch64 assembly compilation, bin space)

V4->V5:
 * Extract cross compilation detection code into rules.mak for sharing
 * Minor comment and code revision in migration-test.c & aarch64-a-b-kernel.S
 
V3->V4:
 * Rename .s to .S, allowing assembly to include C-style header file
 * Move test defines into a new migration-test.h file
 * Use different cpu & gic settings for kvm and tcg modes on aarch64
 * Clean up aarch64-a-b-kernel.S based on Andrew Jones' comments
 
V2->V3:
 * Convert build script to Makefile
 * Add cross-compilation support
 * Fix CPU type for "tcg" machine type
 * Revise asm code and the compilation process from asm to header file

V1->V2:
 * Similar to Dave Gilbert's recent changes to migration-test, we
   provide the test source and a build script in V2.
 * aarch64 kernel blob is defined as "unsigned char" because the source
   is now provided in V2.
 * Add "-machine none" to test_deprecated() because aarch64 doesn't have
   a default machine type.

RFC->V1:
 * aarch64 kernel blob is defined as an uint32_t array
 * The test code is re-written to address a data caching issue under KVM.
   Tests passed under both x86 and aarch64.
 * Re-use init_bootfile_x86() for both x86 and aarch64
 * Other minor fixes

Thanks,
-Wei

Wei Huang (4):
  rules: Move cross compilation auto detection functions to rules.mak
  tests/migration: Convert the boot block compilation script into
Makefile
  tests/migration: Add migration-test header file
  tests: Add migration test for aarch64

 roms/Makefile  | 24 ++-
 rules.mak  | 15 +
 tests/Makefile.include |  1 +
 tests/migration-test.c | 70 ++--
 tests/migration/Makefile   | 44 +
 tests/migration/aarch64-a-b-kernel.S   | 75 ++
 tests/migration/aarch64-a-b-kernel.h   | 19 ++
 tests/migration/migration-test.h   | 27 
 tests/migration/rebuild-x86-bootblock.sh   | 33 --
 .../{x86-a-b-bootblock.s => x86-a-b-bootblock.S}   | 12 ++--
 tests/migration/x86-a-b-bootblock.h|  4 +-
 11 files changed, 248 insertions(+), 76 deletions(-)
 create mode 100644 tests/migration/Makefile
 create mode 100644 tests/migration/aarch64-a-b-kernel.S
 create mode 100644 tests/migration/aarch64-a-b-kernel.h
 create mode 100644 tests/migration/migration-test.h
 delete mode 100755 tests/migration/rebuild-x86-bootblock.sh
 rename tests/migration/{x86-a-b-bootblock.s => x86-a-b-bootblock.S} (88%)

-- 
2.14.3




[Qemu-devel] [PATCH V6 2/4] tests/migration: Convert the boot block compilation script into Makefile

2018-02-26 Thread Wei Huang
The x86 boot block header currently is generated with a shell script.
To better support other CPUs (e.g. aarch64), we convert the script
into Makefile. This allows us to 1) support cross-compilation easily,
and 2) avoid creating a script file for every architecture.

Signed-off-by: Wei Huang 
Reviewed-by: Andrew Jones 
---
 tests/migration/Makefile | 36 
 tests/migration/rebuild-x86-bootblock.sh | 33 -
 tests/migration/x86-a-b-bootblock.h  |  2 +-
 tests/migration/x86-a-b-bootblock.s  |  5 ++---
 4 files changed, 39 insertions(+), 37 deletions(-)
 create mode 100644 tests/migration/Makefile
 delete mode 100755 tests/migration/rebuild-x86-bootblock.sh

diff --git a/tests/migration/Makefile b/tests/migration/Makefile
new file mode 100644
index 00..8fbedaa8b8
--- /dev/null
+++ b/tests/migration/Makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
+#
+# Authors:
+#   Dave Gilbert 
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+#
+export __note
+override define __note
+/* This file is automatically generated from
+ * tests/migration/$<, edit that and then run
+ * "make $@" inside tests/migration to update,
+ * and then remember to send both in your patch submission.
+ */
+endef
+
+all: x86-a-b-bootblock.h
+# Dummy command so that make thinks it has done something
+   @true
+
+SRC_PATH=../..
+include $(SRC_PATH)/rules.mak
+
+x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
+
+x86-a-b-bootblock.h: x86-a-b-bootblock.s
+   $(x86_64_cross_prefix)as --32 -march=i486 $< -o x86.o
+   $(x86_64_cross_prefix)objcopy -O binary x86.o x86.boot
+   dd if=x86.boot of=x86.bootsect bs=256 count=2 skip=124
+   echo "$$__note" > $@
+   xxd -i x86.bootsect | sed -e 's/.*int.*//' >> $@
+
+clean:
+   rm -f *.bootsect *.boot *.o
diff --git a/tests/migration/rebuild-x86-bootblock.sh 
b/tests/migration/rebuild-x86-bootblock.sh
deleted file mode 100755
index 86cec5d284..00
--- a/tests/migration/rebuild-x86-bootblock.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-# Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
-# This work is licensed under the terms of the GNU GPL, version 2 or later.
-# See the COPYING file in the top-level directory.
-#
-# Author: dgilb...@redhat.com
-
-ASMFILE=$PWD/tests/migration/x86-a-b-bootblock.s
-HEADER=$PWD/tests/migration/x86-a-b-bootblock.h
-
-if [ ! -e "$ASMFILE" ]
-then
-  echo "Couldn't find $ASMFILE" >&2
-  exit 1
-fi
-
-ASM_WORK_DIR=$(mktemp -d --tmpdir X86BB.XX)
-cd "$ASM_WORK_DIR" &&
-as --32 -march=i486 "$ASMFILE" -o x86.o &&
-objcopy -O binary x86.o x86.boot &&
-dd if=x86.boot of=x86.bootsect bs=256 count=2 skip=124 &&
-xxd -i x86.bootsect |
-sed -e 's/.*int.*//' > x86.hex &&
-cat - x86.hex < "$HEADER"
-/* This file is automatically generated from
- * tests/migration/x86-a-b-bootblock.s, edit that and then run
- * tests/migration/rebuild-x86-bootblock.sh to update,
- * and then remember to send both in your patch submission.
- */
-HERE
-
-rm x86.hex x86.bootsect x86.boot x86.o
-cd .. && rmdir "$ASM_WORK_DIR"
diff --git a/tests/migration/x86-a-b-bootblock.h 
b/tests/migration/x86-a-b-bootblock.h
index 78a151fe2a..9e8e2e028b 100644
--- a/tests/migration/x86-a-b-bootblock.h
+++ b/tests/migration/x86-a-b-bootblock.h
@@ -1,6 +1,6 @@
 /* This file is automatically generated from
  * tests/migration/x86-a-b-bootblock.s, edit that and then run
- * tests/migration/rebuild-x86-bootblock.sh to update,
+ * "make x86-a-b-bootblock.h" inside tests/migration to update,
  * and then remember to send both in your patch submission.
  */
 unsigned char x86_bootsect[] = {
diff --git a/tests/migration/x86-a-b-bootblock.s 
b/tests/migration/x86-a-b-bootblock.s
index b1642641a7..98dbfab084 100644
--- a/tests/migration/x86-a-b-bootblock.s
+++ b/tests/migration/x86-a-b-bootblock.s
@@ -3,9 +3,8 @@
 #  range.
 #  Outputs an initial 'A' on serial followed by repeated 'B's
 #
-# run   tests/migration/rebuild-x86-bootblock.sh
-#   to regenerate the hex, and remember to include both the .h and .s
-#   in any patches.
+#  In tests/migration dir, run 'make x86-a-b-bootblock.h' to regenerate
+#  the hex, and remember to include both the .h and .s in any patches.
 #
 # Copyright (c) 2016 Red Hat, Inc. and/or its affiliates
 # This work is licensed under the terms of the GNU GPL, version 2 or later.
-- 
2.14.3




Re: [Qemu-devel] [PATCH V5 2/4] tests/migration: Convert the boot block compilation script into Makefile

2018-02-26 Thread Dr. David Alan Gilbert
* Wei Huang (w...@redhat.com) wrote:
> The x86 boot block header currently is generated with a shell script.
> To better support other CPUs (e.g. aarch64), we convert the script
> into Makefile. This allows us to 1) support cross-compilation easily,
> and 2) avoid creating a script file for every architecture.
> 
> Signed-off-by: Wei Huang 

But what happens if you're on a system that doesn't have the cross
compilers?  I found it's too easy to get stuck with it trying
to rebuild the header when there's no need.

Dave

> ---
>  tests/migration/Makefile | 36 
> 
>  tests/migration/rebuild-x86-bootblock.sh | 33 -
>  tests/migration/x86-a-b-bootblock.h  |  2 +-
>  tests/migration/x86-a-b-bootblock.s  |  5 ++---
>  4 files changed, 39 insertions(+), 37 deletions(-)
>  create mode 100644 tests/migration/Makefile
>  delete mode 100755 tests/migration/rebuild-x86-bootblock.sh
> 
> diff --git a/tests/migration/Makefile b/tests/migration/Makefile
> new file mode 100644
> index 00..8fbedaa8b8
> --- /dev/null
> +++ b/tests/migration/Makefile
> @@ -0,0 +1,36 @@
> +#
> +# Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
> +#
> +# Authors:
> +#   Dave Gilbert 
> +#
> +# This work is licensed under the terms of the GNU GPL, version 2 or later.
> +# See the COPYING file in the top-level directory.
> +#
> +export __note
> +override define __note
> +/* This file is automatically generated from
> + * tests/migration/$<, edit that and then run
> + * "make $@" inside tests/migration to update,
> + * and then remember to send both in your patch submission.
> + */
> +endef
> +
> +all: x86-a-b-bootblock.h
> +# Dummy command so that make thinks it has done something
> + @true
> +
> +SRC_PATH=../..
> +include $(SRC_PATH)/rules.mak
> +
> +x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
> +
> +x86-a-b-bootblock.h: x86-a-b-bootblock.s
> + $(x86_64_cross_prefix)as --32 -march=i486 $< -o x86.o
> + $(x86_64_cross_prefix)objcopy -O binary x86.o x86.boot
> + dd if=x86.boot of=x86.bootsect bs=256 count=2 skip=124
> + echo "$$__note" > $@
> + xxd -i x86.bootsect | sed -e 's/.*int.*//' >> $@
> +
> +clean:
> + rm -f *.bootsect *.boot *.o
> diff --git a/tests/migration/rebuild-x86-bootblock.sh 
> b/tests/migration/rebuild-x86-bootblock.sh
> deleted file mode 100755
> index 86cec5d284..00
> --- a/tests/migration/rebuild-x86-bootblock.sh
> +++ /dev/null
> @@ -1,33 +0,0 @@
> -#!/bin/sh
> -# Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
> -# This work is licensed under the terms of the GNU GPL, version 2 or later.
> -# See the COPYING file in the top-level directory.
> -#
> -# Author: dgilb...@redhat.com
> -
> -ASMFILE=$PWD/tests/migration/x86-a-b-bootblock.s
> -HEADER=$PWD/tests/migration/x86-a-b-bootblock.h
> -
> -if [ ! -e "$ASMFILE" ]
> -then
> -  echo "Couldn't find $ASMFILE" >&2
> -  exit 1
> -fi
> -
> -ASM_WORK_DIR=$(mktemp -d --tmpdir X86BB.XX)
> -cd "$ASM_WORK_DIR" &&
> -as --32 -march=i486 "$ASMFILE" -o x86.o &&
> -objcopy -O binary x86.o x86.boot &&
> -dd if=x86.boot of=x86.bootsect bs=256 count=2 skip=124 &&
> -xxd -i x86.bootsect |
> -sed -e 's/.*int.*//' > x86.hex &&
> -cat - x86.hex < "$HEADER"
> -/* This file is automatically generated from
> - * tests/migration/x86-a-b-bootblock.s, edit that and then run
> - * tests/migration/rebuild-x86-bootblock.sh to update,
> - * and then remember to send both in your patch submission.
> - */
> -HERE
> -
> -rm x86.hex x86.bootsect x86.boot x86.o
> -cd .. && rmdir "$ASM_WORK_DIR"
> diff --git a/tests/migration/x86-a-b-bootblock.h 
> b/tests/migration/x86-a-b-bootblock.h
> index 78a151fe2a..9e8e2e028b 100644
> --- a/tests/migration/x86-a-b-bootblock.h
> +++ b/tests/migration/x86-a-b-bootblock.h
> @@ -1,6 +1,6 @@
>  /* This file is automatically generated from
>   * tests/migration/x86-a-b-bootblock.s, edit that and then run
> - * tests/migration/rebuild-x86-bootblock.sh to update,
> + * "make x86-a-b-bootblock.h" inside tests/migration to update,
>   * and then remember to send both in your patch submission.
>   */
>  unsigned char x86_bootsect[] = {
> diff --git a/tests/migration/x86-a-b-bootblock.s 
> b/tests/migration/x86-a-b-bootblock.s
> index b1642641a7..98dbfab084 100644
> --- a/tests/migration/x86-a-b-bootblock.s
> +++ b/tests/migration/x86-a-b-bootblock.s
> @@ -3,9 +3,8 @@
>  #  range.
>  #  Outputs an initial 'A' on serial followed by repeated 'B's
>  #
> -# run   tests/migration/rebuild-x86-bootblock.sh
> -#   to regenerate the hex, and remember to include both the .h and .s
> -#   in any patches.
> +#  In tests/migration dir, run 'make x86-a-b-bootblock.h' to regenerate
> +#  the hex, and remember to include both the .h and .s in any patches.
>  #
>  # Copyright (c) 2016 Red Hat, Inc. and/or its affiliates
>  # This work is licensed under the terms of the GNU GPL, version 2 or later.
> 

[Qemu-devel] [PATCH 6/8] Fix WHPX issue leaking tpr values

2018-02-26 Thread Justin Terry (VM) via Qemu-devel
Fixes an issue where if the tpr is assigned to the array but not a different
value from what is already expected on the vp the code will skip incrementing
the reg_count. In this case its possible that we set an invalid memory section
of the next call for DeliverabilityNotifications that was not expected.

The fix is to use a local variable to store the temporary tpr and only update
the array if the local tpr value is different than the vp context.

Signed-off-by: Justin Terry (VM) 
---
 target/i386/whpx-all.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c
index 7e58d5f68c..47a6935288 100644
--- a/target/i386/whpx-all.c
+++ b/target/i386/whpx-all.c
@@ -687,6 +687,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
 X86CPU *x86_cpu = X86_CPU(cpu);
 int irq;
+uint8_t tpr;
 WHV_X64_PENDING_INTERRUPTION_REGISTER new_int = {0};
 UINT32 reg_count = 0;
 WHV_REGISTER_VALUE reg_values[3] = {0};
@@ -746,9 +747,10 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 }
 
 /* Sync the TPR to the CR8 if was modified during the intercept */
-reg_values[reg_count].Reg64 = cpu_get_apic_tpr(x86_cpu->apic_state);
-if (reg_values[reg_count].Reg64 != vcpu->tpr) {
-vcpu->tpr = reg_values[reg_count].Reg64;
+tpr = cpu_get_apic_tpr(x86_cpu->apic_state);
+if (tpr != vcpu->tpr) {
+vcpu->tpr = tpr;
+reg_values[reg_count].Reg64 = tpr;
 cpu->exit_request = 1;
 reg_names[reg_count] = WHvX64RegisterCr8;
 reg_count += 1;
-- 
2.13.6




[Qemu-devel] [PATCH 7/8] WHXP Removes the use of WHvGetExitContextSize

2018-02-26 Thread Justin Terry (VM) via Qemu-devel
The use of WHvGetExitContextSize will break ABI compatibility if the platform
changes the context size while a qemu compiled executable does not recompile.
To avoid this we now use sizeof and let the platform determine which version
of the struction was passed for ABI compatibility.

Signed-off-by: Justin Terry (VM) 
---
 target/i386/whpx-all.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c
index 47a6935288..24387bebad 100644
--- a/target/i386/whpx-all.c
+++ b/target/i386/whpx-all.c
@@ -32,7 +32,6 @@
 struct whpx_state {
 uint64_t mem_quota;
 WHV_PARTITION_HANDLE partition;
-uint32_t exit_ctx_size;
 };
 
 static const WHV_REGISTER_NAME whpx_register_names[] = {
@@ -899,7 +898,7 @@ static int whpx_vcpu_run(CPUState *cpu)
 }
 
 hr = WHvRunVirtualProcessor(whpx->partition, cpu->cpu_index,
->exit_ctx, whpx->exit_ctx_size);
+>exit_ctx, sizeof(vcpu->exit_ctx));
 
 if (FAILED(hr)) {
 error_report("WHPX: Failed to exec a virtual processor,"
@@ -1042,8 +1041,7 @@ int whpx_init_vcpu(CPUState *cpu)
 }
 }
 
-vcpu = g_malloc0(FIELD_OFFSET(struct whpx_vcpu, exit_ctx) +
- whpx->exit_ctx_size);
+vcpu = g_malloc0(sizeof(struct whpx_vcpu));
 
 if (!vcpu) {
 error_report("WHPX: Failed to allocte VCPU context.");
@@ -1300,9 +1298,6 @@ static int whpx_accel_init(MachineState *ms)
 goto error;
 }
 
-whpx->exit_ctx_size = WHvGetRunExitContextSize();
-assert(whpx->exit_ctx_size);
-
 whpx_memory_init();
 
 cpu_interrupt_handler = whpx_handle_interrupt;
-- 
2.13.6




[Qemu-devel] [PATCH 4/8] Fix WHPX additional lock acquisition

2018-02-26 Thread Justin Terry (VM) via Qemu-devel
The code already is holding the qemu_mutex for the IO thread. We do not need
to additionally take the lock again in this case.

Signed-off-by: Justin Terry (VM) 
---
 target/i386/whpx-all.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c
index 14ea732ec6..74a8f4d599 100644
--- a/target/i386/whpx-all.c
+++ b/target/i386/whpx-all.c
@@ -705,9 +705,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 new_int.InterruptionVector = 2;
 }
 if (cpu->interrupt_request & CPU_INTERRUPT_SMI) {
-qemu_mutex_lock_iothread();
 cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
-qemu_mutex_unlock_iothread();
 }
 }
 
-- 
2.13.6




[Qemu-devel] [PATCH 3/8] Remove unnecessary WHPX __debugbreak();

2018-02-26 Thread Justin Terry (VM) via Qemu-devel
Minor code cleanup. The calls to __debugbreak() are not required and should
no longer be used to prevent unnecessary breaks.

Signed-off-by: Justin Terry (VM) 
---
 target/i386/whpx-all.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c
index 969c2f5f93..14ea732ec6 100644
--- a/target/i386/whpx-all.c
+++ b/target/i386/whpx-all.c
@@ -364,7 +364,6 @@ static void whpx_set_registers(CPUState *cpu)
 if (FAILED(hr)) {
 error_report("WHPX: Failed to set virtual processor context, hr=%08lx",
  hr);
-__debugbreak();
 }
 
 return;
@@ -391,7 +390,6 @@ static void whpx_get_registers(CPUState *cpu)
 if (FAILED(hr)) {
 error_report("WHPX: Failed to get virtual processor context, hr=%08lx",
  hr);
-__debugbreak();
 }
 
 /* Indexes for first 16 registers match between HV and QEMU definitions */
@@ -554,7 +552,6 @@ static HRESULT CALLBACK whpx_emu_getreg_callback(
 if (FAILED(hr)) {
 error_report("WHPX: Failed to get virtual processor registers,"
  " hr=%08lx", hr);
-__debugbreak();
 }
 
 return hr;
@@ -576,7 +573,6 @@ static HRESULT CALLBACK whpx_emu_setreg_callback(
 if (FAILED(hr)) {
 error_report("WHPX: Failed to set virtual processor registers,"
  " hr=%08lx", hr);
-__debugbreak();
 }
 
 /*
@@ -604,7 +600,6 @@ static HRESULT CALLBACK whpx_emu_translate_callback(
  Gva, TranslateFlags, , Gpa);
 if (FAILED(hr)) {
 error_report("WHPX: Failed to translate GVA, hr=%08lx", hr);
-__debugbreak();
 } else {
 *TranslationResult = res.ResultCode;
 }
@@ -631,13 +626,11 @@ static int whpx_handle_mmio(CPUState *cpu, 
WHV_MEMORY_ACCESS_CONTEXT *ctx)
  >exit_ctx.VpContext, ctx,
  _status);
 if (FAILED(hr)) {
-__debugbreak();
 error_report("WHPX: Failed to parse MMIO access, hr=%08lx", hr);
 return -1;
 }
 
 if (!emu_status.EmulationSuccessful) {
-__debugbreak();
 error_report("WHPX: Failed to emulate MMIO access");
 return -1;
 }
@@ -656,13 +649,11 @@ static int whpx_handle_portio(CPUState *cpu,
>exit_ctx.VpContext, ctx,
_status);
 if (FAILED(hr)) {
-__debugbreak();
 error_report("WHPX: Failed to parse PortIO access, hr=%08lx", hr);
 return -1;
 }
 
 if (!emu_status.EmulationSuccessful) {
-__debugbreak();
 error_report("WHPX: Failed to emulate PortMMIO access");
 return -1;
 }
@@ -716,7 +707,6 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 if (cpu->interrupt_request & CPU_INTERRUPT_SMI) {
 qemu_mutex_lock_iothread();
 cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
-__debugbreak();
 qemu_mutex_unlock_iothread();
 }
 }
@@ -785,7 +775,6 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 if (FAILED(hr)) {
 error_report("WHPX: Failed to set interrupt state registers,"
  " hr=%08lx", hr);
-__debugbreak();
 }
 }
 
@@ -812,7 +801,6 @@ static void whpx_vcpu_post_run(CPUState *cpu)
 if (FAILED(hr)) {
 error_report("WHPX: Failed to get interrupt state regusters,"
  " hr=%08lx", hr);
-__debugbreak();
 vcpu->interruptable = false;
 return;
 }
-- 
2.13.6




  1   2   3   >