[Qemu-devel] [Bug 1744654] Re: commit: 4fe6d78 "virtio: postpone the execution of event_notifier_cleanup function" will cause vhost-user device crash

2018-01-24 Thread Thomas Huth
Thanks for the bug report. Patch has now been reverted:
https://git.qemu.org/?p=qemu.git;a=commitdiff;h=1ef8185a0613dd2ed2

** 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/1744654

Title:
  commit: 4fe6d78 "virtio: postpone the execution of
  event_notifier_cleanup function" will cause vhost-user device crash

Status in QEMU:
  Fix Released

Bug description:
  The new commit: 4fe6d78 break the existing vhost-user devices, such as
  vhost-user-scsi/blk and vhost-vsocks when exit the host driver,
  kvm_io_ioeventfd_del will hit the abort().

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



[Qemu-devel] [PATCH] virtio-balloon: unref the memory region before continuing

2018-01-24 Thread Tiwei Bie
Signed-off-by: Tiwei Bie 
---
 hw/virtio/virtio-balloon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 14e08d20d0..f2104bfcef 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -234,6 +234,7 @@ static void virtio_balloon_handle_output(VirtIODevice 
*vdev, VirtQueue *vq)
 memory_region_is_rom(section.mr) ||
 memory_region_is_romd(section.mr)) {
 trace_virtio_balloon_bad_addr(pa);
+memory_region_unref(section.mr);
 continue;
 }
 
-- 
2.13.3




[Qemu-devel] [PULL 13/14] docs: Add section for NVMe VFIO driver

2018-01-24 Thread Fam Zheng
Signed-off-by: Fam Zheng 
Message-Id: <20180110091846.10699-9-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Message-Id: <20180116060901.17413-9-f...@redhat.com>
Signed-off-by: Fam Zheng 
---
 docs/qemu-block-drivers.texi | 37 +
 1 file changed, 37 insertions(+)

diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi
index 503c1847aa..cd74767ed3 100644
--- a/docs/qemu-block-drivers.texi
+++ b/docs/qemu-block-drivers.texi
@@ -785,6 +785,43 @@ warning: ssh server @code{ssh.example.com:22} does not 
support fsync
 With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is
 supported.
 
+@node disk_images_nvme
+@subsection NVMe disk images
+
+NVM Express (NVMe) storage controllers can be accessed directly by a userspace
+driver in QEMU.  This bypasses the host kernel file system and block layers
+while retaining QEMU block layer functionalities, such as block jobs, I/O
+throttling, image formats, etc.  Disk I/O performance is typically higher than
+with @code{-drive file=/dev/sda} using either thread pool or linux-aio.
+
+The controller will be exclusively used by the QEMU process once started. To be
+able to share storage between multiple VMs and other applications on the host,
+please use the file based protocols.
+
+Before starting QEMU, bind the host NVMe controller to the host vfio-pci
+driver.  For example:
+
+@example
+# modprobe vfio-pci
+# lspci -n -s :06:0d.0
+06:0d.0 0401: 1102:0002 (rev 08)
+# echo :06:0d.0 > /sys/bus/pci/devices/:06:0d.0/driver/unbind
+# echo 1102 0002 > /sys/bus/pci/drivers/vfio-pci/new_id
+
+# qemu-system-x86_64 -drive 
file=nvme://@var{host}:@var{bus}:@var{slot}.@var{func}/@var{namespace}
+@end example
+
+Alternative syntax using properties:
+
+@example
+qemu-system-x86_64 -drive 
file.driver=nvme,file.device=@var{host}:@var{bus}:@var{slot}.@var{func},file.namespace=@var{namespace}
+@end example
+
+@var{host}:@var{bus}:@var{slot}.@var{func} is the NVMe controller's PCI device
+address on the host.
+
+@var{namespace} is the NVMe namespace number, starting from 1.
+
 @node disk_image_locking
 @subsection Disk image file locking
 
-- 
2.14.3




[Qemu-devel] [PULL 09/14] block: Introduce buf register API

2018-01-24 Thread Fam Zheng
Allow block driver to map and unmap a buffer for later I/O, as a performance
hint.

Signed-off-by: Fam Zheng 
Message-Id: <20180110091846.10699-5-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Message-Id: <20180116060901.17413-5-f...@redhat.com>
Signed-off-by: Fam Zheng 
---
 block/block-backend.c  | 10 ++
 block/io.c | 24 
 include/block/block.h  | 11 ++-
 include/block/block_int.h  |  9 +
 include/sysemu/block-backend.h |  3 +++
 5 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/block/block-backend.c b/block/block-backend.c
index baef8e7abc..f66349c2c9 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -2096,3 +2096,13 @@ static void blk_root_drained_end(BdrvChild *child)
 }
 }
 }
+
+void blk_register_buf(BlockBackend *blk, void *host, size_t size)
+{
+bdrv_register_buf(blk_bs(blk), host, size);
+}
+
+void blk_unregister_buf(BlockBackend *blk, void *host)
+{
+bdrv_unregister_buf(blk_bs(blk), host);
+}
diff --git a/block/io.c b/block/io.c
index 7ea402352e..89d0745e95 100644
--- a/block/io.c
+++ b/block/io.c
@@ -2825,3 +2825,27 @@ void bdrv_io_unplug(BlockDriverState *bs)
 bdrv_io_unplug(child->bs);
 }
 }
+
+void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size)
+{
+BdrvChild *child;
+
+if (bs->drv && bs->drv->bdrv_register_buf) {
+bs->drv->bdrv_register_buf(bs, host, size);
+}
+QLIST_FOREACH(child, >children, next) {
+bdrv_register_buf(child->bs, host, size);
+}
+}
+
+void bdrv_unregister_buf(BlockDriverState *bs, void *host)
+{
+BdrvChild *child;
+
+if (bs->drv && bs->drv->bdrv_unregister_buf) {
+bs->drv->bdrv_unregister_buf(bs, host);
+}
+QLIST_FOREACH(child, >children, next) {
+bdrv_unregister_buf(child->bs, host);
+}
+}
diff --git a/include/block/block.h b/include/block/block.h
index 9b12774ddf..2025d7ed19 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -631,5 +631,14 @@ void bdrv_del_child(BlockDriverState *parent, BdrvChild 
*child, Error **errp);
 
 bool bdrv_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
  uint32_t granularity, Error **errp);
-
+/**
+ *
+ * bdrv_register_buf/bdrv_unregister_buf:
+ *
+ * Register/unregister a buffer for I/O. For example, VFIO drivers are
+ * interested to know the memory areas that would later be used for I/O, so
+ * that they can prepare IOMMU mapping etc., to get better performance.
+ */
+void bdrv_register_buf(BlockDriverState *bs, void *host, size_t size);
+void bdrv_unregister_buf(BlockDriverState *bs, void *host);
 #endif
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 29cafa4236..99b9190627 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -446,6 +446,15 @@ struct BlockDriver {
 const char *name,
 Error **errp);
 
+/**
+ * Register/unregister a buffer for I/O. For example, when the driver is
+ * interested to know the memory areas that will later be used in iovs, so
+ * that it can do IOMMU mapping with VFIO etc., in order to get better
+ * performance. In the case of VFIO drivers, this callback is used to do
+ * DMA mapping for hot buffers.
+ */
+void (*bdrv_register_buf)(BlockDriverState *bs, void *host, size_t size);
+void (*bdrv_unregister_buf)(BlockDriverState *bs, void *host);
 QLIST_ENTRY(BlockDriver) list;
 };
 
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index c4e52a5fa3..92ab624fac 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -229,4 +229,7 @@ void blk_io_limits_enable(BlockBackend *blk, const char 
*group);
 void blk_io_limits_update_group(BlockBackend *blk, const char *group);
 void blk_set_force_allow_inactivate(BlockBackend *blk);
 
+void blk_register_buf(BlockBackend *blk, void *host, size_t size);
+void blk_unregister_buf(BlockBackend *blk, void *host);
+
 #endif
-- 
2.14.3




[Qemu-devel] [PULL 12/14] block: Move NVMe constants to a separate header

2018-01-24 Thread Fam Zheng
Signed-off-by: Fam Zheng 
Message-Id: <20180110091846.10699-8-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Message-Id: <20180116060901.17413-8-f...@redhat.com>
Signed-off-by: Fam Zheng 
---
 block/nvme.c |   7 +-
 hw/block/nvme.h  | 698 +-
 include/block/nvme.h | 700 +++
 3 files changed, 702 insertions(+), 703 deletions(-)
 create mode 100644 include/block/nvme.h

diff --git a/block/nvme.c b/block/nvme.c
index 30616f50c7..044b15e1f5 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -22,12 +22,7 @@
 #include "block/block_int.h"
 #include "trace.h"
 
-/* TODO: Move nvme spec definitions from hw/block/nvme.h into a separate file
- * that doesn't depend on dma/pci headers. */
-#include "sysemu/dma.h"
-#include "hw/pci/pci.h"
-#include "hw/block/block.h"
-#include "hw/block/nvme.h"
+#include "block/nvme.h"
 
 #define NVME_SQ_ENTRY_BYTES 64
 #define NVME_CQ_ENTRY_BYTES 16
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index 6aab338ff5..59a1504018 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -1,703 +1,7 @@
 #ifndef HW_NVME_H
 #define HW_NVME_H
 #include "qemu/cutils.h"
-
-typedef struct NvmeBar {
-uint64_tcap;
-uint32_tvs;
-uint32_tintms;
-uint32_tintmc;
-uint32_tcc;
-uint32_trsvd1;
-uint32_tcsts;
-uint32_tnssrc;
-uint32_taqa;
-uint64_tasq;
-uint64_tacq;
-uint32_tcmbloc;
-uint32_tcmbsz;
-} NvmeBar;
-
-enum NvmeCapShift {
-CAP_MQES_SHIFT = 0,
-CAP_CQR_SHIFT  = 16,
-CAP_AMS_SHIFT  = 17,
-CAP_TO_SHIFT   = 24,
-CAP_DSTRD_SHIFT= 32,
-CAP_NSSRS_SHIFT= 33,
-CAP_CSS_SHIFT  = 37,
-CAP_MPSMIN_SHIFT   = 48,
-CAP_MPSMAX_SHIFT   = 52,
-};
-
-enum NvmeCapMask {
-CAP_MQES_MASK  = 0x,
-CAP_CQR_MASK   = 0x1,
-CAP_AMS_MASK   = 0x3,
-CAP_TO_MASK= 0xff,
-CAP_DSTRD_MASK = 0xf,
-CAP_NSSRS_MASK = 0x1,
-CAP_CSS_MASK   = 0xff,
-CAP_MPSMIN_MASK= 0xf,
-CAP_MPSMAX_MASK= 0xf,
-};
-
-#define NVME_CAP_MQES(cap)  (((cap) >> CAP_MQES_SHIFT)   & CAP_MQES_MASK)
-#define NVME_CAP_CQR(cap)   (((cap) >> CAP_CQR_SHIFT)& CAP_CQR_MASK)
-#define NVME_CAP_AMS(cap)   (((cap) >> CAP_AMS_SHIFT)& CAP_AMS_MASK)
-#define NVME_CAP_TO(cap)(((cap) >> CAP_TO_SHIFT) & CAP_TO_MASK)
-#define NVME_CAP_DSTRD(cap) (((cap) >> CAP_DSTRD_SHIFT)  & CAP_DSTRD_MASK)
-#define NVME_CAP_NSSRS(cap) (((cap) >> CAP_NSSRS_SHIFT)  & CAP_NSSRS_MASK)
-#define NVME_CAP_CSS(cap)   (((cap) >> CAP_CSS_SHIFT)& CAP_CSS_MASK)
-#define NVME_CAP_MPSMIN(cap)(((cap) >> CAP_MPSMIN_SHIFT) & CAP_MPSMIN_MASK)
-#define NVME_CAP_MPSMAX(cap)(((cap) >> CAP_MPSMAX_SHIFT) & CAP_MPSMAX_MASK)
-
-#define NVME_CAP_SET_MQES(cap, val)   (cap |= (uint64_t)(val & CAP_MQES_MASK)  
\
-   << CAP_MQES_SHIFT)
-#define NVME_CAP_SET_CQR(cap, val)(cap |= (uint64_t)(val & CAP_CQR_MASK)   
\
-   << CAP_CQR_SHIFT)
-#define NVME_CAP_SET_AMS(cap, val)(cap |= (uint64_t)(val & CAP_AMS_MASK)   
\
-   << CAP_AMS_SHIFT)
-#define NVME_CAP_SET_TO(cap, val) (cap |= (uint64_t)(val & CAP_TO_MASK)
\
-   << CAP_TO_SHIFT)
-#define NVME_CAP_SET_DSTRD(cap, val)  (cap |= (uint64_t)(val & CAP_DSTRD_MASK) 
\
-   << CAP_DSTRD_SHIFT)
-#define NVME_CAP_SET_NSSRS(cap, val)  (cap |= (uint64_t)(val & CAP_NSSRS_MASK) 
\
-   << CAP_NSSRS_SHIFT)
-#define NVME_CAP_SET_CSS(cap, val)(cap |= (uint64_t)(val & CAP_CSS_MASK)   
\
-   << CAP_CSS_SHIFT)
-#define NVME_CAP_SET_MPSMIN(cap, val) (cap |= (uint64_t)(val & 
CAP_MPSMIN_MASK)\
-   << CAP_MPSMIN_SHIFT)
-#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & 
CAP_MPSMAX_MASK)\
-<< 
CAP_MPSMAX_SHIFT)
-
-enum NvmeCcShift {
-CC_EN_SHIFT = 0,
-CC_CSS_SHIFT= 4,
-CC_MPS_SHIFT= 7,
-CC_AMS_SHIFT= 11,
-CC_SHN_SHIFT= 14,
-CC_IOSQES_SHIFT = 16,
-CC_IOCQES_SHIFT = 20,
-};
-
-enum NvmeCcMask {
-CC_EN_MASK  = 0x1,
-CC_CSS_MASK = 0x7,
-CC_MPS_MASK = 0xf,
-CC_AMS_MASK = 0x7,
-CC_SHN_MASK = 0x3,
-CC_IOSQES_MASK  = 0xf,
-CC_IOCQES_MASK  = 0xf,
-};
-
-#define NVME_CC_EN(cc) ((cc >> CC_EN_SHIFT) & CC_EN_MASK)
-#define NVME_CC_CSS(cc)((cc >> CC_CSS_SHIFT)& CC_CSS_MASK)
-#define NVME_CC_MPS(cc)((cc >> CC_MPS_SHIFT)& CC_MPS_MASK)
-#define 

[Qemu-devel] [PULL 05/14] curl: convert to CoQueue

2018-01-24 Thread Fam Zheng
From: Paolo Bonzini 

Now that CoQueues can use a QemuMutex for thread-safety, there is no
need for curl to roll its own coroutine queue.  Coroutines can be
placed directly on the queue instead of using a list of CURLAIOCBs.

Signed-off-by: Paolo Bonzini 
Message-Id: <20180116142316.30486-5-pbonz...@redhat.com>
Reviewed-by: Fam Zheng 
Signed-off-by: Fam Zheng 
---
 block/curl.c | 20 
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/block/curl.c b/block/curl.c
index 35cf417f59..cd578d3d14 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -101,8 +101,6 @@ typedef struct CURLAIOCB {
 
 size_t start;
 size_t end;
-
-QSIMPLEQ_ENTRY(CURLAIOCB) next;
 } CURLAIOCB;
 
 typedef struct CURLSocket {
@@ -138,7 +136,7 @@ typedef struct BDRVCURLState {
 bool accept_range;
 AioContext *aio_context;
 QemuMutex mutex;
-QSIMPLEQ_HEAD(, CURLAIOCB) free_state_waitq;
+CoQueue free_state_waitq;
 char *username;
 char *password;
 char *proxyusername;
@@ -538,7 +536,6 @@ static int curl_init_state(BDRVCURLState *s, CURLState 
*state)
 /* Called with s->mutex held.  */
 static void curl_clean_state(CURLState *s)
 {
-CURLAIOCB *next;
 int j;
 for (j = 0; j < CURL_NUM_ACB; j++) {
 assert(!s->acb[j]);
@@ -556,13 +553,7 @@ static void curl_clean_state(CURLState *s)
 
 s->in_use = 0;
 
-next = QSIMPLEQ_FIRST(>s->free_state_waitq);
-if (next) {
-QSIMPLEQ_REMOVE_HEAD(>s->free_state_waitq, next);
-qemu_mutex_unlock(>s->mutex);
-aio_co_wake(next->co);
-qemu_mutex_lock(>s->mutex);
-}
+qemu_co_enter_next(>s->free_state_waitq, >s->mutex);
 }
 
 static void curl_parse_filename(const char *filename, QDict *options,
@@ -784,7 +775,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, 
int flags,
 }
 
 DPRINTF("CURL: Opening %s\n", file);
-QSIMPLEQ_INIT(>free_state_waitq);
+qemu_co_queue_init(>free_state_waitq);
 s->aio_context = bdrv_get_aio_context(bs);
 s->url = g_strdup(file);
 qemu_mutex_lock(>mutex);
@@ -888,10 +879,7 @@ static void curl_setup_preadv(BlockDriverState *bs, 
CURLAIOCB *acb)
 if (state) {
 break;
 }
-QSIMPLEQ_INSERT_TAIL(>free_state_waitq, acb, next);
-qemu_mutex_unlock(>mutex);
-qemu_coroutine_yield();
-qemu_mutex_lock(>mutex);
+qemu_co_queue_wait(>free_state_waitq, >mutex);
 }
 
 if (curl_init_state(s, state) < 0) {
-- 
2.14.3




[Qemu-devel] [PULL 14/14] qapi: Add NVMe driver options to the schema

2018-01-24 Thread Fam Zheng
Signed-off-by: Fam Zheng 
Message-Id: <20180110091846.10699-10-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Message-Id: <20180116060901.17413-10-f...@redhat.com>
Signed-off-by: Fam Zheng 
---
 qapi/block-core.json | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 4e84cf29db..a21bc69388 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2248,6 +2248,7 @@
 #
 # @vxhs: Since 2.10
 # @throttle: Since 2.11
+# @nvme: Since 2.12
 #
 # Since: 2.9
 ##
@@ -2255,7 +2256,7 @@
   'data': [ 'blkdebug', 'blkverify', 'bochs', 'cloop',
 'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
 'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
-'null-aio', 'null-co', 'parallels', 'qcow', 'qcow2', 'qed',
+'null-aio', 'null-co', 'nvme', 'parallels', 'qcow', 'qcow2', 'qed',
 'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
 
@@ -2296,6 +2297,19 @@
 { 'struct': 'BlockdevOptionsNull',
   'data': { '*size': 'int', '*latency-ns': 'uint64' } }
 
+##
+# @BlockdevOptionsNVMe:
+#
+# Driver specific block device options for the NVMe backend.
+#
+# @device:controller address of the NVMe device.
+# @namespace: namespace number of the device, starting from 1.
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevOptionsNVMe',
+  'data': { 'device': 'str', 'namespace': 'int' } }
+
 ##
 # @BlockdevOptionsVVFAT:
 #
@@ -3201,6 +3215,7 @@
   'nfs':'BlockdevOptionsNfs',
   'null-aio':   'BlockdevOptionsNull',
   'null-co':'BlockdevOptionsNull',
+  'nvme':   'BlockdevOptionsNVMe',
   'parallels':  'BlockdevOptionsGenericFormat',
   'qcow2':  'BlockdevOptionsQcow2',
   'qcow':   'BlockdevOptionsQcow',
-- 
2.14.3




[Qemu-devel] [PULL 03/14] coroutine-lock: convert CoQueue to use QemuLockable

2018-01-24 Thread Fam Zheng
From: Paolo Bonzini 

There are cases in which a queued coroutine must be restarted from
non-coroutine context (with qemu_co_enter_next).  In this cases,
qemu_co_enter_next also needs to be thread-safe, but it cannot use
a CoMutex and so cannot qemu_co_queue_wait.  Use QemuLockable so
that the CoQueue can interchangeably use CoMutex or QemuMutex.

Signed-off-by: Paolo Bonzini 
Message-Id: <20180116142316.30486-3-pbonz...@redhat.com>
Reviewed-by: Fam Zheng 
Signed-off-by: Fam Zheng 
---
 include/qemu/coroutine.h   |  6 +-
 util/qemu-coroutine-lock.c | 12 +++-
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 8a5129741c..1e5f0957e6 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -183,7 +183,9 @@ void qemu_co_queue_init(CoQueue *queue);
  * caller of the coroutine.  The mutex is unlocked during the wait and
  * locked again afterwards.
  */
-void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex *mutex);
+#define qemu_co_queue_wait(queue, lock) \
+qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock))
+void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock);
 
 /**
  * Restarts the next coroutine in the CoQueue and removes it from the queue.
@@ -271,4 +273,6 @@ void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, 
int64_t ns);
  */
 void coroutine_fn yield_until_fd_readable(int fd);
 
+#include "qemu/lockable.h"
+
 #endif /* QEMU_COROUTINE_H */
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index 846ff9167f..2a66fc1467 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -40,13 +40,13 @@ void qemu_co_queue_init(CoQueue *queue)
 QSIMPLEQ_INIT(>entries);
 }
 
-void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex *mutex)
+void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock)
 {
 Coroutine *self = qemu_coroutine_self();
 QSIMPLEQ_INSERT_TAIL(>entries, self, co_queue_next);
 
-if (mutex) {
-qemu_co_mutex_unlock(mutex);
+if (lock) {
+qemu_lockable_unlock(lock);
 }
 
 /* There is no race condition here.  Other threads will call
@@ -60,9 +60,11 @@ void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex 
*mutex)
 /* TODO: OSv implements wait morphing here, where the wakeup
  * primitive automatically places the woken coroutine on the
  * mutex's queue.  This avoids the thundering herd effect.
+ * This could be implemented for CoMutexes, but not really for
+ * other cases of QemuLockable.
  */
-if (mutex) {
-qemu_co_mutex_lock(mutex);
+if (lock) {
+qemu_lockable_lock(lock);
 }
 }
 
-- 
2.14.3




[Qemu-devel] [PULL 08/14] block: Add VFIO based NVMe driver

2018-01-24 Thread Fam Zheng
This is a new protocol driver that exclusively opens a host NVMe
controller through VFIO. It achieves better latency than linux-aio by
completely bypassing host kernel vfs/block layer.

$rw-$bs-$iodepth  linux-aio nvme://

randread-4k-1 10.5k 21.6k
randread-512k-1   745   1591
randwrite-4k-130.7k 37.0k
randwrite-512k-1  1945  1980

(unit: IOPS)

The driver also integrates with the polling mechanism of iothread.

This patch is co-authored by Paolo and me.

Signed-off-by: Paolo Bonzini 
Signed-off-by: Fam Zheng 
Message-Id: <20180110091846.10699-4-f...@redhat.com>
Message-Id: <20180116060901.17413-4-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Signed-off-by: Fam Zheng 
---
 MAINTAINERS |6 +
 block/Makefile.objs |1 +
 block/nvme.c| 1180 +++
 block/trace-events  |   21 +
 4 files changed, 1208 insertions(+)
 create mode 100644 block/nvme.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 753e7996ce..7d76707335 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1877,6 +1877,12 @@ L: qemu-bl...@nongnu.org
 S: Supported
 F: block/null.c
 
+NVMe Block Driver
+M: Fam Zheng 
+L: qemu-bl...@nongnu.org
+S: Supported
+F: block/nvme*
+
 Bootdevice
 M: Gonglei 
 S: Maintained
diff --git a/block/Makefile.objs b/block/Makefile.objs
index a73387f1bf..aede94f105 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -11,6 +11,7 @@ block-obj-$(CONFIG_POSIX) += file-posix.o
 block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 block-obj-y += null.o mirror.o commit.o io.o
 block-obj-y += throttle-groups.o
+block-obj-$(CONFIG_LINUX) += nvme.o
 
 block-obj-y += nbd.o nbd-client.o sheepdog.o
 block-obj-$(CONFIG_LIBISCSI) += iscsi.o
diff --git a/block/nvme.c b/block/nvme.c
new file mode 100644
index 00..99cc7702ad
--- /dev/null
+++ b/block/nvme.c
@@ -0,0 +1,1180 @@
+/*
+ * NVMe block driver based on vfio
+ *
+ * Copyright 2016 - 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   Fam Zheng 
+ *   Paolo Bonzini 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qstring.h"
+#include "qemu/error-report.h"
+#include "qemu/cutils.h"
+#include "qemu/vfio-helpers.h"
+#include "block/block_int.h"
+#include "trace.h"
+
+/* TODO: Move nvme spec definitions from hw/block/nvme.h into a separate file
+ * that doesn't depend on dma/pci headers. */
+#include "sysemu/dma.h"
+#include "hw/pci/pci.h"
+#include "hw/block/block.h"
+#include "hw/block/nvme.h"
+
+#define NVME_SQ_ENTRY_BYTES 64
+#define NVME_CQ_ENTRY_BYTES 16
+#define NVME_QUEUE_SIZE 128
+#define NVME_BAR_SIZE 8192
+
+typedef struct {
+int32_t  head, tail;
+uint8_t  *queue;
+uint64_t iova;
+/* Hardware MMIO register */
+volatile uint32_t *doorbell;
+} NVMeQueue;
+
+typedef struct {
+BlockCompletionFunc *cb;
+void *opaque;
+int cid;
+void *prp_list_page;
+uint64_t prp_list_iova;
+bool busy;
+} NVMeRequest;
+
+typedef struct {
+CoQueue free_req_queue;
+QemuMutex   lock;
+
+/* Fields protected by BQL */
+int index;
+uint8_t *prp_list_pages;
+
+/* Fields protected by @lock */
+NVMeQueue   sq, cq;
+int cq_phase;
+NVMeRequest reqs[NVME_QUEUE_SIZE];
+boolbusy;
+int need_kick;
+int inflight;
+} NVMeQueuePair;
+
+/* Memory mapped registers */
+typedef volatile struct {
+uint64_t cap;
+uint32_t vs;
+uint32_t intms;
+uint32_t intmc;
+uint32_t cc;
+uint32_t reserved0;
+uint32_t csts;
+uint32_t nssr;
+uint32_t aqa;
+uint64_t asq;
+uint64_t acq;
+uint32_t cmbloc;
+uint32_t cmbsz;
+uint8_t  reserved1[0xec0];
+uint8_t  cmd_set_specfic[0x100];
+uint32_t doorbells[];
+} QEMU_PACKED NVMeRegs;
+
+QEMU_BUILD_BUG_ON(offsetof(NVMeRegs, doorbells) != 0x1000);
+
+typedef struct {
+AioContext *aio_context;
+QEMUVFIOState *vfio;
+NVMeRegs *regs;
+/* The submission/completion queue pairs.
+ * [0]: admin queue.
+ * [1..]: io queues.
+ */
+NVMeQueuePair **queues;
+int nr_queues;
+size_t page_size;
+/* How many uint32_t elements does each doorbell entry take. */
+size_t doorbell_scale;
+bool write_cache_supported;
+EventNotifier irq_notifier;
+uint64_t nsze; /* Namespace size reported by identify command */
+int nsid;  /* The namespace id to read/write data. */
+uint64_t max_transfer;
+int plugged;
+
+CoMutex dma_map_lock;
+CoQueue dma_flush_queue;
+
+/* Total size of mapped qiov, accessed under 

[Qemu-devel] [PULL 11/14] qemu-img: Map bench buffer

2018-01-24 Thread Fam Zheng
Signed-off-by: Fam Zheng 
Message-Id: <20180110091846.10699-7-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Message-Id: <20180116060901.17413-7-f...@redhat.com>
Signed-off-by: Fam Zheng 
---
 qemu-img.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/qemu-img.c b/qemu-img.c
index 68b375f998..28d0e4e9f8 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3862,6 +3862,7 @@ static int img_bench(int argc, char **argv)
 struct timeval t1, t2;
 int i;
 bool force_share = false;
+size_t buf_size;
 
 for (;;) {
 static const struct option long_options[] = {
@@ -4050,9 +4051,12 @@ static int img_bench(int argc, char **argv)
 printf("Sending flush every %d requests\n", flush_interval);
 }
 
-data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
+buf_size = data.nrreq * data.bufsize;
+data.buf = blk_blockalign(blk, buf_size);
 memset(data.buf, pattern, data.nrreq * data.bufsize);
 
+blk_register_buf(blk, data.buf, buf_size);
+
 data.qiov = g_new(QEMUIOVector, data.nrreq);
 for (i = 0; i < data.nrreq; i++) {
 qemu_iovec_init([i], 1);
@@ -4073,6 +4077,9 @@ static int img_bench(int argc, char **argv)
+ ((double)(t2.tv_usec - t1.tv_usec) / 100));
 
 out:
+if (data.buf) {
+blk_unregister_buf(blk, data.buf);
+}
 qemu_vfree(data.buf);
 blk_unref(blk);
 
-- 
2.14.3




[Qemu-devel] [PULL 04/14] coroutine-lock: make qemu_co_enter_next thread-safe

2018-01-24 Thread Fam Zheng
From: Paolo Bonzini 

qemu_co_queue_next does not need to release and re-acquire the mutex,
because the queued coroutine does not run immediately.  However, this
does not hold for qemu_co_enter_next.  Now that qemu_co_queue_wait
can synchronize (via QemuLockable) with code that is not running in
coroutine context, it's important that code using qemu_co_enter_next
can easily use a standardized locking idiom.

First of all, qemu_co_enter_next must use aio_co_wake to restart the
coroutine.  Second, the function gains a second argument, a QemuLockable*,
and the comments of qemu_co_queue_next and qemu_co_queue_restart_all
are adjusted to clarify the difference.

Signed-off-by: Paolo Bonzini 
Message-Id: <20180116142316.30486-4-pbonz...@redhat.com>
Reviewed-by: Fam Zheng 
Signed-off-by: Fam Zheng 
---
 fsdev/qemu-fsdev-throttle.c |  4 ++--
 include/qemu/coroutine.h| 15 ++-
 util/qemu-coroutine-lock.c  | 10 --
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c
index 49eebb5412..1dc07fbc12 100644
--- a/fsdev/qemu-fsdev-throttle.c
+++ b/fsdev/qemu-fsdev-throttle.c
@@ -20,13 +20,13 @@
 static void fsdev_throttle_read_timer_cb(void *opaque)
 {
 FsThrottle *fst = opaque;
-qemu_co_enter_next(>throttled_reqs[false]);
+qemu_co_enter_next(>throttled_reqs[false], NULL);
 }
 
 static void fsdev_throttle_write_timer_cb(void *opaque)
 {
 FsThrottle *fst = opaque;
-qemu_co_enter_next(>throttled_reqs[true]);
+qemu_co_enter_next(>throttled_reqs[true], NULL);
 }
 
 void fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 1e5f0957e6..6fdbc837c0 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -188,21 +188,26 @@ void qemu_co_queue_init(CoQueue *queue);
 void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock);
 
 /**
- * Restarts the next coroutine in the CoQueue and removes it from the queue.
+ * Removes the next coroutine from the CoQueue; it will run as soon as the
+ * current one yields.
  *
- * Returns true if a coroutine was restarted, false if the queue is empty.
+ * Returns true if a coroutine was removed, false if the queue is empty.
  */
 bool coroutine_fn qemu_co_queue_next(CoQueue *queue);
 
 /**
- * Restarts all coroutines in the CoQueue and leaves the queue empty.
+ * Empties the CoQueue; all coroutines in it will run in FIFO orer as soon
+ * as the current one yields.
  */
 void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue);
 
 /**
- * Enter the next coroutine in the queue
+ * Immediately enter the next coroutine in the queue.  Release the mutex
+ * while it runs.
  */
-bool qemu_co_enter_next(CoQueue *queue);
+#define qemu_co_enter_next(queue, lock) \
+qemu_co_enter_next_impl(queue, QEMU_MAKE_LOCKABLE(lock))
+bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock);
 
 /**
  * Checks if the CoQueue is empty.
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
index 2a66fc1467..78fb79acf8 100644
--- a/util/qemu-coroutine-lock.c
+++ b/util/qemu-coroutine-lock.c
@@ -132,7 +132,7 @@ void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue)
 qemu_co_queue_do_restart(queue, false);
 }
 
-bool qemu_co_enter_next(CoQueue *queue)
+bool qemu_co_enter_next_impl(CoQueue *queue, QemuLockable *lock)
 {
 Coroutine *next;
 
@@ -142,7 +142,13 @@ bool qemu_co_enter_next(CoQueue *queue)
 }
 
 QSIMPLEQ_REMOVE_HEAD(>entries, co_queue_next);
-qemu_coroutine_enter(next);
+if (lock) {
+qemu_lockable_unlock(lock);
+}
+aio_co_wake(next);
+if (lock) {
+qemu_lockable_lock(lock);
+}
 return true;
 }
 
-- 
2.14.3




[Qemu-devel] [PULL 02/14] lockable: add QemuLockable

2018-01-24 Thread Fam Zheng
From: Paolo Bonzini 

QemuLockable is a polymorphic lock type that takes an object and
knows which function to use for locking and unlocking.  The
implementation could use C11 _Generic, but since the support is
not very widespread I am instead using __builtin_choose_expr and
__builtin_types_compatible_p, which are already used by
include/qemu/atomic.h.

QemuLockable can be used to implement lock guards (in which case the
indirect function calls should be inlined and devirtualized), or to
pass around a lock in such a way that a function can release it and
re-acquire it.  The next patch will do this for CoQueue.

Signed-off-by: Paolo Bonzini 
Message-Id: <20180116142316.30486-2-pbonz...@redhat.com>
Reviewed-by: Fam Zheng 
Signed-off-by: Fam Zheng 
---
 include/qemu/compiler.h  | 40 ++
 include/qemu/coroutine.h |  4 +--
 include/qemu/lockable.h  | 75 
 include/qemu/thread.h|  5 ++--
 include/qemu/typedefs.h  |  4 +++
 5 files changed, 123 insertions(+), 5 deletions(-)
 create mode 100644 include/qemu/lockable.h

diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
index 340e5fdc09..5179bedb1e 100644
--- a/include/qemu/compiler.h
+++ b/include/qemu/compiler.h
@@ -111,4 +111,44 @@
 #define GCC_FMT_ATTR(n, m)
 #endif
 
+/* Implement C11 _Generic via GCC builtins.  Example:
+ *
+ *QEMU_GENERIC(x, (float, sinf), (long double, sinl), sin) (x)
+ *
+ * The first argument is the discriminator.  The last is the default value.
+ * The middle ones are tuples in "(type, expansion)" format.
+ */
+
+/* First, find out the number of generic cases.  */
+#define QEMU_GENERIC(x, ...) \
+QEMU_GENERIC_(typeof(x), __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+
+/* There will be extra arguments, but they are not used.  */
+#define QEMU_GENERIC_(x, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, count, ...) \
+QEMU_GENERIC##count(x, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+
+/* Two more helper macros, this time to extract items from a parenthesized
+ * list.
+ */
+#define QEMU_FIRST_(a, b) a
+#define QEMU_SECOND_(a, b) b
+
+/* ... and a final one for the common part of the "recursion".  */
+#define QEMU_GENERIC_IF(x, type_then, else_)   
\
+__builtin_choose_expr(__builtin_types_compatible_p(x,  
\
+   QEMU_FIRST_ type_then), 
\
+  QEMU_SECOND_ type_then, else_)
+
+/* CPP poor man's "recursion".  */
+#define QEMU_GENERIC1(x, a0, ...) (a0)
+#define QEMU_GENERIC2(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC1(x, 
__VA_ARGS__))
+#define QEMU_GENERIC3(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC2(x, 
__VA_ARGS__))
+#define QEMU_GENERIC4(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC3(x, 
__VA_ARGS__))
+#define QEMU_GENERIC5(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC4(x, 
__VA_ARGS__))
+#define QEMU_GENERIC6(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC5(x, 
__VA_ARGS__))
+#define QEMU_GENERIC7(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC6(x, 
__VA_ARGS__))
+#define QEMU_GENERIC8(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC7(x, 
__VA_ARGS__))
+#define QEMU_GENERIC9(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC8(x, 
__VA_ARGS__))
+#define QEMU_GENERIC10(x, a0, ...) QEMU_GENERIC_IF(x, a0, QEMU_GENERIC9(x, 
__VA_ARGS__))
+
 #endif /* COMPILER_H */
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index ce2eb73670..8a5129741c 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -121,7 +121,7 @@ bool qemu_coroutine_entered(Coroutine *co);
  * Provides a mutex that can be used to synchronise coroutines
  */
 struct CoWaitRecord;
-typedef struct CoMutex {
+struct CoMutex {
 /* Count of pending lockers; 0 for a free mutex, 1 for an
  * uncontended mutex.
  */
@@ -142,7 +142,7 @@ typedef struct CoMutex {
 unsigned handoff, sequence;
 
 Coroutine *holder;
-} CoMutex;
+};
 
 /**
  * Initialises a CoMutex. This must be called before any other operation is 
used
diff --git a/include/qemu/lockable.h b/include/qemu/lockable.h
new file mode 100644
index 00..87bdf62b8a
--- /dev/null
+++ b/include/qemu/lockable.h
@@ -0,0 +1,75 @@
+/*
+ * Polymorphic locking functions (aka poor man templates)
+ *
+ * Copyright Red Hat, Inc. 2017-2018
+ *
+ * Author: Paolo Bonzini 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_LOCKABLE_H
+#define QEMU_LOCKABLE_H
+
+#include "qemu/coroutine.h"
+#include "qemu/thread.h"
+
+typedef void QemuLockUnlockFunc(void *);
+
+struct QemuLockable {
+void *object;
+QemuLockUnlockFunc *lock;
+QemuLockUnlockFunc *unlock;
+};
+
+/* This function gives link-time errors if an invalid, non-NULL
+ * pointer type is 

[Qemu-devel] [PULL 10/14] block/nvme: Implement .bdrv_(un)register_buf

2018-01-24 Thread Fam Zheng
Forward these two calls to the IOVA manager.

Signed-off-by: Fam Zheng 
Message-Id: <20180110091846.10699-6-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Message-Id: <20180116060901.17413-6-f...@redhat.com>
Signed-off-by: Fam Zheng 
---
 block/nvme.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/block/nvme.c b/block/nvme.c
index 99cc7702ad..30616f50c7 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -1145,6 +1145,27 @@ static void nvme_aio_unplug(BlockDriverState *bs)
 }
 }
 
+static void nvme_register_buf(BlockDriverState *bs, void *host, size_t size)
+{
+int ret;
+BDRVNVMeState *s = bs->opaque;
+
+ret = qemu_vfio_dma_map(s->vfio, host, size, false, NULL);
+if (ret) {
+/* FIXME: we may run out of IOVA addresses after repeated
+ * bdrv_register_buf/bdrv_unregister_buf, because nvme_vfio_dma_unmap
+ * doesn't reclaim addresses for fixed mappings. */
+error_report("nvme_register_buf failed: %s", strerror(-ret));
+}
+}
+
+static void nvme_unregister_buf(BlockDriverState *bs, void *host)
+{
+BDRVNVMeState *s = bs->opaque;
+
+qemu_vfio_dma_unmap(s->vfio, host);
+}
+
 static BlockDriver bdrv_nvme = {
 .format_name  = "nvme",
 .protocol_name= "nvme",
@@ -1170,6 +1191,9 @@ static BlockDriver bdrv_nvme = {
 
 .bdrv_io_plug = nvme_aio_plug,
 .bdrv_io_unplug   = nvme_aio_unplug,
+
+.bdrv_register_buf= nvme_register_buf,
+.bdrv_unregister_buf  = nvme_unregister_buf,
 };
 
 static void bdrv_nvme_init(void)
-- 
2.14.3




[Qemu-devel] [PULL 07/14] util: Introduce vfio helpers

2018-01-24 Thread Fam Zheng
This is a library to manage the host vfio interface, which could be used
to implement userspace device driver code in QEMU such as NVMe or net
controllers.

Signed-off-by: Fam Zheng 
Message-Id: <20180110091846.10699-3-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Message-Id: <20180116060901.17413-3-f...@redhat.com>
Signed-off-by: Fam Zheng 
---
 include/qemu/vfio-helpers.h |  33 ++
 util/Makefile.objs  |   1 +
 util/trace-events   |  11 +
 util/vfio-helpers.c | 726 
 4 files changed, 771 insertions(+)
 create mode 100644 include/qemu/vfio-helpers.h
 create mode 100644 util/vfio-helpers.c

diff --git a/include/qemu/vfio-helpers.h b/include/qemu/vfio-helpers.h
new file mode 100644
index 00..ce7e7b057f
--- /dev/null
+++ b/include/qemu/vfio-helpers.h
@@ -0,0 +1,33 @@
+/*
+ * QEMU VFIO helpers
+ *
+ * Copyright 2016 - 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   Fam Zheng 
+ *
+ * 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 QEMU_VFIO_HELPERS_H
+#define QEMU_VFIO_HELPERS_H
+#include "qemu/typedefs.h"
+
+typedef struct QEMUVFIOState QEMUVFIOState;
+
+QEMUVFIOState *qemu_vfio_open_pci(const char *device, Error **errp);
+void qemu_vfio_close(QEMUVFIOState *s);
+int qemu_vfio_dma_map(QEMUVFIOState *s, void *host, size_t size,
+  bool temporary, uint64_t *iova_list);
+int qemu_vfio_dma_reset_temporary(QEMUVFIOState *s);
+void qemu_vfio_dma_unmap(QEMUVFIOState *s, void *host);
+void *qemu_vfio_pci_map_bar(QEMUVFIOState *s, int index,
+uint64_t offset, uint64_t size,
+Error **errp);
+void qemu_vfio_pci_unmap_bar(QEMUVFIOState *s, int index, void *bar,
+ uint64_t offset, uint64_t size);
+int qemu_vfio_pci_init_irq(QEMUVFIOState *s, EventNotifier *e,
+   int irq_type, Error **errp);
+
+#endif
diff --git a/util/Makefile.objs b/util/Makefile.objs
index 2973b0a323..3fb611631f 100644
--- a/util/Makefile.objs
+++ b/util/Makefile.objs
@@ -46,3 +46,4 @@ util-obj-y += qht.o
 util-obj-y += range.o
 util-obj-y += stats64.o
 util-obj-y += systemd.o
+util-obj-$(CONFIG_LINUX) += vfio-helpers.o
diff --git a/util/trace-events b/util/trace-events
index 515e6257fb..4822434c89 100644
--- a/util/trace-events
+++ b/util/trace-events
@@ -60,3 +60,14 @@ lockcnt_futex_wake(const void *lockcnt) "lockcnt %p waking 
up one waiter"
 qemu_mutex_lock(void *mutex, const char *file, const int line) "waiting on 
mutex %p (%s:%d)"
 qemu_mutex_locked(void *mutex, const char *file, const int line) "taken mutex 
%p (%s:%d)"
 qemu_mutex_unlock(void *mutex, const char *file, const int line) "released 
mutex %p (%s:%d)"
+
+# util/vfio-helpers.c
+qemu_vfio_dma_reset_temporary(void *s) "s %p"
+qemu_vfio_ram_block_added(void *s, void *p, size_t size) "s %p host %p size 
0x%zx"
+qemu_vfio_ram_block_removed(void *s, void *p, size_t size) "s %p host %p size 
0x%zx"
+qemu_vfio_find_mapping(void *s, void *p) "s %p host %p"
+qemu_vfio_new_mapping(void *s, void *host, size_t size, int index, uint64_t 
iova) "s %p host %p size %zu index %d iova 0x%"PRIx64
+qemu_vfio_do_mapping(void *s, void *host, size_t size, uint64_t iova) "s %p 
host %p size %zu iova 0x%"PRIx64
+qemu_vfio_dma_map(void *s, void *host, size_t size, bool temporary, uint64_t 
*iova) "s %p host %p size %zu temporary %d iova %p"
+qemu_vfio_dma_map_invalid(void *s, void *mapping_host, size_t mapping_size, 
void *host, size_t size) "s %p mapping %p %zu requested %p %zu"
+qemu_vfio_dma_unmap(void *s, void *host) "s %p host %p"
diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c
new file mode 100644
index 00..0660aaf2f7
--- /dev/null
+++ b/util/vfio-helpers.c
@@ -0,0 +1,726 @@
+/*
+ * VFIO utility
+ *
+ * Copyright 2016 - 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   Fam Zheng 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include 
+#include 
+#include "qapi/error.h"
+#include "exec/ramlist.h"
+#include "exec/cpu-common.h"
+#include "trace.h"
+#include "qemu/queue.h"
+#include "qemu/error-report.h"
+#include "standard-headers/linux/pci_regs.h"
+#include "qemu/event_notifier.h"
+#include "qemu/vfio-helpers.h"
+#include "trace.h"
+
+#define QEMU_VFIO_DEBUG 0
+
+#define QEMU_VFIO_IOVA_MIN 0x1ULL
+/* XXX: Once VFIO exposes the iova bit width in the IOMMU capability interface,
+ * we can use a runtime limit; alternatively it's also possible to do platform
+ * specific detection by reading sysfs entries. Until then, 39 is a safe bet.
+ **/
+#define QEMU_VFIO_IOVA_MAX (1ULL << 39)
+
+typedef struct {
+/* Page aligned addr. */
+void *host;
+size_t size;
+uint64_t iova;
+} IOVAMapping;
+

[Qemu-devel] [PULL 06/14] stubs: Add stubs for ram block API

2018-01-24 Thread Fam Zheng
These functions will be wanted by block-obj-y but the actual definition
is in obj-y, so stub them to keep the linker happy.

Signed-off-by: Fam Zheng 
Acked-by: Paolo Bonzini 
Message-Id: <20180110091846.10699-2-f...@redhat.com>
Reviewed-by: Stefan Hajnoczi 
Message-Id: <20180116060901.17413-2-f...@redhat.com>
Signed-off-by: Fam Zheng 
---
 stubs/Makefile.objs |  1 +
 stubs/ram-block.c   | 16 
 2 files changed, 17 insertions(+)
 create mode 100644 stubs/ram-block.c

diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 8cfe34328a..2d59d84091 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -42,3 +42,4 @@ stub-obj-y += vmgenid.o
 stub-obj-y += xen-common.o
 stub-obj-y += xen-hvm.o
 stub-obj-y += pci-host-piix.o
+stub-obj-y += ram-block.o
diff --git a/stubs/ram-block.c b/stubs/ram-block.c
new file mode 100644
index 00..cfa5d8678f
--- /dev/null
+++ b/stubs/ram-block.c
@@ -0,0 +1,16 @@
+#include "qemu/osdep.h"
+#include "exec/ramlist.h"
+#include "exec/cpu-common.h"
+
+void ram_block_notifier_add(RAMBlockNotifier *n)
+{
+}
+
+void ram_block_notifier_remove(RAMBlockNotifier *n)
+{
+}
+
+int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque)
+{
+return 0;
+}
-- 
2.14.3




[Qemu-devel] [PULL 01/14] docker: change Fedora base image to fedora:27

2018-01-24 Thread Fam Zheng
From: Paolo Bonzini 

Using "fedora:latest" makes behavior different depending on when you
actually pulled the image from the docker repository.  In my case,
the supposedly "latest" image was a Fedora 25 download from 8 months
ago, and the new "test-debug" test was failing.

Use "27" to improve reproducibility and make it clear when the image
is obsolete.

Cc: Fam Zheng 
Cc: Marc-André Lureau 
Signed-off-by: Paolo Bonzini 
Message-Id: <1515755504-21341-1-git-send-email-pbonz...@redhat.com>
Reviewed-by: Marc-André Lureau 
Signed-off-by: Fam Zheng 
---
 tests/docker/dockerfiles/fedora.docker | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/docker/dockerfiles/fedora.docker 
b/tests/docker/dockerfiles/fedora.docker
index 32de731675..714adadbfb 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -1,4 +1,4 @@
-FROM fedora:latest
+FROM fedora:27
 ENV PACKAGES \
 ccache gettext git tar PyYAML sparse flex bison python2 bzip2 hostname \
 glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \
-- 
2.14.3




[Qemu-devel] [PULL 00/14] Block and docker patches

2018-01-24 Thread Fam Zheng
The following changes since commit 834a336eb911db8a8ca00e760ee6a85faca19414:

  Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging 
(2018-01-24 19:24:26 +)

are available in the Git repository at:

  git://github.com/famz/qemu.git tags/staging-pull-request

for you to fetch changes up to 6b4c4a84a1c7386df30edb4cb3b846b7ded9c707:

  qapi: Add NVMe driver options to the schema (2018-01-25 13:26:54 +0800)



Hi Peter, this includes:

- Paolo's docker fix for fedora image.
- Paolo's coroutine lock API improvements.
- My userspace NVMe driver.



Fam Zheng (9):
  stubs: Add stubs for ram block API
  util: Introduce vfio helpers
  block: Add VFIO based NVMe driver
  block: Introduce buf register API
  block/nvme: Implement .bdrv_(un)register_buf
  qemu-img: Map bench buffer
  block: Move NVMe constants to a separate header
  docs: Add section for NVMe VFIO driver
  qapi: Add NVMe driver options to the schema

Paolo Bonzini (5):
  docker: change Fedora base image to fedora:27
  lockable: add QemuLockable
  coroutine-lock: convert CoQueue to use QemuLockable
  coroutine-lock: make qemu_co_enter_next thread-safe
  curl: convert to CoQueue

 MAINTAINERS|6 +
 block/Makefile.objs|1 +
 block/block-backend.c  |   10 +
 block/curl.c   |   20 +-
 block/io.c |   24 +
 block/nvme.c   | 1199 
 block/trace-events |   21 +
 docs/qemu-block-drivers.texi   |   37 +
 fsdev/qemu-fsdev-throttle.c|4 +-
 hw/block/nvme.h|  698 +--
 include/block/block.h  |   11 +-
 include/block/block_int.h  |9 +
 include/block/nvme.h   |  700 +++
 include/qemu/compiler.h|   40 ++
 include/qemu/coroutine.h   |   25 +-
 include/qemu/lockable.h|   75 ++
 include/qemu/thread.h  |5 +-
 include/qemu/typedefs.h|4 +
 include/qemu/vfio-helpers.h|   33 +
 include/sysemu/block-backend.h |3 +
 qapi/block-core.json   |   17 +-
 qemu-img.c |9 +-
 stubs/Makefile.objs|1 +
 stubs/ram-block.c  |   16 +
 tests/docker/dockerfiles/fedora.docker |2 +-
 util/Makefile.objs |1 +
 util/qemu-coroutine-lock.c |   22 +-
 util/trace-events  |   11 +
 util/vfio-helpers.c|  726 +++
 29 files changed, 2993 insertions(+), 737 deletions(-)
 create mode 100644 block/nvme.c
 create mode 100644 include/block/nvme.h
 create mode 100644 include/qemu/lockable.h
 create mode 100644 include/qemu/vfio-helpers.h
 create mode 100644 stubs/ram-block.c
 create mode 100644 util/vfio-helpers.c

-- 
2.14.3




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

2018-01-24 Thread Liang Li
On Wed, Jan 24, 2018 at 01:16:39PM -0600, Eric Blake wrote:
> On 01/24/2018 12:17 AM, Liang Li wrote:
> > We found that when doing drive mirror to a low speed shared storage,
> > if there was heavy BLK IO write workload in VM after the 'ready' event,
> > drive mirror block job can't be canceled immediately, it would keep
> > running until the heavy BLK IO workload stopped in the VM. This patch
> > fixed this issue.
> 
> I think you are breaking semantics here.  Libvirt relies on
> 'block-job-cancel' after the 'ready' event to be a clean point-in-time
> snapshot, but that is only possible if there is no out-of-order pending
> I/O at the time the action takes place.  Breaking in the middle of the
> loop, without using bdrv_drain(), risks leaving an inconsistent copy of
> data in the mirror not corresponding to any point-in-time on the source.
> 
> There's ongoing work on adding async mirroring; this may be a better
> solution to the issue you are seeing.
> 
> https://lists.gnu.org/archive/html/qemu-devel/2018-01/msg05419.html
> 
Hi Eric,

Thinks for your information, I didn't know libvirt depends on 'block-job-cancel'
for some of the block related operations.

It's seems a new interface should provided by qemu for use case that just
for aborting block job and don't care abort the mirror data integrality, and
libvirt can make use of this new interface.

Do you think this is the right direction?

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





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

2018-01-24 Thread Alexey Kardashevskiy
This makes use of a new VFIO_REGION_INFO_CAP_MSIX_MAPPABLE capability
which tells that a region with MSIX data can be mapped entirely, i.e.
the VFIO PCI driver won't prevent MSIX vectors area from being mapped.

With this change, all BARs are mapped in a single chunk and MSIX vectors
are emulated on top unless the machine requests not to by defining and
enabling a new "vfio-no-msix-emulation" property. At the moment only
sPAPR machine does so - it prohibits MSIX emulation and does not allow
enabling it as it does not define the "set" callback for the new property;
the new property also does not appear in "-machine pseries,help".

If MSIX vectors section is not aligned to the page size, the KVM memory
listener does not register it with the KVM as a memory slot and MSIX is
emulated by QEMU as before. This may create MMIO RAM memory sections with
an address or/and a size not aligned which will make vfio_dma_map() fail;
to address this, this treats such failures as non-fatal and does not print
an error. This adds a return value from vfio_dma_map() to the tracepoint
and moves the latter further down to let the user have a clue why P2P
might not work.

This requires the kernel change - "vfio-pci: Allow mapping MSIX BAR" -
for the new capability: https://www.spinics.net/lists/kvm/msg160282.html

Signed-off-by: Alexey Kardashevskiy 
---
Changes:
v4:
* silenced dma map errors if unaligned mapping is attempted - they are going
to fail anyway

v3:
* vfio_listener_region_add() won't make qemu exit if failed on MMIO MR
---
 include/hw/vfio/vfio-common.h |  1 +
 linux-headers/linux/vfio.h|  5 +
 hw/ppc/spapr.c|  7 +++
 hw/vfio/common.c  | 27 +--
 hw/vfio/pci.c | 10 ++
 hw/vfio/trace-events  |  2 +-
 6 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index f3a2ac9..927d600 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -171,6 +171,7 @@ int vfio_get_region_info(VFIODevice *vbasedev, int index,
  struct vfio_region_info **info);
 int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type,
  uint32_t subtype, struct vfio_region_info **info);
+bool vfio_is_cap_present(VFIODevice *vbasedev, uint16_t cap_type, int region);
 #endif
 extern const MemoryListener vfio_prereg_listener;
 
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 4312e96..b45182e 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -301,6 +301,11 @@ struct vfio_region_info_cap_type {
 #define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
 #define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG  (3)
 
+/*
+ * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped.
+ */
+#define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3
+
 /**
  * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9,
  * struct vfio_irq_info)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d1acfe8..5ff43ce 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2789,6 +2789,11 @@ static void spapr_set_modern_hotplug_events(Object *obj, 
bool value,
 spapr->use_hotplug_event_source = value;
 }
 
+static bool spapr_get_msix_emulation(Object *obj, Error **errp)
+{
+return true;
+}
+
 static char *spapr_get_resize_hpt(Object *obj, Error **errp)
 {
 sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
@@ -2870,6 +2875,8 @@ static void spapr_instance_init(Object *obj)
 object_property_set_description(obj, "vsmt",
 "Virtual SMT: KVM behaves as if this were"
 " the host's SMT mode", _abort);
+object_property_add_bool(obj, "vfio-no-msix-emulation",
+ spapr_get_msix_emulation, NULL, NULL);
 }
 
 static void spapr_machine_finalizefn(Object *obj)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 3d652c8..04a8280 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -513,13 +513,21 @@ static void vfio_listener_region_add(MemoryListener 
*listener,
 section->offset_within_region +
 (iova - section->offset_within_address_space);
 
-trace_vfio_listener_region_add_ram(iova, end, vaddr);
-
 llsize = int128_sub(llend, int128_make64(iova));
 
 ret = vfio_dma_map(container, iova, int128_get64(llsize),
vaddr, section->readonly);
+trace_vfio_listener_region_add_ram(iova, end, vaddr, ret);
+
 if (ret) {
+hwaddr pgmask = (1ULL << ctz64(hostwin->iova_pgsizes)) - 1;
+
+if (memory_region_is_ram_device(section->mr) &&
+((section->offset_within_region & pgmask) ||
+ (int128_getlo(section->size) & pgmask))) {
+return;
+}
+
 error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", "
  

[Qemu-devel] [PATCH qemu] vfio/common: Remove redundand copy of local variable

2018-01-24 Thread Alexey Kardashevskiy
There is already @hostwin in vfio_listener_region_add() so there is no
point in having the other one.

Fixes: 2e4109de "vfio/spapr: Create DMA window dynamically (SPAPR IOMMU v2)"
Signed-off-by: Alexey Kardashevskiy 
---
 hw/vfio/common.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b77be3a..3d652c8 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -435,7 +435,6 @@ static void vfio_listener_region_add(MemoryListener 
*listener,
 end = int128_get64(int128_sub(llend, int128_one()));
 
 if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {
-VFIOHostDMAWindow *hostwin;
 hwaddr pgsize = 0;
 
 /* For now intersections are not allowed, we may relax this later */
-- 
2.11.0




[Qemu-devel] [PATCH v1 6/6] vhost-user: add VFIO based accelerators support

2018-01-24 Thread Tiwei Bie
This patch does some small extensions to vhost-user protocol to
support VFIO based accelerators, and makes it possible to get the
similar performance of VFIO based PCI passthru while keeping the
virtio device emulation in QEMU.

Any virtio ring compatible devices potentially can be used as the
vhost data path accelerators. We can setup the accelerator based
on the informations (e.g. memory table, features, ring info, etc)
available on the vhost backend. And accelerator will be able to use
the virtio ring provided by the virtio driver in the VM directly.
So the virtio driver in the VM can exchange e.g. network packets
with the accelerator directly via the virtio ring.

But for vhost-user, the critical issue in this case is that the
data path performance is relatively low and some host threads are
needed for the data path, because some necessary mechanisms are
missing to support:

1) guest driver notifies the device directly;
2) device interrupts the guest directly;

So this patch does some small extensions to vhost-user protocol
to make both of them possible. It leverages the same mechanisms
as the VFIO based PCI passthru.

A new protocol feature bit is added to negotiate the accelerator
feature support. Two new slave message types are added to control
the notify region and queue interrupt passthru for each queue.
>From the view of vhost-user protocol design, it's very flexible.
The passthru can be enabled/disabled for each queue individually,
and it's possible to accelerate each queue by different devices.

The key difference with PCI passthru is that, in this case only
the data path of the device (e.g. DMA ring, notify region and
queue interrupt) is pass-throughed to the VM, the device control
path (e.g. PCI configuration space and MMIO regions) is still
defined and emulated by QEMU.

The benefits of keeping virtio device emulation in QEMU compared
with virtio device PCI passthru include (but not limit to):

- consistent device interface for guest OS in the VM;
- max flexibility on the hardware (i.e. the accelerators) design;
- leveraging the existing virtio live-migration framework;

The virtual IOMMU isn't supported by the accelerators for now.
Because vhost-user currently lacks of an efficient way to share
the IOMMU table in VM to vhost backend. That's why the software
implementation of virtual IOMMU support in vhost-user backend
can't support dynamic mapping well. Once this problem is solved
in vhost-user, virtual IOMMU can be supported by accelerators
too, and the IOMMU feature bit checking in this patch can be
removed.

Signed-off-by: Tiwei Bie 
---
 docs/interop/vhost-user.txt|  57 
 hw/virtio/vhost-user.c | 201 +
 include/hw/virtio/vhost-user.h |  17 
 3 files changed, 275 insertions(+)

diff --git a/docs/interop/vhost-user.txt b/docs/interop/vhost-user.txt
index 954771d0d8..15e917019a 100644
--- a/docs/interop/vhost-user.txt
+++ b/docs/interop/vhost-user.txt
@@ -116,6 +116,15 @@ Depending on the request type, payload can be:
 - 3: IOTLB invalidate
 - 4: IOTLB access fail
 
+ * Vring area description
+   ---
+   | u64 | size | offset |
+   ---
+
+   u64: a 64-bit unsigned integer
+   Size: a 64-bit size
+   Offset: a 64-bit offset
+
 In QEMU the vhost-user message is implemented with the following struct:
 
 typedef struct VhostUserMsg {
@@ -129,6 +138,7 @@ typedef struct VhostUserMsg {
 VhostUserMemory memory;
 VhostUserLog log;
 struct vhost_iotlb_msg iotlb;
+VhostUserVringArea area;
 };
 } QEMU_PACKED VhostUserMsg;
 
@@ -317,6 +327,17 @@ The fd is provided via VHOST_USER_SET_SLAVE_REQ_FD 
ancillary data.
 A slave may then send VHOST_USER_SLAVE_* messages to the master
 using this fd communication channel.
 
+VFIO based accelerators
+---
+
+The VFIO based accelerators feature is a protocol extension. It is supported
+when the protocol feature VHOST_USER_PROTOCOL_F_VFIO (bit 7) is set.
+
+The vhost-user backend will set the accelerator context via slave channel,
+and QEMU just needs to handle those messages passively. The accelerator
+context will be set for each queue independently. So the page-per-vq property
+should also be enabled.
+
 Protocol features
 -
 
@@ -327,6 +348,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_VFIO   7
 
 Master message types
 
@@ -614,6 +636,41 @@ Slave message types
   This request should be send only when VIRTIO_F_IOMMU_PLATFORM feature
   has been successfully negotiated.
 
+ * VHOST_USER_SLAVE_VRING_VFIO_GROUP_MSG
+
+  Id: 2
+  Equivalent ioctl: N/A
+  Slave payload: u64
+  Master payload: N/A
+
+  Sets the VFIO group file descriptor which is passed as 

[Qemu-devel] [PATCH v1 4/6] vfio: support getting VFIOGroup from groupfd

2018-01-24 Thread Tiwei Bie
Add an API to support getting VFIOGroup from groupfd. When
groupfd is shared by another process, the VFIOGroup may not
have its container and address space in QEMU.

Besides, add a reference counter to better support getting
VFIOGroup multiple times.

Signed-off-by: Tiwei Bie 
---
 hw/vfio/common.c  | 96 ++-
 include/hw/vfio/vfio-common.h |  2 +
 2 files changed, 97 insertions(+), 1 deletion(-)

diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 7b2924c0ef..027fa005c1 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -962,6 +962,11 @@ static int vfio_connect_container(VFIOGroup *group, 
AddressSpace *as,
 int ret, fd;
 VFIOAddressSpace *space;
 
+if (as == NULL) {
+vfio_kvm_device_add_group(group);
+return 0;
+}
+
 space = vfio_get_address_space(as);
 
 QLIST_FOREACH(container, >containers, next) {
@@ -1153,6 +1158,10 @@ static void vfio_disconnect_container(VFIOGroup *group)
 {
 VFIOContainer *container = group->container;
 
+if (container == NULL) {
+return;
+}
+
 if (ioctl(group->fd, VFIO_GROUP_UNSET_CONTAINER, >fd)) {
 error_report("vfio: error disconnecting group %d from container",
  group->groupid);
@@ -1183,6 +1192,85 @@ static void vfio_disconnect_container(VFIOGroup *group)
 }
 }
 
+static int vfio_groupfd_to_groupid(int groupfd)
+{
+char linkname[PATH_MAX];
+char pathname[PATH_MAX];
+char *filename;
+int groupid, ret;
+
+snprintf(linkname, sizeof(linkname), "/proc/self/fd/%d", groupfd);
+
+ret = readlink(linkname, pathname, sizeof(pathname));
+if (ret < 0) {
+return -1;
+}
+
+filename = g_path_get_basename(pathname);
+groupid = atoi(filename);
+g_free(filename);
+
+return groupid;
+}
+
+/*
+ * The @as param could be NULL. In this case, groupfd is shared by
+ * another process which will setup the DMA mapping for this group,
+ * and this group won't have container and address space in QEMU.
+ */
+VFIOGroup *vfio_get_group_from_fd(int groupfd, AddressSpace *as, Error **errp)
+{
+VFIOGroup *group;
+int groupid;
+
+groupid = vfio_groupfd_to_groupid(groupfd);
+if (groupid < 0) {
+return NULL;
+}
+
+QLIST_FOREACH(group, _group_list, next) {
+if (group->groupid == groupid) {
+/* Found it.  Now is it already in the right context? */
+if ((group->container == NULL && as == NULL) ||
+(group->container && group->container->space->as == as)) {
+group->refcnt++;
+return group;
+}
+error_setg(errp, "group %d used in multiple address spaces",
+   group->groupid);
+return NULL;
+}
+}
+
+group = g_malloc0(sizeof(*group));
+
+group->fd = groupfd;
+group->groupid = groupid;
+group->refcnt = 1;
+
+QLIST_INIT(>device_list);
+
+if (vfio_connect_container(group, as, errp)) {
+error_prepend(errp, "failed to setup container for group %d: ",
+  groupid);
+goto free_group_exit;
+}
+
+if (QLIST_EMPTY(_group_list)) {
+qemu_register_reset(vfio_reset_handler, NULL);
+}
+
+QLIST_INSERT_HEAD(_group_list, group, next);
+
+return group;
+
+free_group_exit:
+g_free(group);
+
+return NULL;
+}
+
+/* The @as param cannot be NULL. */
 VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp)
 {
 VFIOGroup *group;
@@ -1192,7 +1280,8 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, 
Error **errp)
 QLIST_FOREACH(group, _group_list, next) {
 if (group->groupid == groupid) {
 /* Found it.  Now is it already in the right context? */
-if (group->container->space->as == as) {
+if (group->container && group->container->space->as == as) {
+group->refcnt++;
 return group;
 } else {
 error_setg(errp, "group %d used in multiple address spaces",
@@ -1225,6 +1314,7 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, 
Error **errp)
 }
 
 group->groupid = groupid;
+group->refcnt = 1;
 QLIST_INIT(>device_list);
 
 if (vfio_connect_container(group, as, errp)) {
@@ -1256,6 +1346,10 @@ void vfio_put_group(VFIOGroup *group)
 return;
 }
 
+if (--group->refcnt > 0) {
+return;
+}
+
 vfio_kvm_device_del_group(group);
 vfio_disconnect_container(group);
 QLIST_REMOVE(group, next);
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index f3a2ac9fee..2383ded670 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -136,6 +136,7 @@ struct VFIODeviceOps {
 typedef struct VFIOGroup {
 int fd;
 int groupid;
+int refcnt;
 VFIOContainer *container;
 QLIST_HEAD(, VFIODevice) device_list;
   

[Qemu-devel] [PATCH v1 0/6] Extend vhost-user to support VFIO based accelerators

2018-01-24 Thread Tiwei Bie
This patch set does some small extensions to vhost-user protocol
to support VFIO based accelerators, and makes it possible to get
the similar performance of VFIO based PCI passthru while keeping
the virtio device emulation in QEMU.

How does accelerator accelerate vhost (data path)
=

Any virtio ring compatible devices potentially can be used as the
vhost data path accelerators. We can setup the accelerator based
on the informations (e.g. memory table, features, ring info, etc)
available on the vhost backend. And accelerator will be able to use
the virtio ring provided by the virtio driver in the VM directly.
So the virtio driver in the VM can exchange e.g. network packets
with the accelerator directly via the virtio ring. That is to say,
we will be able to use the accelerator to accelerate the vhost
data path. We call it vDPA: vhost Data Path Acceleration.

Notice: Although the accelerator can talk with the virtio driver
in the VM via the virtio ring directly. The control path events
(e.g. device start/stop) in the VM will still be trapped and handled
by QEMU, and QEMU will deliver such events to the vhost backend
via standard vhost protocol.

Below link is an example showing how to setup a such environment
via nested VM. In this case, the virtio device in the outer VM is
the accelerator. It will be used to accelerate the virtio device
in the inner VM. In reality, we could use virtio ring compatible
hardware device as the accelerators.

http://dpdk.org/ml/archives/dev/2017-December/085044.html

In above example, it doesn't require any changes to QEMU, but
it has lower performance compared with the traditional VFIO
based PCI passthru. And that's the problem this patch set wants
to solve.

The performance issue of vDPA/vhost-user and solutions
==

For vhost-user backend, the critical issue in vDPA is that the
data path performance is relatively low and some host threads are
needed for the data path, because some necessary mechanisms are
missing to support:

1) guest driver notifies the device directly;
2) device interrupts the guest directly;

So this patch set does some small extensions to the vhost-user
protocol to make both of them possible. It leverages the same
mechanisms (e.g. EPT and Posted-Interrupt on Intel platform) as
the PCI passthru.

A new protocol feature bit is added to negotiate the accelerator
feature support. Two new slave message types are added to control
the notify region and queue interrupt passthru for each queue.
>From the view of vhost-user protocol design, it's very flexible.
The passthru can be enabled/disabled for each queue individually,
and it's possible to accelerate each queue by different devices.
More design and implementation details can be found from the last
patch.

Difference between vDPA and PCI passthru


The key difference between PCI passthru and vDPA is that, in vDPA
only the data path of the device (e.g. DMA ring, notify region and
queue interrupt) is pass-throughed to the VM, the device control
path (e.g. PCI configuration space and MMIO regions) is still
defined and emulated by QEMU.

The benefits of keeping virtio device emulation in QEMU compared
with virtio device PCI passthru include (but not limit to):

- consistent device interface for guest OS in the VM;
- max flexibility on the hardware (i.e. the accelerators) design;
- leveraging the existing virtio live-migration framework;

Why extend vhost-user for vDPA
==

We have already implemented various virtual switches (e.g. OVS-DPDK)
based on vhost-user for VMs in the Cloud. They are purely software
running on CPU cores. When we have accelerators for such NFVi applications,
it's ideal if the applications could keep using the original interface
(i.e. vhost-user netdev) with QEMU, and infrastructure is able to decide
when and how to switch between CPU and accelerators within the interface.
And the switching (i.e. switch between CPU and accelerators) can be done
flexibly and quickly inside the applications.

More details about this can be found from the Cunming's discussions on
the RFC patch set.

The previous links:
RFC: http://lists.nongnu.org/archive/html/qemu-devel/2017-12/msg04844.html

RFC -> v1:
- Add some details about how vDPA works in cover letter (Alexey)
- Add some details about the OVS offload use-case in cover letter (Jason)
- Move PCI specific stuffs out of vhost-user (Jason)
- Handle the virtual IOMMU case (Jason)
- Move VFIO group management code into vfio/common.c (Alex)
- Various refinements;
(approximately sorted by comment posting time)

Tiwei Bie (6):
  vhost-user: support receiving file descriptors in slave_read
  vhost-user: introduce shared vhost-user state
  virtio: support adding sub-regions for notify region
  vfio: support getting VFIOGroup from groupfd
  vfio: remove DPRINTF() definition from vfio-common.h
  

[Qemu-devel] [PATCH v1 5/6] vfio: remove DPRINTF() definition from vfio-common.h

2018-01-24 Thread Tiwei Bie
This macro isn't used by any VFIO code. And its name is
too generic. The vfio-common.h (in include/hw/vfio) can
be included by other modules in QEMU. It can introduce
conflicts.

Signed-off-by: Tiwei Bie 
---
 include/hw/vfio/vfio-common.h | 9 -
 1 file changed, 9 deletions(-)

diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 2383ded670..3fe99636f3 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -33,15 +33,6 @@
 #define ERR_PREFIX "vfio error: %s: "
 #define WARN_PREFIX "vfio warning: %s: "
 
-/*#define DEBUG_VFIO*/
-#ifdef DEBUG_VFIO
-#define DPRINTF(fmt, ...) \
-do { fprintf(stderr, "vfio: " fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
-do { } while (0)
-#endif
-
 enum {
 VFIO_DEVICE_TYPE_PCI = 0,
 VFIO_DEVICE_TYPE_PLATFORM = 1,
-- 
2.13.3




[Qemu-devel] [PATCH v1 3/6] virtio: support adding sub-regions for notify region

2018-01-24 Thread Tiwei Bie
Provide APIs to support querying whether the page-per-vq
is enabled and adding sub-regions for notify region.

Signed-off-by: Tiwei Bie 
---
 Makefile.target|  4 
 hw/virtio/virtio-pci.c | 48 ++
 hw/virtio/virtio-pci.h |  5 +
 hw/virtio/virtio.c | 39 +
 include/hw/virtio/virtio.h |  5 +
 include/qemu/osdep.h   |  1 +
 6 files changed, 102 insertions(+)

diff --git a/Makefile.target b/Makefile.target
index f9a9da7e7c..bdde6f94d2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -39,6 +39,9 @@ STPFILES=
 config-target.h: config-target.h-timestamp
 config-target.h-timestamp: config-target.mak
 
+config-devices.h: config-devices.h-timestamp
+config-devices.h-timestamp: config-devices.mak
+
 ifdef CONFIG_TRACE_SYSTEMTAP
 stap: $(QEMU_PROG).stp-installed $(QEMU_PROG).stp $(QEMU_PROG)-simpletrace.stp
 
@@ -224,4 +227,5 @@ ifdef CONFIG_TRACE_SYSTEMTAP
 endif
 
 GENERATED_FILES += config-target.h
+GENERATED_FILES += config-devices.h
 Makefile: $(GENERATED_FILES)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index e92837c42b..a7d790c411 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1534,6 +1534,54 @@ static void 
virtio_pci_modern_io_region_unmap(VirtIOPCIProxy *proxy,
 >mr);
 }
 
+static VirtIOPCIProxy *virtio_device_to_virtio_pci_proxy(VirtIODevice *vdev)
+{
+VirtIOPCIProxy *proxy = NULL;
+
+if (vdev->device_id == VIRTIO_ID_NET) {
+VirtIONetPCI *d = container_of(vdev, VirtIONetPCI, vdev.parent_obj);
+proxy = >parent_obj;
+}
+
+return proxy;
+}
+
+bool virtio_pci_page_per_vq_enabled(VirtIODevice *vdev)
+{
+VirtIOPCIProxy *proxy = virtio_device_to_virtio_pci_proxy(vdev);
+
+if (proxy == NULL) {
+return false;
+}
+
+return !!(proxy->flags & VIRTIO_PCI_FLAG_PAGE_PER_VQ);
+}
+
+int virtio_pci_notify_region_map(VirtIODevice *vdev, int queue_idx,
+ MemoryRegion *mr)
+{
+VirtIOPCIProxy *proxy = virtio_device_to_virtio_pci_proxy(vdev);
+int offset;
+
+if (proxy == NULL || !virtio_pci_modern(proxy)) {
+return -1;
+}
+
+offset = virtio_pci_queue_mem_mult(proxy) * queue_idx;
+memory_region_add_subregion(>notify.mr, offset, mr);
+
+return 0;
+}
+
+void virtio_pci_notify_region_unmap(VirtIODevice *vdev, MemoryRegion *mr)
+{
+VirtIOPCIProxy *proxy = virtio_device_to_virtio_pci_proxy(vdev);
+
+if (proxy != NULL) {
+memory_region_del_subregion(>notify.mr, mr);
+}
+}
+
 static void virtio_pci_pre_plugged(DeviceState *d, Error **errp)
 {
 VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 12d3a90686..41dbc3d274 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -209,6 +209,11 @@ static inline void 
virtio_pci_disable_modern(VirtIOPCIProxy *proxy)
 proxy->disable_modern = true;
 }
 
+bool virtio_pci_page_per_vq_enabled(VirtIODevice *vdev);
+int virtio_pci_notify_region_map(VirtIODevice *vdev, int queue_idx,
+ MemoryRegion *mr);
+void virtio_pci_notify_region_unmap(VirtIODevice *vdev, MemoryRegion *mr);
+
 /*
  * virtio-scsi-pci: This extends VirtioPCIProxy.
  */
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index ad564b0132..325349c8b9 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -22,6 +22,7 @@
 #include "qemu/atomic.h"
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/virtio-access.h"
+#include "hw/virtio/virtio-pci.h"
 #include "sysemu/dma.h"
 
 /*
@@ -2661,6 +2662,44 @@ void virtio_device_release_ioeventfd(VirtIODevice *vdev)
 virtio_bus_release_ioeventfd(vbus);
 }
 
+bool virtio_device_parent_is_pci_device(VirtIODevice *vdev)
+{
+BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
+const char *typename = object_get_typename(OBJECT(qbus->parent));
+
+return strstr(typename, "pci") != NULL;
+}
+
+bool virtio_device_page_per_vq_enabled(VirtIODevice *vdev)
+{
+#ifdef CONFIG_VIRTIO_PCI
+if (virtio_device_parent_is_pci_device(vdev)) {
+return virtio_pci_page_per_vq_enabled(vdev);
+}
+#endif
+return false;
+}
+
+int virtio_device_notify_region_map(VirtIODevice *vdev, int queue_idx,
+MemoryRegion *mr)
+{
+#ifdef CONFIG_VIRTIO_PCI
+if (virtio_device_parent_is_pci_device(vdev)) {
+return virtio_pci_notify_region_map(vdev, queue_idx, mr);
+}
+#endif
+return -1;
+}
+
+void virtio_device_notify_region_unmap(VirtIODevice *vdev, MemoryRegion *mr)
+{
+#ifdef CONFIG_VIRTIO_PCI
+if (virtio_device_parent_is_pci_device(vdev)) {
+virtio_pci_notify_region_unmap(vdev, mr);
+}
+#endif
+}
+
 static void virtio_device_class_init(ObjectClass *klass, void *data)
 {
 /* Set the default value here. */
diff --git a/include/hw/virtio/virtio.h 

[Qemu-devel] [PATCH v1 2/6] vhost-user: introduce shared vhost-user state

2018-01-24 Thread Tiwei Bie
When multi-queue is enabled for virtio-net, each virtio
queue pair will have a vhost_dev, and the only thing they
share currently is the chardev. This patch introduces a
vhost-user state structure which will be shared by all
virtio queue pairs of the same virtio device.

Signed-off-by: Tiwei Bie 
---
 hw/scsi/vhost-user-scsi.c   |  6 +++---
 hw/virtio/vhost-user.c  |  9 +
 include/hw/virtio/vhost-user.h  | 17 +
 include/hw/virtio/virtio-scsi.h |  6 +-
 net/vhost-user.c| 30 --
 5 files changed, 46 insertions(+), 22 deletions(-)
 create mode 100644 include/hw/virtio/vhost-user.h

diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index f7561e23fa..2c46c74128 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -73,7 +73,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error 
**errp)
 Error *err = NULL;
 int ret;
 
-if (!vs->conf.chardev.chr) {
+if (!vs->conf.vhost_user.chr.chr) {
 error_setg(errp, "vhost-user-scsi: missing chardev");
 return;
 }
@@ -91,7 +91,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error 
**errp)
 vsc->dev.vq_index = 0;
 vsc->dev.backend_features = 0;
 
-ret = vhost_dev_init(>dev, (void *)>conf.chardev,
+ret = vhost_dev_init(>dev, (void *)>conf.vhost_user,
  VHOST_BACKEND_TYPE_USER, 0);
 if (ret < 0) {
 error_setg(errp, "vhost-user-scsi: vhost initialization failed: %s",
@@ -132,7 +132,7 @@ static uint64_t vhost_user_scsi_get_features(VirtIODevice 
*vdev,
 }
 
 static Property vhost_user_scsi_properties[] = {
-DEFINE_PROP_CHR("chardev", VirtIOSCSICommon, conf.chardev),
+DEFINE_PROP_CHR("chardev", VirtIOSCSICommon, conf.vhost_user.chr),
 DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0),
 DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, 1),
 DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size,
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index e7108138fd..3e308d0a62 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -12,6 +12,7 @@
 #include "qapi/error.h"
 #include "hw/virtio/vhost.h"
 #include "hw/virtio/vhost-backend.h"
+#include "hw/virtio/vhost-user.h"
 #include "hw/virtio/virtio-net.h"
 #include "chardev/char-fe.h"
 #include "sysemu/kvm.h"
@@ -123,7 +124,7 @@ static VhostUserMsg m __attribute__ ((unused));
 #define VHOST_USER_VERSION(0x1)
 
 struct vhost_user {
-CharBackend *chr;
+VhostUser *shared;
 int slave_fd;
 };
 
@@ -135,7 +136,7 @@ static bool ioeventfd_enabled(void)
 static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
 {
 struct vhost_user *u = dev->opaque;
-CharBackend *chr = u->chr;
+CharBackend *chr = >shared->chr;
 uint8_t *p = (uint8_t *) msg;
 int r, size = VHOST_USER_HDR_SIZE;
 
@@ -221,7 +222,7 @@ static int vhost_user_write(struct vhost_dev *dev, 
VhostUserMsg *msg,
 int *fds, int fd_num)
 {
 struct vhost_user *u = dev->opaque;
-CharBackend *chr = u->chr;
+CharBackend *chr = >shared->chr;
 int ret, size = VHOST_USER_HDR_SIZE + msg->size;
 
 /*
@@ -767,7 +768,7 @@ static int vhost_user_init(struct vhost_dev *dev, void 
*opaque)
 assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
 
 u = g_new0(struct vhost_user, 1);
-u->chr = opaque;
+u->shared = opaque;
 u->slave_fd = -1;
 dev->opaque = u;
 
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
new file mode 100644
index 00..4f5a1477d1
--- /dev/null
+++ b/include/hw/virtio/vhost-user.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2017-2018 Intel Corporation
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_VIRTIO_VHOST_USER_H
+#define HW_VIRTIO_VHOST_USER_H
+
+#include "chardev/char-fe.h"
+
+typedef struct VhostUser {
+CharBackend chr;
+} VhostUser;
+
+#endif
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 4c0bcdb788..885c3e84b5 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -19,6 +19,7 @@
 #define VIRTIO_SCSI_SENSE_SIZE 0
 #include "standard-headers/linux/virtio_scsi.h"
 #include "hw/virtio/virtio.h"
+#include "hw/virtio/vhost-user.h"
 #include "hw/pci/pci.h"
 #include "hw/scsi/scsi.h"
 #include "chardev/char-fe.h"
@@ -54,7 +55,10 @@ struct VirtIOSCSIConf {
 char *vhostfd;
 char *wwpn;
 #endif
-CharBackend chardev;
+union {
+VhostUser vhost_user;
+CharBackend chardev;
+};
 uint32_t boot_tpgt;
 IOThread *iothread;
 };
diff --git a/net/vhost-user.c b/net/vhost-user.c
index c23927c912..b398294074 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -12,6 +12,7 @@
 #include 

[Qemu-devel] [PATCH v1 1/6] vhost-user: support receiving file descriptors in slave_read

2018-01-24 Thread Tiwei Bie
Signed-off-by: Tiwei Bie 
---
 hw/virtio/vhost-user.c | 40 +++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 093675ed98..e7108138fd 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -614,14 +614,43 @@ static void slave_read(void *opaque)
 struct vhost_user *u = dev->opaque;
 VhostUserMsg msg = { 0, };
 int size, ret = 0;
+struct iovec iov;
+struct msghdr msgh;
+int fd = -1;
+size_t fdsize = sizeof(fd);
+char control[CMSG_SPACE(fdsize)];
+struct cmsghdr *cmsg;
+
+memset(, 0, sizeof(msgh));
+msgh.msg_iov = 
+msgh.msg_iovlen = 1;
+msgh.msg_control = control;
+msgh.msg_controllen = sizeof(control);
 
 /* Read header */
-size = read(u->slave_fd, , VHOST_USER_HDR_SIZE);
+iov.iov_base = 
+iov.iov_len = VHOST_USER_HDR_SIZE;
+
+size = recvmsg(u->slave_fd, , 0);
 if (size != VHOST_USER_HDR_SIZE) {
 error_report("Failed to read from slave.");
 goto err;
 }
 
+if (msgh.msg_flags & MSG_CTRUNC) {
+error_report("Truncated message.");
+goto err;
+}
+
+for (cmsg = CMSG_FIRSTHDR(); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(, cmsg)) {
+if (cmsg->cmsg_level == SOL_SOCKET &&
+cmsg->cmsg_type == SCM_RIGHTS) {
+memcpy(, CMSG_DATA(cmsg), fdsize);
+break;
+}
+}
+
 if (msg.size > VHOST_USER_PAYLOAD_SIZE) {
 error_report("Failed to read msg header."
 " Size %d exceeds the maximum %zu.", msg.size,
@@ -642,9 +671,15 @@ static void slave_read(void *opaque)
 break;
 default:
 error_report("Received unexpected msg type.");
+if (fd != -1) {
+close(fd);
+}
 ret = -EINVAL;
 }
 
+/* Message handlers need to make sure that fd will be consumed. */
+fd = -1;
+
 /*
  * REPLY_ACK feature handling. Other reply types has to be managed
  * directly in their request handlers.
@@ -669,6 +704,9 @@ err:
 qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
 close(u->slave_fd);
 u->slave_fd = -1;
+if (fd != -1) {
+close(fd);
+}
 return;
 }
 
-- 
2.13.3




Re: [Qemu-devel] GRUB countdown problem in VirtualBox

2018-01-24 Thread microsoft gaofei
https://www.virtualbox.org/ticket/17473 . I sent a bug ticket to Oracle , 
nobody believe what I said .


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

2018-01-24 Thread Peter Xu
On Wed, Jan 24, 2018 at 01:39:34PM +0800, Peter Xu wrote:
> This version should have addressed all comments in previous one, also
> fixed another race condition after I addressed all the comments (a new
> race condition introduced by addressing the comments...).  For some
> more details of the race condition, please see the last entry of
> change log, and please refer to patch 9 for the code change.
> 
> I removed RFC tag from this version.  Please review.  Thanks.
> 
> v7:
> - add some r-bs, and remove some.
> - remove the chardev fix since already queued by Paolo
> - use local var in qemu_chr_fe_add_watch [Stefan]
> - move doc patch to front, mention it in some patches [Eric]
> - Quite a few of English fixes [Eric]
> - fix unlock missing in handle_qmp_command [Stefan]
> - squash some patches according to the review comments
> - don't break gdbserver usage on HMP non-interactive mode by fixing up
>   the suspend/resume logic [Fam, Stefan]
> - move the qemu_chr_fe_set_handlers() call in monitor_init() into a
>   bottom half to avoid race between the call itself and
>   iothread. [Stefan]
> - spent quite a lot of time debugging another assertion failure in
>   io_watch_poll_finalize() after above change is made (ouch! I really
>   hoped we always have the latest glib): when QEMU inits chardevs in
>   chardev_init_func() it's possible that QEMU registers the chardev
>   handlers there, even before CharBackend is connected to that chardev
>   in monitor_init().  Then, when we reach monitor_init() we must make
>   sure we unregister that old one first, or there can have one orphan
>   GSource still in default gcontext (note that this can really happen
>   when we start to use QEMUBH to setup chardev frontends, which is
>   above change).

Online repository updated for v7:

  https://github.com/xzpeter/qemu/tree/monitor-oob

Thanks,

-- 
Peter Xu



Re: [Qemu-devel] [PATCH v3 3/3] hostmem-file: add 'sync' option

2018-01-24 Thread Haozhong Zhang
On 01/24/18 22:23 +0200, Michael S. Tsirkin wrote:
> On Wed, Jan 17, 2018 at 04:13:25PM +0800, Haozhong Zhang wrote:
> > This option controls whether QEMU mmap(2) the memory backend file with
> > MAP_SYNC flag, which can fully guarantee the guest write persistence
> > to the backend, if MAP_SYNC flag is supported by the host kernel
> > (Linux kernel 4.15 and later) and the backend is a file supporting
> > DAX (e.g., file on ext4/xfs file system mounted with '-o dax').
> > 
> > It can take one of following values:
> >  - on:  try to pass MAP_SYNC to mmap(2); if MAP_SYNC is not supported or
> > 'share=off', QEMU will abort
> >  - off: never pass MAP_SYNC to mmap(2)
> >  - auto (default): if MAP_SYNC is supported and 'share=on', work as if
> > 'sync=on'; otherwise, work as if 'sync=off'
> > 
> > Signed-off-by: Haozhong Zhang 
> > Suggested-by: Eduardo Habkost 

[..]
> >  
> >  @table @option
> >  
> > -@item -object 
> > memory-backend-file,id=@var{id},size=@var{size},mem-path=@var{dir},share=@var{on|off},discard-data=@var{on|off},merge=@var{on|off},dump=@var{on|off},prealloc=@var{on|off},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave},align=@var{align}
> > +@item -object 
> > memory-backend-file,id=@var{id},size=@var{size},mem-path=@var{dir},share=@var{on|off},discard-data=@var{on|off},merge=@var{on|off},dump=@var{on|off},prealloc=@var{on|off},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave},align=@var{align},sync=@var{on|off|auto}
> >  
> >  Creates a memory file backend object, which can be used to back
> >  the guest RAM with huge pages.
> > @@ -4034,6 +4034,25 @@ requires an alignment different than the default one 
> > used by QEMU, eg
> >  the device DAX /dev/dax0.0 requires 2M alignment rather than 4K. In
> >  such cases, users can specify the required alignment via this option.
> >  
> > +The @option{sync} option specifies whether QEMU mmap(2) @option{mem-path}
> > +with MAP_SYNC flag, which can fully guarantee the guest write
> > +persistence to @option{mem-path}.
> 
> I would add ... even in case of a host power loss.
> Here and wherever you say "fully".

Without MAP_SYNC, QEMU can only guarantee the guest data is written to
the host NVDIMM after, for example, guest clwb+sfence. However, if
some host file system meta data of the mapped file have not been
written back to the host NVDIMM when a host power failure happens, the
mapped file may be broken though all its data may be still there.

Anyway, I'll remove the confusing word "fully" and add your suggestion.

Thanks,
Haozhong

> 
> > MAP_SYNC requires supports from both
> > +the host kernel (since Linux kernel 4.15) and @option{mem-path} (only
> > +files supporting DAX). It can take one of following values:
> > +
> > +@table @option
> > +@item @var{on}
> > +try to pass MAP_SYNC to mmap(2); if MAP_SYNC is not supported or
> > +@option{share}=@var{off}, QEMU will abort
> > +
> > +@item @var{off}
> > +never pass MAP_SYNC to mmap(2)
> > +
> > +@item @var{auto} (default)
> > +if MAP_SYNC is supported and @option{share}=@var{on}, work as if
> > +@option{sync}=@var{on}; otherwise, work as if @option{sync}=@var{off}
> > +@end table
> > +
> >  @item -object 
> > memory-backend-ram,id=@var{id},merge=@var{on|off},dump=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave}
> >  
> >  Creates a memory backend object, which can be used to back the guest RAM.
> > -- 
> > 2.14.1



[Qemu-devel] [PATCH v3 29/45] target/hppa: Add system registers to gdbstub

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/gdbstub.c | 156 ++
 1 file changed, 156 insertions(+)

diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c
index fc27aec073..e2e9c4d77f 100644
--- a/target/hppa/gdbstub.c
+++ b/target/hppa/gdbstub.c
@@ -41,15 +41,93 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 case 33:
 val = env->iaoq_f;
 break;
+case 34:
+val = env->iasq_f >> 32;
+break;
 case 35:
 val = env->iaoq_b;
 break;
+case 36:
+val = env->iasq_b >> 32;
+break;
+case 37:
+val = env->cr[CR_EIEM];
+break;
+case 38:
+val = env->cr[CR_IIR];
+break;
+case 39:
+val = env->cr[CR_ISR];
+break;
+case 40:
+val = env->cr[CR_IOR];
+break;
+case 41:
+val = env->cr[CR_IPSW];
+break;
+case 43:
+val = env->sr[4] >> 32;
+break;
+case 44:
+val = env->sr[0] >> 32;
+break;
+case 45:
+val = env->sr[1] >> 32;
+break;
+case 46:
+val = env->sr[2] >> 32;
+break;
+case 47:
+val = env->sr[3] >> 32;
+break;
+case 48:
+val = env->sr[5] >> 32;
+break;
+case 49:
+val = env->sr[6] >> 32;
+break;
+case 50:
+val = env->sr[7] >> 32;
+break;
+case 51:
+val = env->cr[CR_RC];
+break;
+case 52:
+val = env->cr[8];
+break;
+case 53:
+val = env->cr[9];
+break;
+case 54:
+val = env->cr[CR_SCRCCR];
+break;
+case 55:
+val = env->cr[12];
+break;
+case 56:
+val = env->cr[13];
+break;
+case 57:
+val = env->cr[24];
+break;
+case 58:
+val = env->cr[25];
+break;
 case 59:
 val = env->cr[26];
 break;
 case 60:
 val = env->cr[27];
 break;
+case 61:
+val = env->cr[28];
+break;
+case 62:
+val = env->cr[29];
+break;
+case 63:
+val = env->cr[30];
+break;
 case 64 ... 127:
 val = extract64(env->fr[(n - 64) / 2], (n & 1 ? 0 : 32), 32);
 break;
@@ -94,15 +172,93 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 case 33:
 env->iaoq_f = val;
 break;
+case 34:
+env->iasq_f = (uint64_t)val << 32;
+break;
 case 35:
 env->iaoq_b = val;
 break;
+case 36:
+env->iasq_b = (uint64_t)val << 32;
+break;
+case 37:
+env->cr[CR_EIEM] = val;
+break;
+case 38:
+env->cr[CR_IIR] = val;
+break;
+case 39:
+env->cr[CR_ISR] = val;
+break;
+case 40:
+env->cr[CR_IOR] = val;
+break;
+case 41:
+env->cr[CR_IPSW] = val;
+break;
+case 43:
+env->sr[4] = (uint64_t)val << 32;
+break;
+case 44:
+env->sr[0] = (uint64_t)val << 32;
+break;
+case 45:
+env->sr[1] = (uint64_t)val << 32;
+break;
+case 46:
+env->sr[2] = (uint64_t)val << 32;
+break;
+case 47:
+env->sr[3] = (uint64_t)val << 32;
+break;
+case 48:
+env->sr[5] = (uint64_t)val << 32;
+break;
+case 49:
+env->sr[6] = (uint64_t)val << 32;
+break;
+case 50:
+env->sr[7] = (uint64_t)val << 32;
+break;
+case 51:
+env->cr[CR_RC] = val;
+break;
+case 52:
+env->cr[8] = val;
+break;
+case 53:
+env->cr[9] = val;
+break;
+case 54:
+env->cr[CR_SCRCCR] = val;
+break;
+case 55:
+env->cr[12] = val;
+break;
+case 56:
+env->cr[13] = val;
+break;
+case 57:
+env->cr[24] = val;
+break;
+case 58:
+env->cr[25] = val;
+break;
 case 59:
 env->cr[26] = val;
 break;
 case 60:
 env->cr[27] = val;
 break;
+case 61:
+env->cr[28] = val;
+break;
+case 62:
+env->cr[29] = val;
+break;
+case 63:
+env->cr[30] = val;
+break;
 case 64:
 env->fr[0] = deposit64(env->fr[0], 32, 32, val);
 cpu_hppa_loaded_fr0(env);
-- 
2.14.3




Re: [Qemu-devel] [PATCH v3 00/22] re-factor softfloat and add fp16 functions

2018-01-24 Thread Howard Spoelstra
On Thu, Jan 25, 2018 at 1:09 AM, Richard Henderson
 wrote:
> On 01/24/2018 01:49 PM, Howard Spoelstra wrote:
>> Hi,
>>
>> I built qemu-system-ppc for OSX and Windows from
>> https://github.com/stsquad/qemu/tree/softfloat-refactor-and-fp16-v3
>> and noticed a considerable drop in floating point performance on both
>> hosts.
>> Running Mac OS 9.2 in OSX, using MacBench 3.0, the score for the
>> floating point performance dropped from ~60 to ~42.
>>
>> Recent tcg optimisations had improved processor and floating point
>> performance considerably, but that gain seems to be more than lost for
>> the floating point performance.
>>
>> Any idea what is causing this?
>
> Is this a 64-bit or a 32-bit build?
>
> We made a conscious choice to share code and use all 64-bit operations, under
> the assumption that x86_64 is the most common host.
>
> Otherwise we have not really done extensive benchmarking.
>
>
> r~

Hi,

Both OSX and Windows builds are 64-bit.

Best,
Howard



Re: [Qemu-devel] [PATCH v3 1/3] util/mmap-alloc: support MAP_SYNC in qemu_ram_mmap()

2018-01-24 Thread Haozhong Zhang
On 01/24/18 22:20 +0200, Michael S. Tsirkin wrote:
> > index 50385e3f81..dd5876471f 100644
> > --- a/include/qemu/mmap-alloc.h
> > +++ b/include/qemu/mmap-alloc.h
> > @@ -7,7 +7,8 @@ size_t qemu_fd_getpagesize(int fd);
> >  
> >  size_t qemu_mempath_getpagesize(const char *mem_path);
> >  
> > -void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared);
> > +void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared,
> > +OnOffAuto sync);
> >  
> >  void qemu_ram_munmap(void *ptr, size_t size);
> >  
> 
> And Marcel plans to add a remappable flag ...  Is it time we
> switched to a flags field?

Yes. Some patches on my hands are going to add another field to this
function, so let's switch to flags.

> 
> > diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> > index adb3758275..0ff10cb529 100644
> > --- a/include/qemu/osdep.h
> > +++ b/include/qemu/osdep.h
> > @@ -372,6 +372,24 @@ void qemu_anon_ram_free(void *ptr, size_t size);
> >  #  define QEMU_VMALLOC_ALIGN getpagesize()
> >  #endif
> >  
> > +/*
> > + * MAP_SHARED_VALIDATE and MAP_SYNC were introduced in Linux kernel
> > + * 4.15, so they may not be defined when compiling on older kernels.
> > + */
> > +#ifdef CONFIG_LINUX
> > +#ifndef MAP_SHARED_VALIDATE
> > +#define MAP_SHARED_VALIDATE   0x3
> > +#endif
> > +#ifndef MAP_SYNC
> > +#define MAP_SYNC  0x8
> > +#endif
> > +#define QEMU_HAS_MAP_SYNC true
> > +#else  /* !CONFIG_LINUX */
> > +#define MAP_SHARED_VALIDATE   0x0
> > +#define MAP_SYNC  0x0
> > +#define QEMU_HAS_MAP_SYNC false
> > +#endif /* CONFIG_LINUX */
> > +
> >  #ifdef CONFIG_POSIX
> >  struct qemu_signalfd_siginfo {
> >  uint32_t ssi_signo;   /* Signal number */
> 
> Please just import this into standard-headers from Linux.
>

Sure, I'll move it to a new file include/standard-headers/linux/mman.h.

Thanks,
Haozhong



Re: [Qemu-devel] [PATCH v3 00/45] hppa-softmmu

2018-01-24 Thread no-reply
Hi,

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

Type: series
Message-id: 20180124232625.30105-1-richard.hender...@linaro.org
Subject: [Qemu-devel] [PATCH v3 00/45] hppa-softmmu

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

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

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

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

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

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
   82de978a8b..834a336eb9  master -> master
 t [tag update]
patchew/20180124131315.30567-1-alex.ben...@linaro.org -> 
patchew/20180124131315.30567-1-alex.ben...@linaro.org
 * [new tag]   
patchew/20180124232625.30105-1-richard.hender...@linaro.org -> 
patchew/20180124232625.30105-1-richard.hender...@linaro.org
Switched to a new branch 'test'
b99944c81d target/hppa: Implement PROBE for system mode
3af572c526 target/hppa: Fix 32-bit operand masks for 0E FCVT
07e8e53239 hw/hppa: Add MAINTAINERS entry
5ce6196a7b pc-bios: Add hppa-firmware.img and git submodule
a5f6d71bc3 hw/hppa: Implement DINO system board
0a021c31ca target/hppa: Enable MTTCG
78fc84282d target/hppa: Implement STWA
fc7ac055da target/hppa: Implement a pause instruction
59e0b0dfc5 target/hppa: Implement LDSID for system mode
427cda161a target/hppa: Fix comment
ac33014238 target/hppa: Increase number of temp regs
749bf4607e target/hppa: Use MMU_DEBUG_LOAD when reloading for CR[IIR]
ad66abd76f qom: Add MMU_DEBUG_LOAD
ab96c7dc94 target/hppa: Only use EXCP_DTLB_MISS
d701de4fc9 target/hppa: Implement B,GATE insn
817022de56 target/hppa: Add migration for the cpu
4f0d3489a1 target/hppa: Add system registers to gdbstub
5a48bce3ec target/hppa: Optimize for flat addressing space
6e79d150e6 target/hppa: Implement halt and reset instructions
5d244025ad target/hppa: Implement SYNCDMA insn
1287570da1 target/hppa: Implement LCI
d21a81fbb2 target/hppa: Implement LPA
6b044368cb target/hppa: Implement LDWA
9380959272 target/hppa: Implement P*TLB and P*TLBE insns
d32053d405 target/hppa: Implement I*TLBA and I*TLBP insns
9d25a6de7c target/hppa: Log unimplemented instructions
1affc34952 target/hppa: Implement the interval timer
db25bc4f01 target/hppa: Implement external interrupts
21cbd1150e target/hppa: Implement tlb_fill
0586d94c71 target/hppa: Implement IASQ
d57e1c4062 target/hppa: Avoid privilege level decrease during branches
a9dc542fcc target/hppa: Use space registers in data operations
8cf161b867 target/hppa: Implement unaligned access trap
92a252ebe6 target/hppa: Fill in hppa_cpu_do_interrupt/hppa_cpu_exec_interrupt
40ea019434 target/hppa: Implement rfi
0dbf97fb19 target/hppa: Adjust insn mask for mfctl, w
40b31dd70b target/hppa: Add control registers
53a773f7c2 target/hppa: Add space registers
c20c384026 target/hppa: Implement the system mask instructions
56cdabcccb target/hppa: Implement mmu_idx from IA privilege level
a7c6af1c7e target/hppa: Split address size from register size
0ef947e1f7 target/hppa: Define hardware exception types
1d2ec5df74 target/hppa: Disable gateway page emulation for system mode
4b896e5406 target/hppa: Define the rest of the PSW
bba2453869 target/hppa: Skeleton support for hppa-softmmu

=== OUTPUT BEGIN ===
Checking PATCH 1/45: target/hppa: Skeleton support for hppa-softmmu...
Checking PATCH 2/45: target/hppa: Define the rest of the PSW...
Checking PATCH 3/45: target/hppa: Disable gateway page emulation for system 
mode...
Checking PATCH 4/45: target/hppa: Define hardware exception types...
Checking PATCH 5/45: target/hppa: Split address size from register size...
Checking PATCH 6/45: target/hppa: Implement mmu_idx from IA privilege level...
Checking PATCH 7/45: target/hppa: Implement the system mask instructions...
Checking PATCH 8/45: target/hppa: Add space registers...
Checking PATCH 9/45: target/hppa: Add control registers...
Checking PATCH 10/45: target/hppa: Adjust insn mask for mfctl, w...
Checking PATCH 11/45: target/hppa: Implement rfi...
Checking PATCH 12/45: target/hppa: Fill in 
hppa_cpu_do_interrupt/hppa_cpu_exec_interrupt...
Checking PATCH 13/45: target/hppa: Implement unaligned access trap...
Checking PATCH 14/45: target/hppa: Use space registers in data operations...
Checking PATCH 15/45: target/hppa: Avoid privilege level decrease during 
branches...
Checking PATCH 16/45: target/hppa: Implement IASQ...
Checking PATCH 17/45: target/hppa: Implement tlb_fill...
ERROR: spaces prohibited around that ':' (ctx:WxW)
#25: FILE: target/hppa/cpu.h:172:
+unsigned u : 1;
^

ERROR: spaces prohibited around that ':' (ctx:WxW)
#26: FILE: target/hppa/cpu.h:173:
+

Re: [Qemu-devel] [PATCH v3 00/22] re-factor softfloat and add fp16 functions

2018-01-24 Thread Richard Henderson
On 01/24/2018 01:49 PM, Howard Spoelstra wrote:
> Hi,
> 
> I built qemu-system-ppc for OSX and Windows from
> https://github.com/stsquad/qemu/tree/softfloat-refactor-and-fp16-v3
> and noticed a considerable drop in floating point performance on both
> hosts.
> Running Mac OS 9.2 in OSX, using MacBench 3.0, the score for the
> floating point performance dropped from ~60 to ~42.
> 
> Recent tcg optimisations had improved processor and floating point
> performance considerably, but that gain seems to be more than lost for
> the floating point performance.
> 
> Any idea what is causing this?

Is this a 64-bit or a 32-bit build?

We made a conscious choice to share code and use all 64-bit operations, under
the assumption that x86_64 is the most common host.

Otherwise we have not really done extensive benchmarking.


r~



[Qemu-devel] [PATCH v3 44/45] target/hppa: Fix 32-bit operand masks for 0E FCVT

2018-01-24 Thread Richard Henderson
We masked the wrong bits, which prevented some of the
32-bit R registers.  E.g. "fcnvxf,sgl,sgl fr22R,fr6R".

Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index b9b097acc9..c62ee72615 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -4381,34 +4381,34 @@ static const DisasInsn table_float_0e[] = {
 /* floating point class one */
 /* float/float */
 { 0x38000a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_s },
-{ 0x38002200, 0xfc1fffc0, FOP_DEW = gen_helper_fcnv_s_d },
+{ 0x38002200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_d },
 /* int/float */
-{ 0x38008200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_w_s },
+{ 0x38008200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_w_s },
 { 0x38008a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_dw_s },
 { 0x3800a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_w_d },
 { 0x3800aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
 /* float/int */
-{ 0x38010200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_w },
+{ 0x38010200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_s_w },
 { 0x38010a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_w },
 { 0x38012200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_dw },
 { 0x38012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
 /* float/int truncate */
-{ 0x38018200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_w },
+{ 0x38018200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_t_s_w },
 { 0x38018a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_w },
 { 0x3801a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_dw },
 { 0x3801aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
 /* uint/float */
-{ 0x38028200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_uw_s },
+{ 0x38028200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_uw_s },
 { 0x38028a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_udw_s },
 { 0x3802a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_uw_d },
 { 0x3802aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
 /* float/uint */
-{ 0x38030200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_uw },
+{ 0x38030200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_s_uw },
 { 0x38030a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_uw },
 { 0x38032200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_udw },
 { 0x38032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
 /* float/uint truncate */
-{ 0x38038200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_uw },
+{ 0x38038200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_t_s_uw },
 { 0x38038a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_uw },
 { 0x3803a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_udw },
 { 0x3803aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
-- 
2.14.3




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

2018-01-24 Thread Richard Henderson
On 01/24/2018 10:58 AM, Jim Wilson wrote:
> I think that qemu is correct here, and that you want to use float32_chs.

Ok.

> Although, looking at this again, I see another statement in a
> different place that says:
> 
> Except when otherwise stated, if the result of a floating-point operation is
> NaN, it is the canonical NaN. The canonical NaN has a positive sign and all
> significand bits clear except the MSB, a.k.a. the quiet bit. For
> single-precision floating-point, this corresponds to the pattern
> 0x7fc0.
Yes, I had read this before as well.  I had assumed that your patch constituted
an intended change to this text.

> This could take a little time to sort out.
Ok.  I don't see this as a blocking issue for merging.


r~



[Qemu-devel] [PATCH v3 38/45] target/hppa: Implement a pause instruction

2018-01-24 Thread Richard Henderson
This is an extension to the base ISA, but we can use this in
the kernel idle loop to reduce the host cpu time consumed.

Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 36 
 1 file changed, 36 insertions(+)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index cf67ca026e..d84090d479 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2826,9 +2826,45 @@ static DisasJumpType trans_ds(DisasContext *ctx, 
uint32_t insn,
 return nullify_end(ctx, DISAS_NEXT);
 }
 
+#ifndef CONFIG_USER_ONLY
+/* These are QEMU extensions and are nops in the real architecture:
+ *
+ * or %r10,%r10,%r10 -- idle loop; wait for interrupt
+ * or %r31,%r31,%r31 -- death loop; offline cpu
+ *  currently implemented as idle.
+ */
+static DisasJumpType trans_pause(DisasContext *ctx, uint32_t insn,
+ const DisasInsn *di)
+{
+TCGv_i32 tmp;
+
+/* No need to check for supervisor, as userland can only pause
+   until the next timer interrupt.  */
+nullify_over(ctx);
+
+/* Advance the instruction queue.  */
+copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
+copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
+nullify_set(ctx, 0);
+
+/* Tell the qemu main loop to halt until this cpu has work.  */
+tmp = tcg_const_i32(1);
+tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) +
+ offsetof(CPUState, halted));
+tcg_temp_free_i32(tmp);
+gen_excp_1(EXCP_HALTED);
+
+return nullify_end(ctx, DISAS_NORETURN);
+}
+#endif
+
 static const DisasInsn table_arith_log[] = {
 { 0x08000240u, 0xfc00u, trans_nop },  /* or x,y,0 */
 { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */
+#ifndef CONFIG_USER_ONLY
+{ 0x094a024au, 0xu, trans_pause }, /* or r10,r10,r10 */
+{ 0x0bff025fu, 0xu, trans_pause }, /* or r31,r31,r31 */
+#endif
 { 0x0800u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_reg },
 { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_reg },
 { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_reg },
-- 
2.14.3




[Qemu-devel] [PATCH v3 36/45] target/hppa: Fix comment

2018-01-24 Thread Richard Henderson
From: Helge Deller 

Signed-off-by: Helge Deller 
Message-Id: <20171212212319.ga31...@ls3530.fritz.box>
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index a93e86c9e3..3327c085ff 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3193,7 +3193,7 @@ static DisasJumpType trans_store_w(DisasContext *ctx, 
uint32_t insn)
 /* FSTW without modification.  */
 return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0);
 case 2:
-/* LDW with modification.  */
+/* STW with modification.  */
 return do_store(ctx, rt, rb, i, sp, (i < 0 ? 1 : -1), MO_TEUL);
 default:
 return gen_illegal(ctx);
-- 
2.14.3




[Qemu-devel] [PATCH v3 43/45] hw/hppa: Add MAINTAINERS entry

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 753e7996ce..bee6b2bec7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -133,6 +133,7 @@ HPPA (PA-RISC)
 M: Richard Henderson 
 S: Maintained
 F: target/hppa/
+F: hw/hppa/
 F: disas/hppa.c
 
 LM32
-- 
2.14.3




[Qemu-devel] [PATCH v3 37/45] target/hppa: Implement LDSID for system mode

2018-01-24 Thread Richard Henderson
From: Helge Deller 

Signed-off-by: Helge Deller 
Message-Id: <20180102203145.ga17...@ls3530.fritz.box>
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 3327c085ff..cf67ca026e 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2211,8 +2211,20 @@ static DisasJumpType trans_ldsid(DisasContext *ctx, 
uint32_t insn,
 unsigned rt = extract32(insn, 0, 5);
 TCGv_reg dest = dest_gpr(ctx, rt);
 
-/* Since we don't implement space registers, this returns zero.  */
+#ifdef CONFIG_USER_ONLY
+/* We don't implement space registers in user mode. */
 tcg_gen_movi_reg(dest, 0);
+#else
+unsigned rb = extract32(insn, 21, 5);
+unsigned sp = extract32(insn, 14, 2);
+TCGv_i64 t0 = tcg_temp_new_i64();
+
+tcg_gen_mov_i64(t0, space_select(ctx, sp, load_gpr(ctx, rb)));
+tcg_gen_shri_i64(t0, t0, 32);
+tcg_gen_trunc_i64_reg(dest, t0);
+
+tcg_temp_free_i64(t0);
+#endif
 save_gpr(ctx, rt, dest);
 
 cond_free(>null_cond);
-- 
2.14.3




[Qemu-devel] [PATCH v3 33/45] qom: Add MMU_DEBUG_LOAD

2018-01-24 Thread Richard Henderson
This lets us tell bottom levels of virtual memory translation
routines that the access is from within QEMU itself and bypass
certain tests.

Cc: Andreas Färber 
Signed-off-by: Richard Henderson 
---
 include/qom/cpu.h  | 3 ++-
 target/sh4/op_helper.c | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 93bd546879..6367acca97 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -64,7 +64,8 @@ typedef uint64_t vaddr;
 typedef enum MMUAccessType {
 MMU_DATA_LOAD  = 0,
 MMU_DATA_STORE = 1,
-MMU_INST_FETCH = 2
+MMU_INST_FETCH = 2,
+MMU_DEBUG_LOAD = 3
 } MMUAccessType;
 
 typedef struct CPUWatchpoint CPUWatchpoint;
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index d798f239cf..8fa7cb6b42 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -36,6 +36,8 @@ void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 case MMU_DATA_STORE:
 cs->exception_index = 0x100;
 break;
+default:
+g_assert_not_reached();
 }
 cpu_loop_exit_restore(cs, retaddr);
 }
-- 
2.14.3




[Qemu-devel] [PATCH v3 39/45] target/hppa: Implement STWA

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 19 ++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index d84090d479..b9b097acc9 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3108,6 +3108,22 @@ static DisasJumpType trans_ldwa_idx_x(DisasContext *ctx, 
uint32_t insn,
 ctx->mmu_idx = hold_mmu_idx;
 return ret;
 }
+
+static DisasJumpType trans_stwa_idx_i(DisasContext *ctx, uint32_t insn,
+  const DisasInsn *di)
+{
+int hold_mmu_idx = ctx->mmu_idx;
+DisasJumpType ret;
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+
+/* ??? needs fixing for hppa64 -- ldda does not follow the same
+   format wrt the sub-opcode in bits 6:9.  */
+ctx->mmu_idx = MMU_PHYS_IDX;
+ret = trans_st_idx_i(ctx, insn, di);
+ctx->mmu_idx = hold_mmu_idx;
+return ret;
+}
 #endif
 
 static const DisasInsn table_index_mem[] = {
@@ -3117,8 +3133,9 @@ static const DisasInsn table_index_mem[] = {
 { 0x0c0001c0u, 0xfc0003c0, trans_ldcw },
 { 0x0c001300u, 0xfc0013c0, trans_stby },
 #ifndef CONFIG_USER_ONLY
-{ 0x0c001180u, 0xfc00d3c0, trans_ldwa_idx_i }, /* LDWA, im */
 { 0x0c000180u, 0xfc00d3c0, trans_ldwa_idx_x }, /* LDWA, rx */
+{ 0x0c001180u, 0xfc00d3c0, trans_ldwa_idx_i }, /* LDWA, im */
+{ 0x0c001380u, 0xfc00d3c0, trans_stwa_idx_i }, /* STWA, im */
 #endif
 };
 
-- 
2.14.3




[Qemu-devel] [PATCH v3 28/45] target/hppa: Optimize for flat addressing space

2018-01-24 Thread Richard Henderson
Linux sets sr4-sr7 all to the same value, which means that we
need not do any runtime computation to find out what space to
use in forming the GVA.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h   | 11 ++-
 target/hppa/translate.c | 29 -
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index a6e4091b6a..57e0bd6f0e 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -282,7 +282,11 @@ static inline target_ulong hppa_form_gva(CPUHPPAState 
*env, uint64_t spc,
 return hppa_form_gva_psw(env->psw, spc, off);
 }
 
-/* Since PSW_CB will never need to be in tb->flags, reuse them.  */
+/* Since PSW_{I,CB} will never need to be in tb->flags, reuse them.
+ * TB_FLAG_SR_SAME indicates that SR4 through SR7 all contain the
+ * same value.
+ */
+#define TB_FLAG_SR_SAME PSW_I
 #define TB_FLAG_PRIV_SHIFT  8
 
 static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc,
@@ -318,6 +322,11 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, 
target_ulong *pc,
 *cs_base |= (uint32_t)diff;
 }
 }
+if ((env->sr[4] == env->sr[5])
+& (env->sr[4] == env->sr[6])
+& (env->sr[4] == env->sr[7])) {
+flags |= TB_FLAG_SR_SAME;
+}
 #endif
 
 *pflags = flags;
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 8c1ae4db78..24d357889e 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -284,6 +284,7 @@ typedef struct DisasContext {
 TCGLabel *null_lab;
 
 uint32_t insn;
+uint32_t tb_flags;
 int mmu_idx;
 int privilege;
 bool psw_n_nonzero;
@@ -323,6 +324,7 @@ typedef struct DisasInsn {
 /* global register indexes */
 static TCGv_reg cpu_gr[32];
 static TCGv_i64 cpu_sr[4];
+static TCGv_i64 cpu_srH;
 static TCGv_reg cpu_iaoq_f;
 static TCGv_reg cpu_iaoq_b;
 static TCGv_i64 cpu_iasq_f;
@@ -360,8 +362,8 @@ void hppa_translate_init(void)
 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
 };
 /* SR[4-7] are not global registers so that we can index them.  */
-static const char sr_names[4][4] = {
-"sr0", "sr1", "sr2", "sr3"
+static const char sr_names[5][4] = {
+"sr0", "sr1", "sr2", "sr3", "srH"
 };
 
 int i;
@@ -377,6 +379,9 @@ void hppa_translate_init(void)
offsetof(CPUHPPAState, sr[i]),
sr_names[i]);
 }
+cpu_srH = tcg_global_mem_new_i64(cpu_env,
+ offsetof(CPUHPPAState, sr[4]),
+ sr_names[4]);
 
 for (i = 0; i < ARRAY_SIZE(vars); ++i) {
 const GlobalVar *v = [i];
@@ -604,6 +609,8 @@ static void load_spr(DisasContext *ctx, TCGv_i64 dest, 
unsigned reg)
 #else
 if (reg < 4) {
 tcg_gen_mov_i64(dest, cpu_sr[reg]);
+} else if (ctx->tb_flags & TB_FLAG_SR_SAME) {
+tcg_gen_mov_i64(dest, cpu_srH);
 } else {
 tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUHPPAState, sr[reg]));
 }
@@ -1362,6 +1369,9 @@ static TCGv_i64 space_select(DisasContext *ctx, int sp, 
TCGv_reg base)
 load_spr(ctx, spc, sp);
 return spc;
 }
+if (ctx->tb_flags & TB_FLAG_SR_SAME) {
+return cpu_srH;
+}
 
 ptr = tcg_temp_new_ptr();
 tmp = tcg_temp_new();
@@ -1405,7 +1415,7 @@ static void form_gva(DisasContext *ctx, TCGv_tl *pgva, 
TCGv_reg *pofs,
 #else
 TCGv_tl addr = get_temp_tl(ctx);
 tcg_gen_extu_reg_tl(addr, modify <= 0 ? ofs : base);
-if (ctx->base.tb->flags & PSW_W) {
+if (ctx->tb_flags & PSW_W) {
 tcg_gen_andi_tl(addr, addr, 0x3fffull);
 }
 if (!is_phys) {
@@ -2112,6 +2122,7 @@ static DisasJumpType trans_mtsp(DisasContext *ctx, 
uint32_t insn,
 
 if (rs >= 4) {
 tcg_gen_st_i64(t64, cpu_env, offsetof(CPUHPPAState, sr[rs]));
+ctx->tb_flags &= ~TB_FLAG_SR_SAME;
 } else {
 tcg_gen_mov_i64(cpu_sr[rs], t64);
 }
@@ -2407,7 +2418,7 @@ static DisasJumpType trans_ixtlbx(DisasContext *ctx, 
uint32_t insn,
 
 /* Exit TB for ITLB change if mmu is enabled.  This *should* not be
the case, since the OS TLB fill handler runs with mmu disabled.  */
-return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C)
+return nullify_end(ctx, !is_data && (ctx->tb_flags & PSW_C)
? DISAS_IAQ_N_STALE : DISAS_NEXT);
 }
 
@@ -2443,7 +2454,7 @@ static DisasJumpType trans_pxtlbx(DisasContext *ctx, 
uint32_t insn,
 }
 
 /* Exit TB for TLB change if mmu is enabled.  */
-return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C)
+return nullify_end(ctx, !is_data && (ctx->tb_flags & PSW_C)
? DISAS_IAQ_N_STALE : DISAS_NEXT);
 }
 
@@ -4556,6 +4567,7 @@ static int hppa_tr_init_disas_context(DisasContextBase 
*dcbase,
 int bound;
 
 ctx->cs = 

[Qemu-devel] [PATCH v3 34/45] target/hppa: Use MMU_DEBUG_LOAD when reloading for CR[IIR]

2018-01-24 Thread Richard Henderson
Bypass any tlb protection checks, as this is not a "real"
access to memory per the architecture.

Signed-off-by: Richard Henderson 
---
 target/hppa/int_helper.c |  2 +-
 target/hppa/mem_helper.c | 19 ++-
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index d54d830196..1a9bbe268a 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -156,7 +156,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
 
 vaddr = hppa_form_gva_psw(old_psw, iasq_f, vaddr);
 t = hppa_get_physical_address(env, vaddr, 0,
-  MMU_INST_FETCH,
+  MMU_DEBUG_LOAD,
   , );
 if (t >= 0) {
 /* We can't re-load the instruction.  */
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 81bcbe45db..4decfca407 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -131,12 +131,21 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr 
addr, int mmu_idx,
 /* ??? Check PSW_P and ent->access_prot.  This can remove PROT_WRITE.  */
 
 /* Map MMUAccessType to QEMU protection.  */
-if (ifetch) {
-a_prot = PROT_EXEC;
-} else if (type == MMU_DATA_STORE) {
-a_prot = PROT_WRITE;
-} else {
+switch (type) {
+case MMU_DATA_LOAD:
 a_prot = PROT_READ;
+break;
+case MMU_DATA_STORE:
+a_prot = PROT_WRITE;
+break;
+case MMU_INST_FETCH:
+a_prot = PROT_EXEC;
+break;
+case MMU_DEBUG_LOAD:
+ret = -1;
+goto egress;
+default:
+g_assert_not_reached();
 }
 
 if (unlikely(!(prot & a_prot))) {
-- 
2.14.3




[Qemu-devel] [PATCH v3 21/45] target/hppa: Implement I*TLBA and I*TLBP insns

2018-01-24 Thread Richard Henderson
The TLB can now be populated, but it cannot yet be cleared.

Signed-off-by: Richard Henderson 
---
 target/hppa/helper.h |  2 ++
 target/hppa/mem_helper.c | 80 ++--
 target/hppa/translate.c  | 54 ++--
 3 files changed, 132 insertions(+), 4 deletions(-)

diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 744b11cb66..d412093914 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -86,4 +86,6 @@ DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, 
void, env, tr)
 DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tr)
 DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr)
 DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr)
+DEF_HELPER_FLAGS_3(itlba, TCG_CALL_NO_RWG, void, env, tl, tr)
+DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr)
 #endif
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 08ab19aacf..7c3c7d1415 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -42,13 +42,40 @@ static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, 
vaddr addr)
 
 for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) {
 hppa_tlb_entry *ent = >tlb[i];
-if (ent->va_b <= addr && addr <= ent->va_e && ent->entry_valid) {
+if (ent->va_b <= addr && addr <= ent->va_e) {
 return ent;
 }
 }
 return NULL;
 }
 
+static void hppa_flush_tlb_ent(CPUHPPAState *env, hppa_tlb_entry *ent)
+{
+CPUState *cs = CPU(hppa_env_get_cpu(env));
+unsigned i, n = 1 << (2 * ent->page_size);
+uint64_t addr = ent->va_b;
+
+for (i = 0; i < n; ++i, addr += TARGET_PAGE_SIZE) {
+/* Do not flush MMU_PHYS_IDX.  */
+tlb_flush_page_by_mmuidx(cs, addr, 0xf);
+}
+
+memset(ent, 0, sizeof(*ent));
+ent->va_b = -1;
+}
+
+static hppa_tlb_entry *hppa_alloc_tlb_ent(CPUHPPAState *env)
+{
+hppa_tlb_entry *ent;
+uint32_t i = env->tlb_last;
+
+env->tlb_last = (i == ARRAY_SIZE(env->tlb) - 1 ? 0 : i + 1);
+ent = >tlb[i];
+
+hppa_flush_tlb_ent(env, ent);
+return ent;
+}
+
 int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
   MMUAccessType type, hwaddr *pphys, int *pprot)
 {
@@ -67,7 +94,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, 
int mmu_idx,
 
 /* Find a valid tlb entry that matches the virtual address.  */
 ent = hppa_find_tlb(env, addr);
-if (ent == NULL) {
+if (ent == NULL || !ent->entry_valid) {
 phys = 0;
 prot = 0;
 ret = (ifetch ? EXCP_ITLB_MISS : EXCP_DTLB_MISS);
@@ -194,4 +221,53 @@ void tlb_fill(CPUState *cs, target_ulong addr, 
MMUAccessType type,
 tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK,
  prot, mmu_idx, TARGET_PAGE_SIZE);
 }
+
+/* Insert (Insn/Data) TLB Address.  Note this is PA 1.1 only.  */
+void HELPER(itlba)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
+{
+hppa_tlb_entry *empty = NULL;
+int i;
+
+/* Zap any old entries covering ADDR; notice empty entries on the way.  */
+for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) {
+hppa_tlb_entry *ent = >tlb[i];
+if (!ent->entry_valid) {
+empty = ent;
+} else if (ent->va_b <= addr && addr <= ent->va_e) {
+hppa_flush_tlb_ent(env, ent);
+empty = ent;
+}
+}
+
+/* If we didn't see an empty entry, evict one.  */
+if (empty == NULL) {
+empty = hppa_alloc_tlb_ent(env);
+}
+
+/* Note that empty->entry_valid == 0 already.  */
+empty->va_b = addr & TARGET_PAGE_MASK;
+empty->va_e = empty->va_b + TARGET_PAGE_SIZE - 1;
+empty->pa = extract32(reg, 5, 20) << TARGET_PAGE_BITS;
+}
+
+/* Insert (Insn/Data) TLB Protection.  Note this is PA 1.1 only.  */
+void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
+{
+hppa_tlb_entry *ent = hppa_find_tlb(env, addr);
+
+if (unlikely(ent == NULL || ent->entry_valid)) {
+qemu_log_mask(LOG_GUEST_ERROR, "ITLBP not following ITLBA\n");
+return;
+}
+
+ent->access_id = extract32(reg, 1, 18);
+ent->u = extract32(reg, 19, 1);
+ent->ar_pl2 = extract32(reg, 20, 2);
+ent->ar_pl1 = extract32(reg, 22, 2);
+ent->ar_type = extract32(reg, 24, 3);
+ent->b = extract32(reg, 27, 1);
+ent->d = extract32(reg, 28, 1);
+ent->t = extract32(reg, 29, 1);
+ent->entry_valid = 1;
+}
 #endif /* CONFIG_USER_ONLY */
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 6288bb9f67..c02d107041 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1344,7 +1344,10 @@ static DisasJumpType do_unit(DisasContext *ctx, unsigned 
rt, TCGv_reg in1,
 }
 
 #ifndef CONFIG_USER_ONLY
-/* Top 2 bits of the base register select sp[4-7].  */
+/* The "normal" usage is SP >= 0, wherein SP == 0 selects the space
+   from the 

[Qemu-devel] [PATCH v3 30/45] target/hppa: Add migration for the cpu

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h |   1 +
 target/hppa/cpu.c |   1 +
 target/hppa/machine.c | 181 ++
 target/hppa/Makefile.objs |   1 +
 4 files changed, 184 insertions(+)
 create mode 100644 target/hppa/machine.c

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 57e0bd6f0e..8a87b8a9b3 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -351,6 +351,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, 
int rw, int midx);
 int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
   MMUAccessType type, hwaddr *pphys, int *pprot);
 extern const MemoryRegionOps hppa_io_eir_ops;
+extern const struct VMStateDescription vmstate_hppa_cpu;
 void hppa_cpu_alarm_timer(void *);
 #endif
 void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t 
ra);
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 6be6eb0a7b..5213347720 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -184,6 +184,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
 cc->handle_mmu_fault = hppa_cpu_handle_mmu_fault;
 #else
 cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug;
+dc->vmsd = _hppa_cpu;
 #endif
 cc->do_unaligned_access = hppa_cpu_do_unaligned_access;
 cc->disas_set_info = hppa_cpu_disas_set_info;
diff --git a/target/hppa/machine.c b/target/hppa/machine.c
new file mode 100644
index 00..8e077788c3
--- /dev/null
+++ b/target/hppa/machine.c
@@ -0,0 +1,181 @@
+/*
+ *  HPPA interrupt helper routines
+ *
+ *  Copyright (c) 2017 Richard Henderson
+ *
+ * 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 "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "migration/cpu.h"
+
+#if TARGET_REGISTER_BITS == 64
+#define qemu_put_betr   qemu_put_be64
+#define qemu_get_betr   qemu_get_be64
+#define VMSTATE_UINTTL_V(_f, _s, _v) \
+VMSTATE_UINT64_V(_f, _s, _v)
+#define VMSTATE_UINTTL_ARRAY_V(_f, _s, _n, _v) \
+VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v)
+#else
+#define qemu_put_betr   qemu_put_be32
+#define qemu_get_betr   qemu_get_be32
+#define VMSTATE_UINTTR_V(_f, _s, _v) \
+VMSTATE_UINT32_V(_f, _s, _v)
+#define VMSTATE_UINTTR_ARRAY_V(_f, _s, _n, _v) \
+VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v)
+#endif
+
+#define VMSTATE_UINTTR(_f, _s) \
+VMSTATE_UINTTR_V(_f, _s, 0)
+#define VMSTATE_UINTTR_ARRAY(_f, _s, _n) \
+VMSTATE_UINTTR_ARRAY_V(_f, _s, _n, 0)
+
+
+static int get_psw(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
+{
+CPUHPPAState *env = opaque;
+cpu_hppa_put_psw(env, qemu_get_betr(f));
+return 0;
+}
+
+static int put_psw(QEMUFile *f, void *opaque, size_t size,
+   VMStateField *field, QJSON *vmdesc)
+{
+CPUHPPAState *env = opaque;
+qemu_put_betr(f, cpu_hppa_get_psw(env));
+return 0;
+}
+
+static const VMStateInfo vmstate_psw = {
+.name = "psw",
+.get = get_psw,
+.put = put_psw,
+};
+
+/* FIXME: Use the PA2.0 format, which is a superset of the PA1.1 format.  */
+static int get_tlb(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
+{
+hppa_tlb_entry *ent = opaque;
+uint32_t val;
+
+memset(ent, 0, sizeof(*ent));
+
+ent->va_b = qemu_get_be64(f);
+ent->pa = qemu_get_betr(f);
+val = qemu_get_be32(f);
+
+ent->entry_valid = extract32(val, 0, 1);
+ent->access_id = extract32(val, 1, 18);
+ent->u = extract32(val, 19, 1);
+ent->ar_pl2 = extract32(val, 20, 2);
+ent->ar_pl1 = extract32(val, 22, 2);
+ent->ar_type = extract32(val, 24, 3);
+ent->b = extract32(val, 27, 1);
+ent->d = extract32(val, 28, 1);
+ent->t = extract32(val, 29, 1);
+
+ent->va_e = ent->va_b + TARGET_PAGE_SIZE - 1;
+return 0;
+}
+
+static int put_tlb(QEMUFile *f, void *opaque, size_t size,
+   VMStateField *field, QJSON *vmdesc)
+{
+hppa_tlb_entry *ent = opaque;
+uint32_t val = 0;
+
+if (ent->entry_valid) {
+val = 1;
+val = deposit32(val, 1, 18, ent->access_id);
+val = deposit32(val, 19, 1, ent->u);
+val = deposit32(val, 20, 2, ent->ar_pl2);
+val = deposit32(val, 22, 2, ent->ar_pl1);
+val = deposit32(val, 24, 3, 

[Qemu-devel] [PATCH v3 20/45] target/hppa: Log unimplemented instructions

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 1cd57f5a90..6288bb9f67 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -4218,6 +4218,8 @@ static DisasJumpType translate_table_int(DisasContext 
*ctx, uint32_t insn,
 return table[i].trans(ctx, insn, [i]);
 }
 }
+qemu_log_mask(LOG_UNIMP, "UNIMP insn %08x @ " TARGET_FMT_lx "\n",
+  insn, ctx->base.pc_next);
 return gen_illegal(ctx);
 }
 
-- 
2.14.3




[Qemu-devel] [PATCH v3 26/45] target/hppa: Implement SYNCDMA insn

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 41e28ff64c..f3942b1baf 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2312,7 +2312,8 @@ static const DisasInsn table_system[] = {
 { 0x14a0u, 0xffe0u, trans_mfia },
 { 0x04a0u, 0x1fe0u, trans_mfsp },
 { 0x08a0u, 0xfc1fbfe0u, trans_mfctl },
-{ 0x0400u, 0xu, trans_sync },
+{ 0x0400u, 0xu, trans_sync },  /* sync */
+{ 0x00100400u, 0xu, trans_sync },  /* syncdma */
 { 0x10a0u, 0xfc1f3fe0u, trans_ldsid },
 #ifndef CONFIG_USER_ONLY
 { 0x0e60u, 0xfc00ffe0u, trans_rsm },
-- 
2.14.3




[Qemu-devel] [PATCH v3 19/45] target/hppa: Implement the interval timer

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h|  2 ++
 target/hppa/helper.h |  3 +++
 target/hppa/cpu.c|  8 
 target/hppa/int_helper.c |  6 ++
 target/hppa/op_helper.c  | 36 
 target/hppa/translate.c  | 16 
 6 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index fc3e62c0af..31a3702684 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -234,6 +234,7 @@ struct HPPACPU {
 /*< public >*/
 
 CPUHPPAState env;
+QEMUTimer *alarm_timer;
 };
 
 static inline HPPACPU *hppa_env_get_cpu(CPUHPPAState *env)
@@ -341,6 +342,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, 
int rw, int midx);
 int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
   MMUAccessType type, hwaddr *pphys, int *pprot);
 extern const MemoryRegionOps hppa_io_eir_ops;
+void hppa_cpu_alarm_timer(void *);
 #endif
 
 #endif /* HPPA_CPU_H */
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 535f086ab4..744b11cb66 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -77,9 +77,12 @@ DEF_HELPER_FLAGS_4(fmpynfadd_s, TCG_CALL_NO_RWG, i32, env, 
i32, i32, i32)
 DEF_HELPER_FLAGS_4(fmpyfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
 
+DEF_HELPER_FLAGS_0(read_interval_timer, TCG_CALL_NO_RWG, tr)
+
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_1(rfi, void, env)
 DEF_HELPER_1(rfi_r, void, env)
+DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr)
 DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tr)
 DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr)
 DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr)
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 888a48f16d..6be6eb0a7b 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -99,6 +99,14 @@ static void hppa_cpu_realizefn(DeviceState *dev, Error 
**errp)
 
 qemu_init_vcpu(cs);
 acc->parent_realize(dev, errp);
+
+#ifndef CONFIG_USER_ONLY
+{
+HPPACPU *cpu = HPPA_CPU(cs);
+cpu->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+hppa_cpu_alarm_timer, cpu);
+}
+#endif
 }
 
 /* Sort hppabetically by type name. */
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 249e14a2a1..d54d830196 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -67,6 +67,12 @@ const MemoryRegionOps hppa_io_eir_ops = {
 .impl.max_access_size = 4,
 };
 
+void hppa_cpu_alarm_timer(void *opaque)
+{
+/* Raise interrupt 0.  */
+io_eir_write(opaque, 0, 0, 4);
+}
+
 void HELPER(write_eirr)(CPUHPPAState *env, target_ureg val)
 {
 env->cr[CR_EIRR] &= ~val;
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index 1963b2439b..6d19cab6c9 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -22,6 +22,8 @@
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 #include "exec/cpu_ldst.h"
+#include "qemu/timer.h"
+
 
 void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp)
 {
@@ -602,7 +604,41 @@ float64 HELPER(fmpynfadd_d)(CPUHPPAState *env, float64 a, 
float64 b, float64 c)
 return ret;
 }
 
+target_ureg HELPER(read_interval_timer)(void)
+{
+#ifdef CONFIG_USER_ONLY
+/* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist.
+   Just pass through the host cpu clock ticks.  */
+return cpu_get_host_ticks();
+#else
+/* In system mode we have access to a decent high-resolution clock.
+   In order to make OS-level time accounting work with the cr16,
+   present it with a well-timed clock fixed at 250MHz.  */
+return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 2;
+#endif
+}
+
 #ifndef CONFIG_USER_ONLY
+void HELPER(write_interval_timer)(CPUHPPAState *env, target_ureg val)
+{
+HPPACPU *cpu = hppa_env_get_cpu(env);
+uint64_t current = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+uint64_t timeout;
+
+/* Even in 64-bit mode, the comparator is always 32-bit.  But the
+   value we expose to the guest is 1/4 of the speed of the clock,
+   so moosh in 34 bits.  */
+timeout = deposit64(current, 0, 34, (uint64_t)val << 2);
+
+/* If the mooshing puts the clock in the past, advance to next round.  */
+if (timeout < current + 1000) {
+timeout += 1ULL << 34;
+}
+
+cpu->env.cr[CR_IT] = timeout;
+timer_mod(cpu->alarm_timer, timeout);
+}
+
 target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm)
 {
 target_ulong psw = env->psw;
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index d6c65f314b..1cd57f5a90 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2038,6 +2038,7 @@ static DisasJumpType trans_mfctl(DisasContext *ctx, 
uint32_t insn,
 unsigned rt = extract32(insn, 0, 5);
 

[Qemu-devel] [PATCH v3 23/45] target/hppa: Implement LDWA

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 5b77688fc0..3d441ef4ac 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2954,12 +2954,50 @@ static DisasJumpType trans_stby(DisasContext *ctx, 
uint32_t insn,
 return nullify_end(ctx, DISAS_NEXT);
 }
 
+#ifndef CONFIG_USER_ONLY
+static DisasJumpType trans_ldwa_idx_i(DisasContext *ctx, uint32_t insn,
+  const DisasInsn *di)
+{
+int hold_mmu_idx = ctx->mmu_idx;
+DisasJumpType ret;
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+
+/* ??? needs fixing for hppa64 -- ldda does not follow the same
+   format wrt the sub-opcode in bits 6:9.  */
+ctx->mmu_idx = MMU_PHYS_IDX;
+ret = trans_ld_idx_i(ctx, insn, di);
+ctx->mmu_idx = hold_mmu_idx;
+return ret;
+}
+
+static DisasJumpType trans_ldwa_idx_x(DisasContext *ctx, uint32_t insn,
+  const DisasInsn *di)
+{
+int hold_mmu_idx = ctx->mmu_idx;
+DisasJumpType ret;
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+
+/* ??? needs fixing for hppa64 -- ldda does not follow the same
+   format wrt the sub-opcode in bits 6:9.  */
+ctx->mmu_idx = MMU_PHYS_IDX;
+ret = trans_ld_idx_x(ctx, insn, di);
+ctx->mmu_idx = hold_mmu_idx;
+return ret;
+}
+#endif
+
 static const DisasInsn table_index_mem[] = {
 { 0x0c001000u, 0xfc001300, trans_ld_idx_i }, /* LD[BHWD], im */
 { 0x0c00u, 0xfc001300, trans_ld_idx_x }, /* LD[BHWD], rx */
 { 0x0c001200u, 0xfc001300, trans_st_idx_i }, /* ST[BHWD] */
 { 0x0c0001c0u, 0xfc0003c0, trans_ldcw },
 { 0x0c001300u, 0xfc0013c0, trans_stby },
+#ifndef CONFIG_USER_ONLY
+{ 0x0c001180u, 0xfc00d3c0, trans_ldwa_idx_i }, /* LDWA, im */
+{ 0x0c000180u, 0xfc00d3c0, trans_ldwa_idx_x }, /* LDWA, rx */
+#endif
 };
 
 static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn)
-- 
2.14.3




[Qemu-devel] [PATCH v3 14/45] target/hppa: Use space registers in data operations

2018-01-24 Thread Richard Henderson
This changes the system virtual address width to 64-bit and
incorporates the space registers into load/store operations.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h   |  14 ++
 target/hppa/translate.c | 334 +++-
 2 files changed, 201 insertions(+), 147 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 6ec3430ae3..94f9c8ca2b 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -23,10 +23,24 @@
 #include "qemu-common.h"
 #include "cpu-qom.h"
 
+#ifdef TARGET_HPPA64
+#define TARGET_LONG_BITS64
+#define TARGET_VIRT_ADDR_SPACE_BITS 64
+#define TARGET_REGISTER_BITS64
+#define TARGET_PHYS_ADDR_SPACE_BITS 64
+#elif defined(CONFIG_USER_ONLY)
 #define TARGET_LONG_BITS32
 #define TARGET_VIRT_ADDR_SPACE_BITS 32
 #define TARGET_REGISTER_BITS32
 #define TARGET_PHYS_ADDR_SPACE_BITS 32
+#else
+/* In order to form the GVA from space:offset,
+   we need a 64-bit virtual address space.  */
+#define TARGET_LONG_BITS64
+#define TARGET_VIRT_ADDR_SPACE_BITS 64
+#define TARGET_REGISTER_BITS32
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#endif
 
 #define CPUArchState struct CPUHPPAState
 
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 34b999fb2c..6be9e0c3ff 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -276,8 +276,9 @@ typedef struct DisasContext {
 target_ureg iaoq_n;
 TCGv_reg iaoq_n_var;
 
-int ntemps;
-TCGv_reg temps[8];
+int ntempr, ntempl;
+TCGv_reg tempr[4];
+TCGv_tl  templ[4];
 
 DisasCond null_cond;
 TCGLabel *null_lab;
@@ -458,11 +459,20 @@ static void cond_free(DisasCond *cond)
 
 static TCGv_reg get_temp(DisasContext *ctx)
 {
-unsigned i = ctx->ntemps++;
-g_assert(i < ARRAY_SIZE(ctx->temps));
-return ctx->temps[i] = tcg_temp_new();
+unsigned i = ctx->ntempr++;
+g_assert(i < ARRAY_SIZE(ctx->tempr));
+return ctx->tempr[i] = tcg_temp_new();
 }
 
+#ifndef CONFIG_USER_ONLY
+static TCGv_tl get_temp_tl(DisasContext *ctx)
+{
+unsigned i = ctx->ntempl++;
+g_assert(i < ARRAY_SIZE(ctx->templ));
+return ctx->templ[i] = tcg_temp_new_tl();
+}
+#endif
+
 static TCGv_reg load_const(DisasContext *ctx, target_sreg v)
 {
 TCGv_reg t = get_temp(ctx);
@@ -1324,6 +1334,70 @@ static DisasJumpType do_unit(DisasContext *ctx, unsigned 
rt, TCGv_reg in1,
 return DISAS_NEXT;
 }
 
+#ifndef CONFIG_USER_ONLY
+/* Top 2 bits of the base register select sp[4-7].  */
+static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_reg base)
+{
+TCGv_ptr ptr;
+TCGv_reg tmp;
+TCGv_i64 spc;
+
+if (sp != 0) {
+return cpu_sr[sp];
+}
+
+ptr = tcg_temp_new_ptr();
+tmp = tcg_temp_new();
+spc = get_temp_tl(ctx);
+
+tcg_gen_shri_reg(tmp, base, TARGET_REGISTER_BITS - 5);
+tcg_gen_andi_reg(tmp, tmp, 030);
+tcg_gen_trunc_reg_ptr(ptr, tmp);
+tcg_temp_free(tmp);
+
+tcg_gen_add_ptr(ptr, ptr, cpu_env);
+tcg_gen_ld_i64(spc, ptr, offsetof(CPUHPPAState, sr[4]));
+tcg_temp_free_ptr(ptr);
+
+return spc;
+}
+#endif
+
+static void form_gva(DisasContext *ctx, TCGv_tl *pgva, TCGv_reg *pofs,
+ unsigned rb, unsigned rx, int scale, target_sreg disp,
+ unsigned sp, int modify, bool is_phys)
+{
+TCGv_reg base = load_gpr(ctx, rb);
+TCGv_reg ofs;
+
+/* Note that RX is mutually exclusive with DISP.  */
+if (rx) {
+ofs = get_temp(ctx);
+tcg_gen_shli_reg(ofs, cpu_gr[rx], scale);
+tcg_gen_add_reg(ofs, ofs, base);
+} else if (disp || modify) {
+ofs = get_temp(ctx);
+tcg_gen_addi_reg(ofs, base, disp);
+} else {
+ofs = base;
+}
+
+*pofs = ofs;
+#ifdef CONFIG_USER_ONLY
+*pgva = (modify <= 0 ? ofs : base);
+#else
+TCGv_tl addr = get_temp_tl(ctx);
+tcg_gen_extu_reg_tl(addr, modify <= 0 ? ofs : base);
+if (ctx->base.tb->flags & PSW_W) {
+tcg_gen_andi_tl(addr, addr, 0x3fffull);
+}
+if (!is_phys) {
+tcg_gen_or_tl(addr, addr, space_select(ctx, sp, base));
+}
+*pgva = addr;
+#endif
+}
+
 /* Emit a memory load.  The modify parameter should be
  * < 0 for pre-modify,
  * > 0 for post-modify,
@@ -1331,118 +1405,74 @@ static DisasJumpType do_unit(DisasContext *ctx, 
unsigned rt, TCGv_reg in1,
  */
 static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
unsigned rx, int scale, target_sreg disp,
-   int modify, TCGMemOp mop)
+   unsigned sp, int modify, TCGMemOp mop)
 {
-TCGv_reg addr, base;
+TCGv_reg ofs;
+TCGv_tl addr;
 
 /* Caller uses nullify_over/nullify_end.  */
 assert(ctx->null_cond.c == TCG_COND_NEVER);
 
-addr = tcg_temp_new();
-base = load_gpr(ctx, rb);
-
-/* Note that RX is mutually exclusive with DISP.  */
-if (rx) {
-

[Qemu-devel] [PATCH v3 41/45] hw/hppa: Implement DINO system board

2018-01-24 Thread Richard Henderson
From: Helge Deller 

Now that we have the prerequisites in target/hppa/,
implement the hardware for a PA7100LC.

This also enables build for hppa-softmmu.

Signed-off-by: Helge Deller 
[rth: Since it is all new code, squashed all branch development
withing hw/hppa/ to a single patch.]
Signed-off-by: Richard Henderson 
---
 Makefile.objs|   1 +
 hw/hppa/hppa_hardware.h  |  40 +++
 hw/hppa/hppa_sys.h   |  24 ++
 hw/hppa/dino.c   | 518 +++
 hw/hppa/machine.c| 246 ++-
 hw/hppa/pci.c|  90 +++
 default-configs/hppa-softmmu.mak |  14 ++
 hw/hppa/Makefile.objs|   2 +-
 hw/hppa/trace-events |   4 +
 9 files changed, 937 insertions(+), 2 deletions(-)
 create mode 100644 hw/hppa/hppa_hardware.h
 create mode 100644 hw/hppa/hppa_sys.h
 create mode 100644 hw/hppa/dino.c
 create mode 100644 hw/hppa/pci.c
 create mode 100644 default-configs/hppa-softmmu.mak
 create mode 100644 hw/hppa/trace-events

diff --git a/Makefile.objs b/Makefile.objs
index 669d8d684d..c52925133a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -155,6 +155,7 @@ trace-events-subdirs += hw/vfio
 trace-events-subdirs += hw/acpi
 trace-events-subdirs += hw/arm
 trace-events-subdirs += hw/alpha
+trace-events-subdirs += hw/hppa
 trace-events-subdirs += hw/xen
 trace-events-subdirs += hw/ide
 trace-events-subdirs += ui
diff --git a/hw/hppa/hppa_hardware.h b/hw/hppa/hppa_hardware.h
new file mode 100644
index 00..2c61b1f77c
--- /dev/null
+++ b/hw/hppa/hppa_hardware.h
@@ -0,0 +1,40 @@
+/* HPPA cores and system support chips.  */
+
+#define FIRMWARE_START  0xf000
+#define FIRMWARE_END0xf080
+
+#define DEVICE_HPA_LEN  0x0010
+
+#define GSC_HPA 0xffc0
+#define DINO_HPA0xfff8
+#define DINO_UART_HPA   0xfff83000
+#define  DINO_UART_BASE 0xfff83800
+#define DINO_SCSI_HPA   0xfff8c000
+#define LASI_HPA0xffd0
+#define LASI_UART_HPA   0xffd05000
+#define LASI_SCSI_HPA   0xffd06000
+#define LASI_LAN_HPA0xffd07000
+#define LASI_LPT_HPA0xffd02000
+#define LASI_AUDIO_HPA  0xffd04000
+#define LASI_PS2KBD_HPA 0xffd08000
+#define LASI_PS2MOU_HPA 0xffd08100
+#define LASI_GFX_HPA0xf800
+#define CPU_HPA 0xfff1
+#define MEMORY_HPA  0xfffbf000
+
+#define PCI_HPA DINO_HPA/* PCI bus */
+#define IDE_HPA 0xf900  /* Boot disc controller */
+
+/* offsets to DINO HPA: */
+#define DINO_PCI_ADDR   0x064
+#define DINO_CONFIG_DATA0x068
+#define DINO_IO_DATA0x06c
+
+#define PORT_PCI_CMD(PCI_HPA + DINO_PCI_ADDR)
+#define PORT_PCI_DATA   (PCI_HPA + DINO_CONFIG_DATA)
+
+#define PORT_SERIAL1(DINO_UART_HPA + 0x800)
+#define PORT_SERIAL2(LASI_UART_HPA + 0x800)
+
+#define HPPA_MAX_CPUS   32  /* max. number of SMP CPUs */
+#define CPU_CLOCK_MHZ   250 /* emulate a 250 MHz CPU */
diff --git a/hw/hppa/hppa_sys.h b/hw/hppa/hppa_sys.h
new file mode 100644
index 00..a182d1f34e
--- /dev/null
+++ b/hw/hppa/hppa_sys.h
@@ -0,0 +1,24 @@
+/* HPPA cores and system support chips.  */
+
+#ifndef HW_HPPA_SYS_H
+#define HW_HPPA_SYS_H
+
+#include "target/hppa/cpu-qom.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/ide.h"
+#include "hw/i386/pc.h"
+#include "hw/irq.h"
+
+#include "hw/hppa/hppa_hardware.h"
+
+PCIBus *dino_init(MemoryRegion *, qemu_irq *, qemu_irq *);
+
+#define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost"
+
+/* hppa_pci.c.  */
+extern const MemoryRegionOps hppa_pci_ignore_ops;
+extern const MemoryRegionOps hppa_pci_conf1_ops;
+extern const MemoryRegionOps hppa_pci_iack_ops;
+
+#endif
diff --git a/hw/hppa/dino.c b/hw/hppa/dino.c
new file mode 100644
index 00..15aefde09c
--- /dev/null
+++ b/hw/hppa/dino.c
@@ -0,0 +1,518 @@
+/*
+ * HP-PARISC Dino PCI chipset emulation.
+ *
+ * (C) 2017 by Helge Deller 
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ * Documentation available at:
+ * https://parisc.wiki.kernel.org/images-parisc/9/91/Dino_ers.pdf
+ * https://parisc.wiki.kernel.org/images-parisc/7/70/Dino_3_1_Errata.pdf
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "hw/devices.h"
+#include "sysemu/sysemu.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hppa_sys.h"
+#include "exec/address-spaces.h"
+
+
+#define TYPE_DINO_PCI_HOST_BRIDGE "dino-pcihost"
+
+#define DINO_IAR0   0x004
+#define DINO_IODC   0x008
+#define DINO_IRR0   0x00C  /* RO */
+#define DINO_IAR1   0x010
+#define DINO_IRR1   0x014  /* RO */
+#define DINO_IMR0x018
+#define DINO_IPR0x01C
+#define DINO_TOC_ADDR   0x020
+#define DINO_ICR0x024
+#define DINO_ILR

[Qemu-devel] [PATCH v3 17/45] target/hppa: Implement tlb_fill

2018-01-24 Thread Richard Henderson
However since HPPA has a software-managed TLB, and the relevant
TLB manipulation instructions are not implemented, this does not
actually do anything.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h|  29 -
 target/hppa/int_helper.c |  15 -
 target/hppa/mem_helper.c | 151 +--
 3 files changed, 188 insertions(+), 7 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index d583ea43dd..c7a2fb5b20 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -165,6 +165,22 @@ typedef int64_t  target_sreg;
 #define TREG_FMT_ld   "%"PRId64
 #endif
 
+typedef struct {
+uint64_t va_b;
+uint64_t va_e;
+target_ureg pa;
+unsigned u : 1;
+unsigned t : 1;
+unsigned d : 1;
+unsigned b : 1;
+unsigned page_size : 4;
+unsigned ar_type : 3;
+unsigned ar_pl1 : 2;
+unsigned ar_pl2 : 2;
+unsigned entry_valid : 1;
+unsigned access_id : 16;
+} hppa_tlb_entry;
+
 struct CPUHPPAState {
 target_ureg gr[32];
 uint64_t fr[32];
@@ -198,6 +214,12 @@ struct CPUHPPAState {
 
 /* Those resources are used only in QEMU core */
 CPU_COMMON
+
+/* ??? The number of entries isn't specified by the architecture.  */
+/* ??? Implement a unified itlb/dtlb for the moment.  */
+/* ??? We should use a more intelligent data structure.  */
+hppa_tlb_entry tlb[256];
+uint32_t tlb_last;
 };
 
 /**
@@ -307,12 +329,17 @@ void cpu_hppa_loaded_fr0(CPUHPPAState *env);
 #define cpu_signal_handler cpu_hppa_signal_handler
 
 int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
-int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, int midx);
 hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
 int hppa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 void hppa_cpu_do_interrupt(CPUState *cpu);
 bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
 void hppa_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function, int);
+#ifdef CONFIG_USER_ONLY
+int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, int midx);
+#else
+int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
+  MMUAccessType type, hwaddr *pphys, int *pprot);
+#endif
 
 #endif /* HPPA_CPU_H */
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 02963b80c6..5ae5233a96 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -79,12 +79,25 @@ void hppa_cpu_do_interrupt(CPUState *cs)
 {
 /* Avoid reading directly from the virtual address, lest we
raise another exception from some sort of TLB issue.  */
+/* ??? An alternate fool-proof method would be to store the
+   instruction data into the unwind info.  That's probably
+   a bit too much in the way of extra storage required.  */
 vaddr vaddr;
 hwaddr paddr;
 
 paddr = vaddr = iaoq_f & -4;
 if (old_psw & PSW_C) {
-vaddr = hppa_form_gva_psw(old_psw, iasq_f, iaoq_f & -4);
+int prot, t;
+
+vaddr = hppa_form_gva_psw(old_psw, iasq_f, vaddr);
+t = hppa_get_physical_address(env, vaddr, 0,
+  MMU_INST_FETCH,
+  , );
+if (t >= 0) {
+/* We can't re-load the instruction.  */
+env->cr[CR_IIR] = 0;
+break;
+}
 }
 env->cr[CR_IIR] = ldl_phys(cs->as, paddr);
 }
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 1afaf89539..08ab19aacf 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -36,18 +36,159 @@ int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
 return 1;
 }
 #else
+static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, vaddr addr)
+{
+int i;
+
+for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) {
+hppa_tlb_entry *ent = >tlb[i];
+if (ent->va_b <= addr && addr <= ent->va_e && ent->entry_valid) {
+return ent;
+}
+}
+return NULL;
+}
+
+int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
+  MMUAccessType type, hwaddr *pphys, int *pprot)
+{
+hwaddr phys;
+int prot, ret, r_prot, w_prot, x_prot, a_prot;
+bool ifetch = type == MMU_INST_FETCH;
+hppa_tlb_entry *ent;
+
+/* Virtual translation disabled.  Direct map virtual to physical.  */
+if (mmu_idx == MMU_PHYS_IDX) {
+phys = addr;
+prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ret = -1;
+goto egress;
+}
+
+/* Find 

[Qemu-devel] [PATCH v3 45/45] target/hppa: Implement PROBE for system mode

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/helper.h|  3 +--
 target/hppa/op_helper.c | 36 +---
 target/hppa/translate.c | 20 
 3 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 31320740da..51dc3f8b09 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -17,8 +17,7 @@ DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, 
env, tl, tr)
 DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tr)
 DEF_HELPER_FLAGS_3(stby_e_parallel, TCG_CALL_NO_WG, void, env, tl, tr)
 
-DEF_HELPER_FLAGS_1(probe_r, TCG_CALL_NO_RWG_SE, tr, tl)
-DEF_HELPER_FLAGS_1(probe_w, TCG_CALL_NO_RWG_SE, tr, tl)
+DEF_HELPER_FLAGS_4(probe, TCG_CALL_NO_WG, tr, env, tl, i32, i32)
 
 DEF_HELPER_FLAGS_1(loaded_fr0, TCG_CALL_NO_RWG, void, env)
 
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index c2eeced0e9..b386394bdf 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -160,21 +160,35 @@ void HELPER(stby_e_parallel)(CPUHPPAState *env, 
target_ulong addr,
 do_stby_e(env, addr, val, true);
 }
 
-target_ureg HELPER(probe_r)(target_ulong addr)
+target_ureg HELPER(probe)(CPUHPPAState *env, target_ulong addr,
+  uint32_t level, uint32_t want)
 {
 #ifdef CONFIG_USER_ONLY
-return page_check_range(addr, 1, PAGE_READ);
+return page_check_range(addr, 1, want);
 #else
-return 1; /* FIXME */
-#endif
-}
+int prot, excp;
+hwaddr phys;
 
-target_ureg HELPER(probe_w)(target_ulong addr)
-{
-#ifdef CONFIG_USER_ONLY
-return page_check_range(addr, 1, PAGE_WRITE);
-#else
-return 1; /* FIXME */
+/* Fail if the requested privilege level is higher than current.  */
+if (level < (env->iaoq_f & 3)) {
+return 0;
+}
+
+/* Use MMU_DEBUG_LOAD to bypass TLB D/B/T bit checks.  */
+excp = hppa_get_physical_address(env, addr, level, MMU_DEBUG_LOAD,
+ , );
+if (excp >= 0) {
+if (env->psw & PSW_Q) {
+/* ??? Needs tweaking for hppa64.  */
+env->cr[CR_IOR] = addr;
+env->cr[CR_ISR] = addr >> 32;
+}
+if (excp == EXCP_DTLB_MISS) {
+excp = EXCP_NA_DTLB_MISS;
+}
+hppa_dynamic_excp(env, excp, GETPC());
+}
+return (want & prot) != 0;
 #endif
 }
 
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index c62ee72615..7c45b1706c 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2380,21 +2380,33 @@ static DisasJumpType trans_probe(DisasContext *ctx, 
uint32_t insn,
 {
 unsigned rt = extract32(insn, 0, 5);
 unsigned sp = extract32(insn, 14, 2);
+unsigned rr = extract32(insn, 16, 5);
 unsigned rb = extract32(insn, 21, 5);
 unsigned is_write = extract32(insn, 6, 1);
+unsigned is_imm = extract32(insn, 13, 1);
 TCGv_reg dest, ofs;
+TCGv_i32 level, want;
 TCGv_tl addr;
 
 nullify_over(ctx);
 
-/* ??? Do something with priv level operand.  */
 dest = dest_gpr(ctx, rt);
 form_gva(ctx, , , rb, 0, 0, 0, sp, 0, false);
-if (is_write) {
-gen_helper_probe_w(dest, addr);
+
+if (is_imm) {
+level = tcg_const_i32(extract32(insn, 16, 2));
 } else {
-gen_helper_probe_r(dest, addr);
+level = tcg_temp_new_i32();
+tcg_gen_trunc_reg_i32(level, load_gpr(ctx, rr));
+tcg_gen_andi_i32(level, level, 3);
 }
+want = tcg_const_i32(is_write ? PROT_WRITE : PROT_READ);
+
+gen_helper_probe(dest, cpu_env, addr, level, want);
+
+tcg_temp_free_i32(want);
+tcg_temp_free_i32(level);
+
 save_gpr(ctx, rt, dest);
 return nullify_end(ctx, DISAS_NEXT);
 }
-- 
2.14.3




[Qemu-devel] [PATCH v3 09/45] target/hppa: Add control registers

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 linux-user/hppa/target_cpu.h |  2 +-
 target/hppa/cpu.h| 23 +++
 linux-user/main.c|  4 +--
 linux-user/signal.c  |  4 +--
 target/hppa/gdbstub.c| 12 
 target/hppa/mem_helper.c |  2 +-
 target/hppa/translate.c  | 70 ++--
 7 files changed, 77 insertions(+), 40 deletions(-)

diff --git a/linux-user/hppa/target_cpu.h b/linux-user/hppa/target_cpu.h
index e50522eae9..7b78bbea80 100644
--- a/linux-user/hppa/target_cpu.h
+++ b/linux-user/hppa/target_cpu.h
@@ -33,7 +33,7 @@ static inline void cpu_clone_regs(CPUHPPAState *env, 
target_ulong newsp)
 
 static inline void cpu_set_tls(CPUHPPAState *env, target_ulong newtls)
 {
-env->cr27 = newtls;
+env->cr[27] = newtls;
 }
 
 #endif
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 24c728c0d2..c92c564a7f 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -123,6 +123,20 @@
 #define PSW_SM_W 0
 #endif
 
+#define CR_RC0
+#define CR_SCRCCR10
+#define CR_SAR   11
+#define CR_IVA   14
+#define CR_EIEM  15
+#define CR_IT16
+#define CR_IIASQ 17
+#define CR_IIAOQ 18
+#define CR_IIR   19
+#define CR_ISR   20
+#define CR_IOR   21
+#define CR_IPSW  22
+#define CR_EIRR  23
+
 typedef struct CPUHPPAState CPUHPPAState;
 
 #if TARGET_REGISTER_BITS == 32
@@ -142,10 +156,6 @@ struct CPUHPPAState {
 uint64_t fr[32];
 uint64_t sr[8];  /* stored shifted into place for gva */
 
-target_ureg sar;
-target_ureg cr26;
-target_ureg cr27;
-
 target_ureg psw; /* All psw bits except the following:  */
 target_ureg psw_n;   /* boolean */
 target_sreg psw_v;   /* in most significant bit */
@@ -163,11 +173,12 @@ struct CPUHPPAState {
 target_ureg iaoq_f;  /* front */
 target_ureg iaoq_b;  /* back, aka next instruction */
 
-target_ureg ior; /* interrupt offset register */
-
 uint32_t fr0_shadow; /* flags, c, ca/cq, rm, d, enables */
 float_status fp_status;
 
+target_ureg cr[32];  /* control registers */
+target_ureg cr_back[2];  /* back of cr17/cr18 */
+
 /* Those resources are used only in QEMU core */
 CPU_COMMON
 };
diff --git a/linux-user/main.c b/linux-user/main.c
index 42f4c66ce6..90ae447368 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3781,14 +3781,14 @@ void cpu_loop(CPUHPPAState *env)
 info.si_signo = TARGET_SIGSEGV;
 info.si_errno = 0;
 info.si_code = TARGET_SEGV_ACCERR;
-info._sifields._sigfault._addr = env->ior;
+info._sifields._sigfault._addr = env->cr[CR_IOR];
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, );
 break;
 case EXCP_UNALIGN:
 info.si_signo = TARGET_SIGBUS;
 info.si_errno = 0;
 info.si_code = 0;
-info._sifields._sigfault._addr = env->ior;
+info._sifields._sigfault._addr = env->cr[CR_IOR];
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, );
 break;
 case EXCP_ILL:
diff --git a/linux-user/signal.c b/linux-user/signal.c
index f85f0dd780..40d5d849f0 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -6440,7 +6440,7 @@ static void setup_sigcontext(struct target_sigcontext 
*sc, CPUArchState *env)
 __put_user(env->fr[i], >sc_fr[i]);
 }
 
-__put_user(env->sar, >sc_sar);
+__put_user(env->cr[CR_SAR], >sc_sar);
 }
 
 static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
@@ -6461,7 +6461,7 @@ static void restore_sigcontext(CPUArchState *env, struct 
target_sigcontext *sc)
 
 __get_user(env->iaoq_f, >sc_iaoq[0]);
 __get_user(env->iaoq_b, >sc_iaoq[1]);
-__get_user(env->sar, >sc_sar);
+__get_user(env->cr[CR_SAR], >sc_sar);
 }
 
 /* No, this doesn't look right, but it's copied straight from the kernel.  */
diff --git a/target/hppa/gdbstub.c b/target/hppa/gdbstub.c
index 228d282fe9..fc27aec073 100644
--- a/target/hppa/gdbstub.c
+++ b/target/hppa/gdbstub.c
@@ -36,7 +36,7 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 val = env->gr[n];
 break;
 case 32:
-val = env->sar;
+val = env->cr[CR_SAR];
 break;
 case 33:
 val = env->iaoq_f;
@@ -45,10 +45,10 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 val = env->iaoq_b;
 break;
 case 59:
-val = env->cr26;
+val = env->cr[26];
 break;
 case 60:
-val = env->cr27;
+val = env->cr[27];
 break;
 case 64 ... 127:
 val = extract64(env->fr[(n - 64) / 2], (n & 1 ? 0 : 32), 32);
@@ -89,7 +89,7 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 

[Qemu-devel] [PATCH v3 32/45] target/hppa: Only use EXCP_DTLB_MISS

2018-01-24 Thread Richard Henderson
Unknown why this works, but if we return EXCP_ITLB_MISS we
will triple-fault the first userland instruction fetch.
Is it something to do with having a combined I/DTLB?

Signed-off-by: Richard Henderson 
---
 target/hppa/mem_helper.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index c14317ebef..81bcbe45db 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -97,7 +97,9 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, 
int mmu_idx,
 if (ent == NULL || !ent->entry_valid) {
 phys = 0;
 prot = 0;
-ret = (ifetch ? EXCP_ITLB_MISS : EXCP_DTLB_MISS);
+/* ??? Unconditionally report data tlb miss,
+   even if this is an instruction fetch.  */
+ret = EXCP_DTLB_MISS;
 goto egress;
 }
 
-- 
2.14.3




[Qemu-devel] [PATCH v3 15/45] target/hppa: Avoid privilege level decrease during branches

2018-01-24 Thread Richard Henderson
These instructions force the destination privilege level
of the branch destination to be no higher than current.

Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 52 -
 1 file changed, 47 insertions(+), 5 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 6be9e0c3ff..4a69f05a91 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1862,6 +1862,40 @@ static DisasJumpType do_ibranch(DisasContext *ctx, 
TCGv_reg dest,
 return DISAS_NEXT;
 }
 
+/* Implement
+ *if (IAOQ_Front{30..31} < GR[b]{30..31})
+ *  IAOQ_Next{30..31} ← GR[b]{30..31};
+ *else
+ *  IAOQ_Next{30..31} ← IAOQ_Front{30..31};
+ * which keeps the privilege level from being increased.
+ */
+static TCGv_reg do_ibranch_priv(DisasContext *ctx, TCGv_reg offset)
+{
+#ifdef CONFIG_USER_ONLY
+return offset;
+#else
+TCGv_reg dest;
+switch (ctx->privilege) {
+case 0:
+/* Privilege 0 is maximum and is allowed to decrease.  */
+return offset;
+case 3:
+/* Privilege 3 is minimum and is never allowed increase.  */
+dest = get_temp(ctx);
+tcg_gen_ori_reg(dest, offset, 3);
+break;
+default:
+dest = tcg_temp_new();
+tcg_gen_andi_reg(dest, offset, -4);
+tcg_gen_ori_reg(dest, dest, ctx->privilege);
+tcg_gen_movcond_reg(TCG_COND_GTU, dest, dest, offset, dest, offset);
+tcg_temp_free(dest);
+break;
+}
+return dest;
+#endif
+}
+
 #ifdef CONFIG_USER_ONLY
 /* On Linux, page zero is normally marked execute only + gateway.
Therefore normal read or write is supposed to fail, but specific
@@ -3441,6 +3475,7 @@ static DisasJumpType trans_be(DisasContext *ctx, uint32_t 
insn, bool is_l)
 unsigned n = extract32(insn, 1, 1);
 unsigned b = extract32(insn, 21, 5);
 target_sreg disp = assemble_17(insn);
+TCGv_reg tmp;
 
 /* unsigned s = low_uextract(insn, 13, 3); */
 /* ??? It seems like there should be a good way of using
@@ -3449,16 +3484,19 @@ static DisasJumpType trans_be(DisasContext *ctx, 
uint32_t insn, bool is_l)
manage along side branch delay slots.  Therefore we handle
entry into the gateway page via absolute address.  */
 
+#ifdef CONFIG_USER_ONLY
 /* Since we don't implement spaces, just branch.  Do notice the special
case of "be disp(*,r0)" using a direct branch to disp, so that we can
goto_tb to the TB containing the syscall.  */
 if (b == 0) {
 return do_dbranch(ctx, disp, is_l ? 31 : 0, n);
-} else {
-TCGv_reg tmp = get_temp(ctx);
-tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp);
-return do_ibranch(ctx, tmp, is_l ? 31 : 0, n);
 }
+#endif
+
+tmp = get_temp(ctx);
+tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp);
+tmp = do_ibranch_priv(ctx, tmp);
+return do_ibranch(ctx, tmp, is_l ? 31 : 0, n);
 }
 
 static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn,
@@ -3490,6 +3528,7 @@ static DisasJumpType trans_blr(DisasContext *ctx, 
uint32_t insn,
 
 tcg_gen_shli_reg(tmp, load_gpr(ctx, rx), 3);
 tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8);
+/* The computation here never changes privilege level.  */
 return do_ibranch(ctx, tmp, link, n);
 }
 
@@ -3508,6 +3547,7 @@ static DisasJumpType trans_bv(DisasContext *ctx, uint32_t 
insn,
 tcg_gen_shli_reg(dest, load_gpr(ctx, rx), 3);
 tcg_gen_add_reg(dest, dest, load_gpr(ctx, rb));
 }
+dest = do_ibranch_priv(ctx, dest);
 return do_ibranch(ctx, dest, 0, n);
 }
 
@@ -3517,8 +3557,10 @@ static DisasJumpType trans_bve(DisasContext *ctx, 
uint32_t insn,
 unsigned n = extract32(insn, 1, 1);
 unsigned rb = extract32(insn, 21, 5);
 unsigned link = extract32(insn, 13, 1) ? 2 : 0;
+TCGv_reg dest;
 
-return do_ibranch(ctx, load_gpr(ctx, rb), link, n);
+dest = do_ibranch_priv(ctx, load_gpr(ctx, rb));
+return do_ibranch(ctx, dest, link, n);
 }
 
 static const DisasInsn table_branch[] = {
-- 
2.14.3




[Qemu-devel] [PATCH v3 40/45] target/hppa: Enable MTTCG

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h | 6 ++
 configure | 1 +
 2 files changed, 7 insertions(+)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 79763b254c..3df3ebd19d 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -42,6 +42,12 @@
 #define TARGET_PHYS_ADDR_SPACE_BITS 32
 #endif
 
+/* PA-RISC 1.x processors have a strong memory model.  */
+/* ??? While we do not yet implement PA-RISC 2.0, those processors have
+   a weak memory model, but with TLB bits that force ordering on a per-page
+   basis.  It's probably easier to fall back to a strong memory model.  */
+#define TCG_GUEST_DEFAULT_MOTCG_MO_ALL
+
 #define CPUArchState struct CPUHPPAState
 
 #include "exec/cpu-defs.h"
diff --git a/configure b/configure
index 044c6fafe2..0046135db6 100755
--- a/configure
+++ b/configure
@@ -6549,6 +6549,7 @@ case "$target_name" in
   cris)
   ;;
   hppa)
+mttcg="yes"
   ;;
   lm32)
   ;;
-- 
2.14.3




[Qemu-devel] [PATCH v3 08/45] target/hppa: Add space registers

2018-01-24 Thread Richard Henderson
Not used where they should be yet, but we can copy them.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h   |  1 +
 target/hppa/helper.c| 14 ++
 target/hppa/translate.c | 73 +
 3 files changed, 77 insertions(+), 11 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 805c93db9c..24c728c0d2 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -140,6 +140,7 @@ typedef int64_t  target_sreg;
 struct CPUHPPAState {
 target_ureg gr[32];
 uint64_t fr[32];
+uint64_t sr[8];  /* stored shifted into place for gva */
 
 target_ureg sar;
 target_ureg cr26;
diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index b6521f61fc..48ac80cb2d 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -168,12 +168,16 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f,
 psw, psw_cb, psw_c);
 
 for (i = 0; i < 32; i++) {
-cpu_fprintf(f, "GR%02d " TREG_FMT_lx " ", i, env->gr[i]);
-if ((i % 4) == 3) {
-cpu_fprintf(f, "\n");
-}
+cpu_fprintf(f, "GR%02d " TREG_FMT_lx "%c", i, env->gr[i],
+(i & 3) == 3 ? '\n' : ' ');
+}
+#ifndef CONFIG_USER_ONLY
+for (i = 0; i < 8; i++) {
+cpu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32),
+(i & 3) == 3 ? '\n' : ' ');
 }
-cpu_fprintf(f, "\n");
+#endif
+ cpu_fprintf(f, "\n");
 
 /* ??? FR */
 }
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 088031e7f3..50d41b0c63 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -320,6 +320,7 @@ typedef struct DisasInsn {
 
 /* global register indexes */
 static TCGv_reg cpu_gr[32];
+static TCGv_i64 cpu_sr[4];
 static TCGv_reg cpu_iaoq_f;
 static TCGv_reg cpu_iaoq_b;
 static TCGv_reg cpu_sar;
@@ -358,6 +359,10 @@ void hppa_translate_init(void)
 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
 };
+/* SR[4-7] are not global registers so that we can index them.  */
+static const char sr_names[4][4] = {
+"sr0", "sr1", "sr2", "sr3"
+};
 
 int i;
 
@@ -367,6 +372,11 @@ void hppa_translate_init(void)
offsetof(CPUHPPAState, gr[i]),
gr_names[i]);
 }
+for (i = 0; i < 4; i++) {
+cpu_sr[i] = tcg_global_mem_new_i64(cpu_env,
+   offsetof(CPUHPPAState, sr[i]),
+   sr_names[i]);
+}
 
 for (i = 0; i < ARRAY_SIZE(vars); ++i) {
 const GlobalVar *v = [i];
@@ -571,6 +581,19 @@ static void save_frd(unsigned rt, TCGv_i64 val)
 tcg_gen_st_i64(val, cpu_env, offsetof(CPUHPPAState, fr[rt]));
 }
 
+static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg)
+{
+#ifdef CONFIG_USER_ONLY
+tcg_gen_movi_i64(dest, 0);
+#else
+if (reg < 4) {
+tcg_gen_mov_i64(dest, cpu_sr[reg]);
+} else {
+tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUHPPAState, sr[reg]));
+}
+#endif
+}
+
 /* Skip over the implementation of an insn that has been nullified.
Use this when the insn is too complex for a conditional move.  */
 static void nullify_over(DisasContext *ctx)
@@ -785,6 +808,13 @@ static unsigned assemble_rc64(uint32_t insn)
 return r2 * 32 + r1 * 4 + r0;
 }
 
+static unsigned assemble_sr3(uint32_t insn)
+{
+unsigned s2 = extract32(insn, 13, 1);
+unsigned s0 = extract32(insn, 14, 2);
+return s2 * 4 + s0;
+}
+
 static target_sreg assemble_12(uint32_t insn)
 {
 target_ureg x = -(target_ureg)(insn & 1);
@@ -1894,11 +1924,17 @@ static DisasJumpType trans_mfsp(DisasContext *ctx, 
uint32_t insn,
 const DisasInsn *di)
 {
 unsigned rt = extract32(insn, 0, 5);
-TCGv_reg tmp = dest_gpr(ctx, rt);
+unsigned rs = assemble_sr3(insn);
+TCGv_i64 t0 = tcg_temp_new_i64();
+TCGv_reg t1 = tcg_temp_new();
 
-/* ??? We don't implement space registers.  */
-tcg_gen_movi_reg(tmp, 0);
-save_gpr(ctx, rt, tmp);
+load_spr(ctx, t0, rs);
+tcg_gen_shri_i64(t0, t0, 32);
+tcg_gen_trunc_i64_reg(t1, t0);
+
+save_gpr(ctx, rt, t1);
+tcg_temp_free(t1);
+tcg_temp_free_i64(t0);
 
 cond_free(>null_cond);
 return DISAS_NEXT;
@@ -1944,6 +1980,32 @@ static DisasJumpType trans_mfctl(DisasContext *ctx, 
uint32_t insn,
 return DISAS_NEXT;
 }
 
+static DisasJumpType trans_mtsp(DisasContext *ctx, uint32_t insn,
+const DisasInsn *di)
+{
+unsigned rr = extract32(insn, 16, 5);
+unsigned rs = assemble_sr3(insn);
+TCGv_i64 t64;
+
+if (rs >= 5) {
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
+}
+nullify_over(ctx);
+
+t64 = tcg_temp_new_i64();
+tcg_gen_extu_reg_i64(t64, load_gpr(ctx, rr));
+

[Qemu-devel] [PATCH v3 31/45] target/hppa: Implement B,GATE insn

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h|  1 +
 target/hppa/mem_helper.c |  8 
 target/hppa/translate.c  | 48 
 3 files changed, 57 insertions(+)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 8a87b8a9b3..79763b254c 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -353,6 +353,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr 
addr, int mmu_idx,
 extern const MemoryRegionOps hppa_io_eir_ops;
 extern const struct VMStateDescription vmstate_hppa_cpu;
 void hppa_cpu_alarm_timer(void *);
+int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr);
 #endif
 void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t 
ra);
 
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index fbe2e19d5d..c14317ebef 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -123,6 +123,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr 
addr, int mmu_idx,
 break;
 default: /* execute: promote to privilege level type & 3 */
 prot = x_prot;
+break;
 }
 
 /* ??? Check PSW_P and ent->access_prot.  This can remove PROT_WRITE.  */
@@ -328,4 +329,11 @@ target_ureg HELPER(lpa)(CPUHPPAState *env, target_ulong 
addr)
 }
 return phys;
 }
+
+/* Return the ar_type of the TLB at VADDR, or -1.  */
+int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr)
+{
+hppa_tlb_entry *ent = hppa_find_tlb(env, vaddr);
+return ent ? ent->ar_type : -1;
+}
 #endif /* CONFIG_USER_ONLY */
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 24d357889e..5b7824f065 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -3782,6 +3782,53 @@ static DisasJumpType trans_bl(DisasContext *ctx, 
uint32_t insn,
 return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n);
 }
 
+static DisasJumpType trans_b_gate(DisasContext *ctx, uint32_t insn,
+  const DisasInsn *di)
+{
+unsigned n = extract32(insn, 1, 1);
+unsigned link = extract32(insn, 21, 5);
+target_sreg disp = assemble_17(insn);
+target_ureg dest = iaoq_dest(ctx, disp);
+
+/* Make sure the caller hasn't done something weird with the queue.
+ * ??? This is not quite the same as the PSW[B] bit, which would be
+ * expensive to track.  Real hardware will trap for
+ *b  gateway
+ *b  gateway+4  (in delay slot of first branch)
+ * However, checking for a non-sequential instruction queue *will*
+ * diagnose the security hole
+ *b  gateway
+ *b  evil
+ * in which instructions at evil would run with increased privs.
+ */
+if (ctx->iaoq_b == -1 || ctx->iaoq_b != ctx->iaoq_f + 4) {
+return gen_illegal(ctx);
+}
+
+#ifndef CONFIG_USER_ONLY
+if (ctx->tb_flags & PSW_C) {
+CPUHPPAState *env = ctx->cs->env_ptr;
+int type = hppa_artype_for_page(env, ctx->base.pc_next);
+/* If we could not find a TLB entry, then we need to generate an
+   ITLB miss exception so the kernel will provide it.
+   The resulting TLB fill operation will invalidate this TB and
+   we will re-translate, at which point we *will* be able to find
+   the TLB entry and determine if this is in fact a gateway page.  */
+if (type < 0) {
+return gen_excp(ctx, EXCP_ITLB_MISS);
+}
+/* No change for non-gateway pages or for priv decrease.  */
+if (type >= 4 && type - 4 < ctx->privilege) {
+dest = deposit32(dest, 0, 2, type - 4);
+}
+} else {
+dest &= -4;  /* priv = 0 */
+}
+#endif
+
+return do_dbranch(ctx, dest, link, n);
+}
+
 static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn,
const DisasInsn *di)
 {
@@ -3860,6 +3907,7 @@ static const DisasInsn table_branch[] = {
 { 0xe8004000u, 0xfc00fffdu, trans_blr },
 { 0xe800c000u, 0xfc00fffdu, trans_bv },
 { 0xe800d000u, 0xfc00dffcu, trans_bve },
+{ 0xe8002000u, 0xfc00e000u, trans_b_gate },
 };
 
 static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn,
-- 
2.14.3




[Qemu-devel] [PATCH v3 05/45] target/hppa: Split address size from register size

2018-01-24 Thread Richard Henderson
For system mode, we will need 64-bit virtual addresses even when
we have 32-bit register sizes.  Since the rest of QEMU equates
TARGET_LONG_BITS with the address size, redefine everything
related to register size in terms of a new TARGET_REGISTER_BITS.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h   |  48 ++-
 target/hppa/helper.h|  26 +-
 target/hppa/gdbstub.c   |  19 +-
 target/hppa/helper.c|  18 +-
 target/hppa/op_helper.c |  22 +-
 target/hppa/translate.c | 964 ++--
 6 files changed, 683 insertions(+), 414 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index d84af91860..1524ef91b6 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -23,10 +23,10 @@
 #include "qemu-common.h"
 #include "cpu-qom.h"
 
-/* We only support hppa-linux-user at present, so 32-bit only.  */
-#define TARGET_LONG_BITS 32
-#define TARGET_PHYS_ADDR_SPACE_BITS  32
-#define TARGET_VIRT_ADDR_SPACE_BITS  32
+#define TARGET_LONG_BITS32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+#define TARGET_REGISTER_BITS32
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
 
 #define CPUArchState struct CPUHPPAState
 
@@ -123,17 +123,29 @@
 
 typedef struct CPUHPPAState CPUHPPAState;
 
+#if TARGET_REGISTER_BITS == 32
+typedef uint32_t target_ureg;
+typedef int32_t  target_sreg;
+#define TREG_FMT_lx   "%08"PRIx32
+#define TREG_FMT_ld   "%"PRId32
+#else
+typedef uint64_t target_ureg;
+typedef int64_t  target_sreg;
+#define TREG_FMT_lx   "%016"PRIx64
+#define TREG_FMT_ld   "%"PRId64
+#endif
+
 struct CPUHPPAState {
-target_ulong gr[32];
+target_ureg gr[32];
 uint64_t fr[32];
 
-target_ulong sar;
-target_ulong cr26;
-target_ulong cr27;
+target_ureg sar;
+target_ureg cr26;
+target_ureg cr27;
 
-target_long  psw;/* All psw bits except the following:  */
-target_ulong psw_n;  /* boolean */
-target_long  psw_v;  /* in most significant bit */
+target_ureg psw; /* All psw bits except the following:  */
+target_ureg psw_n;   /* boolean */
+target_sreg psw_v;   /* in most significant bit */
 
 /* Splitting the carry-borrow field into the MSB and "the rest", allows
  * for "the rest" to be deleted when it is unused, but the MSB is in use.
@@ -142,13 +154,13 @@ struct CPUHPPAState {
  * host has the appropriate add-with-carry insn to compute the msb).
  * Therefore the carry bits are stored as: cb_msb : cb & 0x1110.
  */
-target_ulong psw_cb; /* in least significant bit of next nibble */
-target_ulong psw_cb_msb; /* boolean */
+target_ureg psw_cb;  /* in least significant bit of next nibble */
+target_ureg psw_cb_msb;  /* boolean */
 
-target_ulong iaoq_f; /* front */
-target_ulong iaoq_b; /* back, aka next instruction */
+target_ureg iaoq_f;  /* front */
+target_ureg iaoq_b;  /* back, aka next instruction */
 
-target_ulong ior;/* interrupt offset register */
+target_ureg ior; /* interrupt offset register */
 
 uint32_t fr0_shadow; /* flags, c, ca/cq, rm, d, enables */
 float_status fp_status;
@@ -201,8 +213,8 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, 
target_ulong *pc,
 *pflags = env->psw_n;
 }
 
-target_ulong cpu_hppa_get_psw(CPUHPPAState *env);
-void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong);
+target_ureg cpu_hppa_get_psw(CPUHPPAState *env);
+void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg);
 void cpu_hppa_loaded_fr0(CPUHPPAState *env);
 
 #define cpu_signal_handler cpu_hppa_signal_handler
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 0a6b900555..c720de523b 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -1,14 +1,24 @@
+#if TARGET_REGISTER_BITS == 64
+# define dh_alias_tr i64
+# define dh_is_64bit_tr  1
+#else
+# define dh_alias_tr i32
+# define dh_is_64bit_tr  0
+#endif
+#define dh_ctype_tr  target_ureg
+#define dh_is_signed_tr  0
+
 DEF_HELPER_2(excp, noreturn, env, int)
-DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tl)
-DEF_HELPER_FLAGS_2(tcond, TCG_CALL_NO_WG, void, env, tl)
+DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tr)
+DEF_HELPER_FLAGS_2(tcond, TCG_CALL_NO_WG, void, env, tr)
 
-DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl)
-DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tl)
-DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tl)
-DEF_HELPER_FLAGS_3(stby_e_parallel, TCG_CALL_NO_WG, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tr)
+DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tr)
+DEF_HELPER_FLAGS_3(stby_e, TCG_CALL_NO_WG, void, env, tl, tr)
+DEF_HELPER_FLAGS_3(stby_e_parallel, TCG_CALL_NO_WG, void, env, tl, tr)
 
-DEF_HELPER_FLAGS_1(probe_r, TCG_CALL_NO_RWG_SE, tl, tl)
-DEF_HELPER_FLAGS_1(probe_w, TCG_CALL_NO_RWG_SE, tl, tl)

[Qemu-devel] [PATCH v3 35/45] target/hppa: Increase number of temp regs

2018-01-24 Thread Richard Henderson
HP-UX 10.20 CD contains "add r0, r0, r27" in a delay slot,
which uses at least 5 temps.

Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 5b7824f065..a93e86c9e3 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -277,7 +277,7 @@ typedef struct DisasContext {
 TCGv_reg iaoq_n_var;
 
 int ntempr, ntempl;
-TCGv_reg tempr[4];
+TCGv_reg tempr[8];
 TCGv_tl  templ[4];
 
 DisasCond null_cond;
-- 
2.14.3




[Qemu-devel] [PATCH v3 07/45] target/hppa: Implement the system mask instructions

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/helper.h|  4 +++
 target/hppa/op_helper.c | 14 
 target/hppa/translate.c | 96 -
 3 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index c720de523b..254a4da133 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -76,3 +76,7 @@ DEF_HELPER_FLAGS_4(fmpyfadd_s, TCG_CALL_NO_RWG, i32, env, 
i32, i32, i32)
 DEF_HELPER_FLAGS_4(fmpynfadd_s, TCG_CALL_NO_RWG, i32, env, i32, i32, i32)
 DEF_HELPER_FLAGS_4(fmpyfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
 DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
+
+#ifndef CONFIG_USER_ONLY
+DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr)
+#endif
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index 479bfc0fdf..1c3e043cc0 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -601,3 +601,17 @@ float64 HELPER(fmpynfadd_d)(CPUHPPAState *env, float64 a, 
float64 b, float64 c)
 update_fr0_op(env, GETPC());
 return ret;
 }
+
+#ifndef CONFIG_USER_ONLY
+target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm)
+{
+target_ulong psw = env->psw;
+/* ??? On second reading this condition simply seems
+   to be undefined rather than a diagnosed trap.  */
+if (nsm & ~psw & PSW_Q) {
+dynexcp(env, EXCP_ILL, GETPC());
+}
+env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM);
+return psw & PSW_SM;
+}
+#endif
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 33605a2d15..088031e7f3 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -299,6 +299,10 @@ typedef struct DisasContext {
updated the iaq for the next instruction to be executed.  */
 #define DISAS_IAQ_N_STALEDISAS_TARGET_1
 
+/* Similarly, but we want to return to the main loop immediately
+   to recognize unmasked interrupts.  */
+#define DISAS_IAQ_N_STALE_EXIT  DISAS_TARGET_2
+
 typedef struct DisasInsn {
 uint32_t insn, mask;
 DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn,
@@ -697,6 +701,14 @@ static DisasJumpType gen_illegal(DisasContext *ctx)
 return nullify_end(ctx, gen_excp(ctx, EXCP_ILL));
 }
 
+#define CHECK_MOST_PRIVILEGED(EXCP)   \
+do {  \
+if (ctx->privilege != 0) {\
+nullify_over(ctx);\
+return nullify_end(ctx, gen_excp(ctx, EXCP)); \
+} \
+} while (0)
+
 static bool use_goto_tb(DisasContext *ctx, target_ureg dest)
 {
 /* Suppress goto_tb in the case of single-steping and IO.  */
@@ -1982,6 +1994,79 @@ static DisasJumpType trans_ldsid(DisasContext *ctx, 
uint32_t insn,
 return DISAS_NEXT;
 }
 
+#ifndef CONFIG_USER_ONLY
+/* Note that ssm/rsm instructions number PSW_W and PSW_E differently.  */
+static target_ureg extract_sm_imm(uint32_t insn)
+{
+target_ureg val = extract32(insn, 16, 10);
+
+if (val & PSW_SM_E) {
+val = (val & ~PSW_SM_E) | PSW_E;
+}
+if (val & PSW_SM_W) {
+val = (val & ~PSW_SM_W) | PSW_W;
+}
+return val;
+}
+
+static DisasJumpType trans_rsm(DisasContext *ctx, uint32_t insn,
+   const DisasInsn *di)
+{
+unsigned rt = extract32(insn, 0, 5);
+target_ureg sm = extract_sm_imm(insn);
+TCGv_reg tmp;
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+nullify_over(ctx);
+
+tmp = get_temp(ctx);
+tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
+tcg_gen_andi_reg(tmp, tmp, ~sm);
+gen_helper_swap_system_mask(tmp, cpu_env, tmp);
+save_gpr(ctx, rt, tmp);
+
+/* Exit the TB to recognize new interrupts, e.g. PSW_M.  */
+return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
+}
+
+static DisasJumpType trans_ssm(DisasContext *ctx, uint32_t insn,
+   const DisasInsn *di)
+{
+unsigned rt = extract32(insn, 0, 5);
+target_ureg sm = extract_sm_imm(insn);
+TCGv_reg tmp;
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+nullify_over(ctx);
+
+tmp = get_temp(ctx);
+tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
+tcg_gen_ori_reg(tmp, tmp, sm);
+gen_helper_swap_system_mask(tmp, cpu_env, tmp);
+save_gpr(ctx, rt, tmp);
+
+/* Exit the TB to recognize new interrupts, e.g. PSW_I.  */
+return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
+}
+
+static DisasJumpType trans_mtsm(DisasContext *ctx, uint32_t insn,
+const DisasInsn *di)
+{
+unsigned rr = extract32(insn, 16, 5);
+TCGv_reg tmp, reg;
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+nullify_over(ctx);
+
+reg = load_gpr(ctx, rr);
+tmp = get_temp(ctx);
+gen_helper_swap_system_mask(tmp, 

[Qemu-devel] [PATCH v3 25/45] target/hppa: Implement LCI

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 082221f450..41e28ff64c 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2462,6 +2462,25 @@ static DisasJumpType trans_lpa(DisasContext *ctx, 
uint32_t insn,
 
 return nullify_end(ctx, DISAS_NEXT);
 }
+
+static DisasJumpType trans_lci(DisasContext *ctx, uint32_t insn,
+   const DisasInsn *di)
+{
+unsigned rt = extract32(insn, 0, 5);
+TCGv_reg ci;
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+
+/* The Coherence Index is an implementation-defined function of the
+   physical address.  Two addresses with the same CI have a coherent
+   view of the cache.  Our implementation is to return 0 for all,
+   since the entire address space is coherent.  */
+ci = tcg_const_reg(0);
+save_gpr(ctx, rt, ci);
+tcg_temp_free(ci);
+
+return DISAS_NEXT;
+}
 #endif /* !CONFIG_USER_ONLY */
 
 static const DisasInsn table_mem_mgmt[] = {
@@ -2490,6 +2509,7 @@ static const DisasInsn table_mem_mgmt[] = {
 { 0x04001200u, 0xfc001fdfu, trans_pxtlbx },   /* pdtlb */
 { 0x04001240u, 0xfc001fdfu, trans_pxtlbx },   /* pdtlbe */
 { 0x04001340u, 0xfc003fc0u, trans_lpa },
+{ 0x04001300u, 0xfc003fe0u, trans_lci },
 #endif
 };
 
-- 
2.14.3




[Qemu-devel] [PATCH v3 27/45] target/hppa: Implement halt and reset instructions

2018-01-24 Thread Richard Henderson
From: Helge Deller 

Real hardware would use an external device to control the power.
But for the moment let's invent instructions in reserved space,
to be used by our custom firmware.

Signed-off-by: Helge Deller 
Signed-off-by: Richard Henderson 
---
 target/hppa/helper.h|  2 ++
 target/hppa/op_helper.c | 13 +
 target/hppa/translate.c | 25 -
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 1e733b7926..31320740da 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -80,6 +80,8 @@ DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, 
i64, i64, i64)
 DEF_HELPER_FLAGS_0(read_interval_timer, TCG_CALL_NO_RWG, tr)
 
 #ifndef CONFIG_USER_ONLY
+DEF_HELPER_1(shutdown, noreturn, env)
+DEF_HELPER_1(reset, noreturn, env)
 DEF_HELPER_1(rfi, void, env)
 DEF_HELPER_1(rfi_r, void, env)
 DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr)
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index d270f94e31..c2eeced0e9 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -22,6 +22,7 @@
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 #include "exec/cpu_ldst.h"
+#include "sysemu/sysemu.h"
 #include "qemu/timer.h"
 
 
@@ -639,6 +640,18 @@ void HELPER(write_interval_timer)(CPUHPPAState *env, 
target_ureg val)
 timer_mod(cpu->alarm_timer, timeout);
 }
 
+void HELPER(shutdown)(CPUHPPAState *env)
+{
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+helper_excp(env, EXCP_HLT);
+}
+
+void HELPER(reset)(CPUHPPAState *env)
+{
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+helper_excp(env, EXCP_HLT);
+}
+
 target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm)
 {
 target_ulong psw = env->psw;
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index f3942b1baf..8c1ae4db78 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2302,6 +2302,18 @@ static DisasJumpType trans_rfi(DisasContext *ctx, 
uint32_t insn,
 /* Exit the TB to recognize new interrupts.  */
 return nullify_end(ctx, DISAS_NORETURN);
 }
+
+static DisasJumpType gen_hlt(DisasContext *ctx, int reset)
+{
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+nullify_over(ctx);
+if (reset) {
+gen_helper_reset(cpu_env);
+} else {
+gen_helper_shutdown(cpu_env);
+}
+return nullify_end(ctx, DISAS_NORETURN);
+}
 #endif /* !CONFIG_USER_ONLY */
 
 static const DisasInsn table_system[] = {
@@ -4519,7 +4531,18 @@ static DisasJumpType translate_one(DisasContext *ctx, 
uint32_t insn)
 case 0x15: /* unassigned */
 case 0x1D: /* unassigned */
 case 0x37: /* unassigned */
-case 0x3F: /* unassigned */
+break;
+case 0x3F:
+#ifndef CONFIG_USER_ONLY
+/* Unassigned, but use as system-halt.  */
+if (insn == 0xfffdead0) {
+return gen_hlt(ctx, 0); /* halt system */
+}
+if (insn == 0xfffdead1) {
+return gen_hlt(ctx, 1); /* reset system */
+}
+#endif
+break;
 default:
 break;
 }
-- 
2.14.3




[Qemu-devel] [PATCH v3 12/45] target/hppa: Fill in hppa_cpu_do_interrupt/hppa_cpu_exec_interrupt

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.c |   2 +
 target/hppa/helper.c  |  63 -
 target/hppa/int_helper.c  | 176 ++
 target/hppa/translate.c   |  16 -
 target/hppa/Makefile.objs |   1 +
 5 files changed, 192 insertions(+), 66 deletions(-)
 create mode 100644 target/hppa/int_helper.c

diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 9962ab71ee..ca619578dd 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -106,8 +106,10 @@ static void hppa_cpu_initfn(Object *obj)
 CPUHPPAState *env = >env;
 
 cs->env_ptr = env;
+cs->exception_index = -1;
 cpu_hppa_loaded_fr0(env);
 set_snan_bit_is_one(true, >fp_status);
+cpu_hppa_put_psw(env, PSW_W);
 }
 
 static ObjectClass *hppa_cpu_class_by_name(const char *cpu_model)
diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index 48ac80cb2d..6e8758f82c 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -67,69 +67,6 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw)
 env->psw_cb = cb;
 }
 
-void hppa_cpu_do_interrupt(CPUState *cs)
-{
-HPPACPU *cpu = HPPA_CPU(cs);
-CPUHPPAState *env = >env;
-int i = cs->exception_index;
-
-if (qemu_loglevel_mask(CPU_LOG_INT)) {
-static const char * const names[] = {
-[EXCP_HPMC]  = "high priority machine check",
-[EXCP_POWER_FAIL]= "power fail interrupt",
-[EXCP_RC]= "recovery counter trap",
-[EXCP_EXT_INTERRUPT] = "external interrupt",
-[EXCP_LPMC]  = "low priority machine check",
-[EXCP_ITLB_MISS] = "instruction tlb miss fault",
-[EXCP_IMP]   = "instruction memory protection trap",
-[EXCP_ILL]   = "illegal instruction trap",
-[EXCP_BREAK] = "break instruction trap",
-[EXCP_PRIV_OPR]  = "privileged operation trap",
-[EXCP_PRIV_REG]  = "privileged register trap",
-[EXCP_OVERFLOW]  = "overflow trap",
-[EXCP_COND]  = "conditional trap",
-[EXCP_ASSIST]= "assist exception trap",
-[EXCP_DTLB_MISS] = "data tlb miss fault",
-[EXCP_NA_ITLB_MISS]  = "non-access instruction tlb miss",
-[EXCP_NA_DTLB_MISS]  = "non-access data tlb miss",
-[EXCP_DMP]   = "data memory protection trap",
-[EXCP_DMB]   = "data memory break trap",
-[EXCP_TLB_DIRTY] = "tlb dirty bit trap",
-[EXCP_PAGE_REF]  = "page reference trap",
-[EXCP_ASSIST_EMU]= "assist emulation trap",
-[EXCP_HPT]   = "high-privilege transfer trap",
-[EXCP_LPT]   = "low-privilege transfer trap",
-[EXCP_TB]= "taken branch trap",
-[EXCP_DMAR]  = "data memory access rights trap",
-[EXCP_DMPI]  = "data memory protection id trap",
-[EXCP_UNALIGN]   = "unaligned data reference trap",
-[EXCP_PER_INTERRUPT] = "performance monitor interrupt",
-[EXCP_SYSCALL]   = "syscall",
-[EXCP_SYSCALL_LWS]   = "syscall-lws",
-};
-static int count;
-const char *name = NULL;
-
-if (i >= 0 && i < ARRAY_SIZE(names)) {
-name = names[i];
-}
-if (name) {
-qemu_log("INT %6d: %s ia_f=" TARGET_FMT_lx "\n",
- ++count, name, env->iaoq_f);
-} else {
-qemu_log("INT %6d: unknown %d ia_f=" TARGET_FMT_lx "\n",
- ++count, i, env->iaoq_f);
-}
-}
-cs->exception_index = -1;
-}
-
-bool hppa_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
-{
-abort();
-return false;
-}
-
 void hppa_cpu_dump_state(CPUState *cs, FILE *f,
  fprintf_function cpu_fprintf, int flags)
 {
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
new file mode 100644
index 00..a59aae1189
--- /dev/null
+++ b/target/hppa/int_helper.c
@@ -0,0 +1,176 @@
+/*
+ *  HPPA interrupt helper routines
+ *
+ *  Copyright (c) 2017 Richard Henderson
+ *
+ * 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-devel] [PATCH v3 06/45] target/hppa: Implement mmu_idx from IA privilege level

2018-01-24 Thread Richard Henderson
Most aspects of privilege are not yet handled.  But this
gives us the start from which to begin checking.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h   | 19 +
 target/hppa/cpu.c   |  2 +-
 target/hppa/translate.c | 55 ++---
 3 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 1524ef91b6..805c93db9c 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -36,8 +36,10 @@
 #define TARGET_PAGE_BITS 12
 
 #define ALIGNED_ONLY
-#define NB_MMU_MODES 1
-#define MMU_USER_IDX 0
+#define NB_MMU_MODES 5
+#define MMU_KERNEL_IDX   0
+#define MMU_USER_IDX 3
+#define MMU_PHYS_IDX 4
 #define TARGET_INSN_START_EXTRA_WORDS 1
 
 /* Hardware exceptions, interupts, faults, and traps.  */
@@ -195,7 +197,14 @@ static inline HPPACPU *hppa_env_get_cpu(CPUHPPAState *env)
 
 static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch)
 {
-return 0;
+#ifdef CONFIG_USER_ONLY
+return MMU_USER_IDX;
+#else
+if (env->psw & (ifetch ? PSW_C : PSW_D)) {
+return env->iaoq_f & 3;
+}
+return MMU_PHYS_IDX;  /* mmu disabled */
+#endif
 }
 
 void hppa_translate_init(void);
@@ -210,7 +219,9 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, 
target_ulong *pc,
 {
 *pc = env->iaoq_f;
 *cs_base = env->iaoq_b;
-*pflags = env->psw_n;
+/* ??? E, T, H, L, B, P bits need to be here, when implemented.  */
+*pflags = (env->psw & (PSW_W | PSW_C | PSW_D))
+| env->psw_n * PSW_N;
 }
 
 target_ureg cpu_hppa_get_psw(CPUHPPAState *env);
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index f6d92de972..9962ab71ee 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -39,7 +39,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, 
TranslationBlock *tb)
 
 cpu->env.iaoq_f = tb->pc;
 cpu->env.iaoq_b = tb->cs_base;
-cpu->env.psw_n = tb->flags & 1;
+cpu->env.psw_n = (tb->flags & PSW_N) != 0;
 }
 
 static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index dd96147bf1..33605a2d15 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -282,6 +282,8 @@ typedef struct DisasContext {
 DisasCond null_cond;
 TCGLabel *null_lab;
 
+int mmu_idx;
+int privilege;
 bool psw_n_nonzero;
 } DisasContext;
 
@@ -1299,10 +1301,10 @@ static void do_load_32(DisasContext *ctx, TCGv_i32 
dest, unsigned rb,
 }
 
 if (modify == 0) {
-tcg_gen_qemu_ld_i32(dest, addr, MMU_USER_IDX, mop);
+tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop);
 } else {
 tcg_gen_qemu_ld_i32(dest, (modify < 0 ? addr : base),
-MMU_USER_IDX, mop);
+ctx->mmu_idx, mop);
 save_gpr(ctx, rb, addr);
 }
 tcg_temp_free(addr);
@@ -1329,10 +1331,10 @@ static void do_load_64(DisasContext *ctx, TCGv_i64 
dest, unsigned rb,
 }
 
 if (modify == 0) {
-tcg_gen_qemu_ld_i64(dest, addr, MMU_USER_IDX, mop);
+tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop);
 } else {
 tcg_gen_qemu_ld_i64(dest, (modify < 0 ? addr : base),
-MMU_USER_IDX, mop);
+ctx->mmu_idx, mop);
 save_gpr(ctx, rb, addr);
 }
 tcg_temp_free(addr);
@@ -1358,7 +1360,7 @@ static void do_store_32(DisasContext *ctx, TCGv_i32 src, 
unsigned rb,
 tcg_gen_addi_reg(addr, base, disp);
 }
 
-tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), MMU_USER_IDX, mop);
+tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop);
 
 if (modify != 0) {
 save_gpr(ctx, rb, addr);
@@ -1386,7 +1388,7 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, 
unsigned rb,
 tcg_gen_addi_reg(addr, base, disp);
 }
 
-tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), MMU_USER_IDX, mop);
+tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop);
 
 if (modify != 0) {
 save_gpr(ctx, rb, addr);
@@ -2497,7 +2499,7 @@ static DisasJumpType trans_ldcw(DisasContext *ctx, 
uint32_t insn,
 
 zero = tcg_const_reg(0);
 tcg_gen_atomic_xchg_reg(dest, (modify <= 0 ? addr : base),
-zero, MMU_USER_IDX, mop);
+zero, ctx->mmu_idx, mop);
 if (modify) {
 save_gpr(ctx, rb, addr);
 }
@@ -3971,30 +3973,43 @@ static int hppa_tr_init_disas_context(DisasContextBase 
*dcbase,
   CPUState *cs, int max_insns)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
-TranslationBlock *tb = ctx->base.tb;
 int bound;
 
 ctx->cs = cs;
-ctx->iaoq_f = tb->pc;
-ctx->iaoq_b = tb->cs_base;
+
+#ifdef CONFIG_USER_ONLY
+ctx->privilege = MMU_USER_IDX;
+ctx->mmu_idx = 

[Qemu-devel] [PATCH v3 24/45] target/hppa: Implement LPA

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h|  1 +
 target/hppa/helper.h |  1 +
 target/hppa/mem_helper.c | 21 +
 target/hppa/op_helper.c  | 10 +-
 target/hppa/translate.c  | 30 ++
 5 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 31a3702684..a6e4091b6a 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -344,5 +344,6 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr 
addr, int mmu_idx,
 extern const MemoryRegionOps hppa_io_eir_ops;
 void hppa_cpu_alarm_timer(void *);
 #endif
+void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t 
ra);
 
 #endif /* HPPA_CPU_H */
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index f059ddf3b9..1e733b7926 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -90,4 +90,5 @@ DEF_HELPER_FLAGS_3(itlba, TCG_CALL_NO_RWG, void, env, tl, tr)
 DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr)
 DEF_HELPER_FLAGS_2(ptlb, TCG_CALL_NO_RWG, void, env, tl)
 DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tr, env, tl)
 #endif
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 2835d890f2..fbe2e19d5d 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -307,4 +307,25 @@ void HELPER(ptlbe)(CPUHPPAState *env)
 memset(env->tlb, 0, sizeof(env->tlb));
 tlb_flush_by_mmuidx(src, 0xf);
 }
+
+target_ureg HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
+{
+hwaddr phys;
+int prot, excp;
+
+excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX,
+ MMU_DATA_LOAD, , );
+if (excp >= 0) {
+if (env->psw & PSW_Q) {
+/* ??? Needs tweaking for hppa64.  */
+env->cr[CR_IOR] = addr;
+env->cr[CR_ISR] = addr >> 32;
+}
+if (excp == EXCP_DTLB_MISS) {
+excp = EXCP_NA_DTLB_MISS;
+}
+hppa_dynamic_excp(env, excp, GETPC());
+}
+return phys;
+}
 #endif /* CONFIG_USER_ONLY */
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index 6d19cab6c9..d270f94e31 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -34,7 +34,7 @@ void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp)
 cpu_loop_exit(cs);
 }
 
-static void QEMU_NORETURN dynexcp(CPUHPPAState *env, int excp, uintptr_t ra)
+void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra)
 {
 HPPACPU *cpu = hppa_env_get_cpu(env);
 CPUState *cs = CPU(cpu);
@@ -46,14 +46,14 @@ static void QEMU_NORETURN dynexcp(CPUHPPAState *env, int 
excp, uintptr_t ra)
 void HELPER(tsv)(CPUHPPAState *env, target_ureg cond)
 {
 if (unlikely((target_sreg)cond < 0)) {
-dynexcp(env, EXCP_OVERFLOW, GETPC());
+hppa_dynamic_excp(env, EXCP_OVERFLOW, GETPC());
 }
 }
 
 void HELPER(tcond)(CPUHPPAState *env, target_ureg cond)
 {
 if (unlikely(cond)) {
-dynexcp(env, EXCP_COND, GETPC());
+hppa_dynamic_excp(env, EXCP_COND, GETPC());
 }
 }
 
@@ -237,7 +237,7 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
 env->fr[0] = (uint64_t)shadow << 32;
 
 if (hard_exp & shadow) {
-dynexcp(env, EXCP_ASSIST, ra);
+hppa_dynamic_excp(env, EXCP_ASSIST, ra);
 }
 }
 
@@ -645,7 +645,7 @@ target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, 
target_ureg nsm)
 /* ??? On second reading this condition simply seems
to be undefined rather than a diagnosed trap.  */
 if (nsm & ~psw & PSW_Q) {
-dynexcp(env, EXCP_ILL, GETPC());
+hppa_dynamic_excp(env, EXCP_ILL, GETPC());
 }
 env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM);
 return psw & PSW_SM;
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 3d441ef4ac..082221f450 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2433,6 +2433,35 @@ static DisasJumpType trans_pxtlbx(DisasContext *ctx, 
uint32_t insn,
 return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C)
? DISAS_IAQ_N_STALE : DISAS_NEXT);
 }
+
+static DisasJumpType trans_lpa(DisasContext *ctx, uint32_t insn,
+   const DisasInsn *di)
+{
+unsigned rt = extract32(insn, 0, 5);
+unsigned m = extract32(insn, 5, 1);
+unsigned sp = extract32(insn, 14, 2);
+unsigned rx = extract32(insn, 16, 5);
+unsigned rb = extract32(insn, 21, 5);
+TCGv_tl vaddr;
+TCGv_reg ofs, paddr;
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+nullify_over(ctx);
+
+form_gva(ctx, , , rb, rx, 0, 0, sp, m, false);
+
+paddr = tcg_temp_new();
+gen_helper_lpa(paddr, cpu_env, vaddr);
+
+/* Note that physical address result overrides base modification.  */
+if (m) {
+save_gpr(ctx, rb, ofs);
+}
+save_gpr(ctx, rt, paddr);
+

[Qemu-devel] [PATCH v3 22/45] target/hppa: Implement P*TLB and P*TLBE insns

2018-01-24 Thread Richard Henderson
We now have all of the TLB manipulation instructions.

Signed-off-by: Richard Henderson 
---
 target/hppa/helper.h |  2 ++
 target/hppa/mem_helper.c | 37 +
 target/hppa/translate.c  | 40 
 3 files changed, 79 insertions(+)

diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index d412093914..f059ddf3b9 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -88,4 +88,6 @@ DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr)
 DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr)
 DEF_HELPER_FLAGS_3(itlba, TCG_CALL_NO_RWG, void, env, tl, tr)
 DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr)
+DEF_HELPER_FLAGS_2(ptlb, TCG_CALL_NO_RWG, void, env, tl)
+DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env)
 #endif
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 7c3c7d1415..2835d890f2 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -270,4 +270,41 @@ void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, 
target_ureg reg)
 ent->t = extract32(reg, 29, 1);
 ent->entry_valid = 1;
 }
+
+/* Purge (Insn/Data) TLB.  This is explicitly page-based, and is
+   synchronous across all processors.  */
+static void ptlb_work(CPUState *cpu, run_on_cpu_data data)
+{
+CPUHPPAState *env = cpu->env_ptr;
+target_ulong addr = (target_ulong) data.target_ptr;
+hppa_tlb_entry *ent = hppa_find_tlb(env, addr);
+
+if (ent && ent->entry_valid) {
+hppa_flush_tlb_ent(env, ent);
+}
+}
+
+void HELPER(ptlb)(CPUHPPAState *env, target_ulong addr)
+{
+CPUState *src = CPU(hppa_env_get_cpu(env));
+CPUState *cpu;
+run_on_cpu_data data = RUN_ON_CPU_TARGET_PTR(addr);
+
+CPU_FOREACH(cpu) {
+if (cpu != src) {
+async_run_on_cpu(cpu, ptlb_work, data);
+}
+}
+async_safe_run_on_cpu(src, ptlb_work, data);
+}
+
+/* Purge (Insn/Data) TLB entry.  This affects an implementation-defined
+   number of pages/entries (we choose all), and is local to the cpu.  */
+void HELPER(ptlbe)(CPUHPPAState *env)
+{
+CPUState *src = CPU(hppa_env_get_cpu(env));
+
+memset(env->tlb, 0, sizeof(env->tlb));
+tlb_flush_by_mmuidx(src, 0xf);
+}
 #endif /* CONFIG_USER_ONLY */
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index c02d107041..5b77688fc0 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2397,6 +2397,42 @@ static DisasJumpType trans_ixtlbx(DisasContext *ctx, 
uint32_t insn,
 return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C)
? DISAS_IAQ_N_STALE : DISAS_NEXT);
 }
+
+static DisasJumpType trans_pxtlbx(DisasContext *ctx, uint32_t insn,
+  const DisasInsn *di)
+{
+unsigned m = extract32(insn, 5, 1);
+unsigned sp;
+unsigned rx = extract32(insn, 16, 5);
+unsigned rb = extract32(insn, 21, 5);
+unsigned is_data = insn & 0x1000;
+unsigned is_local = insn & 0x40;
+TCGv_tl addr;
+TCGv_reg ofs;
+
+if (is_data) {
+sp = extract32(insn, 14, 2);
+} else {
+sp = ~assemble_sr3(insn);
+}
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+nullify_over(ctx);
+
+form_gva(ctx, , , rb, rx, 0, 0, sp, m, false);
+if (m) {
+save_gpr(ctx, rb, ofs);
+}
+if (is_local) {
+gen_helper_ptlbe(cpu_env);
+} else {
+gen_helper_ptlb(cpu_env, addr);
+}
+
+/* Exit TB for TLB change if mmu is enabled.  */
+return nullify_end(ctx, !is_data && (ctx->base.tb->flags & PSW_C)
+   ? DISAS_IAQ_N_STALE : DISAS_NEXT);
+}
 #endif /* !CONFIG_USER_ONLY */
 
 static const DisasInsn table_mem_mgmt[] = {
@@ -2420,6 +2456,10 @@ static const DisasInsn table_mem_mgmt[] = {
 { 0x0440u, 0xfc001fffu, trans_ixtlbx },   /* iitlba */
 { 0x04001000u, 0xfc001fffu, trans_ixtlbx },   /* idtlbp */
 { 0x04001040u, 0xfc001fffu, trans_ixtlbx },   /* idtlba */
+{ 0x04000200u, 0xfc001fdfu, trans_pxtlbx },   /* pitlb */
+{ 0x04000240u, 0xfc001fdfu, trans_pxtlbx },   /* pitlbe */
+{ 0x04001200u, 0xfc001fdfu, trans_pxtlbx },   /* pdtlb */
+{ 0x04001240u, 0xfc001fdfu, trans_pxtlbx },   /* pdtlbe */
 #endif
 };
 
-- 
2.14.3




[Qemu-devel] [PATCH v3 10/45] target/hppa: Adjust insn mask for mfctl, w

2018-01-24 Thread Richard Henderson
While the E bit is only used for pa2.0 mfctl,w from sar,
the otherwise reserved bit does not appear to be decoded.

Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 89b336c2c4..8ca58f3df3 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2162,7 +2162,7 @@ static const DisasInsn table_system[] = {
 { 0x016018c0u, 0xffe0u, trans_mtsarcm },
 { 0x14a0u, 0xffe0u, trans_mfia },
 { 0x04a0u, 0x1fe0u, trans_mfsp },
-{ 0x08a0u, 0xfc1fffe0u, trans_mfctl },
+{ 0x08a0u, 0xfc1fbfe0u, trans_mfctl },
 { 0x0400u, 0xu, trans_sync },
 { 0x10a0u, 0xfc1f3fe0u, trans_ldsid },
 #ifndef CONFIG_USER_ONLY
-- 
2.14.3




[Qemu-devel] [PATCH v3 03/45] target/hppa: Disable gateway page emulation for system mode

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/translate.c | 27 +--
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 31d9a2a31b..8e357cc60c 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1543,6 +1543,7 @@ static DisasJumpType do_ibranch(DisasContext *ctx, TCGv 
dest,
 return DISAS_NEXT;
 }
 
+#ifdef CONFIG_USER_ONLY
 /* On Linux, page zero is normally marked execute only + gateway.
Therefore normal read or write is supposed to fail, but specific
offsets have kernel code mapped to raise permissions to implement
@@ -1600,6 +1601,7 @@ static DisasJumpType do_page_zero(DisasContext *ctx)
 return DISAS_NORETURN;
 }
 }
+#endif
 
 static DisasJumpType trans_nop(DisasContext *ctx, uint32_t insn,
const DisasInsn *di)
@@ -3787,10 +3789,13 @@ static void hppa_tr_translate_insn(DisasContextBase 
*dcbase, CPUState *cs)
 int i, n;
 
 /* Execute one insn.  */
+#ifdef CONFIG_USER_ONLY
 if (ctx->iaoq_f < TARGET_PAGE_SIZE) {
 ret = do_page_zero(ctx);
 assert(ret != DISAS_NEXT);
-} else {
+} else
+#endif
+{
 /* Always fetch the insn, even if nullified, so that we check
the page permissions for execute.  */
 uint32_t insn = cpu_ldl_code(env, ctx->iaoq_f);
@@ -3885,25 +3890,27 @@ static void hppa_tr_tb_stop(DisasContextBase *dcbase, 
CPUState *cs)
 static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
 {
 TranslationBlock *tb = dcbase->tb;
+target_ulong pc = tb->pc;
 
-switch (tb->pc) {
+#ifdef CONFIG_USER_ONLY
+switch (pc) {
 case 0x00:
 qemu_log("IN:\n0x:  (null)\n");
-break;
+return;
 case 0xb0:
 qemu_log("IN:\n0x00b0:  light-weight-syscall\n");
-break;
+return;
 case 0xe0:
 qemu_log("IN:\n0x00e0:  set-thread-pointer-syscall\n");
-break;
+return;
 case 0x100:
 qemu_log("IN:\n0x0100:  syscall\n");
-break;
-default:
-qemu_log("IN: %s\n", lookup_symbol(tb->pc));
-log_target_disas(cs, tb->pc, tb->size);
-break;
+return;
 }
+#endif
+
+qemu_log("IN: %s\n", lookup_symbol(pc));
+log_target_disas(cs, pc, tb->size);
 }
 
 static const TranslatorOps hppa_tr_ops = {
-- 
2.14.3




[Qemu-devel] [PATCH v3 18/45] target/hppa: Implement external interrupts

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h|  1 +
 target/hppa/helper.h |  2 ++
 target/hppa/cpu.c|  6 +
 target/hppa/int_helper.c | 59 
 target/hppa/translate.c  | 16 -
 5 files changed, 83 insertions(+), 1 deletion(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index c7a2fb5b20..fc3e62c0af 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -340,6 +340,7 @@ int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, 
int rw, int midx);
 #else
 int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
   MMUAccessType type, hwaddr *pphys, int *pprot);
+extern const MemoryRegionOps hppa_io_eir_ops;
 #endif
 
 #endif /* HPPA_CPU_H */
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 79d22ae486..535f086ab4 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -80,5 +80,7 @@ DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, 
i64, i64, i64)
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_1(rfi, void, env)
 DEF_HELPER_1(rfi_r, void, env)
+DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tr)
+DEF_HELPER_FLAGS_2(write_eiem, TCG_CALL_NO_RWG, void, env, tr)
 DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr)
 #endif
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 2970afd58d..888a48f16d 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -57,6 +57,11 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, 
TranslationBlock *tb)
 cpu->env.psw_n = (tb->flags & PSW_N) != 0;
 }
 
+static bool hppa_cpu_has_work(CPUState *cs)
+{
+return cs->interrupt_request & CPU_INTERRUPT_HARD;
+}
+
 static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
 {
 info->mach = bfd_mach_hppa20;
@@ -159,6 +164,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
 dc->realize = hppa_cpu_realizefn;
 
 cc->class_by_name = hppa_cpu_class_by_name;
+cc->has_work = hppa_cpu_has_work;
 cc->do_interrupt = hppa_cpu_do_interrupt;
 cc->cpu_exec_interrupt = hppa_cpu_exec_interrupt;
 cc->dump_state = hppa_cpu_dump_state;
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index 5ae5233a96..249e14a2a1 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -24,6 +24,65 @@
 #include "exec/helper-proto.h"
 #include "qom/cpu.h"
 
+#ifndef CONFIG_USER_ONLY
+static void eval_interrupt(HPPACPU *cpu)
+{
+CPUState *cs = CPU(cpu);
+if (cpu->env.cr[CR_EIRR] & cpu->env.cr[CR_EIEM]) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+}
+
+/* Each CPU has a word mapped into the GSC bus.  Anything on the GSC bus
+ * can write to this word to raise an external interrupt on the target CPU.
+ * This includes the system controler (DINO) for regular devices, or
+ * another CPU for SMP interprocessor interrupts.
+ */
+static uint64_t io_eir_read(void *opaque, hwaddr addr, unsigned size)
+{
+HPPACPU *cpu = opaque;
+
+/* ??? What does a read of this register over the GSC bus do?  */
+return cpu->env.cr[CR_EIRR];
+}
+
+static void io_eir_write(void *opaque, hwaddr addr,
+ uint64_t data, unsigned size)
+{
+HPPACPU *cpu = opaque;
+int le_bit = ~data & (TARGET_REGISTER_BITS - 1);
+
+cpu->env.cr[CR_EIRR] |= (target_ureg)1 << le_bit;
+eval_interrupt(cpu);
+}
+
+const MemoryRegionOps hppa_io_eir_ops = {
+.read = io_eir_read,
+.write = io_eir_write,
+.valid.min_access_size = 4,
+.valid.max_access_size = 4,
+.impl.min_access_size = 4,
+.impl.max_access_size = 4,
+};
+
+void HELPER(write_eirr)(CPUHPPAState *env, target_ureg val)
+{
+env->cr[CR_EIRR] &= ~val;
+qemu_mutex_lock_iothread();
+eval_interrupt(hppa_env_get_cpu(env));
+qemu_mutex_unlock_iothread();
+}
+
+void HELPER(write_eiem)(CPUHPPAState *env, target_ureg val)
+{
+env->cr[CR_EIEM] = val;
+qemu_mutex_lock_iothread();
+eval_interrupt(hppa_env_get_cpu(env));
+qemu_mutex_unlock_iothread();
+}
+#endif /* !CONFIG_USER_ONLY */
 
 void hppa_cpu_do_interrupt(CPUState *cs)
 {
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 44abc9006b..d6c65f314b 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2124,12 +2124,25 @@ static DisasJumpType trans_mtctl(DisasContext *ctx, 
uint32_t insn,
 /* All other control registers are privileged or read-only.  */
 CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
 
+#ifdef CONFIG_USER_ONLY
+g_assert_not_reached();
+#else
+DisasJumpType ret = DISAS_NEXT;
+
 nullify_over(ctx);
 switch (ctl) {
 case CR_IT:
 /* ??? modify interval timer offset */
 break;
 
+case CR_EIRR:
+gen_helper_write_eirr(cpu_env, reg);
+break;
+case CR_EIEM:
+gen_helper_write_eiem(cpu_env, reg);
+ret 

[Qemu-devel] [PATCH v3 16/45] target/hppa: Implement IASQ

2018-01-24 Thread Richard Henderson
Any one TB will have only one space value.  If we change spaces,
we change TBs.  Thus BE and BEV must exit the TB immediately.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h|  53 -
 target/hppa/cpu.c|  15 ++
 target/hppa/helper.c |   3 +-
 target/hppa/int_helper.c |  16 +--
 target/hppa/op_helper.c  |   2 +
 target/hppa/translate.c  | 117 ++-
 6 files changed, 179 insertions(+), 27 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 94f9c8ca2b..d583ea43dd 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -186,6 +186,8 @@ struct CPUHPPAState {
 
 target_ureg iaoq_f;  /* front */
 target_ureg iaoq_b;  /* back, aka next instruction */
+uint64_t iasq_f;
+uint64_t iasq_b;
 
 uint32_t fr0_shadow; /* flags, c, ca/cq, rm, d, enables */
 float_status fp_status;
@@ -240,15 +242,62 @@ void hppa_translate_init(void);
 
 void hppa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 
+static inline target_ulong hppa_form_gva_psw(target_ureg psw, uint64_t spc,
+ target_ureg off)
+{
+#ifdef CONFIG_USER_ONLY
+return off;
+#else
+off &= (psw & PSW_W ? 0x3fffull : 0xull);
+return spc | off;
+#endif
+}
+
+static inline target_ulong hppa_form_gva(CPUHPPAState *env, uint64_t spc,
+ target_ureg off)
+{
+return hppa_form_gva_psw(env->psw, spc, off);
+}
+
+/* Since PSW_CB will never need to be in tb->flags, reuse them.  */
+#define TB_FLAG_PRIV_SHIFT  8
+
 static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc,
 target_ulong *cs_base,
 uint32_t *pflags)
 {
+uint32_t flags = env->psw_n * PSW_N;
+
+/* TB lookup assumes that PC contains the complete virtual address.
+   If we leave space+offset separate, we'll get ITLB misses to an
+   incomplete virtual address.  This also means that we must separate
+   out current cpu priviledge from the low bits of IAOQ_F.  */
+#ifdef CONFIG_USER_ONLY
 *pc = env->iaoq_f;
 *cs_base = env->iaoq_b;
+#else
 /* ??? E, T, H, L, B, P bits need to be here, when implemented.  */
-*pflags = (env->psw & (PSW_W | PSW_C | PSW_D))
-| env->psw_n * PSW_N;
+flags |= env->psw & (PSW_W | PSW_C | PSW_D);
+flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
+
+*pc = (env->psw & PSW_C
+   ? hppa_form_gva_psw(env->psw, env->iasq_f, env->iaoq_f & -4)
+   : env->iaoq_f & -4);
+*cs_base = env->iasq_f;
+
+/* Insert a difference between IAOQ_B and IAOQ_F within the otherwise zero
+   low 32-bits of CS_BASE.  This will succeed for all direct branches,
+   which is the primary case we care about -- using goto_tb within a page.
+   Failure is indicated by a zero difference.  */
+if (env->iasq_f == env->iasq_b) {
+target_sreg diff = env->iaoq_b - env->iaoq_f;
+if (TARGET_REGISTER_BITS == 32 || diff == (int32_t)diff) {
+*cs_base |= (uint32_t)diff;
+}
+}
+#endif
+
+*pflags = flags;
 }
 
 target_ureg cpu_hppa_get_psw(CPUHPPAState *env);
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 4d0b760baa..2970afd58d 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -37,8 +37,23 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, 
TranslationBlock *tb)
 {
 HPPACPU *cpu = HPPA_CPU(cs);
 
+#ifdef CONFIG_USER_ONLY
 cpu->env.iaoq_f = tb->pc;
 cpu->env.iaoq_b = tb->cs_base;
+#else
+/* Recover the IAOQ values from the GVA + PRIV.  */
+uint32_t priv = (tb->flags >> TB_FLAG_PRIV_SHIFT) & 3;
+target_ulong cs_base = tb->cs_base;
+target_ulong iasq_f = cs_base & ~0xull;
+int32_t diff = cs_base;
+
+cpu->env.iasq_f = iasq_f;
+cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv;
+if (diff) {
+cpu->env.iaoq_b = cpu->env.iaoq_f + diff;
+}
+#endif
+
 cpu->env.psw_n = (tb->flags & PSW_N) != 0;
 }
 
diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index 6e8758f82c..858ec205b6 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -78,7 +78,8 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f,
 int i;
 
 cpu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx "\n",
-(target_ulong)env->iaoq_f, (target_ulong)env->iaoq_b);
+hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f),
+hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b));
 
 psw_c[0]  = (psw & PSW_W ? 'W' : '-');
 psw_c[1]  = (psw & PSW_E ? 'E' : '-');
diff --git a/target/hppa/int_helper.c b/target/hppa/int_helper.c
index a59aae1189..02963b80c6 100644
--- a/target/hppa/int_helper.c
+++ b/target/hppa/int_helper.c
@@ -32,6 +32,8 @@ void hppa_cpu_do_interrupt(CPUState *cs)
 int i = 

[Qemu-devel] [PATCH v3 04/45] target/hppa: Define hardware exception types

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h| 39 +++
 linux-user/main.c| 26 ++---
 target/hppa/helper.c | 61 ++--
 target/hppa/mem_helper.c |  4 +++-
 target/hppa/op_helper.c  |  6 ++---
 target/hppa/translate.c  |  8 +++
 6 files changed, 111 insertions(+), 33 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index ea7e495408..d84af91860 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -40,11 +40,40 @@
 #define MMU_USER_IDX 0
 #define TARGET_INSN_START_EXTRA_WORDS 1
 
-#define EXCP_SYSCALL 1
-#define EXCP_SYSCALL_LWS 2
-#define EXCP_SIGSEGV 3
-#define EXCP_SIGILL  4
-#define EXCP_SIGFPE  5
+/* Hardware exceptions, interupts, faults, and traps.  */
+#define EXCP_HPMC1  /* high priority machine check */
+#define EXCP_POWER_FAIL  2
+#define EXCP_RC  3  /* recovery counter */
+#define EXCP_EXT_INTERRUPT   4  /* external interrupt */
+#define EXCP_LPMC5  /* low priority machine check */
+#define EXCP_ITLB_MISS   6  /* itlb miss / instruction page fault */
+#define EXCP_IMP 7  /* instruction memory protection trap */
+#define EXCP_ILL 8  /* illegal instruction trap */
+#define EXCP_BREAK   9  /* break instruction */
+#define EXCP_PRIV_OPR10 /* privileged operation trap */
+#define EXCP_PRIV_REG11 /* privileged register trap */
+#define EXCP_OVERFLOW12 /* signed overflow trap */
+#define EXCP_COND13 /* trap-on-condition */
+#define EXCP_ASSIST  14 /* assist exception trap */
+#define EXCP_DTLB_MISS   15 /* dtlb miss / data page fault */
+#define EXCP_NA_ITLB_MISS16 /* non-access itlb miss */
+#define EXCP_NA_DTLB_MISS17 /* non-access dtlb miss */
+#define EXCP_DMP 18 /* data memory protection trap */
+#define EXCP_DMB 19 /* data memory break trap */
+#define EXCP_TLB_DIRTY   20 /* tlb dirty bit trap */
+#define EXCP_PAGE_REF21 /* page reference trap */
+#define EXCP_ASSIST_EMU  22 /* assist emulation trap */
+#define EXCP_HPT 23 /* high-privilege transfer trap */
+#define EXCP_LPT 24 /* low-privilege transfer trap */
+#define EXCP_TB  25 /* taken branch trap */
+#define EXCP_DMAR26 /* data memory access rights trap */
+#define EXCP_DMPI27 /* data memory protection id trap */
+#define EXCP_UNALIGN 28 /* unaligned data reference trap */
+#define EXCP_PER_INTERRUPT   29 /* performance monitor interrupt */
+
+/* Exceptions for linux-user emulation.  */
+#define EXCP_SYSCALL 30
+#define EXCP_SYSCALL_LWS 31
 
 /* Taken from Linux kernel: arch/parisc/include/asm/psw.h */
 #define PSW_I0x0001
diff --git a/linux-user/main.c b/linux-user/main.c
index 450eb3ce65..42f4c66ce6 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3768,21 +3768,41 @@ void cpu_loop(CPUHPPAState *env)
 env->iaoq_f = env->gr[31];
 env->iaoq_b = env->gr[31] + 4;
 break;
-case EXCP_SIGSEGV:
+case EXCP_ITLB_MISS:
+case EXCP_DTLB_MISS:
+case EXCP_NA_ITLB_MISS:
+case EXCP_NA_DTLB_MISS:
+case EXCP_IMP:
+case EXCP_DMP:
+case EXCP_DMB:
+case EXCP_PAGE_REF:
+case EXCP_DMAR:
+case EXCP_DMPI:
 info.si_signo = TARGET_SIGSEGV;
 info.si_errno = 0;
 info.si_code = TARGET_SEGV_ACCERR;
 info._sifields._sigfault._addr = env->ior;
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, );
 break;
-case EXCP_SIGILL:
+case EXCP_UNALIGN:
+info.si_signo = TARGET_SIGBUS;
+info.si_errno = 0;
+info.si_code = 0;
+info._sifields._sigfault._addr = env->ior;
+queue_signal(env, info.si_signo, QEMU_SI_FAULT, );
+break;
+case EXCP_ILL:
+case EXCP_PRIV_OPR:
+case EXCP_PRIV_REG:
 info.si_signo = TARGET_SIGILL;
 info.si_errno = 0;
 info.si_code = TARGET_ILL_ILLOPN;
 info._sifields._sigfault._addr = env->iaoq_f;
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, );
 break;
-case EXCP_SIGFPE:
+case EXCP_OVERFLOW:
+case EXCP_COND:
+case EXCP_ASSIST:
 info.si_signo = TARGET_SIGFPE;
 info.si_errno = 0;
 info.si_code = 0;
diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index 4231ef3bff..6439179a0e 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -74,25 +74,52 @@ void hppa_cpu_do_interrupt(CPUState *cs)
 int i = cs->exception_index;
 
 if 

[Qemu-devel] [PATCH v3 02/45] target/hppa: Define the rest of the PSW

2018-01-24 Thread Richard Henderson
We don't actually do anything with most of the bits yet,
but at least they have names and we have somewhere to
store them.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h| 47 ++
 target/hppa/helper.c | 53 ++--
 2 files changed, 86 insertions(+), 14 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 7fad92144c..ea7e495408 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -46,6 +46,52 @@
 #define EXCP_SIGILL  4
 #define EXCP_SIGFPE  5
 
+/* Taken from Linux kernel: arch/parisc/include/asm/psw.h */
+#define PSW_I0x0001
+#define PSW_D0x0002
+#define PSW_P0x0004
+#define PSW_Q0x0008
+#define PSW_R0x0010
+#define PSW_F0x0020
+#define PSW_G0x0040 /* PA1.x only */
+#define PSW_O0x0080 /* PA2.0 only */
+#define PSW_CB   0xff00
+#define PSW_M0x0001
+#define PSW_V0x0002
+#define PSW_C0x0004
+#define PSW_B0x0008
+#define PSW_X0x0010
+#define PSW_N0x0020
+#define PSW_L0x0040
+#define PSW_H0x0080
+#define PSW_T0x0100
+#define PSW_S0x0200
+#define PSW_E0x0400
+#ifdef TARGET_HPPA64
+#define PSW_W0x0800 /* PA2.0 only */
+#else
+#define PSW_W0
+#endif
+#define PSW_Z0x4000 /* PA1.x only */
+#define PSW_Y0x8000 /* PA1.x only */
+
+#define PSW_SM (PSW_W | PSW_E | PSW_O | PSW_G | PSW_F \
+   | PSW_R | PSW_Q | PSW_P | PSW_D | PSW_I)
+
+/* ssm/rsm instructions number PSW_W and PSW_E differently */
+#define PSW_SM_I PSW_I  /* Enable External Interrupts */
+#define PSW_SM_D PSW_D
+#define PSW_SM_P PSW_P
+#define PSW_SM_Q PSW_Q  /* Enable Interrupt State Collection */
+#define PSW_SM_R PSW_R  /* Enable Recover Counter Trap */
+#ifdef TARGET_HPPA64
+#define PSW_SM_E 0x100
+#define PSW_SM_W 0x200  /* PA2.0 only : Enable Wide Mode */
+#else
+#define PSW_SM_E 0
+#define PSW_SM_W 0
+#endif
+
 typedef struct CPUHPPAState CPUHPPAState;
 
 struct CPUHPPAState {
@@ -56,6 +102,7 @@ struct CPUHPPAState {
 target_ulong cr26;
 target_ulong cr27;
 
+target_long  psw;/* All psw bits except the following:  */
 target_ulong psw_n;  /* boolean */
 target_long  psw_v;  /* in most significant bit */
 
diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index d6d6f06cb0..4231ef3bff 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -39,10 +39,11 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
 /* .bcdefgh */
 psw |= (psw >> 12) & 0xf;
 psw |= env->psw_cb_msb << 7;
-psw <<= 8;
+psw = (psw & 0xff) << 8;
 
-psw |= env->psw_n << 21;
-psw |= (env->psw_v < 0) << 17;
+psw |= env->psw_n * PSW_N;
+psw |= (env->psw_v < 0) * PSW_V;
+psw |= env->psw;
 
 return psw;
 }
@@ -51,8 +52,9 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
 {
 target_ulong cb = 0;
 
-env->psw_n = (psw >> 21) & 1;
-env->psw_v = -((psw >> 17) & 1);
+env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
+env->psw_n = (psw / PSW_N) & 1;
+env->psw_v = -((psw / PSW_V) & 1);
 env->psw_cb_msb = (psw >> 15) & 1;
 
 cb |= ((psw >> 14) & 1) << 28;
@@ -106,22 +108,45 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f,
 {
 HPPACPU *cpu = HPPA_CPU(cs);
 CPUHPPAState *env = >env;
+target_ulong psw = cpu_hppa_get_psw(env);
+target_ulong psw_cb;
+char psw_c[20];
 int i;
 
-cpu_fprintf(f, "IA_F " TARGET_FMT_lx
-   " IA_B " TARGET_FMT_lx
-   " PSW  " TARGET_FMT_lx
-   " [N:" TARGET_FMT_ld " V:%d"
-   " CB:" TARGET_FMT_lx "]\n  ",
-env->iaoq_f, env->iaoq_b, cpu_hppa_get_psw(env),
-env->psw_n, env->psw_v < 0,
-((env->psw_cb >> 4) & 0x0111) | (env->psw_cb_msb << 28));
-for (i = 1; i < 32; i++) {
+cpu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx "\n",
+env->iaoq_f, env->iaoq_b);
+
+psw_c[0]  = (psw & PSW_W ? 'W' : '-');
+psw_c[1]  = (psw & PSW_E ? 'E' : '-');
+psw_c[2]  = (psw & PSW_S ? 'S' : '-');
+psw_c[3]  = (psw & PSW_T ? 'T' : '-');
+psw_c[4]  = (psw & PSW_H ? 'H' : '-');
+psw_c[5]  = (psw & PSW_L ? 'L' : '-');
+psw_c[6]  = (psw & PSW_N ? 'N' : '-');
+psw_c[7]  = (psw & PSW_X ? 'X' : '-');
+psw_c[8]  = (psw & PSW_B ? 'B' : '-');
+psw_c[9]  = (psw & PSW_C ? 'C' : '-');
+psw_c[10] = (psw & PSW_V ? 'V' : '-');
+psw_c[11] = (psw & PSW_M ? 'M' : '-');
+psw_c[12] = (psw & PSW_F ? 

[Qemu-devel] [PATCH v3 13/45] target/hppa: Implement unaligned access trap

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.c | 19 ++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index ca619578dd..4d0b760baa 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -48,6 +48,23 @@ static void hppa_cpu_disas_set_info(CPUState *cs, 
disassemble_info *info)
 info->print_insn = print_insn_hppa;
 }
 
+static void hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+ MMUAccessType access_type,
+ int mmu_idx, uintptr_t retaddr)
+{
+HPPACPU *cpu = HPPA_CPU(cs);
+CPUHPPAState *env = >env;
+
+cs->exception_index = EXCP_UNALIGN;
+if (env->psw & PSW_Q) {
+/* ??? Needs tweaking for hppa64.  */
+env->cr[CR_IOR] = addr;
+env->cr[CR_ISR] = addr >> 32;
+}
+
+cpu_loop_exit_restore(cs, retaddr);
+}
+
 static void hppa_cpu_realizefn(DeviceState *dev, Error **errp)
 {
 CPUState *cs = CPU(dev);
@@ -139,7 +156,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
 #else
 cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug;
 #endif
-
+cc->do_unaligned_access = hppa_cpu_do_unaligned_access;
 cc->disas_set_info = hppa_cpu_disas_set_info;
 cc->tcg_initialize = hppa_translate_init;
 
-- 
2.14.3




[Qemu-devel] [PATCH v3 11/45] target/hppa: Implement rfi

2018-01-24 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h   |  1 +
 target/hppa/helper.h|  2 ++
 target/hppa/op_helper.c | 24 
 target/hppa/translate.c | 30 --
 4 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index c92c564a7f..6ec3430ae3 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -178,6 +178,7 @@ struct CPUHPPAState {
 
 target_ureg cr[32];  /* control registers */
 target_ureg cr_back[2];  /* back of cr17/cr18 */
+target_ureg shadow[7];   /* shadow registers */
 
 /* Those resources are used only in QEMU core */
 CPU_COMMON
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 254a4da133..79d22ae486 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -78,5 +78,7 @@ DEF_HELPER_FLAGS_4(fmpyfadd_d, TCG_CALL_NO_RWG, i64, env, 
i64, i64, i64)
 DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
 
 #ifndef CONFIG_USER_ONLY
+DEF_HELPER_1(rfi, void, env)
+DEF_HELPER_1(rfi_r, void, env)
 DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tr, env, tr)
 #endif
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index 1c3e043cc0..3f5dcbbca0 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -614,4 +614,28 @@ target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, 
target_ureg nsm)
 env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM);
 return psw & PSW_SM;
 }
+
+void HELPER(rfi)(CPUHPPAState *env)
+{
+/* ??? On second reading this condition simply seems
+   to be undefined rather than a diagnosed trap.  */
+if (env->psw & (PSW_I | PSW_R | PSW_Q)) {
+helper_excp(env, EXCP_ILL);
+}
+env->iaoq_f = env->cr[CR_IIAOQ];
+env->iaoq_b = env->cr_back[1];
+cpu_hppa_put_psw(env, env->cr[CR_IPSW]);
+}
+
+void HELPER(rfi_r)(CPUHPPAState *env)
+{
+env->gr[1] = env->shadow[0];
+env->gr[8] = env->shadow[1];
+env->gr[9] = env->shadow[2];
+env->gr[16] = env->shadow[3];
+env->gr[17] = env->shadow[4];
+env->gr[24] = env->shadow[5];
+env->gr[25] = env->shadow[6];
+helper_rfi(env);
+}
 #endif
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 8ca58f3df3..df0bb04907 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -655,6 +655,10 @@ static DisasJumpType nullify_end(DisasContext *ctx, 
DisasJumpType status)
 {
 TCGLabel *null_lab = ctx->null_lab;
 
+/* For NEXT, NORETURN, STALE, we can easily continue (or exit).
+   For UPDATED, we cannot update on the nullified path.  */
+assert(status != DISAS_IAQ_N_UPDATED);
+
 if (likely(null_lab == NULL)) {
 /* The current insn wasn't conditional or handled the condition
applied to it without a branch, so the (new) setting of
@@ -676,8 +680,6 @@ static DisasJumpType nullify_end(DisasContext *ctx, 
DisasJumpType status)
 gen_set_label(null_lab);
 ctx->null_cond = cond_make_n();
 }
-
-assert(status != DISAS_NORETURN && status != DISAS_IAQ_N_UPDATED);
 if (status == DISAS_NORETURN) {
 status = DISAS_NEXT;
 }
@@ -2153,6 +2155,29 @@ static DisasJumpType trans_mtsm(DisasContext *ctx, 
uint32_t insn,
 /* Exit the TB to recognize new interrupts.  */
 return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
 }
+
+static DisasJumpType trans_rfi(DisasContext *ctx, uint32_t insn,
+   const DisasInsn *di)
+{
+unsigned comp = extract32(insn, 5, 4);
+
+CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
+nullify_over(ctx);
+
+if (comp == 5) {
+gen_helper_rfi_r(cpu_env);
+} else {
+gen_helper_rfi(cpu_env);
+}
+if (ctx->base.singlestep_enabled) {
+gen_excp_1(EXCP_DEBUG);
+} else {
+tcg_gen_exit_tb(0);
+}
+
+/* Exit the TB to recognize new interrupts.  */
+return nullify_end(ctx, DISAS_NORETURN);
+}
 #endif /* !CONFIG_USER_ONLY */
 
 static const DisasInsn table_system[] = {
@@ -2169,6 +2194,7 @@ static const DisasInsn table_system[] = {
 { 0x0e60u, 0xfc00ffe0u, trans_rsm },
 { 0x0d60u, 0xfc00ffe0u, trans_ssm },
 { 0x1860u, 0xffe0u, trans_mtsm },
+{ 0x0c00u, 0xfe1fu, trans_rfi },
 #endif
 };
 
-- 
2.14.3




[Qemu-devel] [PATCH v3 01/45] target/hppa: Skeleton support for hppa-softmmu

2018-01-24 Thread Richard Henderson
From: Helge Deller 

With the addition of default-configs/hppa-softmmu.mak, this
will compile.  It is not enabled with this patch, however.

Signed-off-by: Helge Deller 
Signed-off-by: Richard Henderson 
---
 include/sysemu/arch_init.h |  1 +
 target/hppa/cpu.h  |  1 +
 arch_init.c|  2 ++
 hw/hppa/machine.c  | 38 
 target/hppa/cpu.c  |  5 +
 target/hppa/helper.c   | 10 -
 target/hppa/mem_helper.c   | 54 ++
 target/hppa/op_helper.c| 13 +--
 hw/hppa/Makefile.objs  |  1 +
 target/hppa/Makefile.objs  |  2 +-
 10 files changed, 114 insertions(+), 13 deletions(-)
 create mode 100644 hw/hppa/machine.c
 create mode 100644 target/hppa/mem_helper.c
 create mode 100644 hw/hppa/Makefile.objs

diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 8751c468ed..f999bfd3be 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -24,6 +24,7 @@ enum {
 QEMU_ARCH_MOXIE = (1 << 15),
 QEMU_ARCH_TRICORE = (1 << 16),
 QEMU_ARCH_NIOS2 = (1 << 17),
+QEMU_ARCH_HPPA = (1 << 18),
 };
 
 extern const uint32_t arch_type;
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 8d14077763..7fad92144c 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -133,6 +133,7 @@ void cpu_hppa_loaded_fr0(CPUHPPAState *env);
 
 int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
 int hppa_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, int midx);
+hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
 int hppa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 int hppa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 void hppa_cpu_do_interrupt(CPUState *cpu);
diff --git a/arch_init.c b/arch_init.c
index a0b8ed6167..4c36f2b076 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -53,6 +53,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_CRIS
 #elif defined(TARGET_I386)
 #define QEMU_ARCH QEMU_ARCH_I386
+#elif defined(TARGET_HPPA)
+#define QEMU_ARCH QEMU_ARCH_HPPA
 #elif defined(TARGET_M68K)
 #define QEMU_ARCH QEMU_ARCH_M68K
 #elif defined(TARGET_LM32)
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
new file mode 100644
index 00..79958da18f
--- /dev/null
+++ b/hw/hppa/machine.c
@@ -0,0 +1,38 @@
+/*
+ * QEMU HPPA hardware system emulator.
+ * Copyright 2018 Helge Deller 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "hw/hw.h"
+#include "elf.h"
+#include "hw/loader.h"
+#include "hw/boards.h"
+#include "qemu/error-report.h"
+#include "sysemu/sysemu.h"
+#include "hw/timer/mc146818rtc.h"
+#include "hw/ide.h"
+#include "hw/timer/i8254.h"
+#include "hw/char/serial.h"
+#include "qemu/cutils.h"
+#include "qapi/error.h"
+
+
+static void machine_hppa_init(MachineState *machine)
+{
+}
+
+static void machine_hppa_machine_init(MachineClass *mc)
+{
+mc->desc = "HPPA generic machine";
+mc->init = machine_hppa_init;
+mc->block_default_type = IF_SCSI;
+mc->max_cpus = 1;
+mc->is_default = 1;
+mc->default_ram_size = 512 * M_BYTE;
+mc->default_boot_order = "cd";
+}
+
+DEFINE_MACHINE("hppa", machine_hppa_machine_init)
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 9e7b0d4ccb..f6d92de972 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -132,7 +132,12 @@ static void hppa_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->synchronize_from_tb = hppa_cpu_synchronize_from_tb;
 cc->gdb_read_register = hppa_cpu_gdb_read_register;
 cc->gdb_write_register = hppa_cpu_gdb_write_register;
+#ifdef CONFIG_USER_ONLY
 cc->handle_mmu_fault = hppa_cpu_handle_mmu_fault;
+#else
+cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug;
+#endif
+
 cc->disas_set_info = hppa_cpu_disas_set_info;
 cc->tcg_initialize = hppa_translate_init;
 
diff --git a/target/hppa/helper.c b/target/hppa/helper.c
index ba04a9a52b..d6d6f06cb0 100644
--- a/target/hppa/helper.c
+++ b/target/hppa/helper.c
@@ -65,16 +65,6 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
 env->psw_cb = cb;
 }
 
-int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
-  int rw, int mmu_idx)
-{
-HPPACPU *cpu = HPPA_CPU(cs);
-
-cs->exception_index = EXCP_SIGSEGV;
-cpu->env.ior = address;
-return 1;
-}
-
 void hppa_cpu_do_interrupt(CPUState *cs)
 {
 HPPACPU *cpu = HPPA_CPU(cs);
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
new file mode 100644
index 00..e0802bc935
--- /dev/null
+++ b/target/hppa/mem_helper.c
@@ -0,0 +1,54 @@
+/*
+ *  HPPA memory access helper routines
+ *
+ *  Copyright (c) 2017 Helge Deller
+ *
+ * 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 

[Qemu-devel] [PATCH v3 00/45] hppa-softmmu

2018-01-24 Thread Richard Henderson
A third revision.  Changes since last:

  * sh4 build failure fixed (needed clang to see it)
  * checkpatch whitespace errors fixed.
  * Still updates to IIR, IOR, ISR when !PSW[Q]
  * Fix fcnv instruction masks.
  * Implement probe insn.

The middle three points progress in booting hpux-11.
Booting Linux still works.


r~


Helge Deller (5):
  target/hppa: Skeleton support for hppa-softmmu
  target/hppa: Implement halt and reset instructions
  target/hppa: Fix comment
  target/hppa: Implement LDSID for system mode
  hw/hppa: Implement DINO system board

Richard Henderson (40):
  target/hppa: Define the rest of the PSW
  target/hppa: Disable gateway page emulation for system mode
  target/hppa: Define hardware exception types
  target/hppa: Split address size from register size
  target/hppa: Implement mmu_idx from IA privilege level
  target/hppa: Implement the system mask instructions
  target/hppa: Add space registers
  target/hppa: Add control registers
  target/hppa: Adjust insn mask for mfctl,w
  target/hppa: Implement rfi
  target/hppa: Fill in hppa_cpu_do_interrupt/hppa_cpu_exec_interrupt
  target/hppa: Implement unaligned access trap
  target/hppa: Use space registers in data operations
  target/hppa: Avoid privilege level decrease during branches
  target/hppa: Implement IASQ
  target/hppa: Implement tlb_fill
  target/hppa: Implement external interrupts
  target/hppa: Implement the interval timer
  target/hppa: Log unimplemented instructions
  target/hppa: Implement I*TLBA and I*TLBP insns
  target/hppa: Implement P*TLB and P*TLBE insns
  target/hppa: Implement LDWA
  target/hppa: Implement LPA
  target/hppa: Implement LCI
  target/hppa: Implement SYNCDMA insn
  target/hppa: Optimize for flat addressing space
  target/hppa: Add system registers to gdbstub
  target/hppa: Add migration for the cpu
  target/hppa: Implement B,GATE insn
  target/hppa: Only use EXCP_DTLB_MISS
  qom: Add MMU_DEBUG_LOAD
  target/hppa: Use MMU_DEBUG_LOAD when reloading for CR[IIR]
  target/hppa: Increase number of temp regs
  target/hppa: Implement a pause instruction
  target/hppa: Implement STWA
  target/hppa: Enable MTTCG
  pc-bios: Add hppa-firmware.img and git submodule
  hw/hppa: Add MAINTAINERS entry
  target/hppa: Fix 32-bit operand masks for 0E FCVT
  target/hppa: Implement PROBE for system mode

 Makefile |3 +-
 Makefile.objs|1 +
 hw/hppa/hppa_hardware.h  |   40 +
 hw/hppa/hppa_sys.h   |   24 +
 include/qom/cpu.h|3 +-
 include/sysemu/arch_init.h   |1 +
 linux-user/hppa/target_cpu.h |2 +-
 target/hppa/cpu.h|  282 -
 target/hppa/helper.h |   43 +-
 arch_init.c  |2 +
 hw/hppa/dino.c   |  518 ++
 hw/hppa/machine.c|  282 +
 hw/hppa/pci.c|   90 ++
 linux-user/main.c|   28 +-
 linux-user/signal.c  |4 +-
 target/hppa/cpu.c|   56 +-
 target/hppa/gdbstub.c|  187 +++-
 target/hppa/helper.c |  120 +--
 target/hppa/int_helper.c |  264 +
 target/hppa/machine.c|  181 
 target/hppa/mem_helper.c |  350 +++
 target/hppa/op_helper.c  |  154 ++-
 target/hppa/translate.c  | 2108 --
 target/sh4/op_helper.c   |2 +
 .gitmodules  |3 +
 MAINTAINERS  |1 +
 configure|1 +
 default-configs/hppa-softmmu.mak |   14 +
 hw/hppa/Makefile.objs|1 +
 hw/hppa/trace-events |4 +
 pc-bios/hppa-firmware.img|  Bin 0 -> 461352 bytes
 roms/seabios-hppa|1 +
 target/hppa/Makefile.objs|4 +-
 33 files changed, 4069 insertions(+), 705 deletions(-)
 create mode 100644 hw/hppa/hppa_hardware.h
 create mode 100644 hw/hppa/hppa_sys.h
 create mode 100644 hw/hppa/dino.c
 create mode 100644 hw/hppa/machine.c
 create mode 100644 hw/hppa/pci.c
 create mode 100644 target/hppa/int_helper.c
 create mode 100644 target/hppa/machine.c
 create mode 100644 target/hppa/mem_helper.c
 create mode 100644 default-configs/hppa-softmmu.mak
 create mode 100644 hw/hppa/Makefile.objs
 create mode 100644 hw/hppa/trace-events
 create mode 100755 pc-bios/hppa-firmware.img
 create mode 16 roms/seabios-hppa

-- 
2.14.3




[Qemu-devel] [Bug 902413] Re: qemu-i386-user on ARM host: wine hangs/spins when trying to run anything

2018-01-24 Thread Thomas Huth
There hasn't been an update within a year, so let's assume this bug has
been fixed.

** Changed in: qemu
   Status: Incomplete => 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/902413

Title:
  qemu-i386-user on ARM host: wine hangs/spins when trying to run
  anything

Status in QEMU:
  Fix Released
Status in wine package in Gentoo Linux:
  New

Bug description:
  With qemu built from git from 217bfb445b54db618a30f3a39170bebd9fd9dbf2
  and configured with './configure --target-list=i386-linux-user
  --static --interp-prefix=/home/pgriffais/natty-i386/', trying to run
  wine 1.3.15 from an Ubuntu 11.04 chroot results in hangs. If I run an
  i386 emulated wineserver, wineserver hangs in:

  0x600c7f8c in read () at ../sysdeps/unix/syscall-template.S:82
  82../sysdeps/unix/syscall-template.S: No such file or directory.
in ../sysdeps/unix/syscall-template.S
  (gdb) bt
  #0  0x600c7f8c in read () at ../sysdeps/unix/syscall-template.S:82
  #1  0x6004a316 in read (cpu_env=0x622c3ee8, num=3, arg1=6, arg2=1121255519, 
  arg3=1, arg4=134875664, arg5=1, arg6=1121255528, arg7=0, arg8=0)
  at /usr/include/bits/unistd.h:45
  #2  do_syscall (cpu_env=0x622c3ee8, num=3, arg1=6, arg2=1121255519, arg3=1, 
  arg4=134875664, arg5=1, arg6=1121255528, arg7=0, arg8=0)
  at /home/ubuntu/src/qemu/linux-user/syscall.c:4691
  #3  0x600262f0 in cpu_loop (env=0x622c3ee8)
  at /home/ubuntu/src/qemu/linux-user/main.c:321
  #4  0x60026bbc in main (argc=, 
  argv=, envp=)
  at /home/ubuntu/src/qemu/linux-user/main.c:3817

  While wine hangs in:

  0x600c84ac in recvmsg () at ../sysdeps/unix/syscall-template.S:82
  82../sysdeps/unix/syscall-template.S: No such file or directory.
in ../sysdeps/unix/syscall-template.S
  (gdb) bt
  #0  0x600c84ac in recvmsg () at ../sysdeps/unix/syscall-template.S:82
  #1  0x60041c4e in do_sendrecvmsg (fd=4, target_msg=, 
  flags=1073741824, send=0)
  at /home/ubuntu/src/qemu/linux-user/syscall.c:1834
  #2  0x600497ec in do_socketcall (cpu_env=, num=102, 
  arg1=17, arg2=1122504544, arg3=2076831732, arg4=1122504568, 
  arg5=2076942688, arg6=1122504888, arg7=0, arg8=0)
  at /home/ubuntu/src/qemu/linux-user/syscall.c:2235
  #3  do_syscall (cpu_env=, num=102, arg1=17, 
  arg2=1122504544, arg3=2076831732, arg4=1122504568, arg5=2076942688, 
  arg6=1122504888, arg7=0, arg8=0)
  at /home/ubuntu/src/qemu/linux-user/syscall.c:6085
  #4  0x600262f0 in cpu_loop (env=0x622c3f08)
  at /home/ubuntu/src/qemu/linux-user/main.c:321
  #5  0x60026bbc in main (argc=, 
  argv=, envp=)
  at /home/ubuntu/src/qemu/linux-user/main.c:3817

  However if I build wineserver 1.3.15 natively for ARM and run it on
  the host while wine is emulated, I get the following:

  root@tiberiusstation:/home/ubuntu# ./natty-i386/usr/bin/wine notepad
  Unsupported ancillary data: 1/2
  Unsupported ancillary data: 1/2
  Unsupported ancillary data: 1/2
  err:process:__wine_kernel_init boot event wait timed out

  I assume the last one is due to wineboot.exe hanging. The main wine
  process hangs in there:

  cg_temp_new_internal_i32 (temp_local=)
  at /home/ubuntu/src/qemu/tcg/tcg.c:483
  483   }
  (gdb) bt
  #0  tcg_temp_new_internal_i32 (temp_local=)
  at /home/ubuntu/src/qemu/tcg/tcg.c:483
  #1  0x60052ac6 in tcg_temp_new_i32 (val=6)
  at /home/ubuntu/src/qemu/tcg/tcg.h:442
  #2  tcg_const_i32 (val=6) at /home/ubuntu/src/qemu/tcg/tcg.c:530
  #3  0x6005ef0c in tcg_gen_shri_i32 (ot=2, op1=2, op2=7, is_right=1, 
  is_arith=0, s=)
  at /home/ubuntu/src/qemu/tcg/tcg-op.h:605
  #4  gen_shift_rm_im (ot=2, op1=2, op2=7, is_right=1, is_arith=0, 
  s=)
  at /home/ubuntu/src/qemu/target-i386/translate.c:1514
  #5  0x6006df90 in gen_shifti (s=0xbefea970, pc_start=)
  at /home/ubuntu/src/qemu/target-i386/translate.c:1946
  #6  disas_insn (s=0xbefea970, pc_start=)
  at /home/ubuntu/src/qemu/target-i386/translate.c:5397
  #7  0x60091758 in gen_intermediate_code_internal (env=0x625656f8, 
  tb=0x402cdf48) at /home/ubuntu/src/qemu/target-i386/translate.c:7825
  #8  gen_intermediate_code_pc (env=0x625656f8, tb=0x402cdf48)
  at /home/ubuntu/src/qemu/target-i386/translate.c:7896
  #9  0x60054bf2 in cpu_restore_state (tb=0x402cdf48, env=0x62565690, 
  searched_pc=1617393812) at /home/ubuntu/src/qemu/translate-all.c:126
  #10 0x60091d9e in handle_cpu_signal (host_signum=, 
  pinfo=, puc=0xbefeab70)
  at /home/ubuntu/src/qemu/user-exec.c:117
  #11 cpu_x86_signal_handler (host_signum=, 
  pinfo=, puc=0xbefeab70)
  at /home/ubuntu/src/qemu/user-exec.c:458
  #12 0x6003c764 in host_signal_handler (host_signum=11, info=0xbefeaaf0, 
  puc=)
  at /home/ubuntu/src/qemu/linux-user/signal.c:492
  #13 
  #14 0x60677894 in static_code_gen_buffer ()
  #15 0x6000a260 in cpu_x86_exec (env=0x0)
  at 

Re: [Qemu-devel] [PULL v2 0/3] virtio: quick fix

2018-01-24 Thread Peter Maydell
On 24 January 2018 at 17:22, Michael S. Tsirkin  wrote:
> So this just reverts Gal's patches. I hope he'll be able to resubmit
> shortly but it's causing too many issues to too many people to try to do
> incremental fixups, and this way there's no timing pressure on anyone.
>
> The following changes since commit 52483b067cce4a88ffbf8fbeea26de7549d2ad23:
>
>   Merge remote-tracking branch 'remotes/huth/tags/pull-request-2018-01-22' 
> into staging (2018-01-23 10:15:09 +)
>
> are available in the git repository at:
>
>   git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
>
> for you to fetch changes up to e044c0f8dd028ea296396ad8066ba436e9acf350:
>
>   Revert "qemu: add a cleanup callback function to EventNotifier" (2018-01-24 
> 19:20:19 +0200)
>
> 
> virtio: quick fix
>
> Fixes a regression in virtio that's causing issues
> for many people.
>
> Signed-off-by: Michael S. Tsirkin 
>
> 
> Michael S. Tsirkin (3):
>   Revert "virtio: improve virtio devices initialization time"
>   Revert "virtio: postpone the execution of event_notifier_cleanup 
> function"
>   Revert "qemu: add a cleanup callback function to EventNotifier"

Applied, thanks.

-- PMM



Re: [Qemu-devel] [PATCH v9 03/13] block/dirty-bitmap: add _locked version of bdrv_reclaim_dirty_bitmap

2018-01-24 Thread John Snow


On 01/24/2018 05:16 AM, Paolo Bonzini wrote:
> On 22/01/2018 13:14, Vladimir Sementsov-Ogievskiy wrote:
>>> so, accessing the bitmap needs mutex lock?
>>>
>>> Then what do you mean under accessing the bitmap? Any touch of
>>> BdrvDirtyBitmap fields? Then "reading the list" will require bitmap
>>> mutex too.
>>> Or accessing the bitmap is accessing any field except
>>> BdrvDirtyBitmap.list? Then in (2), what do you mean? For example
>>> query-block will go through
>>> the list, but it touches other fields too, so it should lock mutex.
> 
> The bitmap mutex is internal to block/dirty-bitmap.c.
> 
>> and one more question:
>>
>> What about qmp transactions? Should we lock mutex during the whole
>> transaction?
> 
> Transactions hold the BQL, but you don't need to lock the bitmap mutex.
> 
> Paolo
> 

I would further add that attempting to lock all of the bitmap mutexes
during a transaction might cause complications if you try to perform two
actions on the same bitmap, and it deadlocks.

With the BQL held we're probably okay, but worst-case scenario locking
and unlocking per-each action is probably sufficient, I'd think.



Re: [Qemu-devel] [PATCH v3 04/22] target/*/cpu.h: remove softfloat.h

2018-01-24 Thread David Gibson
On Wed, Jan 24, 2018 at 01:12:57PM +, Alex Bennée wrote:
> As cpu.h is another typically widely included file which doesn't need
> full access to the softfloat API we can remove the includes from here
> as well. Where they do need types it's typically for float_status and
> the rounding modes so we move that to softfloat-types.h as well.
> 
> As a result of not having softfloat in every cpu.h call we now need to
> add it to various helpers that do need the full softfloat.h
> definitions.
> 
> Signed-off-by: Alex Bennée 

ppc part

Acked-by: David Gibson 

> ---
>  include/fpu/softfloat-types.h   | 64 
> +
>  include/fpu/softfloat.h | 53 --
>  target/alpha/cpu.h  |  2 --
>  target/arm/cpu.c|  1 +
>  target/arm/cpu.h|  2 --
>  target/arm/helper-a64.c |  1 +
>  target/arm/helper.c |  1 +
>  target/arm/neon_helper.c|  1 +
>  target/hppa/cpu.c   |  1 +
>  target/hppa/cpu.h   |  1 -
>  target/hppa/op_helper.c |  1 +
>  target/i386/cpu.h   |  4 ---
>  target/i386/fpu_helper.c|  1 +
>  target/m68k/cpu.c   |  2 +-
>  target/m68k/cpu.h   |  1 -
>  target/m68k/fpu_helper.c|  1 +
>  target/m68k/helper.c|  1 +
>  target/m68k/translate.c |  2 ++
>  target/microblaze/cpu.c |  1 +
>  target/microblaze/cpu.h |  2 +-
>  target/microblaze/op_helper.c   |  1 +
>  target/moxie/cpu.h  |  1 -
>  target/nios2/cpu.h  |  1 -
>  target/openrisc/cpu.h   |  1 -
>  target/openrisc/fpu_helper.c|  1 +
>  target/ppc/cpu.h|  1 -
>  target/ppc/fpu_helper.c |  1 +
>  target/ppc/int_helper.c |  1 +
>  target/ppc/translate_init.c |  1 +
>  target/s390x/cpu.c  |  1 +
>  target/s390x/cpu.h  |  2 --
>  target/s390x/fpu_helper.c   |  1 +
>  target/sh4/cpu.c|  1 +
>  target/sh4/cpu.h|  2 --
>  target/sh4/op_helper.c  |  1 +
>  target/sparc/cpu.h  |  2 --
>  target/sparc/fop_helper.c   |  1 +
>  target/tricore/cpu.h|  1 -
>  target/tricore/fpu_helper.c |  1 +
>  target/tricore/helper.c |  1 +
>  target/unicore32/cpu.c  |  1 +
>  target/unicore32/cpu.h  |  1 -
>  target/unicore32/ucf64_helper.c |  1 +
>  target/xtensa/cpu.h |  1 -
>  target/xtensa/op_helper.c   |  1 +
>  45 files changed, 93 insertions(+), 78 deletions(-)
> 
> diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
> index 8210a94ea1..4e378cb612 100644
> --- a/include/fpu/softfloat-types.h
> +++ b/include/fpu/softfloat-types.h
> @@ -80,6 +80,12 @@ this code that are retained.
>  #ifndef SOFTFLOAT_TYPES_H
>  #define SOFTFLOAT_TYPES_H
>  
> +/* This 'flag' type must be able to hold at least 0 and 1. It should
> + * probably be replaced with 'bool' but the uses would need to be audited
> + * to check that they weren't accidentally relying on it being a larger type.
> + */
> +typedef uint8_t flag;
> +
>  /*
>   * Software IEC/IEEE floating-point types.
>   */
> @@ -112,4 +118,62 @@ typedef struct {
>  #define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ 
> })
>  #define make_float128_init(high_, low_) { .high = high_, .low = low_ }
>  
> +/*
> + * Software IEC/IEEE floating-point underflow tininess-detection mode.
> + */
> +
> +enum {
> +float_tininess_after_rounding  = 0,
> +float_tininess_before_rounding = 1
> +};
> +
> +/*
> + *Software IEC/IEEE floating-point rounding mode.
> + */
> +
> +enum {
> +float_round_nearest_even = 0,
> +float_round_down = 1,
> +float_round_up   = 2,
> +float_round_to_zero  = 3,
> +float_round_ties_away= 4,
> +/* Not an IEEE rounding mode: round to the closest odd mantissa value */
> +float_round_to_odd   = 5,
> +};
> +
> +/*
> + * Software IEC/IEEE floating-point exception flags.
> + */
> +
> +enum {
> +float_flag_invalid   =  1,
> +float_flag_divbyzero =  4,
> +float_flag_overflow  =  8,
> +float_flag_underflow = 16,
> +float_flag_inexact   = 32,
> +float_flag_input_denormal = 64,
> +float_flag_output_denormal = 128
> +};
> +
> +
> +/*
> + * Floating Point Status. Individual architectures may maintain
> + * several versions of float_status for different functions. The
> + * correct status for the operation is then passed by reference to
> + * most of the softfloat functions.
> + */
> +
> +typedef struct float_status {
> +signed char float_detect_tininess;
> +signed char float_rounding_mode;
> +uint8_t float_exception_flags;
> +signed char floatx80_rounding_precision;
> +/* should denormalised results go to zero and set the inexact flag? */
> +flag flush_to_zero;
> + 

[Qemu-devel] [PATCH v3] xilinx_spips: Correct usage of an uninitialized local variable

2018-01-24 Thread Francisco Iglesias
Coverity found that the variable tx_rx in the function
xilinx_spips_flush_txfifo was being used uninitialized (CID 1383841). This
patch corrects this by always initializing tx_rx to zeros.

Signed-off-by: Francisco Iglesias 

---
v3. Change to report errors on the num_busses property via the Error**
parameter when realizing the devices.
---
v2. Add a sanity check on the num_busses property when realizing the
devices.
---
 hw/ssi/xilinx_spips.c | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index 85c5d0c..8af36ca 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -210,6 +210,9 @@
 #define SNOOP_NONE 0xEE
 #define SNOOP_STRIPING 0
 
+#define MIN_NUM_BUSSES 1
+#define MAX_NUM_BUSSES 2
+
 static inline int num_effective_busses(XilinxSPIPS *s)
 {
 return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
@@ -573,7 +576,7 @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
 for (;;) {
 int i;
 uint8_t tx = 0;
-uint8_t tx_rx[num_effective_busses(s)];
+uint8_t tx_rx[MAX_NUM_BUSSES] = { 0 };
 uint8_t dummy_cycles = 0;
 uint8_t addr_length;
 
@@ -1221,6 +1224,19 @@ static void xilinx_spips_realize(DeviceState *dev, Error 
**errp)
 
 DB_PRINT_L(0, "realized spips\n");
 
+if (s->num_busses > MAX_NUM_BUSSES) {
+error_setg(errp,
+   "requested number of SPI busses %u exceeds maximum %d",
+   s->num_busses, MAX_NUM_BUSSES);
+return;
+}
+if (s->num_busses < MIN_NUM_BUSSES) {
+error_setg(errp,
+   "requested number of SPI busses %u is below minimum %d",
+   s->num_busses, MIN_NUM_BUSSES);
+return;
+}
+
 s->spi = g_new(SSIBus *, s->num_busses);
 for (i = 0; i < s->num_busses; ++i) {
 char bus_name[16];
-- 
2.9.3




Re: [Qemu-devel] [PATCH v3 00/22] re-factor softfloat and add fp16 functions

2018-01-24 Thread Howard Spoelstra
Hi,

I built qemu-system-ppc for OSX and Windows from
https://github.com/stsquad/qemu/tree/softfloat-refactor-and-fp16-v3
and noticed a considerable drop in floating point performance on both
hosts.
Running Mac OS 9.2 in OSX, using MacBench 3.0, the score for the
floating point performance dropped from ~60 to ~42.

Recent tcg optimisations had improved processor and floating point
performance considerably, but that gain seems to be more than lost for
the floating point performance.

Any idea what is causing this?

Best regards,
Howard



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

2018-01-24 Thread Philippe Mathieu-Daudé
Hi Pavel,

On 01/24/2018 05:22 PM, Pavel Pisa wrote:
> Hello everybody,
> 
> On Tuesday 23 of January 2018 22:42:31 Pavel Pisa wrote:
>> When Linux specific object file is linked in then some local
>> function needs to be called before QOM instances population.
>> I know how to do that GCC specific/non-portable way
>>
>> static void __attribute__((constructor)) can_socketcan_setup_variant(void)
>> {
>>
>> }
>>
>> but I expect that something like
>>
>> module_init()
>>
>> in can_socketcan.c should be used.
> 
> 
> I have experimented with code changes to get rid of stub for
> non Linux systems. type_init() is used because it is more
> portable than constructor attribute.
> 
> I have seen that a few other type_init-s do more
> than simple sequence of type_register_static().
> Is it acceptable to use type_init for registration
> to CAN core by function call for now? Conversion simplifies
> makefiles and unnecessary stub file is removed.
> 
> But I would use attribute if that solution is preferred because
> it is allways present on Linux where SocketCAN is used anyway
> and it is used in other Qemu subsystems as well.

using stubs/monitor.c as a template for stubs/can_host_variant.c doesn't
work?

> 
> 
> Solution with attribute
> 
> #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
> static void __attribute__((constructor))
> can_bus_socketcan_setup(void)
> {
> can_bus_set_connect_to_host(can_bus_connect_to_host_socketcan);
> }
> #endif
> 
> 
> Solution with type_init
> branch 
> https://gitlab.fel.cvut.cz/canbus/qemu-canbus/tree/can-pci-socketcan-init
> 
> diff --git a/hw/can/can_socketcan.c b/hw/can/can_socketcan.c
> index 42099fb696..fb41853c2b 100644
> --- a/hw/can/can_socketcan.c
> +++ b/hw/can/can_socketcan.c
> @@ -309,5 +309,14 @@ static int can_bus_connect_to_host_socketcan(CanBusState 
> *bus,
>  return 0;
>  }
>  
> -int (*can_bus_connect_to_host_variant)(CanBusState *bus, const char *name) =
> -can_bus_connect_to_host_socketcan;
> +static void can_bus_socketcan_type_init(void)
> +{
> +/*
> + * There should be object registration when CanBusSocketcanConnectState
> + * is converted into QOM object. Use for registration of host
> + * can bus access for now.
> + */
> +can_bus_set_connect_to_host(can_bus_connect_to_host_socketcan);
> +}
> +
> +type_init(can_bus_socketcan_type_init);
> 
> 
> diff --git a/hw/can/Makefile.objs b/hw/can/Makefile.objs
> index 1ce9950de0..14c2369718 100644
> --- a/hw/can/Makefile.objs
> +++ b/hw/can/Makefile.objs
> @@ -2,11 +2,7 @@
>  
>  ifeq ($(CONFIG_CAN_BUS),y)
>  common-obj-y += can_core.o
> -ifeq ($(CONFIG_LINUX),y)
> -common-obj-y += can_socketcan.o
> -else
> -common-obj-y += can_host_stub.o
> -endif
> +common-obj-$(CONFIG_LINUX) += can_socketcan.o
>  common-obj-$(CONFIG_CAN_SJA1000) += can_sja1000.o
>  common-obj-$(CONFIG_CAN_PCI) += can_kvaser_pci.o
>  common-obj-$(CONFIG_CAN_PCI) += can_pcm3680_pci.o
> diff --git a/hw/can/can_core.c b/hw/can/can_core.c
> index 41c458c792..c14807b188 100644
> --- a/hw/can/can_core.c
> +++ b/hw/can/can_core.c
> @@ -34,6 +34,8 @@
>  static QTAILQ_HEAD(, CanBusState) can_buses =
>  QTAILQ_HEAD_INITIALIZER(can_buses);
>  
> +static can_bus_connect_to_host_t can_bus_connect_to_host_fnc;
> +
>  CanBusState *can_bus_find_by_name(const char *name, bool create_missing)
>  {
>  CanBusState *bus;
> @@ -127,10 +129,15 @@ int can_bus_client_set_filters(CanBusClientState 
> *client,
>  
>  int can_bus_connect_to_host_device(CanBusState *bus, const char *name)
>  {
> -if (can_bus_connect_to_host_variant == NULL) {
> +if (can_bus_connect_to_host_fnc == NULL) {
>  error_report("CAN bus connect to host device is not "
>   "supported on this system");
>  exit(1);
>  }
> -return can_bus_connect_to_host_variant(bus, name);
> +return can_bus_connect_to_host_fnc(bus, name);
> +}
> +
> +void can_bus_set_connect_to_host(can_bus_connect_to_host_t connect_fnc)
> +{
> +can_bus_connect_to_host_fnc = connect_fnc;
>  }
> diff --git a/hw/can/can_host_stub.c b/hw/can/can_host_stub.c
> deleted file mode 100644
> index 748d25f995..00
> --- a/hw/can/can_host_stub.c
> +++ /dev/null
> @@ -1,36 +0,0 @@
> 
> 
> 
> -
> -
> -int (*can_bus_connect_to_host_variant)(CanBusState *bus, const char *name) =
> -NULL;
> 
> diff --git a/include/can/can_emu.h b/include/can/can_emu.h
> index 85237ee3c9..7f0705e49f 100644
> --- a/include/can/can_emu.h
> +++ b/include/can/can_emu.h
> @@ -107,8 +107,9 @@ struct CanBusState {
>  QTAILQ_ENTRY(CanBusState) next;
>  };
>  
> -extern int (*can_bus_connect_to_host_variant)(CanBusState *bus,
> -  const char *name);
> +typedef int (*can_bus_connect_to_host_t)(CanBusState *bus, const char *name);
> +
> +void 

[Qemu-devel] [PATCH V1 1/1] tests: Add migration test for aarch64

2018-01-24 Thread Wei Huang
This patch adds the migration test support for aarch64. The test code,
which implements the same functionality as x86, is compiled into a binary
and booted as a kernel in qemu. Here are the design ideas:

 * We choose this -kernel design 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.

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

Note that the test code is as the following:

.section .text

.globl  start

start:
/* disable MMU to use phys mem address */
mrs x0, sctlr_el1
bic x0, x0, #(1<<0)
msr sctlr_el1, x0
isb

/* output char 'A' to PL011 */
mov w4, #65
mov x5, #0x900
strbw4, [x5]

/* w6 keeps a counter so we can limit the output speed */
mov w6, #0

/* phys mem base addr = 0x4000 */
mov x3, #(0x4000 + 100 *1024*1024) /* traverse 1M-100M */
mov x2, #(0x4000 + 1 * 1024*1024)

/* clean up memory first */
mov w1, #0  
clean:
strbw1, [x2]
add x2, x2, #(4096)
cmp x2, x3
ble clean

/* main body */
mainloop:
mov x2, #(0x4000 + 1 * 1024*1024)

innerloop:
/* clean cache because el2 might still cache guest data under KVM */
dc  civac, x2
ldrbw1, [x2]
add w1, w1, #1
and w1, w1, #(0xff)
strbw1, [x2]

add x2, x2, #(4096)
cmp x2, x3
blt innerloop

add w6, w6, #1
and w6, w6, #(0xff)
cmp w6, #0
bne mainloop

/* output char 'B' to PL011 */
mov w4, #66
mov x5, #0x900
strbw4, [x5]

bl  mainloop

The code is compiled with the following commands:
 > gcc -c -o fill.o fill.s
 > gcc -O2 -o fill.elf -Wl,-T,/tmp/flat.lds,--build-id=none,-Ttext=4008 \
   -nostdlib fill.o
 > objcopy -O binary fill.elf fill.flat
 > truncate -c -s 144 ./fill.flat
 > xxd -g 4 -c 24 -e fill.flat | awk '{print "0x"$2 ", " "0x"$3 ", " "0x"C$4 ", 
 > " "0x"C$5 ", " "0x"$6 ", " "0x"C$7 "," }'

The linker file (borrowed from KVM unit test) is defined as:

SECTIONS
{
.text : { *(.init) *(.text) *(.text.*) }
. = ALIGN(64K);
etext = .;
.data : {
*(.data)
}
. = ALIGN(16);
.rodata : { *(.rodata) }
. = ALIGN(16);
.bss : { *(.bss) }
. = ALIGN(64K);
edata = .;
. += 64K;
. = ALIGN(64K);
/*
 * stack depth is 16K for arm and PAGE_SIZE for arm64, see THREAD_SIZE
 * sp must be 16 byte aligned for arm64, and 8 byte aligned for arm
 * sp must always be strictly less than the true stacktop
 */
stackptr = . - 16;
stacktop = .;
}

ENTRY(start)

Signed-off-by: Wei Huang 
---
 tests/Makefile.include |  1 +
 tests/migration-test.c | 37 +++--
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index b4bcc872f2..2a520e53ab 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -357,6 +357,7 @@ check-qtest-arm-y += tests/test-arm-mptimer$(EXESUF)
 gcov-files-arm-y += hw/timer/arm_mptimer.c
 
 check-qtest-aarch64-y = tests/numa-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 be598d3257..3237fe93b2 100644
--- a/tests/migration-test.c
+++ b/tests/migration-test.c
@@ -22,8 +22,8 @@
 
 #define MIN_NVRAM_SIZE 8192 /* from spapr_nvram.c */
 
-const unsigned start_address = 1024 * 1024;
-const unsigned end_address = 100 * 1024 * 1024;
+unsigned start_address = 1024 * 1024;
+unsigned end_address = 100 * 1024 * 1024;
 bool got_stop;
 
 #if defined(__linux__)
@@ -79,7 +79,7 @@ static const char *tmpfs;
 /* A simple PC boot sector that modifies memory (1-100MB) quickly
  * outputing a 'B' every so often if it's still running.
  */
-unsigned char bootsect[] = {
+unsigned char x86_bootsect[] = {
   0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
   0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
@@ -125,11 +125,20 @@ unsigned char bootsect[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
 };
 
-static void init_bootfile_x86(const char 

Re: [Qemu-devel] [PATCH 0/2] linux-user: Fix race between threads in page_unprotect()

2018-01-24 Thread Laurent Vivier
Le 19/01/2018 à 15:51, Riku Voipio a écrit :
> Hi Laurent,
> 
> On Mon, Jan 15, 2018 at 01:52:32PM +0100, Laurent Vivier wrote:
>> Le 15/01/2018 à 13:48, Peter Maydell a écrit :
>>> On 28 November 2017 at 14:35, Peter Maydell  
>>> wrote:
 If multiple guest threads in user-mode emulation write to a
 page which QEMU has marked read-only because of cached TCG
 translations, the threads can race in page_unprotect:
>>>
 Peter Maydell (2):
   linux-user: Propagate siginfo_t through to handle_cpu_signal()
   page_unprotect(): handle calls to pages that are PAGE_WRITE
>>>
>>> Ping! Linux-user maintainers, any chance this could get into
>>> a pull-request sometime soon? (I have another cleanup I'm
>>> thinking of that will touch the same code so I'd rather this
>>> went into master before I look at that.)
>>>
>>> (I have a bunch of other pending linux-user patchsets which
>>> I shan't bother to ping individually unless you want me to.)
>>
>> Riku,
>>
>> if you have no time to prepare a pull request, I can.
> 
> Thanks, that would be great.

Riku, if you agree, I can continue to collect patches for the next
pull-request. It's easier to collect patches on the fly than scanning
the ML when we want to create a pull request.

Thanks,
Laurent




[Qemu-devel] [PATCH v4 3/4] linux-user, m68k: select CPU according to ELF header values

2018-01-24 Thread Laurent Vivier
M680x0 doesn't support the same set of instructions
as ColdFire, so we can't use "any" CPU type to execute
m68020 instructions.
We select CPU type ("m68040" or "any" for ColdFire)
according to the ELF header. If we can't, we
use by default the value used until now: "any".

Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
---
 include/elf.h| 28 
 linux-user/m68k/target_elf.h |  6 ++
 2 files changed, 34 insertions(+)

diff --git a/include/elf.h b/include/elf.h
index e8a515ce3d..ca9a419043 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -537,6 +537,34 @@ typedef struct {
 #define HWCAP_S390_HIGH_GPRS512
 #define HWCAP_S390_TE   1024
 
+/* M68K specific definitions. */
+/* We use the top 24 bits to encode information about the
+   architecture variant.  */
+#define EF_M68K_CPU320x0081
+#define EF_M68K_M68000   0x0100
+#define EF_M68K_CFV4E0x8000
+#define EF_M68K_FIDO 0x0200
+#define EF_M68K_ARCH_MASK   \
+  (EF_M68K_M68000 | EF_M68K_CPU32 | EF_M68K_CFV4E | EF_M68K_FIDO)
+
+/* We use the bottom 8 bits to encode information about the
+   coldfire variant.  If we use any of these bits, the top 24 bits are
+   either 0 or EF_M68K_CFV4E.  */
+#define EF_M68K_CF_ISA_MASK 0x0F  /* Which ISA */
+#define EF_M68K_CF_ISA_A_NODIV  0x01  /* ISA A except for div */
+#define EF_M68K_CF_ISA_A0x02
+#define EF_M68K_CF_ISA_A_PLUS   0x03
+#define EF_M68K_CF_ISA_B_NOUSP  0x04  /* ISA_B except for USP */
+#define EF_M68K_CF_ISA_B0x05
+#define EF_M68K_CF_ISA_C0x06
+#define EF_M68K_CF_ISA_C_NODIV  0x07  /* ISA C except for div */
+#define EF_M68K_CF_MAC_MASK 0x30
+#define EF_M68K_CF_MAC  0x10  /* MAC */
+#define EF_M68K_CF_EMAC 0x20  /* EMAC */
+#define EF_M68K_CF_EMAC_B   0x30  /* EMAC_B */
+#define EF_M68K_CF_FLOAT0x40  /* Has float insns */
+#define EF_M68K_CF_MASK 0xFF
+
 /*
  * 68k ELF relocation types
  */
diff --git a/linux-user/m68k/target_elf.h b/linux-user/m68k/target_elf.h
index df375ad5d3..998fe0fe2f 100644
--- a/linux-user/m68k/target_elf.h
+++ b/linux-user/m68k/target_elf.h
@@ -9,6 +9,12 @@
 #define M68K_TARGET_ELF_H
 static inline const char *cpu_get_model(uint32_t eflags)
 {
+if (eflags == 0 || (eflags & EF_M68K_M68000)) {
+/* 680x0 */
+return "m68040";
+}
+
+/* Coldfire */
 return "any";
 }
 #endif
-- 
2.14.3




[Qemu-devel] [PATCH v4 2/4] linux-user: introduce functions to detect CPU type

2018-01-24 Thread Laurent Vivier
From: YunQiang Su 

Add a function to return ELF e_flags and use it
to select the CPU model.

Signed-off-by: YunQiang Su 
[lv: split the patch and some cleanup in get_elf_eflags()]
Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
---
 linux-user/elfload.c | 35 +++
 linux-user/main.c| 20 ++--
 linux-user/qemu.h|  1 +
 3 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 20f3d8c2c3..67e2425ac6 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2376,6 +2376,41 @@ give_up:
 g_free(syms);
 }
 
+uint32_t get_elf_eflags(int fd)
+{
+struct elfhdr ehdr;
+off_t offset;
+int ret;
+
+/* Read ELF header */
+offset = lseek(fd, 0, SEEK_SET);
+if (offset == (off_t) -1) {
+return 0;
+}
+ret = read(fd, , sizeof(ehdr));
+if (ret < sizeof(ehdr)) {
+return 0;
+}
+offset = lseek(fd, offset, SEEK_SET);
+if (offset == (off_t) -1) {
+return 0;
+}
+
+/* Check ELF signature */
+if (!elf_check_ident()) {
+return 0;
+}
+
+/* check header */
+bswap_ehdr();
+if (!elf_check_ehdr()) {
+return 0;
+}
+
+/* return architecture id */
+return ehdr.e_flags;
+}
+
 int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
 {
 struct image_info interp_info;
diff --git a/linux-user/main.c b/linux-user/main.c
index 3954e8996b..6845b56030 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4319,8 +4319,17 @@ int main(int argc, char **argv, char **envp)
 
 init_qemu_uname_release();
 
+execfd = qemu_getauxval(AT_EXECFD);
+if (execfd == 0) {
+execfd = open(filename, O_RDONLY);
+if (execfd < 0) {
+printf("Error while loading %s: %s\n", filename, strerror(errno));
+_exit(EXIT_FAILURE);
+}
+}
+
 if (cpu_model == NULL) {
-cpu_model = cpu_get_model(0);
+cpu_model = cpu_get_model(get_elf_eflags(execfd));
 }
 tcg_exec_init(0);
 /* NOTE: we need to init the CPU at this stage to get
@@ -4413,15 +4422,6 @@ int main(int argc, char **argv, char **envp)
 cpu->opaque = ts;
 task_settid(ts);
 
-execfd = qemu_getauxval(AT_EXECFD);
-if (execfd == 0) {
-execfd = open(filename, O_RDONLY);
-if (execfd < 0) {
-printf("Error while loading %s: %s\n", filename, strerror(errno));
-_exit(EXIT_FAILURE);
-}
-}
-
 ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
 info, );
 if (ret != 0) {
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 4edd7d0c08..47ca71159c 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -188,6 +188,7 @@ int loader_exec(int fdexec, const char *filename, char 
**argv, char **envp,
  struct target_pt_regs * regs, struct image_info *infop,
  struct linux_binprm *);
 
+uint32_t get_elf_eflags(int fd);
 int load_elf_binary(struct linux_binprm *bprm, struct image_info *info);
 int load_flt_binary(struct linux_binprm *bprm, struct image_info *info);
 
-- 
2.14.3




[Qemu-devel] [PATCH v4 4/4] linux-user: MIPS set cpu to r6 CPU if binary is R6

2018-01-24 Thread Laurent Vivier
From: YunQiang Su 

So here we need to detect the version of binaries and set
cpu_model for it.

Signed-off-by: YunQiang Su 
[lv: original patch modified to move code into cpu_get_model()]
Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
---
 include/elf.h  | 4 
 linux-user/mips/target_elf.h   | 3 +++
 linux-user/mips64/target_elf.h | 3 +++
 3 files changed, 10 insertions(+)

diff --git a/include/elf.h b/include/elf.h
index ca9a419043..746b6d393b 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -40,6 +40,10 @@ typedef int64_t  Elf64_Sxword;
 #define EF_MIPS_ARCH_5 0x4000  /* -mips5 code.  */
 #define EF_MIPS_ARCH_320x5000  /* MIPS32 code.  */
 #define EF_MIPS_ARCH_640x6000  /* MIPS64 code.  */
+#define EF_MIPS_ARCH_32R2   0x7000  /* MIPS32r2 code.  */
+#define EF_MIPS_ARCH_64R2   0x8000  /* MIPS64r2 code.  */
+#define EF_MIPS_ARCH_32R6   0x9000  /* MIPS32r6 code.  */
+#define EF_MIPS_ARCH_64R6   0xa000  /* MIPS64r6 code.  */
 
 /* The ABI of a file. */
 #define EF_MIPS_ABI_O320x1000  /* O32 ABI.  */
diff --git a/linux-user/mips/target_elf.h b/linux-user/mips/target_elf.h
index bed0b43259..14b53d7469 100644
--- a/linux-user/mips/target_elf.h
+++ b/linux-user/mips/target_elf.h
@@ -9,6 +9,9 @@
 #define MIPS_TARGET_ELF_H
 static inline const char *cpu_get_model(uint32_t eflags)
 {
+if (eflags & EF_MIPS_ARCH_32R6) {
+return "mips32r6-generic";
+}
 return "24Kf";
 }
 #endif
diff --git a/linux-user/mips64/target_elf.h b/linux-user/mips64/target_elf.h
index 5b6f4692e0..ae14b38bfa 100644
--- a/linux-user/mips64/target_elf.h
+++ b/linux-user/mips64/target_elf.h
@@ -9,6 +9,9 @@
 #define MIPS64_TARGET_ELF_H
 static inline const char *cpu_get_model(uint32_t eflags)
 {
+if (eflags & EF_MIPS_ARCH_64R6) {
+return "I6400";
+}
 return "5KEf";
 }
 #endif
-- 
2.14.3




[Qemu-devel] [PATCH v4 0/4] linux-user: select CPU type according ELF header values

2018-01-24 Thread Laurent Vivier
This idea has been suggested to me before by Philippe
Mathieu-Daudé, and recently YunQiang Su has proposed a
patch to manage the MIPS r6 case.

Based on this, this series tries to clean-up the original
patch, and introduces the use for m68k architecture and
port the patch from YunQiang Su.

v4: Add YunQiang Su's S-o-b
I don't use cpu type as suggested by Igor because
his latest series "generalize parsing of cpu_model (part 4)" v3
doesn't seem to need this anymore (use of parse_cpu_model())
v3: fix code indent problem reported by patchew
remove useless "!= 0"
check for EF_M68K_M68000
add EF_M68K_* flags in elf.h
set 680x0 default CPU to m68040
change "#if ... #endif" structure for ppc
v2: move cpu_model selection to linux-user/*/target_elf.h
provide eflags to cpu_get_model() instead of fd
(and modify other patches accordingly)

Laurent Vivier (2):
  linux-user: Move CPU type name selection to a function
  linux-user,m68k: select CPU according to ELF header values

YunQiang Su (2):
  linux-user: introduce functions to detect CPU type
  linux-user: MIPS set cpu to r6 CPU if binary is R6

 include/elf.h  | 32 +
 linux-user/aarch64/target_elf.h| 14 +
 linux-user/alpha/target_elf.h  | 14 +
 linux-user/arm/target_elf.h| 14 +
 linux-user/cris/target_elf.h   | 14 +
 linux-user/elfload.c   | 35 ++
 linux-user/hppa/target_elf.h   | 14 +
 linux-user/i386/target_elf.h   | 14 +
 linux-user/m68k/target_elf.h   | 20 +
 linux-user/main.c  | 59 +++---
 linux-user/microblaze/target_elf.h | 14 +
 linux-user/mips/target_elf.h   | 17 +++
 linux-user/mips64/target_elf.h | 17 +++
 linux-user/nios2/target_elf.h  | 14 +
 linux-user/openrisc/target_elf.h   | 14 +
 linux-user/ppc/target_elf.h| 18 
 linux-user/qemu.h  |  1 +
 linux-user/s390x/target_elf.h  | 14 +
 linux-user/sh4/target_elf.h| 14 +
 linux-user/sparc/target_elf.h  | 14 +
 linux-user/sparc64/target_elf.h| 14 +
 linux-user/tilegx/target_elf.h | 14 +
 linux-user/unicore32/target_elf.h  | 14 +
 linux-user/x86_64/target_elf.h | 14 +
 24 files changed, 375 insertions(+), 48 deletions(-)
 create mode 100644 linux-user/aarch64/target_elf.h
 create mode 100644 linux-user/alpha/target_elf.h
 create mode 100644 linux-user/arm/target_elf.h
 create mode 100644 linux-user/cris/target_elf.h
 create mode 100644 linux-user/hppa/target_elf.h
 create mode 100644 linux-user/i386/target_elf.h
 create mode 100644 linux-user/m68k/target_elf.h
 create mode 100644 linux-user/microblaze/target_elf.h
 create mode 100644 linux-user/mips/target_elf.h
 create mode 100644 linux-user/mips64/target_elf.h
 create mode 100644 linux-user/nios2/target_elf.h
 create mode 100644 linux-user/openrisc/target_elf.h
 create mode 100644 linux-user/ppc/target_elf.h
 create mode 100644 linux-user/s390x/target_elf.h
 create mode 100644 linux-user/sh4/target_elf.h
 create mode 100644 linux-user/sparc/target_elf.h
 create mode 100644 linux-user/sparc64/target_elf.h
 create mode 100644 linux-user/tilegx/target_elf.h
 create mode 100644 linux-user/unicore32/target_elf.h
 create mode 100644 linux-user/x86_64/target_elf.h

-- 
2.14.3




[Qemu-devel] [PATCH v4 1/4] linux-user: Move CPU type name selection to a function

2018-01-24 Thread Laurent Vivier
Instead of a sequence of "#if ... #endif" move the
selection to a function in linux-user/*/target_elf.h

We can't add them in linux-user/*/target_cpu.h
because we will need to include "elf.h" to
use ELF flags with eflags, and including
"elf.h" in "target_cpu.h" introduces some
conflicts in elfload.c

Suggested-by: Richard Henderson 
Signed-off-by: Laurent Vivier 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 linux-user/aarch64/target_elf.h| 14 +
 linux-user/alpha/target_elf.h  | 14 +
 linux-user/arm/target_elf.h| 14 +
 linux-user/cris/target_elf.h   | 14 +
 linux-user/hppa/target_elf.h   | 14 +
 linux-user/i386/target_elf.h   | 14 +
 linux-user/m68k/target_elf.h   | 14 +
 linux-user/main.c  | 41 ++
 linux-user/microblaze/target_elf.h | 14 +
 linux-user/mips/target_elf.h   | 14 +
 linux-user/mips64/target_elf.h | 14 +
 linux-user/nios2/target_elf.h  | 14 +
 linux-user/openrisc/target_elf.h   | 14 +
 linux-user/ppc/target_elf.h| 18 +
 linux-user/s390x/target_elf.h  | 14 +
 linux-user/sh4/target_elf.h| 14 +
 linux-user/sparc/target_elf.h  | 14 +
 linux-user/sparc64/target_elf.h| 14 +
 linux-user/tilegx/target_elf.h | 14 +
 linux-user/unicore32/target_elf.h  | 14 +
 linux-user/x86_64/target_elf.h | 14 +
 21 files changed, 286 insertions(+), 39 deletions(-)
 create mode 100644 linux-user/aarch64/target_elf.h
 create mode 100644 linux-user/alpha/target_elf.h
 create mode 100644 linux-user/arm/target_elf.h
 create mode 100644 linux-user/cris/target_elf.h
 create mode 100644 linux-user/hppa/target_elf.h
 create mode 100644 linux-user/i386/target_elf.h
 create mode 100644 linux-user/m68k/target_elf.h
 create mode 100644 linux-user/microblaze/target_elf.h
 create mode 100644 linux-user/mips/target_elf.h
 create mode 100644 linux-user/mips64/target_elf.h
 create mode 100644 linux-user/nios2/target_elf.h
 create mode 100644 linux-user/openrisc/target_elf.h
 create mode 100644 linux-user/ppc/target_elf.h
 create mode 100644 linux-user/s390x/target_elf.h
 create mode 100644 linux-user/sh4/target_elf.h
 create mode 100644 linux-user/sparc/target_elf.h
 create mode 100644 linux-user/sparc64/target_elf.h
 create mode 100644 linux-user/tilegx/target_elf.h
 create mode 100644 linux-user/unicore32/target_elf.h
 create mode 100644 linux-user/x86_64/target_elf.h

diff --git a/linux-user/aarch64/target_elf.h b/linux-user/aarch64/target_elf.h
new file mode 100644
index 00..a7eb962fba
--- /dev/null
+++ b/linux-user/aarch64/target_elf.h
@@ -0,0 +1,14 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+
+#ifndef AARCH64_TARGET_ELF_H
+#define AARCH64_TARGET_ELF_H
+static inline const char *cpu_get_model(uint32_t eflags)
+{
+return "any";
+}
+#endif
diff --git a/linux-user/alpha/target_elf.h b/linux-user/alpha/target_elf.h
new file mode 100644
index 00..344e9f4d39
--- /dev/null
+++ b/linux-user/alpha/target_elf.h
@@ -0,0 +1,14 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+
+#ifndef ALPHA_TARGET_ELF_H
+#define ALPHA_TARGET_ELF_H
+static inline const char *cpu_get_model(uint32_t eflags)
+{
+return "any";
+}
+#endif
diff --git a/linux-user/arm/target_elf.h b/linux-user/arm/target_elf.h
new file mode 100644
index 00..58ff6a0986
--- /dev/null
+++ b/linux-user/arm/target_elf.h
@@ -0,0 +1,14 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+
+#ifndef ARM_TARGET_ELF_H
+#define ARM_TARGET_ELF_H
+static inline const char *cpu_get_model(uint32_t eflags)
+{
+return "any";
+}
+#endif
diff --git a/linux-user/cris/target_elf.h b/linux-user/cris/target_elf.h
new file mode 100644
index 00..99eb4ec704
--- /dev/null
+++ b/linux-user/cris/target_elf.h
@@ -0,0 +1,14 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public 

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

2018-01-24 Thread Michael S. Tsirkin
On Wed, Jan 24, 2018 at 10:40:14AM +0100, Paolo Bonzini wrote:
> On 23/01/2018 18:54, Jose Ricardo Ziviani wrote:
> > This commit partially reverts the commit 4fe6d78b2e because of issues
> > reported in the virtio.
> > 
> > Examples:
> > 
> > $ qemu-system-ppc64 -cpu POWER8 -nographic -vga none -m 4G \
> >   -M pseries,accel=kvm -netdev type=user,id=net0 \
> >   -device virtio-net-pci,netdev=net0 -drive file=../disk.qcow2,if=virtio
> > 
> > Populating /vdevice/nvram@7101
> > Populating /vdevice/v-scsi@7102
> >SCSI: Looking for devices
> >   8200 CD-ROM   : "QEMU QEMU CD-ROM  2.5+"
> > Populating /pci@8002000
> >  00  (D) : 1af4 1000virtio [ net ]
> > Aborted
> > 
> > $ qemu-system-x86_64 -m 4G -enable-kvm -drive file=util.qcow2,if=virtio
> > 
> > Running QEMU with GTK 2.x is deprecated, and will be removed
> > in a future release. Please switch to GTK 3.x instead
> > [1]5282 abort
> > 
> > Reference 
> > http://lists.nongnu.org/archive/html/qemu-devel/2018-01/msg05457.html
> > 
> > Reported-by: Anton Blanchard 
> > Signed-off-by: Jose Ricardo Ziviani 
> > ---
> >  accel/kvm/kvm-all.c | 4 
> >  1 file changed, 4 deletions(-)
> 
> Michael, please send a revert for all three of Gal's patches.
> 
> Thanks,
> 
> Paolo

Yes, I've done exactly that.
Thanks for the suggestion.

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



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

2018-01-24 Thread Michael S. Tsirkin
On Wed, Jan 24, 2018 at 08:17:08PM +, Peter Maydell wrote:
> On 23 January 2018 at 22:44, Michael S. Tsirkin  wrote:
> > This is just a quick bugfix so people can make progress.
> > Will send a pull req with more patches queues later this week.
> >
> > The following changes since commit 52483b067cce4a88ffbf8fbeea26de7549d2ad23:
> >
> >   Merge remote-tracking branch 'remotes/huth/tags/pull-request-2018-01-22' 
> > into staging (2018-01-23 10:15:09 +)
> >
> > are available in the git repository at:
> >
> >   git://git.kernel.org/pub/scm/virt/kvm/mst/qemu.git tags/for_upstream
> >
> > for you to fetch changes up to 3e59a4745a1668eeec94d142b0f5a7847b866a87:
> >
> >   kvm-all: Partially reverts 4fe6d78b2e to remove the cleanup call 
> > (2018-01-24 00:41:50 +0200)
> >
> > 
> > virtio: quick fix
> >
> > Fixes a regression in virtio that's causing issues
> > for many people.
> >
> > Signed-off-by: Michael S. Tsirkin 
> >
> > 
> > Jose Ricardo Ziviani (1):
> >   kvm-all: Partially reverts 4fe6d78b2e to remove the cleanup call
> >
> >  accel/kvm/kvm-all.c | 4 
> >  1 file changed, 4 deletions(-)
> 
> Hi -- this pullreq is superseded by your later one, right?
> 
> thanks
> -- PMM

Exactly, thanks!

-- 
MST



Re: [Qemu-devel] [PATCH v3 3/3] hostmem-file: add 'sync' option

2018-01-24 Thread Michael S. Tsirkin
On Wed, Jan 17, 2018 at 04:13:25PM +0800, Haozhong Zhang wrote:
> This option controls whether QEMU mmap(2) the memory backend file with
> MAP_SYNC flag, which can fully guarantee the guest write persistence
> to the backend, if MAP_SYNC flag is supported by the host kernel
> (Linux kernel 4.15 and later) and the backend is a file supporting
> DAX (e.g., file on ext4/xfs file system mounted with '-o dax').
> 
> It can take one of following values:
>  - on:  try to pass MAP_SYNC to mmap(2); if MAP_SYNC is not supported or
> 'share=off', QEMU will abort
>  - off: never pass MAP_SYNC to mmap(2)
>  - auto (default): if MAP_SYNC is supported and 'share=on', work as if
> 'sync=on'; otherwise, work as if 'sync=off'
> 
> Signed-off-by: Haozhong Zhang 
> Suggested-by: Eduardo Habkost 
> ---
>  backends/hostmem-file.c | 40 +++-
>  docs/nvdimm.txt | 15 ++-
>  exec.c  | 13 -
>  include/exec/memory.h   |  4 
>  include/exec/ram_addr.h |  6 +++---
>  memory.c|  6 --
>  numa.c  |  2 +-
>  qemu-options.hx | 21 -
>  8 files changed, 93 insertions(+), 14 deletions(-)
> 
> diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
> index ed7d145365..96dff38619 100644
> --- a/backends/hostmem-file.c
> +++ b/backends/hostmem-file.c
> @@ -15,6 +15,7 @@
>  #include "sysemu/hostmem.h"
>  #include "sysemu/sysemu.h"
>  #include "qom/object_interfaces.h"
> +#include "qapi-visit.h"
>  
>  /* hostmem-file.c */
>  /**
> @@ -35,6 +36,7 @@ struct HostMemoryBackendFile {
>  bool discard_data;
>  char *mem_path;
>  uint64_t align;
> +OnOffAuto sync;
>  };
>  
>  static void
> @@ -60,7 +62,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error 
> **errp)
>  memory_region_init_ram_from_file(>mr, OBJECT(backend),
>   path,
>   backend->size, fb->align, fb->share,
> - fb->mem_path, errp);
> + fb->sync, fb->mem_path, errp);
>  g_free(path);
>  }
>  #endif
> @@ -153,6 +155,39 @@ static void file_memory_backend_set_align(Object *o, 
> Visitor *v,
>  error_propagate(errp, local_err);
>  }
>  
> +static void file_memory_backend_get_sync(
> +Object *obj, Visitor *v, const char *name, void *opaque, Error **errp)
> +{
> +HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
> +OnOffAuto value = fb->sync;
> +
> +visit_type_OnOffAuto(v, name, , errp);
> +}
> +
> +static void file_memory_backend_set_sync(
> +Object *obj, Visitor *v, const char *name, void *opaque, Error **errp)
> +{
> +HostMemoryBackend *backend = MEMORY_BACKEND(obj);
> +HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
> +Error *local_err = NULL;
> +OnOffAuto value;
> +
> +if (host_memory_backend_mr_inited(backend)) {
> +error_setg(_err, "cannot change property '%s' of %s '%s'",
> +   name, object_get_typename(obj), backend->id);
> +goto out;
> +}
> +
> +visit_type_OnOffAuto(v, name, , _err);
> +if (local_err) {
> +goto out;
> +}
> +fb->sync = value;
> +
> + out:
> +error_propagate(errp, local_err);
> +}
> +
>  static void file_backend_unparent(Object *obj)
>  {
>  HostMemoryBackend *backend = MEMORY_BACKEND(obj);
> @@ -187,6 +222,9 @@ file_backend_class_init(ObjectClass *oc, void *data)
>  file_memory_backend_get_align,
>  file_memory_backend_set_align,
>  NULL, NULL, _abort);
> +object_class_property_add(oc, "sync", "OnOffAuto",
> +file_memory_backend_get_sync, file_memory_backend_set_sync,
> +NULL, NULL, _abort);
>  }
>  
>  static void file_backend_instance_finalize(Object *o)
> diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt
> index e903d8bb09..49b174fe66 100644
> --- a/docs/nvdimm.txt
> +++ b/docs/nvdimm.txt
> @@ -143,10 +143,23 @@ Guest Data Persistence
>  --
>  
>  Though QEMU supports multiple types of vNVDIMM backends on Linux,
> -currently the only one that can guarantee the guest write persistence
> +if MAP_SYNC is not supported by the host kernel and the backends,
> +the only backend that can guarantee the guest write persistence
>  is the device DAX on the real NVDIMM device (e.g., /dev/dax0.0), to
>  which all guest access do not involve any host-side kernel cache.
>  
> +mmap(2) flag MAP_SYNC is added since Linux kernel 4.15. On such
> +systems, QEMU can mmap(2) the backend with MAP_SYNC, which can
> +guarantee the guest write persistence to vNVDIMM. Besides the host
> +kernel support, enabling MAP_SYNC in QEMU also requires:
> +
> + - the backend is a file supporting DAX, e.g., a file on an ext4 or
> +   xfs file system mounted with "-o dax",
> +
> + - 'sync' option of memory-backend-file is not 'off', and

Re: [Qemu-devel] [PATCH v3 2/3] hostmem: add more information in error messages

2018-01-24 Thread Michael S. Tsirkin
On Wed, Jan 17, 2018 at 04:13:24PM +0800, Haozhong Zhang wrote:
> When there are multiple memory backends in use, including the object type
> name, ID and the property name in the error message can help users to
> locate the error.
> 
> Signed-off-by: Haozhong Zhang 
> Suggested-by: "Dr. David Alan Gilbert" 

Reviewed-by: Michael S. Tsirkin 

> ---
>  backends/hostmem-file.c |  9 ++---
>  backends/hostmem.c  | 11 +++
>  2 files changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
> index e319ec1ad8..ed7d145365 100644
> --- a/backends/hostmem-file.c
> +++ b/backends/hostmem-file.c
> @@ -79,7 +79,8 @@ static void set_mem_path(Object *o, const char *str, Error 
> **errp)
>  HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
>  
>  if (host_memory_backend_mr_inited(backend)) {
> -error_setg(errp, "cannot change property value");
> +error_setg(errp, "cannot change property 'mem-path' of %s '%s'",
> +   object_get_typename(o), backend->id);
>  return;
>  }
>  g_free(fb->mem_path);
> @@ -99,7 +100,8 @@ static void file_memory_backend_set_share(Object *o, bool 
> value, Error **errp)
>  HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
>  
>  if (host_memory_backend_mr_inited(backend)) {
> -error_setg(errp, "cannot change property value");
> +error_setg(errp, "cannot change property 'share' of %s '%s'",
> +   object_get_typename(o), backend->id);
>  return;
>  }
>  fb->share = value;
> @@ -136,7 +138,8 @@ static void file_memory_backend_set_align(Object *o, 
> Visitor *v,
>  uint64_t val;
>  
>  if (host_memory_backend_mr_inited(backend)) {
> -error_setg(_err, "cannot change property value");
> +error_setg(_err, "cannot change property '%s' of %s '%s'",
> +   name, object_get_typename(o), backend->id);
>  goto out;
>  }
>  
> diff --git a/backends/hostmem.c b/backends/hostmem.c
> index ee2c2d5bfd..6853d19bc5 100644
> --- a/backends/hostmem.c
> +++ b/backends/hostmem.c
> @@ -46,7 +46,8 @@ host_memory_backend_set_size(Object *obj, Visitor *v, const 
> char *name,
>  uint64_t value;
>  
>  if (host_memory_backend_mr_inited(backend)) {
> -error_setg(_err, "cannot change property value");
> +error_setg(_err, "cannot change property %s of %s '%s'",
> +   name, object_get_typename(obj), backend->id);
>  goto out;
>  }
>  
> @@ -55,8 +56,9 @@ host_memory_backend_set_size(Object *obj, Visitor *v, const 
> char *name,
>  goto out;
>  }
>  if (!value) {
> -error_setg(_err, "Property '%s.%s' doesn't take value '%"
> -   PRIu64 "'", object_get_typename(obj), name, value);
> +error_setg(_err,
> +   "property '%s' of %s '%s' doesn't take value '%" PRIu64 
> "'",
> +   name, object_get_typename(obj), backend->id, value);
>  goto out;
>  }
>  backend->size = value;
> @@ -363,7 +365,8 @@ static void set_id(Object *o, const char *str, Error 
> **errp)
>  HostMemoryBackend *backend = MEMORY_BACKEND(o);
>  
>  if (backend->id) {
> -error_setg(errp, "cannot change property value");
> +error_setg(errp, "cannot change property 'id' of %s '%s'",
> +   object_get_typename(o), backend->id);
>  return;
>  }
>  backend->id = g_strdup(str);
> -- 
> 2.14.1



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

2018-01-24 Thread Pavel Pisa
Hello everybody,

On Tuesday 23 of January 2018 22:42:31 Pavel Pisa wrote:
> When Linux specific object file is linked in then some local
> function needs to be called before QOM instances population.
> I know how to do that GCC specific/non-portable way
>
> static void __attribute__((constructor)) can_socketcan_setup_variant(void)
> {
>
> }
>
> but I expect that something like
>
> module_init()
>
> in can_socketcan.c should be used.


I have experimented with code changes to get rid of stub for
non Linux systems. type_init() is used because it is more
portable than constructor attribute.

I have seen that a few other type_init-s do more
than simple sequence of type_register_static().
Is it acceptable to use type_init for registration
to CAN core by function call for now? Conversion simplifies
makefiles and unnecessary stub file is removed.

But I would use attribute if that solution is preferred because
it is allways present on Linux where SocketCAN is used anyway
and it is used in other Qemu subsystems as well.


Solution with attribute

#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
static void __attribute__((constructor))
can_bus_socketcan_setup(void)
{
can_bus_set_connect_to_host(can_bus_connect_to_host_socketcan);
}
#endif


Solution with type_init
branch https://gitlab.fel.cvut.cz/canbus/qemu-canbus/tree/can-pci-socketcan-init

diff --git a/hw/can/can_socketcan.c b/hw/can/can_socketcan.c
index 42099fb696..fb41853c2b 100644
--- a/hw/can/can_socketcan.c
+++ b/hw/can/can_socketcan.c
@@ -309,5 +309,14 @@ static int can_bus_connect_to_host_socketcan(CanBusState 
*bus,
 return 0;
 }
 
-int (*can_bus_connect_to_host_variant)(CanBusState *bus, const char *name) =
-can_bus_connect_to_host_socketcan;
+static void can_bus_socketcan_type_init(void)
+{
+/*
+ * There should be object registration when CanBusSocketcanConnectState
+ * is converted into QOM object. Use for registration of host
+ * can bus access for now.
+ */
+can_bus_set_connect_to_host(can_bus_connect_to_host_socketcan);
+}
+
+type_init(can_bus_socketcan_type_init);


diff --git a/hw/can/Makefile.objs b/hw/can/Makefile.objs
index 1ce9950de0..14c2369718 100644
--- a/hw/can/Makefile.objs
+++ b/hw/can/Makefile.objs
@@ -2,11 +2,7 @@
 
 ifeq ($(CONFIG_CAN_BUS),y)
 common-obj-y += can_core.o
-ifeq ($(CONFIG_LINUX),y)
-common-obj-y += can_socketcan.o
-else
-common-obj-y += can_host_stub.o
-endif
+common-obj-$(CONFIG_LINUX) += can_socketcan.o
 common-obj-$(CONFIG_CAN_SJA1000) += can_sja1000.o
 common-obj-$(CONFIG_CAN_PCI) += can_kvaser_pci.o
 common-obj-$(CONFIG_CAN_PCI) += can_pcm3680_pci.o
diff --git a/hw/can/can_core.c b/hw/can/can_core.c
index 41c458c792..c14807b188 100644
--- a/hw/can/can_core.c
+++ b/hw/can/can_core.c
@@ -34,6 +34,8 @@
 static QTAILQ_HEAD(, CanBusState) can_buses =
 QTAILQ_HEAD_INITIALIZER(can_buses);
 
+static can_bus_connect_to_host_t can_bus_connect_to_host_fnc;
+
 CanBusState *can_bus_find_by_name(const char *name, bool create_missing)
 {
 CanBusState *bus;
@@ -127,10 +129,15 @@ int can_bus_client_set_filters(CanBusClientState *client,
 
 int can_bus_connect_to_host_device(CanBusState *bus, const char *name)
 {
-if (can_bus_connect_to_host_variant == NULL) {
+if (can_bus_connect_to_host_fnc == NULL) {
 error_report("CAN bus connect to host device is not "
  "supported on this system");
 exit(1);
 }
-return can_bus_connect_to_host_variant(bus, name);
+return can_bus_connect_to_host_fnc(bus, name);
+}
+
+void can_bus_set_connect_to_host(can_bus_connect_to_host_t connect_fnc)
+{
+can_bus_connect_to_host_fnc = connect_fnc;
 }
diff --git a/hw/can/can_host_stub.c b/hw/can/can_host_stub.c
deleted file mode 100644
index 748d25f995..00
--- a/hw/can/can_host_stub.c
+++ /dev/null
@@ -1,36 +0,0 @@



-
-
-int (*can_bus_connect_to_host_variant)(CanBusState *bus, const char *name) =
-NULL;

diff --git a/include/can/can_emu.h b/include/can/can_emu.h
index 85237ee3c9..7f0705e49f 100644
--- a/include/can/can_emu.h
+++ b/include/can/can_emu.h
@@ -107,8 +107,9 @@ struct CanBusState {
 QTAILQ_ENTRY(CanBusState) next;
 };
 
-extern int (*can_bus_connect_to_host_variant)(CanBusState *bus,
-  const char *name);
+typedef int (*can_bus_connect_to_host_t)(CanBusState *bus, const char *name);
+
+void can_bus_set_connect_to_host(can_bus_connect_to_host_t connect_fnc);
 
 int can_bus_filter_match(struct qemu_can_filter *filter, qemu_canid_t can_id);


Best wishes,

Pavel



Re: [Qemu-devel] [PATCH v3 3/3] hostmem-file: add 'sync' option

2018-01-24 Thread Michael S. Tsirkin
On Wed, Jan 17, 2018 at 04:13:25PM +0800, Haozhong Zhang wrote:
> This option controls whether QEMU mmap(2) the memory backend file with
> MAP_SYNC flag, which can fully guarantee the guest write persistence
> to the backend, if MAP_SYNC flag is supported by the host kernel
> (Linux kernel 4.15 and later) and the backend is a file supporting
> DAX (e.g., file on ext4/xfs file system mounted with '-o dax').
> 
> It can take one of following values:
>  - on:  try to pass MAP_SYNC to mmap(2); if MAP_SYNC is not supported or
> 'share=off', QEMU will abort
>  - off: never pass MAP_SYNC to mmap(2)
>  - auto (default): if MAP_SYNC is supported and 'share=on', work as if
> 'sync=on'; otherwise, work as if 'sync=off'
> 
> Signed-off-by: Haozhong Zhang 
> Suggested-by: Eduardo Habkost 

Reviewed-by: Michael S. Tsirkin 


> ---
>  backends/hostmem-file.c | 40 +++-
>  docs/nvdimm.txt | 15 ++-
>  exec.c  | 13 -
>  include/exec/memory.h   |  4 
>  include/exec/ram_addr.h |  6 +++---
>  memory.c|  6 --
>  numa.c  |  2 +-
>  qemu-options.hx | 21 -
>  8 files changed, 93 insertions(+), 14 deletions(-)
> 
> diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
> index ed7d145365..96dff38619 100644
> --- a/backends/hostmem-file.c
> +++ b/backends/hostmem-file.c
> @@ -15,6 +15,7 @@
>  #include "sysemu/hostmem.h"
>  #include "sysemu/sysemu.h"
>  #include "qom/object_interfaces.h"
> +#include "qapi-visit.h"
>  
>  /* hostmem-file.c */
>  /**
> @@ -35,6 +36,7 @@ struct HostMemoryBackendFile {
>  bool discard_data;
>  char *mem_path;
>  uint64_t align;
> +OnOffAuto sync;
>  };
>  
>  static void
> @@ -60,7 +62,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error 
> **errp)
>  memory_region_init_ram_from_file(>mr, OBJECT(backend),
>   path,
>   backend->size, fb->align, fb->share,
> - fb->mem_path, errp);
> + fb->sync, fb->mem_path, errp);
>  g_free(path);
>  }
>  #endif
> @@ -153,6 +155,39 @@ static void file_memory_backend_set_align(Object *o, 
> Visitor *v,
>  error_propagate(errp, local_err);
>  }
>  
> +static void file_memory_backend_get_sync(
> +Object *obj, Visitor *v, const char *name, void *opaque, Error **errp)
> +{
> +HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
> +OnOffAuto value = fb->sync;
> +
> +visit_type_OnOffAuto(v, name, , errp);
> +}
> +
> +static void file_memory_backend_set_sync(
> +Object *obj, Visitor *v, const char *name, void *opaque, Error **errp)
> +{
> +HostMemoryBackend *backend = MEMORY_BACKEND(obj);
> +HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(obj);
> +Error *local_err = NULL;
> +OnOffAuto value;
> +
> +if (host_memory_backend_mr_inited(backend)) {
> +error_setg(_err, "cannot change property '%s' of %s '%s'",
> +   name, object_get_typename(obj), backend->id);
> +goto out;
> +}
> +
> +visit_type_OnOffAuto(v, name, , _err);
> +if (local_err) {
> +goto out;
> +}
> +fb->sync = value;
> +
> + out:
> +error_propagate(errp, local_err);
> +}
> +
>  static void file_backend_unparent(Object *obj)
>  {
>  HostMemoryBackend *backend = MEMORY_BACKEND(obj);
> @@ -187,6 +222,9 @@ file_backend_class_init(ObjectClass *oc, void *data)
>  file_memory_backend_get_align,
>  file_memory_backend_set_align,
>  NULL, NULL, _abort);
> +object_class_property_add(oc, "sync", "OnOffAuto",
> +file_memory_backend_get_sync, file_memory_backend_set_sync,
> +NULL, NULL, _abort);
>  }
>  
>  static void file_backend_instance_finalize(Object *o)
> diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt
> index e903d8bb09..49b174fe66 100644
> --- a/docs/nvdimm.txt
> +++ b/docs/nvdimm.txt
> @@ -143,10 +143,23 @@ Guest Data Persistence
>  --
>  
>  Though QEMU supports multiple types of vNVDIMM backends on Linux,
> -currently the only one that can guarantee the guest write persistence
> +if MAP_SYNC is not supported by the host kernel and the backends,
> +the only backend that can guarantee the guest write persistence
>  is the device DAX on the real NVDIMM device (e.g., /dev/dax0.0), to
>  which all guest access do not involve any host-side kernel cache.
>  
> +mmap(2) flag MAP_SYNC is added since Linux kernel 4.15. On such
> +systems, QEMU can mmap(2) the backend with MAP_SYNC, which can
> +guarantee the guest write persistence to vNVDIMM. Besides the host
> +kernel support, enabling MAP_SYNC in QEMU also requires:
> +
> + - the backend is a file supporting DAX, e.g., a file on an ext4 or
> +   xfs file system mounted with "-o dax",
> +
> + - 

  1   2   3   >