Re: [PATCH v6 07/11] iotests: add findtests.py

2021-01-13 Thread Vladimir Sementsov-Ogievskiy

12.01.2021 19:42, Kevin Wolf wrote:

+def find_tests(self, groups: Optional[List[str]] = None,
+   exclude_groups: Optional[List[str]] = None,
+   tests: Optional[List[str]] = None,

group and tests seem to be read-only, so this can be simplified to
'groups: Sequence[str] = ()' etc. without the explicit handling of None
below.


None comes when cmdline argument is not set, will sequence as you propose I get

Traceback (most recent call last):
  File "/work/src/qemu/up-refactor-iotests/build/tests/qemu-iotests/./check", line 
37, in 
tests, remaining_argv = find_tests(env.remaining_argv,
  File "/work/src/qemu/up-refactor-iotests/tests/qemu-iotests/findtests.py", 
line 208, in find_tests
return tf.find_tests_argv(argv)
  File "/work/src/qemu/up-refactor-iotests/tests/qemu-iotests/findtests.py", 
line 193, in find_tests_argv
return self.find_tests(**vars(args)), remaining
  File "/work/src/qemu/up-refactor-iotests/tests/qemu-iotests/findtests.py", 
line 165, in find_tests
if 'disabled' not in groups and 'disabled' not in exclude_groups:
TypeError: argument of type 'NoneType' is not iterable

So, seems simpler to keep all as is than modifying find_tests_argv to not pass 
None arguments.

--
Best regards,
Vladimir



[PATCH v3 4/4] hw/blocl/nvme: trigger async event during injecting smart warning

2021-01-13 Thread zhenwei pi
During smart critical warning injection by setting property from QMP
command, also try to trigger asynchronous event.

Signed-off-by: zhenwei pi 
---
 hw/block/nvme.c | 47 ---
 1 file changed, 40 insertions(+), 7 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index ce9a9c9023..1feb603471 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -847,6 +847,36 @@ static void nvme_enqueue_event(NvmeCtrl *n, uint8_t 
event_type,
 nvme_process_aers(n);
 }
 
+static void nvme_enqueue_smart_event(NvmeCtrl *n, uint8_t event)
+{
+uint8_t aer_info;
+
+if (!(NVME_AEC_SMART(n->features.async_config) & event)) {
+return;
+}
+
+/* Ref SPEC  */
+switch (event) {
+case NVME_SMART_SPARE:
+aer_info = NVME_AER_INFO_SMART_SPARE_THRESH;
+break;
+case NVME_SMART_TEMPERATURE:
+aer_info = NVME_AER_INFO_SMART_TEMP_THRESH;
+break;
+case NVME_SMART_RELIABILITY:
+case NVME_SMART_MEDIA_READ_ONLY:
+case NVME_SMART_FAILED_VOLATILE_MEDIA:
+aer_info = NVME_AER_INFO_SMART_RELIABILITY;
+break;
+case NVME_SMART_PMR_UNRELIABLE:
+/* TODO if NVME_SMART_PMR_UNRELIABLE is defined in future */
+default:
+return;
+}
+
+nvme_enqueue_event(n, NVME_AER_TYPE_SMART, aer_info, NVME_LOG_SMART_INFO);
+}
+
 static void nvme_clear_events(NvmeCtrl *n, uint8_t event_type)
 {
 n->aer_mask &= ~(1 << event_type);
@@ -1824,12 +1854,9 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, 
NvmeRequest *req)
 return NVME_INVALID_FIELD | NVME_DNR;
 }
 
-if (((n->temperature >= n->features.temp_thresh_hi) ||
- (n->temperature <= n->features.temp_thresh_low)) &&
-NVME_AEC_SMART(n->features.async_config) & NVME_SMART_TEMPERATURE) 
{
-nvme_enqueue_event(n, NVME_AER_TYPE_SMART,
-   NVME_AER_INFO_SMART_TEMP_THRESH,
-   NVME_LOG_SMART_INFO);
+if ((n->temperature >= n->features.temp_thresh_hi) ||
+ (n->temperature <= n->features.temp_thresh_low)) {
+nvme_enqueue_smart_event(n, NVME_AER_INFO_SMART_TEMP_THRESH);
 }
 
 break;
@@ -2841,7 +2868,7 @@ static void nvme_set_smart_warning(Object *obj, Visitor 
*v, const char *name,
void *opaque, Error **errp)
 {
 NvmeCtrl *s = NVME(obj);
-uint8_t value, cap = 0;
+uint8_t value, cap = 0, event;
 uint64_t pmr_cap = CAP_PMR_MASK;
 
 if (!visit_type_uint8(v, name, , errp)) {
@@ -2860,6 +2887,12 @@ static void nvme_set_smart_warning(Object *obj, Visitor 
*v, const char *name,
 }
 
 s->smart_critical_warning = value;
+
+/* test each bit of uint8_t for smart.critical_warning */
+for (event = 0; event < 8; event++) {
+if (value & (1 << event))
+nvme_enqueue_smart_event(s, 1 << event);
+}
 }
 
 static const VMStateDescription nvme_vmstate = {
-- 
2.25.1




[PATCH v3 3/4] hw/block/nvme: add smart_critical_warning property

2021-01-13 Thread zhenwei pi
There is a very low probability that hitting physical NVMe disk
hardware critical warning case, it's hard to write & test a monitor
agent service.

For debugging purposes, add a new 'smart_critical_warning' property
to emulate this situation.

The orignal version of this change is implemented by adding a fixed
property which could be initialized by QEMU command line. Suggested
by Philippe & Klaus, rework like current version.

Test with this patch:
1, change smart_critical_warning property for a running VM:
 #virsh qemu-monitor-command nvme-upstream '{ "execute": "qom-set",
  "arguments": { "path": "/machine/peripheral-anon/device[0]",
  "property": "smart_critical_warning", "value":16 } }'
2, run smartctl in guest
 #smartctl -H -l error /dev/nvme0n1

  === START OF SMART DATA SECTION ===
  SMART overall-health self-assessment test result: FAILED!
  - volatile memory backup device has failed

Signed-off-by: zhenwei pi 
---
 hw/block/nvme.c | 40 
 hw/block/nvme.h |  1 +
 2 files changed, 41 insertions(+)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index f361103bb4..ce9a9c9023 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -1214,6 +1214,7 @@ static uint16_t nvme_smart_info(NvmeCtrl *n, uint8_t rae, 
uint32_t buf_len,
 }
 
 trans_len = MIN(sizeof(smart) - off, buf_len);
+smart.critical_warning = n->smart_critical_warning;
 
 smart.data_units_read[0] = cpu_to_le64(DIV_ROUND_UP(stats.units_read,
 1000));
@@ -2826,6 +2827,41 @@ static Property nvme_props[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+
+static void nvme_get_smart_warning(Object *obj, Visitor *v, const char *name,
+   void *opaque, Error **errp)
+{
+NvmeCtrl *s = NVME(obj);
+uint8_t value = s->smart_critical_warning;
+
+visit_type_uint8(v, name, , errp);
+}
+
+static void nvme_set_smart_warning(Object *obj, Visitor *v, const char *name,
+   void *opaque, Error **errp)
+{
+NvmeCtrl *s = NVME(obj);
+uint8_t value, cap = 0;
+uint64_t pmr_cap = CAP_PMR_MASK;
+
+if (!visit_type_uint8(v, name, , errp)) {
+return;
+}
+
+cap = NVME_SMART_SPARE | NVME_SMART_TEMPERATURE | NVME_SMART_RELIABILITY
+  | NVME_SMART_MEDIA_READ_ONLY | NVME_SMART_FAILED_VOLATILE_MEDIA;
+if (s->bar.cap & (pmr_cap << CAP_PMR_SHIFT)) {
+cap |= NVME_SMART_PMR_UNRELIABLE;
+}
+
+if ((value & cap) != value) {
+error_setg(errp, "unsupported smart critical warning value");
+return;
+}
+
+s->smart_critical_warning = value;
+}
+
 static const VMStateDescription nvme_vmstate = {
 .name = "nvme",
 .unmigratable = 1,
@@ -2856,6 +2892,10 @@ static void nvme_instance_init(Object *obj)
   "bootindex", "/namespace@1,0",
   DEVICE(obj));
 }
+
+object_property_add(obj, "smart_critical_warning", "uint8",
+nvme_get_smart_warning,
+nvme_set_smart_warning, NULL, NULL);
 }
 
 static const TypeInfo nvme_info = {
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index e080a2318a..64e3497244 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -139,6 +139,7 @@ typedef struct NvmeCtrl {
 uint64_ttimestamp_set_qemu_clock_ms;/* QEMU clock time */
 uint64_tstarttime_ms;
 uint16_ttemperature;
+uint8_t smart_critical_warning;
 
 HostMemoryBackend *pmrdev;
 
-- 
2.25.1




[PATCH v3 2/4] hw/block/nvme: fix overwritten bar.cap

2021-01-13 Thread zhenwei pi
After PMR initialization, bar.cap should not be clear in function
nvme_init_ctrl. Otherwise the PMR cap would be always disabled.

Signed-off-by: zhenwei pi 
---
 hw/block/nvme.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 27d2c72716..f361103bb4 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2745,7 +2745,6 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
 id->psd[0].enlat = cpu_to_le32(0x10);
 id->psd[0].exlat = cpu_to_le32(0x4);
 
-n->bar.cap = 0;
 NVME_CAP_SET_MQES(n->bar.cap, 0x7ff);
 NVME_CAP_SET_CQR(n->bar.cap, 1);
 NVME_CAP_SET_TO(n->bar.cap, 0xf);
-- 
2.25.1




[PATCH v3 1/4] block/nvme: introduce bit 5 for critical warning

2021-01-13 Thread zhenwei pi
According to NVMe spec 1.4 section
, introduce bit 5
for "Persistent Memory Region has become read-only or unreliable".

Signed-off-by: zhenwei pi 
---
 include/block/nvme.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/block/nvme.h b/include/block/nvme.h
index 3e02d9ca98..f68a88c712 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -749,6 +749,7 @@ enum NvmeSmartWarn {
 NVME_SMART_RELIABILITY= 1 << 2,
 NVME_SMART_MEDIA_READ_ONLY= 1 << 3,
 NVME_SMART_FAILED_VOLATILE_MEDIA  = 1 << 4,
+NVME_SMART_PMR_UNRELIABLE = 1 << 5,
 };
 
 enum NvmeLogIdentifier {
-- 
2.25.1




[PATCH v3 0/4] support NVMe smart critial warning injection

2021-01-13 Thread zhenwei pi
v2 -> v3:
- Introduce "Persistent Memory Region has become read-only or
  unreliable"

- Fix overwritten bar.cap

- Check smart critical warning value from QOM.

- Trigger asynchronous event during smart warning injection.

v1 -> v2:
- Suggested by Philippe & Klaus, set/get smart_critical_warning by QMP.

v1:
- Add smart_critical_warning for nvme device which can be set by QEMU
  command line to emulate hardware error.

Zhenwei Pi (4):
  block/nvme: introduce bit 5 for critical warning
  hw/block/nvme: fix overwritten bar.cap
  hw/block/nvme: add smart_critical_warning property
  hw/blocl/nvme: trigger async event during injecting smart warning

 hw/block/nvme.c  | 86 
 hw/block/nvme.h  |  1 +
 include/block/nvme.h |  1 +
 3 files changed, 81 insertions(+), 7 deletions(-)

-- 
2.25.1




[PATCH v3 1/2] Fix net.c warning on GCC 11

2021-01-13 Thread Miroslav Rezanina
When building qemu with GCC 11, compiling eth.c file produce following warning:

   warning: array subscript 'struct ip6_ext_hdr_routing[0]' is partly outside 
array bounds of 'struct ip6_ext_hdr[1]' [-Warray-bounds]

This is caused by retyping from ip6_ext_hdr to ip6_ext_hdr_routing that has more
attributes.

As this usage is expected, suppress the warning temporarily through the function
using this retyping.

Signed-off-by: Miroslav Rezanina 
---
 net/eth.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/eth.c b/net/eth.c
index 1e0821c5f8..b9bdd0435c 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -405,6 +405,8 @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int 
pkt_frags,
 struct ip6_ext_hdr *ext_hdr,
 struct in6_address *dst_addr)
 {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
 struct ip6_ext_hdr_routing *rthdr = (struct ip6_ext_hdr_routing *) ext_hdr;
 
 if ((rthdr->rtype == 2) &&
@@ -426,6 +428,7 @@ _eth_get_rss_ex_dst_addr(const struct iovec *pkt, int 
pkt_frags,
 }
 
 return false;
+#pragma GCC diagnostic pop
 }
 
 static bool
-- 
2.18.4




[PATCH v3 0/2] Fixing several GCC 11 warnings

2021-01-13 Thread Miroslav Rezanina
Compiling qemu using GCC 11 we got several new warnings. To allow
build with --enable-werror, we need to solve issues generating these
warnings.
  
Signed-of-by: Miroslav Rezanina 

v2:
 - Patch 2 rewrite to use strpadcpy
 - removed Patch 3 (different version sent by Philippe Mathieu-Daudé)

v3:
 - Fixed patch commit logs (no cod changes)

Miroslav Rezanina (2):
  Fix net.c warning on GCC 11
  s390x: Use strpadcpy for copying vm name

 net/eth.c  |  3 +++
 target/s390x/kvm.c | 12 +---
 target/s390x/misc_helper.c |  7 +--
 3 files changed, 13 insertions(+), 9 deletions(-)

-- 
2.18.4




[PATCH v3 2/2] s390x: Use strpadcpy for copying vm name

2021-01-13 Thread Miroslav Rezanina
Using strncpy with length equal to the size of target array, GCC 11
reports following warning:

  warning: '__builtin_strncpy' specified bound 256 equals destination size 
[-Wstringop-truncation]

We can prevent this warning by using strpadcpy that copies string
up to specified length, zeroes target array after copied string
and does not raise warning when length is equal to target array
size (and ending '\0' is discarded).

Signed-off-by: Miroslav Rezanina 
---
 target/s390x/kvm.c | 12 +---
 target/s390x/misc_helper.c |  7 +--
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index b8385e6b95..dc27fa36c9 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -29,6 +29,7 @@
 #include "internal.h"
 #include "kvm_s390x.h"
 #include "sysemu/kvm_int.h"
+#include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
@@ -1910,18 +1911,15 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, 
uint8_t ar)
 strlen(qemu_name)));
 }
 sysib.vm[0].ext_name_encoding = 2; /* 2 = UTF-8 */
-memset(sysib.ext_names[0], 0, sizeof(sysib.ext_names[0]));
 /* If hypervisor specifies zero Extended Name in STSI322 SYSIB, it's
  * considered by s390 as not capable of providing any Extended Name.
  * Therefore if no name was specified on qemu invocation, we go with the
  * same "KVMguest" default, which KVM has filled into short name field.
  */
-if (qemu_name) {
-strncpy((char *)sysib.ext_names[0], qemu_name,
-sizeof(sysib.ext_names[0]));
-} else {
-strcpy((char *)sysib.ext_names[0], "KVMguest");
-}
+strpadcpy((char *)sysib.ext_names[0],
+  sizeof(sysib.ext_names[0]),
+  qemu_name ?: "KVMguest", '\0');
+
 /* Insert UUID */
 memcpy(sysib.vm[0].uuid, _uuid, sizeof(sysib.vm[0].uuid));
 
diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index 58dbc023eb..7ea90d414a 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -19,6 +19,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 #include "qemu/main-loop.h"
 #include "cpu.h"
 #include "internal.h"
@@ -369,8 +370,10 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0, 
uint64_t r0, uint64_t r1)
 ebcdic_put(sysib.sysib_322.vm[0].name, qemu_name,
MIN(sizeof(sysib.sysib_322.vm[0].name),
strlen(qemu_name)));
-strncpy((char *)sysib.sysib_322.ext_names[0], qemu_name,
-sizeof(sysib.sysib_322.ext_names[0]));
+strpadcpy((char *)sysib.sysib_322.ext_names[0],
+  sizeof(sysib.sysib_322.ext_names[0]),
+  qemu_name, '\0');
+
 } else {
 ebcdic_put(sysib.sysib_322.vm[0].name, "TCGguest", 8);
 strcpy((char *)sysib.sysib_322.ext_names[0], "TCGguest");
-- 
2.18.4




Re: [PATCH V3 0/4] bsd-user: Fix some code style problems

2021-01-13 Thread shiliyang


On 2021/1/14 6:03, Warner Losh wrote:
> While these changes look good, can you submit this against the bsd-user 
> repository? White space changes like this in mainline make rebasing harder 
> than needed.
> 
> https://github.com/qemu-bsd-user/qemu-bsd-user 
>  branch 
> bsd-user-rebase-3.1and we'll make sure they get via our coming pull requests..
> 
> Warner
> 
> On Wed, Jan 13, 2021 at 2:31 AM shiliyang  > wrote:
> 
> This patch series fixes error style problems found by checkpatch.pl 
> .
> 
> V2->V3:
> Make the patch into a series.
> 
> V1->V2:
> Add cover letter message.
> Fix some style error in patch file before.
> 
> Liyang Shi (4):
>   bsd-user: "foo * bar" should be "foo *bar"
>   bsd-user: suspect code indent for conditional statements
>   bsd-user: space required after semicolon
>   bsd-user: do not use C99 // comments
> 
>  bsd-user/bsdload.c |  6 +++---
>  bsd-user/elfload.c | 38 +++---
>  bsd-user/qemu.h    | 14 +++---
>  bsd-user/syscall.c |  6 +++---
>  4 files changed, 32 insertions(+), 32 deletions(-)
> 
> -- 
> 2.29.1.59.gf9b6481aed
> 
> 

OK, I get it, thanks!

Best regards.



Re: [PATCH v2] osdep.h: Remove include

2021-01-13 Thread Thomas Huth

On 13/01/2021 22.56, Michael Forney wrote:

Prior to 2a4b472c3c, sys/signal.h was only included on OpenBSD
(apart from two .c files). The POSIX standard location for this
header is just  and in fact, OpenBSD's signal.h includes
sys/signal.h itself.

Unconditionally including  on musl causes warnings
for just about every source file:

   /usr/include/sys/signal.h:1:2: warning: #warning redirecting incorrect #include 
 to  [-Wcpp]
   1 | #warning redirecting incorrect #include  to 
 |  ^~~

Since there don't seem to be any platforms which require including
 in addition to , and some platforms like
Haiku lack it completely, just remove it.

Tested building on OpenBSD after removing this include.

Signed-off-by: Michael Forney 
Reviewed-by: Eric Blake 
---
Changes since v1: rebase on latest master

  include/qemu/osdep.h | 4 
  meson.build  | 1 -
  2 files changed, 5 deletions(-)

diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index f9ec8c84e9..a434382c58 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -104,10 +104,6 @@ extern int daemon(int, int);
  #include 
  #include 
  
-#ifdef HAVE_SYS_SIGNAL_H

-#include 
-#endif
-
  #ifndef _WIN32
  #include 
  #else
diff --git a/meson.build b/meson.build
index 3d889857a0..af2bc89741 100644
--- a/meson.build
+++ b/meson.build
@@ -1113,7 +1113,6 @@ config_host_data.set('HAVE_DRM_H', 
cc.has_header('libdrm/drm.h'))
  config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h'))
  config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h'))
  config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h'))
-config_host_data.set('HAVE_SYS_SIGNAL_H', cc.has_header('sys/signal.h'))
  
  ignored = ['CONFIG_QEMU_INTERP_PREFIX'] # actually per-target

  arrays = ['CONFIG_AUDIO_DRIVERS', 'CONFIG_BDRV_RW_WHITELIST', 
'CONFIG_BDRV_RO_WHITELIST']



Reviewed-by: Thomas Huth 




Re: [PATCH v1 4/4] vhost-vdpa:add callback function for configure interrupt

2021-01-13 Thread Cindy Lu
On Thu, Jan 14, 2021 at 12:17 AM Michael S. Tsirkin  wrote:
>
> On Wed, Jan 13, 2021 at 11:45:40PM +0800, Cindy Lu wrote:
> > Add call back function for configure interrupt.
> > Set the notifier's fd to the kernel driver when vdpa start.
> > also set -1 when vdpa stop. then the kernel will release
> > the related聽resource聽
>
> Something weird happened to the commit log here.
>
Thanks Micheal, I will fix this part
> >
> > Signed-off-by: Cindy Lu 
> > ---
> >  hw/virtio/trace-events|  2 ++
> >  hw/virtio/vhost-vdpa.c| 29 -
> >  include/hw/virtio/vhost-backend.h |  4 
> >  3 files changed, 34 insertions(+), 1 deletion(-)
> >
> > diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> > index 2060a144a2..6710835b46 100644
> > --- a/hw/virtio/trace-events
> > +++ b/hw/virtio/trace-events
> > @@ -52,6 +52,8 @@ vhost_vdpa_set_vring_call(void *dev, unsigned int index, 
> > int fd) "dev: %p index:
> >  vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 
> > 0x%"PRIx64
> >  vhost_vdpa_set_owner(void *dev) "dev: %p"
> >  vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, 
> > uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p 
> > desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 
> > 0x%"PRIx64
> > +vhost_vdpa_set_config_call(void *dev, int *fd)"dev: %p fd: %p"
> > +
> >
> >  # virtio.c
> >  virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned 
> > out_num) "elem %p size %zd in_num %u out_num %u"
> > diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> > index 01d2101d09..1647bff8b0 100644
> > --- a/hw/virtio/vhost-vdpa.c
> > +++ b/hw/virtio/vhost-vdpa.c
> > @@ -467,20 +467,39 @@ static int vhost_vdpa_get_config(struct vhost_dev 
> > *dev, uint8_t *config,
> >  }
> >  return ret;
> >   }
> > +static void vhost_vdpa_config_notify_start(struct vhost_dev *dev,
> > +struct VirtIODevice *vdev, bool start)
> > +{
> > +int fd, r;
> > +if (start) {
> > +fd = event_notifier_get_fd(>config_notifier);
> > + } else {
> > +fd = -1;
> > + }
> > +r = dev->vhost_ops->vhost_set_config_call(dev, );
> > +if (r) {
> > +error_report("vhost_vdpa_config_notify_start error!");
> > +}
> > +return;
> >
> > +}
> >  static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
> >  {
> >  struct vhost_vdpa *v = dev->opaque;
> >  trace_vhost_vdpa_dev_start(dev, started);
> > +VirtIODevice *vdev = dev->vdev;
> > +
> >  if (started) {
> >  uint8_t status = 0;
> >  memory_listener_register(>listener, _space_memory);
> >  vhost_vdpa_set_vring_ready(dev);
> >  vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
> >  vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, );
> > -
> > +/*set the configure interrupt call back*/
> > +vhost_vdpa_config_notify_start(dev, vdev, true);
> >  return !(status & VIRTIO_CONFIG_S_DRIVER_OK);
> >  } else {
> > +vhost_vdpa_config_notify_start(dev, vdev, false);
> >  vhost_vdpa_reset_device(dev);
> >  vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
> > VIRTIO_CONFIG_S_DRIVER);
> > @@ -546,6 +565,13 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev 
> > *dev,
> >  return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file);
> >  }
> >
> > +static int vhost_vdpa_set_config_call(struct vhost_dev *dev,
> > +   int *fd)
> > +{
> > +trace_vhost_vdpa_set_config_call(dev, fd);
> > +return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, fd);
> > +}
> > +
> >  static int vhost_vdpa_get_features(struct vhost_dev *dev,
> >   uint64_t *features)
> >  {
> > @@ -611,4 +637,5 @@ const VhostOps vdpa_ops = {
> >  .vhost_get_device_id = vhost_vdpa_get_device_id,
> >  .vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
> >  .vhost_force_iommu = vhost_vdpa_force_iommu,
> > +.vhost_set_config_call = vhost_vdpa_set_config_call,
> >  };
> > diff --git a/include/hw/virtio/vhost-backend.h 
> > b/include/hw/virtio/vhost-backend.h
> > index 8a6f8e2a7a..1a2fee8994 100644
> > --- a/include/hw/virtio/vhost-backend.h
> > +++ b/include/hw/virtio/vhost-backend.h
> > @@ -125,6 +125,9 @@ typedef int (*vhost_get_device_id_op)(struct vhost_dev 
> > *dev, uint32_t *dev_id);
> >
> >  typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);
> >
> > +typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,
> > +   int *fd);
> > +
> >  typedef struct VhostOps {
> >  VhostBackendType backend_type;
> >  vhost_backend_init vhost_backend_init;
> > @@ -170,6 +173,7 @@ typedef struct VhostOps {
> >  vhost_vq_get_addr_op  vhost_vq_get_addr;
> >  vhost_get_device_id_op 

Re: [PATCH v6 08/11] iotests: add testenv.py

2021-01-13 Thread Vladimir Sementsov-Ogievskiy

14.01.2021 09:14, Vladimir Sementsov-Ogievskiy wrote:

12.01.2021 20:36, Kevin Wolf wrote:

Am 09.01.2021 um 13:26 hat Vladimir Sementsov-Ogievskiy geschrieben:

Add TestEnv class, which will handle test environment in a new python
iotests running framework.

Difference with current ./check interface:
- -v (verbose) option dropped, as it is unused

- -xdiff option is dropped, until somebody complains that it is needed
- same for -n option

Signed-off-by: Vladimir Sementsov-Ogievskiy 


+* Module testenv
+testenv.py:48:0: R0902: Too many instance attributes (34/7) 
(too-many-instance-attributes)
+testenv.py:212:16: R1722: Consider using sys.exit() (consider-using-sys-exit)
+testenv.py:214:16: R1722: Consider using sys.exit() (consider-using-sys-exit)
+testenv.py:324:8: R1722: Consider using sys.exit() (consider-using-sys-exit)
+testenv.py:1:0: R0801: Similar lines in 2 files
+==findtests:45
+==testenv:72
+    _argparser = None
+    @classmethod
+    def get_argparser(cls) -> argparse.ArgumentParser:
+    if cls._argparser is not None:
+    return cls._argparser
+ (duplicate-code)
+testenv.py:294: error: Function is missing a type annotation for one or more 
arguments


Interesting, I don't see "similar lines" error in the output..



Ah, that's because I added a newline in findtests.py. Add it in testenv.py and 
the error comes back.





I wonder whether we should just disable the "similar lines" check? The
instance attributes one looks kind of arbitrary, too. The rest looks
valid enough.

Kevin







--
Best regards,
Vladimir



Re: [PATCH v1 0/4] vhost-vdpa: add support for configure interrupt

2021-01-13 Thread Cindy Lu
On Thu, Jan 14, 2021 at 12:36 PM Jason Wang  wrote:
>
>
> On 2021/1/13 下午11:45, Cindy Lu wrote:
> > Add configure interrupt support in vdpa_vhost. qemu will use the irqfd
> > process to support this feature.
> >
> > These code are all tested in vp-vdpa (support configure interrupt)
> > vdpa_sim (not support configure interrupt)
> >
> >
> > Cindy Lu (4):
> >virtio:add support in configure interrupt
> >virtio-pci:add support for configure interrupt
>
>
> If possible, I would like to add the MMIO support for this.
>
> One great advantage of vDPA is that it can avoid to expose a PCI device
> for guest.
>
> Thanks
>
Sure, Thanks Jason, I will check this part.
>
> >vhost_net:enable configure interrupt when vhost_net start
> >vhost-vdpa:add callback function for configure interrupt
> >
> >   hw/net/vhost_net.c| 19 ++-
> >   hw/virtio/trace-events|  2 +
> >   hw/virtio/vhost-vdpa.c| 29 +-
> >   hw/virtio/virtio-pci.c| 93 +++
> >   hw/virtio/virtio.c| 25 +
> >   include/hw/virtio/vhost-backend.h |  4 ++
> >   include/hw/virtio/virtio-bus.h|  2 +
> >   include/hw/virtio/virtio.h|  5 ++
> >   8 files changed, 177 insertions(+), 2 deletions(-)
> >
>




Re: [PATCH v6 08/11] iotests: add testenv.py

2021-01-13 Thread Vladimir Sementsov-Ogievskiy

12.01.2021 20:36, Kevin Wolf wrote:

Am 09.01.2021 um 13:26 hat Vladimir Sementsov-Ogievskiy geschrieben:

Add TestEnv class, which will handle test environment in a new python
iotests running framework.

Difference with current ./check interface:
- -v (verbose) option dropped, as it is unused

- -xdiff option is dropped, until somebody complains that it is needed
- same for -n option

Signed-off-by: Vladimir Sementsov-Ogievskiy 


+* Module testenv
+testenv.py:48:0: R0902: Too many instance attributes (34/7) 
(too-many-instance-attributes)
+testenv.py:212:16: R1722: Consider using sys.exit() (consider-using-sys-exit)
+testenv.py:214:16: R1722: Consider using sys.exit() (consider-using-sys-exit)
+testenv.py:324:8: R1722: Consider using sys.exit() (consider-using-sys-exit)
+testenv.py:1:0: R0801: Similar lines in 2 files
+==findtests:45
+==testenv:72
+_argparser = None
+@classmethod
+def get_argparser(cls) -> argparse.ArgumentParser:
+if cls._argparser is not None:
+return cls._argparser
+ (duplicate-code)
+testenv.py:294: error: Function is missing a type annotation for one or more 
arguments


Interesting, I don't see "similar lines" error in the output..

[root@kvm qemu-iotests]# pylint-3 --score=n findtests.py testenv.py
* Module testenv
testenv.py:48:0: R0902: Too many instance attributes (34/7) 
(too-many-instance-attributes)
testenv.py:212:16: R1722: Consider using sys.exit() (consider-using-sys-exit)
testenv.py:214:16: R1722: Consider using sys.exit() (consider-using-sys-exit)
testenv.py:324:8: R1722: Consider using sys.exit() (consider-using-sys-exit)
[root@kvm qemu-iotests]# pylint --score=n findtests.py testenv.py
* Module testenv
testenv.py:48:0: R0902: Too many instance attributes (34/7) 
(too-many-instance-attributes)
testenv.py:212:16: R1722: Consider using sys.exit() (consider-using-sys-exit)
testenv.py:214:16: R1722: Consider using sys.exit() (consider-using-sys-exit)
testenv.py:324:8: R1722: Consider using sys.exit() (consider-using-sys-exit)
[root@kvm qemu-iotests]# pylint-3 --version
pylint 2.6.0
astroid 2.4.2
Python 3.9.1 (default, Dec  8 2020, 00:00:00)
[GCC 10.2.1 20201125 (Red Hat 10.2.1-9)]
[root@kvm qemu-iotests]# pylint --version
pylint 2.6.0
astroid 2.4.2
Python 3.9.1 (default, Dec  8 2020, 00:00:00)
[GCC 10.2.1 20201125 (Red Hat 10.2.1-9)]
[root@kvm qemu-iotests]# which pylint-3
/usr/bin/pylint-3
[root@kvm qemu-iotests]# rpm -qf /usr/bin/pylint-3
python3-pylint-2.6.0-2.fc33.noarch



I wonder whether we should just disable the "similar lines" check? The
instance attributes one looks kind of arbitrary, too. The rest looks
valid enough.

Kevin




--
Best regards,
Vladimir



Re: [PATCH v1 4/4] vhost-vdpa:add callback function for configure interrupt

2021-01-13 Thread Cindy Lu
On Thu, Jan 14, 2021 at 12:46 PM Jason Wang  wrote:
>
>
> On 2021/1/13 下午11:45, Cindy Lu wrote:
> > Add call back function for configure interrupt.
> > Set the notifier's fd to the kernel driver when vdpa start.
> > also set -1 when vdpa stop. then the kernel will release
> > the related聽resource聽
> >
> > Signed-off-by: Cindy Lu 
> > ---
> >   hw/virtio/trace-events|  2 ++
> >   hw/virtio/vhost-vdpa.c| 29 -
> >   include/hw/virtio/vhost-backend.h |  4 
> >   3 files changed, 34 insertions(+), 1 deletion(-)
> >
> > diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
> > index 2060a144a2..6710835b46 100644
> > --- a/hw/virtio/trace-events
> > +++ b/hw/virtio/trace-events
> > @@ -52,6 +52,8 @@ vhost_vdpa_set_vring_call(void *dev, unsigned int index, 
> > int fd) "dev: %p index:
> >   vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 
> > 0x%"PRIx64
> >   vhost_vdpa_set_owner(void *dev) "dev: %p"
> >   vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, 
> > uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p 
> > desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 
> > 0x%"PRIx64
> > +vhost_vdpa_set_config_call(void *dev, int *fd)"dev: %p fd: %p"
> > +
> >
> >   # virtio.c
> >   virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned 
> > out_num) "elem %p size %zd in_num %u out_num %u"
> > diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> > index 01d2101d09..1647bff8b0 100644
> > --- a/hw/virtio/vhost-vdpa.c
> > +++ b/hw/virtio/vhost-vdpa.c
> > @@ -467,20 +467,39 @@ static int vhost_vdpa_get_config(struct vhost_dev 
> > *dev, uint8_t *config,
> >   }
> >   return ret;
> >}
> > +static void vhost_vdpa_config_notify_start(struct vhost_dev *dev,
> > +struct VirtIODevice *vdev, bool start)
> > +{
> > +int fd, r;
> > +if (start) {
> > +fd = event_notifier_get_fd(>config_notifier);
> > + } else {
> > +fd = -1;
> > + }
> > +r = dev->vhost_ops->vhost_set_config_call(dev, );
> > +if (r) {
> > +error_report("vhost_vdpa_config_notify_start error!");
> > +}
>
>
> So on early version of kernel without config interrupt support. This
> will fail for sure. We need seek a way to make it work.
>
> Thanks
>
Thanks Jason I will test the old version and fix this one
>
> > +return;
> >
> > +}
> >   static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
> >   {
> >   struct vhost_vdpa *v = dev->opaque;
> >   trace_vhost_vdpa_dev_start(dev, started);
> > +VirtIODevice *vdev = dev->vdev;
> > +
> >   if (started) {
> >   uint8_t status = 0;
> >   memory_listener_register(>listener, _space_memory);
> >   vhost_vdpa_set_vring_ready(dev);
> >   vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
> >   vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, );
> > -
> > +/*set the configure interrupt call back*/
> > +vhost_vdpa_config_notify_start(dev, vdev, true);
> >   return !(status & VIRTIO_CONFIG_S_DRIVER_OK);
> >   } else {
> > +vhost_vdpa_config_notify_start(dev, vdev, false);
> >   vhost_vdpa_reset_device(dev);
> >   vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
> >  VIRTIO_CONFIG_S_DRIVER);
> > @@ -546,6 +565,13 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev 
> > *dev,
> >   return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file);
> >   }
> >
> > +static int vhost_vdpa_set_config_call(struct vhost_dev *dev,
> > +   int *fd)
> > +{
> > +trace_vhost_vdpa_set_config_call(dev, fd);
> > +return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, fd);
> > +}
> > +
> >   static int vhost_vdpa_get_features(struct vhost_dev *dev,
> >uint64_t *features)
> >   {
> > @@ -611,4 +637,5 @@ const VhostOps vdpa_ops = {
> >   .vhost_get_device_id = vhost_vdpa_get_device_id,
> >   .vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
> >   .vhost_force_iommu = vhost_vdpa_force_iommu,
> > +.vhost_set_config_call = vhost_vdpa_set_config_call,
> >   };
> > diff --git a/include/hw/virtio/vhost-backend.h 
> > b/include/hw/virtio/vhost-backend.h
> > index 8a6f8e2a7a..1a2fee8994 100644
> > --- a/include/hw/virtio/vhost-backend.h
> > +++ b/include/hw/virtio/vhost-backend.h
> > @@ -125,6 +125,9 @@ typedef int (*vhost_get_device_id_op)(struct vhost_dev 
> > *dev, uint32_t *dev_id);
> >
> >   typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);
> >
> > +typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,
> > +   int *fd);
> > +
> >   typedef struct VhostOps {
> >   VhostBackendType backend_type;
> >   vhost_backend_init vhost_backend_init;
> > @@ -170,6 

Re: [PATCH v1 2/4] virtio-pci:add support for configure interrupt

2021-01-13 Thread Cindy Lu
On Thu, Jan 14, 2021 at 12:43 PM Jason Wang  wrote:
>
>
> On 2021/1/13 下午11:45, Cindy Lu wrote:
> > Add support for configure interrupt, use kvm_irqfd_assign and set the
> > gsi to kernel. When the configure notifier was eventfd_signal by host
> > kernel, this will finally inject an msix interrupt to guest
> >
> > Signed-off-by: Cindy Lu 
> > ---
> >   hw/virtio/virtio-pci.c | 93 ++
> >   include/hw/virtio/virtio-bus.h |  2 +
> >   2 files changed, 95 insertions(+)
> >
> > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > index 36524a5728..f8053e1fab 100644
> > --- a/hw/virtio/virtio-pci.c
> > +++ b/hw/virtio/virtio-pci.c
> > @@ -762,6 +762,98 @@ undo:
> >   return ret;
> >   }
> >
> > + static int kvm_virtio_pci_config_irqfd_use(VirtIOPCIProxy *proxy,
> > + unsigned int vector)
> > +{
> > +VirtIOIRQFD *irqfd = >vector_irqfd[vector];
> > +VirtIODevice *vdev = virtio_bus_get_device(>bus);
> > +EventNotifier *n = virtio_queue_get_config_notifier(vdev);
> > +assert(irqfd);
> > +return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, 
> > irqfd->virq);
> > +}
> > +
> > +static void kvm_virtio_pci_config_irqfd_release(VirtIOPCIProxy *proxy,
> > +  unsigned int vector)
> > +{
> > +VirtIODevice *vdev = virtio_bus_get_device(>bus);
> > +EventNotifier *n = virtio_queue_get_config_notifier(vdev);
> > +VirtIOIRQFD *irqfd = >vector_irqfd[vector];
> > +assert(irqfd);
> > +kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq);
> > +return;
> > +}
> > +static int kvm_virtio_pci_config_vector_use(VirtIOPCIProxy *proxy,
> > +unsigned int vector)
> > +{
> > +VirtIOIRQFD *irqfd = >vector_irqfd[vector];
> > +int ret;
> > +
> > +if (irqfd->users == 0) {
> > +ret = kvm_irqchip_add_msi_route(kvm_state, vector, 
> > >pci_dev);
> > +if (ret < 0) {
> > +return ret;
> > +}
> > +irqfd->virq = ret;
> > +}
> > +irqfd->users++;
> > +
> > +return 0;
> > +}
>
>
> Any reason that we can't resue kvm_virtio_pci_vq_vector_use()? Note that
> at MSIX level there's no difference if it belongs to vq or config.
>
>
> > +static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy)
> > +{
> > +
> > +VirtIODevice *vdev = virtio_bus_get_device(>bus);
> > +unsigned int vector;
> > +int ret;
> > +VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
> > +
> > +vector = vdev->config_vector ;
> > +ret = kvm_virtio_pci_config_vector_use(proxy, vector);
> > +if (ret < 0) {
> > +goto undo;
> > +}
> > +ret = kvm_virtio_pci_config_irqfd_use(proxy,  vector);
> > +if (ret < 0) {
> > +goto undo;
> > +}
> > +return 0;
> > +undo:
> > +kvm_virtio_pci_config_irqfd_release(proxy, vector);
> > +return ret;
> > +}
> > +static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy)
> > +{
> > +PCIDevice *dev = >pci_dev;
> > +VirtIODevice *vdev = virtio_bus_get_device(>bus);
> > +unsigned int vector;
> > +VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
> > +vector = vdev->config_vector ;
> > +if (vector >= msix_nr_vectors_allocated(dev)) {
> > +return;
> > +}
> > +kvm_virtio_pci_config_irqfd_release(proxy, vector);
> > +kvm_virtio_pci_vq_vector_release(proxy, vector);
> > +}
> > +
> > +static int virtio_pci_set_guest_config_notifier(DeviceState *d,  bool 
> > assign,
> > + bool with_irqfd)
> > +{
> > +VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> > +VirtIODevice *vdev = virtio_bus_get_device(>bus);
> > +EventNotifier *notifier = virtio_queue_get_config_notifier(vdev);
> > +int r = 0;
> > +if (assign) {
> > +r = event_notifier_init(notifier, 1);
> > +virtio_set_config_notifier_fd_handler(vdev, true, with_irqfd);
> > +kvm_virtio_pci_vector_config_use(proxy);
> > +} else {
> > +virtio_set_config_notifier_fd_handler(vdev, false, with_irqfd);
> > +kvm_virtio_pci_vector_config_release(proxy);
> > +event_notifier_cleanup(notifier);
> > +}
> > +return r;
> > +}
>
>
> Any way to re-use virtio_pci_set_guest_notifier() here?
>
> Thanks
>
These  two functions you mentioned all have something needed such as
queue no/guest_notifier. so I created a new one.
but it's a good idea to re-organize it,  I will post a new version
>
> > +
> >   static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
> >   {
> >   PCIDevice *dev = >pci_dev;
> > @@ -2137,6 +2229,7 @@ static void virtio_pci_bus_class_init(ObjectClass 
> > *klass, void *data)
> >   k->ioeventfd_assign = virtio_pci_ioeventfd_assign;
> >   k->get_dma_as = virtio_pci_get_dma_as;
> >   k->queue_enabled = virtio_pci_queue_enabled;
> > +

Re: [PATCH v1 1/4] virtio:add support in configure interrupt

2021-01-13 Thread Cindy Lu
On Thu, Jan 14, 2021 at 12:34 PM Jason Wang  wrote:
>
>
> On 2021/1/13 下午11:45, Cindy Lu wrote:
> > Add configure notifier and virtio_set_config_notifier_fd_handler
> > in virtio
> >
> > Signed-off-by: Cindy Lu 
> > ---
> >   hw/virtio/virtio.c | 25 +
> >   include/hw/virtio/virtio.h |  5 +
> >   2 files changed, 30 insertions(+)
> >
> > diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> > index ceb58fda6c..66ed1daf95 100644
> > --- a/hw/virtio/virtio.c
> > +++ b/hw/virtio/virtio.c
> > @@ -3502,6 +3502,15 @@ static void 
> > virtio_queue_guest_notifier_read(EventNotifier *n)
> >   }
> >   }
> >
> > +static void virtio_queue_config_read(EventNotifier *n)
> > +{
>
>
> Note that the config interrupt belongs to the device. So it's better not
> name it as "queue" here.
>
sure I will fix this
>
> > +VirtIODevice *vdev = container_of(n, VirtIODevice, config_notifier);
> > +
> > +if (event_notifier_test_and_clear(n)) {
> > +
> > +virtio_notify_config(vdev);
> > +}
> > +}
> >   void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool 
> > assign,
> >   bool with_irqfd)
> >   {
> > @@ -3518,6 +3527,17 @@ void 
> > virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
> >   }
> >   }
> >
> > +void virtio_set_config_notifier_fd_handler(VirtIODevice *vdev, bool assign,
> > +bool with_irqfd)
> > +{
> > +if (assign && !with_irqfd) {
> > +event_notifier_set_handler(>config_notifier,
> > +   virtio_queue_config_read);
> > +} else {
> > +   event_notifier_set_handler(>config_notifier, NULL);
> > +}
> > +}
>
>
> I wonder whether we can simply generalize
> virtio_queue_set_guest_notifier_fd_handler from
>
> void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
>  bool with_irqfd)
>
> to
>
> void virtio_set_guest_notifier_fd_handler(EventNotifier *e, bool assign,
>  bool with_irqfd)
>
>
> Since there's actually no virtqueue specific setup in this function,
> what its callee really want is a simple EventNotifier.
>
> Thanks
>
Thanks Jason, I will fix ths
>
> > +
> >   EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
> >   {
> >   return >guest_notifier;
> > @@ -3591,6 +3611,11 @@ EventNotifier 
> > *virtio_queue_get_host_notifier(VirtQueue *vq)
> >   return >host_notifier;
> >   }
> >
> > +EventNotifier *virtio_queue_get_config_notifier(VirtIODevice *vdev)
> > +{
> > +return >config_notifier;
> > +
> > +}
> >   void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled)
> >   {
> >   vq->host_notifier_enabled = enabled;
> > diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> > index b7ece7a6a8..38bd28242e 100644
> > --- a/include/hw/virtio/virtio.h
> > +++ b/include/hw/virtio/virtio.h
> > @@ -108,6 +108,7 @@ struct VirtIODevice
> >   bool use_guest_notifier_mask;
> >   AddressSpace *dma_as;
> >   QLIST_HEAD(, VirtQueue) *vector_queues;
> > +EventNotifier config_notifier;
> >   };
> >
> >   struct VirtioDeviceClass {
> > @@ -310,11 +311,15 @@ uint16_t virtio_get_queue_index(VirtQueue *vq);
> >   EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
> >   void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool 
> > assign,
> >   bool with_irqfd);
> > +void virtio_set_config_notifier_fd_handler(VirtIODevice *vdev, bool assign,
> > +bool with_irqfd);
> > +
> >   int virtio_device_start_ioeventfd(VirtIODevice *vdev);
> >   int virtio_device_grab_ioeventfd(VirtIODevice *vdev);
> >   void virtio_device_release_ioeventfd(VirtIODevice *vdev);
> >   bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev);
> >   EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
> > +EventNotifier *virtio_queue_get_config_notifier(VirtIODevice *vdev);
> >   void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled);
> >   void virtio_queue_host_notifier_read(EventNotifier *n);
> >   void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext 
> > *ctx,
>




Re: [PATCH v4 2/5] qapi: A couple more QAPI_LIST_PREPEND() stragglers

2021-01-13 Thread Vladimir Sementsov-Ogievskiy

14.01.2021 01:10, Eric Blake wrote:

Commit 54aa3de72e switched multiple sites to use QAPI_LIST_PREPEND
instead of open-coding, but missed a couple of spots.

Signed-off-by: Eric Blake


Reviewed-by: Vladimir Sementsov-Ogievskiy 

--
Best regards,
Vladimir



Re: [PATCH v4 1/5] net: Clarify early exit condition

2021-01-13 Thread Vladimir Sementsov-Ogievskiy

14.01.2021 01:10, Eric Blake wrote:

On first glance, the loop in qmp_query_rx_filter() has early return
paths that could leak any allocation of filter_list from a previous
iteration.  But on closer inspection, it is obvious that all of the
early exits are guarded by has_name, and that the bulk of the loop
body can be executed at most once if the user is filtering by name,
thus, any early exit coincides with an empty list.  Add asserts to
make this obvious.


A bit simpler (for me :) observation:

But on closer inspection, it is obvious that all of the early exits are guarded 
by has_name, and in case when has_name is true we leave the loop (by break) 
immediately after allocation and assigning filter_list for the first time.



Signed-off-by: Eric Blake 
Reviewed-by: Markus Armbruster 


Reviewed-by: Vladimir Sementsov-Ogievskiy 


---
  net/net.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/net/net.c b/net/net.c
index e1035f21d183..e581c8a26868 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1211,6 +1211,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, 
const char *name,
  if (nc->info->type != NET_CLIENT_DRIVER_NIC) {
  if (has_name) {
  error_setg(errp, "net client(%s) isn't a NIC", name);
+assert(!filter_list);
  return NULL;
  }
  continue;
@@ -1236,6 +1237,7 @@ RxFilterInfoList *qmp_query_rx_filter(bool has_name, 
const char *name,
  } else if (has_name) {
  error_setg(errp, "net client(%s) doesn't support"
 " rx-filter querying", name);
+assert(!filter_list);
  return NULL;
  }




--
Best regards,
Vladimir



Re: [PATCH v1 4/4] vhost-vdpa:add callback function for configure interrupt

2021-01-13 Thread Jason Wang



On 2021/1/13 涓嬪崍11:45, Cindy Lu wrote:

Add call back function for configure interrupt.
Set the notifier's fd to the kernel driver when vdpa start.
also set -1 when vdpa stop. then the kernel will release
the related鑱絩esource鑱�

Signed-off-by: Cindy Lu 
---
  hw/virtio/trace-events|  2 ++
  hw/virtio/vhost-vdpa.c| 29 -
  include/hw/virtio/vhost-backend.h |  4 
  3 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 2060a144a2..6710835b46 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -52,6 +52,8 @@ vhost_vdpa_set_vring_call(void *dev, unsigned int index, int fd) 
"dev: %p index:
  vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 
0x%"PRIx64
  vhost_vdpa_set_owner(void *dev) "dev: %p"
  vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t 
used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 
0x%"PRIx64" used_user_addr: 0x%"PRIx64
+vhost_vdpa_set_config_call(void *dev, int *fd)"dev: %p fd: %p"
+
  
  # virtio.c

  virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) 
"elem %p size %zd in_num %u out_num %u"
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 01d2101d09..1647bff8b0 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -467,20 +467,39 @@ static int vhost_vdpa_get_config(struct vhost_dev *dev, 
uint8_t *config,
  }
  return ret;
   }
+static void vhost_vdpa_config_notify_start(struct vhost_dev *dev,
+struct VirtIODevice *vdev, bool start)
+{
+int fd, r;
+if (start) {
+fd = event_notifier_get_fd(>config_notifier);
+ } else {
+fd = -1;
+ }
+r = dev->vhost_ops->vhost_set_config_call(dev, );
+if (r) {
+error_report("vhost_vdpa_config_notify_start error!");
+}



So on early version of kernel without config interrupt support. This 
will fail for sure. We need seek a way to make it work.


Thanks



+return;
  
+}

  static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
  {
  struct vhost_vdpa *v = dev->opaque;
  trace_vhost_vdpa_dev_start(dev, started);
+VirtIODevice *vdev = dev->vdev;
+
  if (started) {
  uint8_t status = 0;
  memory_listener_register(>listener, _space_memory);
  vhost_vdpa_set_vring_ready(dev);
  vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
  vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, );
-
+/*set the configure interrupt call back*/
+vhost_vdpa_config_notify_start(dev, vdev, true);
  return !(status & VIRTIO_CONFIG_S_DRIVER_OK);
  } else {
+vhost_vdpa_config_notify_start(dev, vdev, false);
  vhost_vdpa_reset_device(dev);
  vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
 VIRTIO_CONFIG_S_DRIVER);
@@ -546,6 +565,13 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev *dev,
  return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file);
  }
  
+static int vhost_vdpa_set_config_call(struct vhost_dev *dev,

+   int *fd)
+{
+trace_vhost_vdpa_set_config_call(dev, fd);
+return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, fd);
+}
+
  static int vhost_vdpa_get_features(struct vhost_dev *dev,
   uint64_t *features)
  {
@@ -611,4 +637,5 @@ const VhostOps vdpa_ops = {
  .vhost_get_device_id = vhost_vdpa_get_device_id,
  .vhost_vq_get_addr = vhost_vdpa_vq_get_addr,
  .vhost_force_iommu = vhost_vdpa_force_iommu,
+.vhost_set_config_call = vhost_vdpa_set_config_call,
  };
diff --git a/include/hw/virtio/vhost-backend.h 
b/include/hw/virtio/vhost-backend.h
index 8a6f8e2a7a..1a2fee8994 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -125,6 +125,9 @@ typedef int (*vhost_get_device_id_op)(struct vhost_dev 
*dev, uint32_t *dev_id);
  
  typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev);
  
+typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev,

+   int *fd);
+
  typedef struct VhostOps {
  VhostBackendType backend_type;
  vhost_backend_init vhost_backend_init;
@@ -170,6 +173,7 @@ typedef struct VhostOps {
  vhost_vq_get_addr_op  vhost_vq_get_addr;
  vhost_get_device_id_op vhost_get_device_id;
  vhost_force_iommu_op vhost_force_iommu;
+vhost_set_config_call_op vhost_set_config_call;
  } VhostOps;
  
  extern const VhostOps user_ops;





Re: [PATCH v1 2/4] virtio-pci:add support for configure interrupt

2021-01-13 Thread Jason Wang



On 2021/1/13 下午11:45, Cindy Lu wrote:

Add support for configure interrupt, use kvm_irqfd_assign and set the
gsi to kernel. When the configure notifier was eventfd_signal by host
kernel, this will finally inject an msix interrupt to guest

Signed-off-by: Cindy Lu 
---
  hw/virtio/virtio-pci.c | 93 ++
  include/hw/virtio/virtio-bus.h |  2 +
  2 files changed, 95 insertions(+)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 36524a5728..f8053e1fab 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -762,6 +762,98 @@ undo:
  return ret;
  }
  
+ static int kvm_virtio_pci_config_irqfd_use(VirtIOPCIProxy *proxy,

+ unsigned int vector)
+{
+VirtIOIRQFD *irqfd = >vector_irqfd[vector];
+VirtIODevice *vdev = virtio_bus_get_device(>bus);
+EventNotifier *n = virtio_queue_get_config_notifier(vdev);
+assert(irqfd);
+return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq);
+}
+
+static void kvm_virtio_pci_config_irqfd_release(VirtIOPCIProxy *proxy,
+  unsigned int vector)
+{
+VirtIODevice *vdev = virtio_bus_get_device(>bus);
+EventNotifier *n = virtio_queue_get_config_notifier(vdev);
+VirtIOIRQFD *irqfd = >vector_irqfd[vector];
+assert(irqfd);
+kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq);
+return;
+}
+static int kvm_virtio_pci_config_vector_use(VirtIOPCIProxy *proxy,
+unsigned int vector)
+{
+VirtIOIRQFD *irqfd = >vector_irqfd[vector];
+int ret;
+
+if (irqfd->users == 0) {
+ret = kvm_irqchip_add_msi_route(kvm_state, vector, >pci_dev);
+if (ret < 0) {
+return ret;
+}
+irqfd->virq = ret;
+}
+irqfd->users++;
+
+return 0;
+}



Any reason that we can't resue kvm_virtio_pci_vq_vector_use()? Note that 
at MSIX level there's no difference if it belongs to vq or config.




+static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy)
+{
+
+VirtIODevice *vdev = virtio_bus_get_device(>bus);
+unsigned int vector;
+int ret;
+VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+
+vector = vdev->config_vector ;
+ret = kvm_virtio_pci_config_vector_use(proxy, vector);
+if (ret < 0) {
+goto undo;
+}
+ret = kvm_virtio_pci_config_irqfd_use(proxy,  vector);
+if (ret < 0) {
+goto undo;
+}
+return 0;
+undo:
+kvm_virtio_pci_config_irqfd_release(proxy, vector);
+return ret;
+}
+static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy)
+{
+PCIDevice *dev = >pci_dev;
+VirtIODevice *vdev = virtio_bus_get_device(>bus);
+unsigned int vector;
+VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
+vector = vdev->config_vector ;
+if (vector >= msix_nr_vectors_allocated(dev)) {
+return;
+}
+kvm_virtio_pci_config_irqfd_release(proxy, vector);
+kvm_virtio_pci_vq_vector_release(proxy, vector);
+}
+
+static int virtio_pci_set_guest_config_notifier(DeviceState *d,  bool assign,
+ bool with_irqfd)
+{
+VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
+VirtIODevice *vdev = virtio_bus_get_device(>bus);
+EventNotifier *notifier = virtio_queue_get_config_notifier(vdev);
+int r = 0;
+if (assign) {
+r = event_notifier_init(notifier, 1);
+virtio_set_config_notifier_fd_handler(vdev, true, with_irqfd);
+kvm_virtio_pci_vector_config_use(proxy);
+} else {
+virtio_set_config_notifier_fd_handler(vdev, false, with_irqfd);
+kvm_virtio_pci_vector_config_release(proxy);
+event_notifier_cleanup(notifier);
+}
+return r;
+}



Any way to re-use virtio_pci_set_guest_notifier() here?

Thanks



+
  static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs)
  {
  PCIDevice *dev = >pci_dev;
@@ -2137,6 +2229,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, 
void *data)
  k->ioeventfd_assign = virtio_pci_ioeventfd_assign;
  k->get_dma_as = virtio_pci_get_dma_as;
  k->queue_enabled = virtio_pci_queue_enabled;
+k->set_config_notifiers = virtio_pci_set_guest_config_notifier;
  }
  
  static const TypeInfo virtio_pci_bus_info = {

diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
index ef8abe49c5..dae81ee414 100644
--- a/include/hw/virtio/virtio-bus.h
+++ b/include/hw/virtio/virtio-bus.h
@@ -93,6 +93,8 @@ struct VirtioBusClass {
   */
  bool has_variable_vring_alignment;
  AddressSpace *(*get_dma_as)(DeviceState *d);
+int (*set_config_notifiers)(DeviceState *d, bool assign, bool with_irqfd);
+
  };
  
  struct VirtioBusState {





Re: [PATCH v1 0/4] vhost-vdpa: add support for configure interrupt

2021-01-13 Thread Jason Wang



On 2021/1/13 下午11:45, Cindy Lu wrote:

Add configure interrupt support in vdpa_vhost. qemu will use the irqfd
process to support this feature.

These code are all tested in vp-vdpa (support configure interrupt)
vdpa_sim (not support configure interrupt)


Cindy Lu (4):
   virtio:add support in configure interrupt
   virtio-pci:add support for configure interrupt



If possible, I would like to add the MMIO support for this.

One great advantage of vDPA is that it can avoid to expose a PCI device 
for guest.


Thanks



   vhost_net:enable configure interrupt when vhost_net start
   vhost-vdpa:add callback function for configure interrupt

  hw/net/vhost_net.c| 19 ++-
  hw/virtio/trace-events|  2 +
  hw/virtio/vhost-vdpa.c| 29 +-
  hw/virtio/virtio-pci.c| 93 +++
  hw/virtio/virtio.c| 25 +
  include/hw/virtio/vhost-backend.h |  4 ++
  include/hw/virtio/virtio-bus.h|  2 +
  include/hw/virtio/virtio.h|  5 ++
  8 files changed, 177 insertions(+), 2 deletions(-)






[Bug 1748296] Re: TCG throws Invalid Opcode when executing x86 BMI shlx instruction

2021-01-13 Thread David Greenaway
I hit this today on QEMU head. The problem appears to crop up when:

  1. Decoding a VEX instruction (see [1]) that uses the 0x66 mandatory
 prefix; and

  2. The OSFXSR bit in CR4 is clear (that is, SSE is disabled)

This means that x86_64 instructions such as:

 c4 e2 f9 f7 c0shlxq   %rax, %rax, %rax

fail. Similar instructions the use a different mandatory prefix
(such as `shrxq`, which uses prefix 0xf2) work fine.

Most operating systems presumably set the OSFXSR bit fairly early on, which I
guess is why this problem isn't likely to be seen except in low-level or early
boot code.

The culprit appears to be the block of code in `gen_sse` [2]:

if (is_xmm
&& !(s->flags & HF_OSFXSR_MASK)
&& ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))) {
goto unknown_op;
}

Removing the check `... || (s->prefix & DATA_DATA)` causes QEMU to correctly
translate the instruction, and allows doug16k's test above to pass.

I must confess, I'm not clear what this clause was testing for. My best guess
is that early code (e.g. 4242b1bd8ac) required it to avoid accessing invalid
opcode tables, but we seem to be handling that more gracefully today (e.g.
[3]), so I suspect it is no longer needed.

[1]: https://wiki.osdev.org/X86-64_Instruction_Encoding#VEX.2FXOP_opcodes
[2]: 
https://github.com/qemu/qemu/blob/6b63d126121a9535784003924fcb67f574a6afc0/target/i386/tcg/translate.c#L3078
[3]: 
https://github.com/qemu/qemu/blob/6b63d126121a9535784003924fcb67f574a6afc0/target/i386/tcg/translate.c#L3696-L3700

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

Title:
  TCG throws Invalid Opcode when executing x86 BMI shlx instruction

Status in QEMU:
  New

Bug description:
  I am unable to use BMI in my project when running under TCG. I
  narrowed the problem down to incorrect instruction decoding for BMI
  instructions (which have a 2 byte VEX prefix). The gen_sse function in
  translate.c reaches the goto label do_0f_38_fx, but b does not equal
  0x1f7, 0x2f7, or 0x3f7, so the switch takes the default path and
  raises an invalid opcode exception.

  The code executes correctly and passes the test under KVM.

  I have created a complete repro here: https://github.com/doug65536
  /qemu-bmibug

  The makefile has the following utility targets:

  debug-kvm: Build and run the VM using KVM and wait for gdbstub attach

  run: Run the test case with TCG, make fails if the test fails. (It
  will fail)

  run-kvm: Run the test case with KVM, make fails if the test fails. (It
  will succeed)

  debug: Build and run the VM with TCG and wait for GDB attach

  attach-gdb: Run GDB and attach to QEMU gdbstub

  The VM runs with -cpu max. CPUID reports support for BMI, BMI2, and
  ABM.

  You can quickly verify the issue by executing `make run-kvm` to
  confirm that KVM passes, then `make run` to confirm that TCG fails.

  I believe the bug affects other BMI, BMI2, and ABM instructions, but I
  have only completely verified incorrect execution of SHLX.

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



Re: [PATCH v1 1/4] virtio:add support in configure interrupt

2021-01-13 Thread Jason Wang



On 2021/1/13 下午11:45, Cindy Lu wrote:

Add configure notifier and virtio_set_config_notifier_fd_handler
in virtio

Signed-off-by: Cindy Lu 
---
  hw/virtio/virtio.c | 25 +
  include/hw/virtio/virtio.h |  5 +
  2 files changed, 30 insertions(+)

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index ceb58fda6c..66ed1daf95 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3502,6 +3502,15 @@ static void 
virtio_queue_guest_notifier_read(EventNotifier *n)
  }
  }
  
+static void virtio_queue_config_read(EventNotifier *n)

+{



Note that the config interrupt belongs to the device. So it's better not 
name it as "queue" here.




+VirtIODevice *vdev = container_of(n, VirtIODevice, config_notifier);
+
+if (event_notifier_test_and_clear(n)) {
+
+virtio_notify_config(vdev);
+}
+}
  void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
  bool with_irqfd)
  {
@@ -3518,6 +3527,17 @@ void 
virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
  }
  }
  
+void virtio_set_config_notifier_fd_handler(VirtIODevice *vdev, bool assign,

+bool with_irqfd)
+{
+if (assign && !with_irqfd) {
+event_notifier_set_handler(>config_notifier,
+   virtio_queue_config_read);
+} else {
+   event_notifier_set_handler(>config_notifier, NULL);
+}
+}



I wonder whether we can simply generalize 
virtio_queue_set_guest_notifier_fd_handler from


void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
    bool with_irqfd)

to

void virtio_set_guest_notifier_fd_handler(EventNotifier *e, bool assign,
    bool with_irqfd)


Since there's actually no virtqueue specific setup in this function, 
what its callee really want is a simple EventNotifier.


Thanks



+
  EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq)
  {
  return >guest_notifier;
@@ -3591,6 +3611,11 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue 
*vq)
  return >host_notifier;
  }
  
+EventNotifier *virtio_queue_get_config_notifier(VirtIODevice *vdev)

+{
+return >config_notifier;
+
+}
  void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled)
  {
  vq->host_notifier_enabled = enabled;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index b7ece7a6a8..38bd28242e 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -108,6 +108,7 @@ struct VirtIODevice
  bool use_guest_notifier_mask;
  AddressSpace *dma_as;
  QLIST_HEAD(, VirtQueue) *vector_queues;
+EventNotifier config_notifier;
  };
  
  struct VirtioDeviceClass {

@@ -310,11 +311,15 @@ uint16_t virtio_get_queue_index(VirtQueue *vq);
  EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
  void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign,
  bool with_irqfd);
+void virtio_set_config_notifier_fd_handler(VirtIODevice *vdev, bool assign,
+bool with_irqfd);
+
  int virtio_device_start_ioeventfd(VirtIODevice *vdev);
  int virtio_device_grab_ioeventfd(VirtIODevice *vdev);
  void virtio_device_release_ioeventfd(VirtIODevice *vdev);
  bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev);
  EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
+EventNotifier *virtio_queue_get_config_notifier(VirtIODevice *vdev);
  void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled);
  void virtio_queue_host_notifier_read(EventNotifier *n);
  void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext 
*ctx,





Re: [PATCH v6 08/11] iotests: add testenv.py

2021-01-13 Thread Vladimir Sementsov-Ogievskiy

09.01.2021 15:26, Vladimir Sementsov-Ogievskiy wrote:

Add TestEnv class, which will handle test environment in a new python
iotests running framework.

Difference with current ./check interface:
- -v (verbose) option dropped, as it is unused

- -xdiff option is dropped, until somebody complains that it is needed
- same for -n option


One more thing dropped is looking for binaries in $build_iotests directory.
Do someone use this feature? Or we can drop it, and reimplement when someone 
report the degradation?

--
Best regards,
Vladimir



[Bug 1770724] Re: e1000 takes a long time (2 seconds) to set link ready

2021-01-13 Thread Launchpad Bug Tracker
[Expired for QEMU because there has been no activity for 60 days.]

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

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

Title:
  e1000 takes a long time (2 seconds) to set link ready

Status in QEMU:
  Expired

Bug description:
  When a VM is booted with e1000 NIC, it takes a long time (2 seconds)
  for the guest to bring up the link. This can be seen in the following
  dmesg messages:

  [4.899773] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
  [6.889165] e1000: eth0 NIC Link is Up 1000 Mbps Full Duplex, Flow 
Control: RX
  [6.891372] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

  The first message happens when the guest calls to ifup eth0; ifup does
  not hold control until the link is established. The guest I am using
  (cirros 0.4.0) then starts udhcpc DHCP client that issues a DHCP
  request, then waits for 60 seconds for reply, then repeats the DHCP
  request. When the first request is sent, the link is not ready yet, so
  the frame is lost; when the second request is sent, the link is up and
  DHCP lease is received.

  If I use different NICs (e1000e, virtio, rtl*), there are no dmesg
  messages, and the very first DHCP request correctly reaches outside
  and results in a lease acquired.

  The qemu version I am using is 2.10.1 from Fedora 27. I tried to
  reproduce with runtime from Fedora 29 that includes 2.12 but I have
  different issues there that block me from reproducing the original
  issue (there, I get kernel traces, irq interrupt errors, and no
  network link at all).

  For the record, the qemu in question is started by kubevirt inside a
  docker container with Fedora 27 based image.

  ===

  The command line of qemu is as follows:

  27404 ?Sl 0:10 /usr/bin/qemu-system-x86_64 -machine
  accel=kvm -name guest=default_ovm-cirros,debug-threads=on -S -object
  secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1
  -default_ovm-cirros/master-key.aes -machine
  pc-q35-2.10,accel=kvm,usb=off,dump-guest-core=off -m 62 -realtime
  mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid
  8769fdbe-d957-5567-bd71-114ba0eb4811 -no-user-config -nodefaults
  -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-1
  -default_ovm-cirros/monitor.sock,server,nowait -mon
  chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown
  -no-acpi -boot strict=on -device
  i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e -device pci-
  bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 -device pcie-root-
  port,port=0x10,chassis=3,id=pci.3,bus=pcie.0,multifunction=on,addr=0x2
  -device pcie-root-
  port,port=0x11,chassis=4,id=pci.4,bus=pcie.0,addr=0x2.0x1 -device
  pcie-root-port,port=0x12,chassis=5,id=pci.5,bus=pcie.0,addr=0x2.0x2
  -device pcie-root-
  port,port=0x13,chassis=6,id=pci.6,bus=pcie.0,addr=0x2.0x3 -device
  pcie-root-port,port=0x14,chassis=7,id=pci.7,bus=pcie.0,addr=0x2.0x4
  -device nec-usb-xhci,id=usb,bus=pci.3,addr=0x0 -drive
  file=/var/run/libvirt/kubevirt-ephemeral-disk/registry-disk-
  data/default/ovm-cirros/disk_registryvolume/disk-
  image.raw,format=raw,if=none,id=drive-virtio-disk0 -device virtio-blk-
  pci,scsi=off,bus=pci.4,addr=0x0,drive=drive-virtio-disk0,id=virtio-
  disk0,bootindex=1 -drive file=/var/run/libvirt/kubevirt-ephemeral-disk
  /cloud-init-data/default/ovm-cirros/noCloud.iso,format=raw,if=none,id
  =drive-virtio-disk1 -device virtio-blk-
  pci,scsi=off,bus=pci.5,addr=0x0,drive=drive-virtio-disk1,id=virtio-
  disk1 -netdev tap,fd=23,id=hostnet0 -device
  e1000,netdev=hostnet0,id=net0,mac=0a:58:0a:f4:01:e1,bus=pci.2,addr=0x1
  -chardev socket,id=charserial0,path=/var/run/kubevirt-private/default
  /ovm-cirros/virt-serial0,server,nowait -device isa-
  serial,chardev=charserial0,id=serial0 -vnc vnc=unix:/var/run/kubevirt-
  private/default/ovm-cirros/virt-vnc -device
  VGA,id=video0,vgamem_mb=16,bus=pcie.0,addr=0x1 -device virtio-balloon-
  pci,id=balloon0,bus=pci.6,addr=0x0 -msg timestamp=on

  

  Hypervisor versions of interest:

  [vagrant@node02 ~]$ sudo docker exec -it $(sudo docker ps | grep 
virt-launcher-ovm-cirros | grep entrypoint | awk -e '{print $1}') rpm -qa | 
grep 'qemu\|libvirt'
  qemu-block-curl-2.10.1-2.fc27.x86_64
  qemu-block-ssh-2.10.1-2.fc27.x86_64
  qemu-block-nfs-2.10.1-2.fc27.x86_64
  qemu-system-x86-core-2.10.1-2.fc27.x86_64
  libvirt-daemon-3.7.0-4.fc27.x86_64
  libvirt-daemon-driver-storage-disk-3.7.0-4.fc27.x86_64
  libvirt-daemon-driver-storage-mpath-3.7.0-4.fc27.x86_64
  libvirt-daemon-driver-storage-zfs-3.7.0-4.fc27.x86_64
  libvirt-daemon-driver-nwfilter-3.7.0-4.fc27.x86_64
  qemu-img-2.10.1-2.fc27.x86_64
  qemu-common-2.10.1-2.fc27.x86_64
  qemu-block-dmg-2.10.1-2.fc27.x86_64
  qemu-block-rbd-2.10.1-2.fc27.x86_64
  qemu-system-x86-2.10.1-2.fc27.x86_64
  

RE: [PATCH 07/10] Disable auto-coverge before entering COLO mode.

2021-01-13 Thread Rao, Lei
I think there is a difference between doing checkpoints in COLO and live 
migration.
The feature of auto-converge is to ensure the success of live migration even 
though the dirty page generation speed is faster than data transfer.
but for COLO, we will force the VM to stop when something is doing a 
checkpoint. This will ensure the success of doing a checkpoint and this has 
nothing to do with auto-converge.

Thanks,
Lei.

-Original Message-
From: Dr. David Alan Gilbert  
Sent: Wednesday, January 13, 2021 7:32 PM
To: Rao, Lei 
Cc: Zhang, Chen ; lizhij...@cn.fujitsu.com; 
jasow...@redhat.com; zhang.zhanghaili...@huawei.com; quint...@redhat.com; 
qemu-devel@nongnu.org
Subject: Re: [PATCH 07/10] Disable auto-coverge before entering COLO mode.

* leirao (lei@intel.com) wrote:
> From: "Rao, Lei" 
> 
> If we don't disable the feature of auto-converge for live migration 
> before entering COLO mode, it will continue to run with COLO running, 
> and eventually the system will hang due to the CPU throttle reaching 
> DEFAULT_MIGRATE_MAX_CPU_THROTTLE.
> 
> Signed-off-by: Lei Rao 

I don't think that's the right answer, because it would seem reasonable to use 
auto-converge to ensure that a COLO snapshot succeeded by limiting guest CPU 
time.  Is the right fix here to reset the state of the auto-converge counters 
at the start of each colo snapshot?

Dave

> ---
>  migration/migration.c | 16 +++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c index 
> 31417ce..6ab37e5 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -1673,6 +1673,20 @@ void migrate_set_block_enabled(bool value, Error 
> **errp)
>  qapi_free_MigrationCapabilityStatusList(cap);
>  }
>  
> +static void colo_auto_converge_enabled(bool value, Error **errp) {
> +MigrationCapabilityStatusList *cap = NULL;
> +
> +if (migrate_colo_enabled() && migrate_auto_converge()) {
> +QAPI_LIST_PREPEND(cap,
> +  migrate_cap_add(MIGRATION_CAPABILITY_AUTO_CONVERGE,
> +  value));
> +qmp_migrate_set_capabilities(cap, errp);
> +qapi_free_MigrationCapabilityStatusList(cap);
> +}
> +cpu_throttle_stop();
> +}
> +
>  static void migrate_set_block_incremental(MigrationState *s, bool 
> value)  {
>  s->parameters.block_incremental = value; @@ -3401,7 +3415,7 @@ 
> static MigIterateState migration_iteration_run(MigrationState *s)  
> static void migration_iteration_finish(MigrationState *s)  {
>  /* If we enabled cpu throttling for auto-converge, turn it off. */
> -cpu_throttle_stop();
> +colo_auto_converge_enabled(false, _abort);
>  
>  qemu_mutex_lock_iothread();
>  switch (s->state) {
> --
> 1.8.3.1
> 
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




Re: [PATCH 0/9] Fix some style problems in net

2021-01-13 Thread zhanghan (J)
ping?

This patch set is submmitted a month ago, and have received no replies.
Did I miss any replies?

The link follows:
http://patchwork.ozlabs.org/project/qemu-devel/cover/20201222082340.67405-1-zhangha...@huawei.com/



[PULL 22/24] tcg/ppc: Use tcg_constant_vec with tcg vec expanders

2021-01-13 Thread Richard Henderson
Improve expand_vec_shi to use sign-extraction for MO_32.
This allows a single VSPLTISB instruction to load all of
the valid shift constants.

Signed-off-by: Richard Henderson 
---
 tcg/ppc/tcg-target.c.inc | 44 
 1 file changed, 27 insertions(+), 17 deletions(-)

diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 1fbb1b6db0..cf64892295 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -3336,13 +3336,22 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 static void expand_vec_shi(TCGType type, unsigned vece, TCGv_vec v0,
TCGv_vec v1, TCGArg imm, TCGOpcode opci)
 {
-TCGv_vec t1 = tcg_temp_new_vec(type);
+TCGv_vec t1;
 
-/* Splat w/bytes for xxspltib.  */
-tcg_gen_dupi_vec(MO_8, t1, imm & ((8 << vece) - 1));
+if (vece == MO_32) {
+/*
+ * Only 5 bits are significant, and VSPLTISB can represent -16..15.
+ * So using negative numbers gets us the 4th bit easily.
+ */
+imm = sextract32(imm, 0, 5);
+} else {
+imm &= (8 << vece) - 1;
+}
+
+/* Splat w/bytes for xxspltib when 2.07 allows MO_64. */
+t1 = tcg_constant_vec(type, MO_8, imm);
 vec_gen_3(opci, type, vece, tcgv_vec_arg(v0),
   tcgv_vec_arg(v1), tcgv_vec_arg(t1));
-tcg_temp_free_vec(t1);
 }
 
 static void expand_vec_cmp(TCGType type, unsigned vece, TCGv_vec v0,
@@ -3400,7 +3409,7 @@ static void expand_vec_mul(TCGType type, unsigned vece, 
TCGv_vec v0,
 {
 TCGv_vec t1 = tcg_temp_new_vec(type);
 TCGv_vec t2 = tcg_temp_new_vec(type);
-TCGv_vec t3, t4;
+TCGv_vec c0, c16;
 
 switch (vece) {
 case MO_8:
@@ -3419,21 +3428,22 @@ static void expand_vec_mul(TCGType type, unsigned vece, 
TCGv_vec v0,
 
 case MO_32:
 tcg_debug_assert(!have_isa_2_07);
-t3 = tcg_temp_new_vec(type);
-t4 = tcg_temp_new_vec(type);
-tcg_gen_dupi_vec(MO_8, t4, -16);
+/*
+ * Only 5 bits are significant, and VSPLTISB can represent -16..15.
+ * So using -16 is a quick way to represent 16.
+ */
+c16 = tcg_constant_vec(type, MO_8, -16);
+c0 = tcg_constant_vec(type, MO_8, 0);
+
 vec_gen_3(INDEX_op_rotlv_vec, type, MO_32, tcgv_vec_arg(t1),
-  tcgv_vec_arg(v2), tcgv_vec_arg(t4));
+  tcgv_vec_arg(v2), tcgv_vec_arg(c16));
 vec_gen_3(INDEX_op_ppc_mulou_vec, type, MO_16, tcgv_vec_arg(t2),
   tcgv_vec_arg(v1), tcgv_vec_arg(v2));
-tcg_gen_dupi_vec(MO_8, t3, 0);
-vec_gen_4(INDEX_op_ppc_msum_vec, type, MO_16, tcgv_vec_arg(t3),
-  tcgv_vec_arg(v1), tcgv_vec_arg(t1), tcgv_vec_arg(t3));
-vec_gen_3(INDEX_op_shlv_vec, type, MO_32, tcgv_vec_arg(t3),
-  tcgv_vec_arg(t3), tcgv_vec_arg(t4));
-tcg_gen_add_vec(MO_32, v0, t2, t3);
-tcg_temp_free_vec(t3);
-tcg_temp_free_vec(t4);
+vec_gen_4(INDEX_op_ppc_msum_vec, type, MO_16, tcgv_vec_arg(t1),
+  tcgv_vec_arg(v1), tcgv_vec_arg(t1), tcgv_vec_arg(c0));
+vec_gen_3(INDEX_op_shlv_vec, type, MO_32, tcgv_vec_arg(t1),
+  tcgv_vec_arg(t1), tcgv_vec_arg(c16));
+tcg_gen_add_vec(MO_32, v0, t1, t2);
 break;
 
 default:
-- 
2.25.1




[PULL 17/24] tcg/tci: Add special tci_movi_{i32,i64} opcodes

2021-01-13 Thread Richard Henderson
The normal movi opcodes are going away.  We need something
for TCI to use internally.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-opc.h| 8 
 tcg/tci.c| 4 ++--
 tcg/tci/tcg-target.c.inc | 4 ++--
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index 70a76646c4..43711634f6 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -278,6 +278,14 @@ DEF(last_generic, 0, 0, 0, TCG_OPF_NOT_PRESENT)
 #include "tcg-target.opc.h"
 #endif
 
+#ifdef TCG_TARGET_INTERPRETER
+/* These opcodes are only for use between the tci generator and interpreter. */
+DEF(tci_movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT)
+#if TCG_TARGET_REG_BITS == 64
+DEF(tci_movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
+#endif
+#endif
+
 #undef TLADDR_ARGS
 #undef DATA64_ARGS
 #undef IMPL
diff --git a/tcg/tci.c b/tcg/tci.c
index 2bcc4409be..2311aa7d3a 100644
--- a/tcg/tci.c
+++ b/tcg/tci.c
@@ -593,7 +593,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState 
*env,
 t1 = tci_read_r32(regs, _ptr);
 tci_write_reg32(regs, t0, t1);
 break;
-case INDEX_op_movi_i32:
+case INDEX_op_tci_movi_i32:
 t0 = *tb_ptr++;
 t1 = tci_read_i32(_ptr);
 tci_write_reg32(regs, t0, t1);
@@ -864,7 +864,7 @@ uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState 
*env,
 t1 = tci_read_r64(regs, _ptr);
 tci_write_reg64(regs, t0, t1);
 break;
-case INDEX_op_movi_i64:
+case INDEX_op_tci_movi_i64:
 t0 = *tb_ptr++;
 t1 = tci_read_i64(_ptr);
 tci_write_reg64(regs, t0, t1);
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
index d5a4d9d37c..e9e5f94c04 100644
--- a/tcg/tci/tcg-target.c.inc
+++ b/tcg/tci/tcg-target.c.inc
@@ -529,13 +529,13 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
 uint8_t *old_code_ptr = s->code_ptr;
 uint32_t arg32 = arg;
 if (type == TCG_TYPE_I32 || arg == arg32) {
-tcg_out_op_t(s, INDEX_op_movi_i32);
+tcg_out_op_t(s, INDEX_op_tci_movi_i32);
 tcg_out_r(s, t0);
 tcg_out32(s, arg32);
 } else {
 tcg_debug_assert(type == TCG_TYPE_I64);
 #if TCG_TARGET_REG_BITS == 64
-tcg_out_op_t(s, INDEX_op_movi_i64);
+tcg_out_op_t(s, INDEX_op_tci_movi_i64);
 tcg_out_r(s, t0);
 tcg_out64(s, arg);
 #else
-- 
2.25.1




Re: [PATCH 0/4] Fix some style problems in qobject

2021-01-13 Thread zhanghan (J)
ping?

This patch set was submitted two weeks ago,and 2 of patches ([1/4], [4/4]) has 
been reviewd.
Whose tree should it go via?

Other patches receive no replies.
Did I miss any response?

The link follows:
http://patchwork.ozlabs.org/project/qemu-devel/cover/20201228071129.24563-1-zhangha...@huawei.com/



[PULL 19/24] tcg: Add tcg_reg_alloc_dup2

2021-01-13 Thread Richard Henderson
There are several ways we can expand a vector dup of a 64-bit
element on a 32-bit host.

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

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 5b0e42be91..8f8badb61c 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -4084,6 +4084,98 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 }
 }
 
+static bool tcg_reg_alloc_dup2(TCGContext *s, const TCGOp *op)
+{
+const TCGLifeData arg_life = op->life;
+TCGTemp *ots, *itsl, *itsh;
+TCGType vtype = TCGOP_VECL(op) + TCG_TYPE_V64;
+
+/* This opcode is only valid for 32-bit hosts, for 64-bit elements. */
+tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
+tcg_debug_assert(TCGOP_VECE(op) == MO_64);
+
+ots = arg_temp(op->args[0]);
+itsl = arg_temp(op->args[1]);
+itsh = arg_temp(op->args[2]);
+
+/* ENV should not be modified.  */
+tcg_debug_assert(!temp_readonly(ots));
+
+/* Allocate the output register now.  */
+if (ots->val_type != TEMP_VAL_REG) {
+TCGRegSet allocated_regs = s->reserved_regs;
+TCGRegSet dup_out_regs =
+tcg_op_defs[INDEX_op_dup_vec].args_ct[0].regs;
+
+/* Make sure to not spill the input registers. */
+if (!IS_DEAD_ARG(1) && itsl->val_type == TEMP_VAL_REG) {
+tcg_regset_set_reg(allocated_regs, itsl->reg);
+}
+if (!IS_DEAD_ARG(2) && itsh->val_type == TEMP_VAL_REG) {
+tcg_regset_set_reg(allocated_regs, itsh->reg);
+}
+
+ots->reg = tcg_reg_alloc(s, dup_out_regs, allocated_regs,
+ op->output_pref[0], ots->indirect_base);
+ots->val_type = TEMP_VAL_REG;
+ots->mem_coherent = 0;
+s->reg_to_temp[ots->reg] = ots;
+}
+
+/* Promote dup2 of immediates to dupi_vec. */
+if (itsl->val_type == TEMP_VAL_CONST && itsh->val_type == TEMP_VAL_CONST) {
+uint64_t val = deposit64(itsl->val, 32, 32, itsh->val);
+MemOp vece = MO_64;
+
+if (val == dup_const(MO_8, val)) {
+vece = MO_8;
+} else if (val == dup_const(MO_16, val)) {
+vece = MO_16;
+} else if (val == dup_const(MO_32, val)) {
+vece = MO_32;
+}
+
+tcg_out_dupi_vec(s, vtype, vece, ots->reg, val);
+goto done;
+}
+
+/* If the two inputs form one 64-bit value, try dupm_vec. */
+if (itsl + 1 == itsh && itsl->base_type == TCG_TYPE_I64) {
+if (!itsl->mem_coherent) {
+temp_sync(s, itsl, s->reserved_regs, 0, 0);
+}
+if (!itsh->mem_coherent) {
+temp_sync(s, itsh, s->reserved_regs, 0, 0);
+}
+#ifdef HOST_WORDS_BIGENDIAN
+TCGTemp *its = itsh;
+#else
+TCGTemp *its = itsl;
+#endif
+if (tcg_out_dupm_vec(s, vtype, MO_64, ots->reg,
+ its->mem_base->reg, its->mem_offset)) {
+goto done;
+}
+}
+
+/* Fall back to generic expansion. */
+return false;
+
+ done:
+if (IS_DEAD_ARG(1)) {
+temp_dead(s, itsl);
+}
+if (IS_DEAD_ARG(2)) {
+temp_dead(s, itsh);
+}
+if (NEED_SYNC_ARG(0)) {
+temp_sync(s, ots, s->reserved_regs, 0, IS_DEAD_ARG(0));
+} else if (IS_DEAD_ARG(0)) {
+temp_dead(s, ots);
+}
+return true;
+}
+
 #ifdef TCG_TARGET_STACK_GROWSUP
 #define STACK_DIR(x) (-(x))
 #else
@@ -4501,6 +4593,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
 case INDEX_op_call:
 tcg_reg_alloc_call(s, op);
 break;
+case INDEX_op_dup2_vec:
+if (tcg_reg_alloc_dup2(s, op)) {
+break;
+}
+/* fall through */
 default:
 /* Sanity check that we've not introduced any unhandled opcodes. */
 tcg_debug_assert(tcg_op_supported(opc));
-- 
2.25.1




[PULL 24/24] decodetree: Open files with encoding='utf-8'

2021-01-13 Thread Richard Henderson
From: Philippe Mathieu-Daudé 

When decodetree.py was added in commit 568ae7efae7, QEMU was
using Python 2 which happily reads UTF-8 files in text mode.
Python 3 requires either UTF-8 locale or an explicit encoding
passed to open(). Now that Python 3 is required, explicit
UTF-8 encoding for decodetree source files.

To avoid further problems with the user locale, also explicit
UTF-8 encoding for the generated C files.

Explicit both input/output are plain text by using the 't' mode.

This fixes:

  $ /usr/bin/python3 scripts/decodetree.py test.decode
  Traceback (most recent call last):
File "scripts/decodetree.py", line 1397, in 
  main()
File "scripts/decodetree.py", line 1308, in main
  parse_file(f, toppat)
File "scripts/decodetree.py", line 994, in parse_file
  for line in f:
File "/usr/lib/python3.6/encodings/ascii.py", line 26, in decode
  return codecs.ascii_decode(input, self.errors)[0]
  UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 80:
  ordinal not in range(128)

Reported-by: Peter Maydell 
Suggested-by: Yonggang Luo 
Reviewed-by: Eduardo Habkost 
Signed-off-by: Philippe Mathieu-Daudé 
Message-Id: <2021011240.761122-1-f4...@amsat.org>
Signed-off-by: Richard Henderson 
---
 scripts/decodetree.py | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index 47aa9caf6d..4637b633e7 100644
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -20,6 +20,7 @@
 # See the syntax and semantics in docs/devel/decodetree.rst.
 #
 
+import io
 import os
 import re
 import sys
@@ -1304,7 +1305,7 @@ def main():
 
 for filename in args:
 input_file = filename
-f = open(filename, 'r')
+f = open(filename, 'rt', encoding='utf-8')
 parse_file(f, toppat)
 f.close()
 
@@ -1324,9 +1325,11 @@ def main():
 prop_size(stree)
 
 if output_file:
-output_fd = open(output_file, 'w')
+output_fd = open(output_file, 'wt', encoding='utf-8')
 else:
-output_fd = sys.stdout
+output_fd = io.TextIOWrapper(sys.stdout.buffer,
+ encoding=sys.stdout.encoding,
+ errors="ignore")
 
 output_autogen()
 for n in sorted(arguments.keys()):
-- 
2.25.1




[PULL 11/24] tcg/optimize: Use tcg_constant_internal with constant folding

2021-01-13 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 108 ++---
 1 file changed, 49 insertions(+), 59 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 49bf1386c7..bda727d5ed 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -178,37 +178,6 @@ static bool args_are_copies(TCGArg arg1, TCGArg arg2)
 return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
 }
 
-static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, uint64_t 
val)
-{
-const TCGOpDef *def;
-TCGOpcode new_op;
-uint64_t mask;
-TempOptInfo *di = arg_info(dst);
-
-def = _op_defs[op->opc];
-if (def->flags & TCG_OPF_VECTOR) {
-new_op = INDEX_op_dupi_vec;
-} else if (def->flags & TCG_OPF_64BIT) {
-new_op = INDEX_op_movi_i64;
-} else {
-new_op = INDEX_op_movi_i32;
-}
-op->opc = new_op;
-/* TCGOP_VECL and TCGOP_VECE remain unchanged.  */
-op->args[0] = dst;
-op->args[1] = val;
-
-reset_temp(dst);
-di->is_const = true;
-di->val = val;
-mask = val;
-if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
-/* High bits of the destination are now garbage.  */
-mask |= ~0xull;
-}
-di->mask = mask;
-}
-
 static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
 {
 TCGTemp *dst_ts = arg_temp(dst);
@@ -259,6 +228,27 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 }
 }
 
+static void tcg_opt_gen_movi(TCGContext *s, TCGTempSet *temps_used,
+ TCGOp *op, TCGArg dst, uint64_t val)
+{
+const TCGOpDef *def = _op_defs[op->opc];
+TCGType type;
+TCGTemp *tv;
+
+if (def->flags & TCG_OPF_VECTOR) {
+type = TCGOP_VECL(op) + TCG_TYPE_V64;
+} else if (def->flags & TCG_OPF_64BIT) {
+type = TCG_TYPE_I64;
+} else {
+type = TCG_TYPE_I32;
+}
+
+/* Convert movi to mov with constant temp. */
+tv = tcg_constant_internal(type, val);
+init_ts_info(temps_used, tv);
+tcg_opt_gen_mov(s, op, dst, temp_arg(tv));
+}
+
 static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
 {
 uint64_t l64, h64;
@@ -622,7 +612,7 @@ void tcg_optimize(TCGContext *s)
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
 
-bitmap_zero(temps_used.l, nb_temps);
+memset(_used, 0, sizeof(temps_used));
 for (i = 0; i < nb_temps; ++i) {
 s->temps[i].state_ptr = NULL;
 }
@@ -727,7 +717,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64(rotr):
 if (arg_is_const(op->args[1])
 && arg_info(op->args[1])->val == 0) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -1054,7 +1044,7 @@ void tcg_optimize(TCGContext *s)
 
 if (partmask == 0) {
 tcg_debug_assert(nb_oargs == 1);
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 if (affected == 0) {
@@ -1071,7 +1061,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64(mulsh):
 if (arg_is_const(op->args[2])
 && arg_info(op->args[2])->val == 0) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -1098,7 +1088,7 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64_VEC(sub):
 CASE_OP_32_64_VEC(xor):
 if (args_are_copies(op->args[1], op->args[2])) {
-tcg_opt_gen_movi(s, op, op->args[0], 0);
+tcg_opt_gen_movi(s, _used, op, op->args[0], 0);
 continue;
 }
 break;
@@ -1115,14 +1105,14 @@ void tcg_optimize(TCGContext *s)
 break;
 CASE_OP_32_64(movi):
 case INDEX_op_dupi_vec:
-tcg_opt_gen_movi(s, op, op->args[0], op->args[1]);
+tcg_opt_gen_movi(s, _used, op, op->args[0], op->args[1]);
 break;
 
 case INDEX_op_dup_vec:
 if (arg_is_const(op->args[1])) {
 tmp = arg_info(op->args[1])->val;
 tmp = dup_const(TCGOP_VECE(op), tmp);
-tcg_opt_gen_movi(s, op, op->args[0], tmp);
+tcg_opt_gen_movi(s, _used, op, op->args[0], tmp);
 break;
 }
 goto do_default;
@@ -1132,7 +1122,7 @@ void tcg_optimize(TCGContext *s)
 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
 tmp = arg_info(op->args[1])->val;
 if (tmp == arg_info(op->args[2])->val) {
-tcg_opt_gen_movi(s, op, op->args[0], tmp);
+tcg_opt_gen_movi(s, _used, op, op->args[0], tmp);
  

[PULL 14/24] tcg: Use tcg_constant_{i32,i64} with tcg int expanders

2021-01-13 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-op.h |  13 +--
 tcg/tcg-op.c | 227 ---
 2 files changed, 109 insertions(+), 131 deletions(-)

diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index 901b19f32a..ed8de045e2 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -271,6 +271,7 @@ void tcg_gen_mb(TCGBar);
 
 /* 32 bit ops */
 
+void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg);
 void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
 void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 arg2);
 void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2);
@@ -349,11 +350,6 @@ static inline void tcg_gen_mov_i32(TCGv_i32 ret, TCGv_i32 
arg)
 }
 }
 
-static inline void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
-{
-tcg_gen_op2i_i32(INDEX_op_movi_i32, ret, arg);
-}
-
 static inline void tcg_gen_ld8u_i32(TCGv_i32 ret, TCGv_ptr arg2,
 tcg_target_long offset)
 {
@@ -467,6 +463,7 @@ static inline void tcg_gen_not_i32(TCGv_i32 ret, TCGv_i32 
arg)
 
 /* 64 bit ops */
 
+void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg);
 void tcg_gen_addi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
 void tcg_gen_subfi_i64(TCGv_i64 ret, int64_t arg1, TCGv_i64 arg2);
 void tcg_gen_subi_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2);
@@ -550,11 +547,6 @@ static inline void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 
arg)
 }
 }
 
-static inline void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg)
-{
-tcg_gen_op2i_i64(INDEX_op_movi_i64, ret, arg);
-}
-
 static inline void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2,
 tcg_target_long offset)
 {
@@ -698,7 +690,6 @@ static inline void tcg_gen_sub_i64(TCGv_i64 ret, TCGv_i64 
arg1, TCGv_i64 arg2)
 
 void tcg_gen_discard_i64(TCGv_i64 arg);
 void tcg_gen_mov_i64(TCGv_i64 ret, TCGv_i64 arg);
-void tcg_gen_movi_i64(TCGv_i64 ret, int64_t arg);
 void tcg_gen_ld8u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
 void tcg_gen_ld8s_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
 void tcg_gen_ld16u_i64(TCGv_i64 ret, TCGv_ptr arg2, tcg_target_long offset);
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index 0374b5d56d..70475773f4 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -104,15 +104,18 @@ void tcg_gen_mb(TCGBar mb_type)
 
 /* 32 bit ops */
 
+void tcg_gen_movi_i32(TCGv_i32 ret, int32_t arg)
+{
+tcg_gen_mov_i32(ret, tcg_constant_i32(arg));
+}
+
 void tcg_gen_addi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
 {
 /* some cases can be optimized here */
 if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_add_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_add_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -122,9 +125,7 @@ void tcg_gen_subfi_i32(TCGv_i32 ret, int32_t arg1, TCGv_i32 
arg2)
 /* Don't recurse with tcg_gen_neg_i32.  */
 tcg_gen_op2_i32(INDEX_op_neg_i32, ret, arg2);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg1);
-tcg_gen_sub_i32(ret, t0, arg2);
-tcg_temp_free_i32(t0);
+tcg_gen_sub_i32(ret, tcg_constant_i32(arg1), arg2);
 }
 }
 
@@ -134,15 +135,12 @@ void tcg_gen_subi_i32(TCGv_i32 ret, TCGv_i32 arg1, 
int32_t arg2)
 if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_sub_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_sub_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
 void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
 {
-TCGv_i32 t0;
 /* Some cases can be optimized here.  */
 switch (arg2) {
 case 0:
@@ -165,9 +163,8 @@ void tcg_gen_andi_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 }
 break;
 }
-t0 = tcg_const_i32(arg2);
-tcg_gen_and_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+
+tcg_gen_and_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 
 void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t arg2)
@@ -178,9 +175,7 @@ void tcg_gen_ori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 } else if (arg2 == 0) {
 tcg_gen_mov_i32(ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_or_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_or_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -193,9 +188,7 @@ void tcg_gen_xori_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 /* Don't recurse with tcg_gen_not_i32.  */
 tcg_gen_op2_i32(INDEX_op_not_i32, ret, arg1);
 } else {
-TCGv_i32 t0 = tcg_const_i32(arg2);
-tcg_gen_xor_i32(ret, arg1, t0);
-tcg_temp_free_i32(t0);
+tcg_gen_xor_i32(ret, arg1, tcg_constant_i32(arg2));
 }
 }
 
@@ -205,9 +198,7 @@ void tcg_gen_shli_i32(TCGv_i32 ret, TCGv_i32 arg1, int32_t 
arg2)
 if (arg2 == 0) {
   

[PULL 21/24] tcg: Remove tcg_gen_dup{8,16,32,64}i_vec

2021-01-13 Thread Richard Henderson
These interfaces have been replaced by tcg_gen_dupi_vec
and tcg_constant_vec.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-op.h |  4 
 tcg/tcg-op-vec.c | 20 
 2 files changed, 24 deletions(-)

diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
index ed8de045e2..2cd1faf9c4 100644
--- a/include/tcg/tcg-op.h
+++ b/include/tcg/tcg-op.h
@@ -959,10 +959,6 @@ void tcg_gen_mov_vec(TCGv_vec, TCGv_vec);
 void tcg_gen_dup_i32_vec(unsigned vece, TCGv_vec, TCGv_i32);
 void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec, TCGv_i64);
 void tcg_gen_dup_mem_vec(unsigned vece, TCGv_vec, TCGv_ptr, tcg_target_long);
-void tcg_gen_dup8i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup16i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup32i_vec(TCGv_vec, uint32_t);
-void tcg_gen_dup64i_vec(TCGv_vec, uint64_t);
 void tcg_gen_dupi_vec(unsigned vece, TCGv_vec, uint64_t);
 void tcg_gen_add_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
 void tcg_gen_sub_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b);
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index ce0d2f6e0e..d19aa7373e 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -241,26 +241,6 @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
 return tcg_const_ones_vec(t->base_type);
 }
 
-void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
-{
-tcg_gen_dupi_vec(MO_64, r, a);
-}
-
-void tcg_gen_dup32i_vec(TCGv_vec r, uint32_t a)
-{
-tcg_gen_dupi_vec(MO_32, r, a);
-}
-
-void tcg_gen_dup16i_vec(TCGv_vec r, uint32_t a)
-{
-tcg_gen_dupi_vec(MO_16, r, a);
-}
-
-void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
-{
-tcg_gen_dupi_vec(MO_8, r, a);
-}
-
 void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
 {
 TCGTemp *rt = tcgv_vec_temp(r);
-- 
2.25.1




[PULL 12/24] tcg: Convert tcg_gen_dupi_vec to TCG_CONST

2021-01-13 Thread Richard Henderson
Because we now store uint64_t in TCGTemp, we can now always
store the full 64-bit duplicate immediate.  So remove the
difference between 32- and 64-bit hosts.

Signed-off-by: Richard Henderson 
---
 tcg/optimize.c   |  9 -
 tcg/tcg-op-vec.c | 39 ++-
 tcg/tcg.c|  7 +--
 3 files changed, 15 insertions(+), 40 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index bda727d5ed..dbb03ef96b 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1120,11 +1120,10 @@ void tcg_optimize(TCGContext *s)
 case INDEX_op_dup2_vec:
 assert(TCG_TARGET_REG_BITS == 32);
 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
-tmp = arg_info(op->args[1])->val;
-if (tmp == arg_info(op->args[2])->val) {
-tcg_opt_gen_movi(s, _used, op, op->args[0], tmp);
-break;
-}
+tcg_opt_gen_movi(s, _used, op, op->args[0],
+ deposit64(arg_info(op->args[1])->val, 32, 32,
+   arg_info(op->args[2])->val));
+break;
 } else if (args_are_copies(op->args[1], op->args[2])) {
 op->opc = INDEX_op_dup_vec;
 TCGOP_VECE(op) = MO_32;
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index cdbf11c573..9fbed1366c 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -216,25 +216,17 @@ void tcg_gen_mov_vec(TCGv_vec r, TCGv_vec a)
 }
 }
 
-#define MO_REG  (TCG_TARGET_REG_BITS == 64 ? MO_64 : MO_32)
-
-static void do_dupi_vec(TCGv_vec r, unsigned vece, TCGArg a)
-{
-TCGTemp *rt = tcgv_vec_temp(r);
-vec_gen_2(INDEX_op_dupi_vec, rt->base_type, vece, temp_arg(rt), a);
-}
-
 TCGv_vec tcg_const_zeros_vec(TCGType type)
 {
 TCGv_vec ret = tcg_temp_new_vec(type);
-do_dupi_vec(ret, MO_REG, 0);
+tcg_gen_dupi_vec(MO_64, ret, 0);
 return ret;
 }
 
 TCGv_vec tcg_const_ones_vec(TCGType type)
 {
 TCGv_vec ret = tcg_temp_new_vec(type);
-do_dupi_vec(ret, MO_REG, -1);
+tcg_gen_dupi_vec(MO_64, ret, -1);
 return ret;
 }
 
@@ -252,39 +244,28 @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
 
 void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
 {
-if (TCG_TARGET_REG_BITS == 64) {
-do_dupi_vec(r, MO_64, a);
-} else if (a == dup_const(MO_32, a)) {
-do_dupi_vec(r, MO_32, a);
-} else {
-TCGv_i64 c = tcg_const_i64(a);
-tcg_gen_dup_i64_vec(MO_64, r, c);
-tcg_temp_free_i64(c);
-}
+tcg_gen_dupi_vec(MO_64, r, a);
 }
 
 void tcg_gen_dup32i_vec(TCGv_vec r, uint32_t a)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_32, a));
+tcg_gen_dupi_vec(MO_32, r, a);
 }
 
 void tcg_gen_dup16i_vec(TCGv_vec r, uint32_t a)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_16, a));
+tcg_gen_dupi_vec(MO_16, r, a);
 }
 
 void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
 {
-do_dupi_vec(r, MO_REG, dup_const(MO_8, a));
+tcg_gen_dupi_vec(MO_8, r, a);
 }
 
 void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
 {
-if (vece == MO_64) {
-tcg_gen_dup64i_vec(r, a);
-} else {
-do_dupi_vec(r, MO_REG, dup_const(vece, a));
-}
+TCGTemp *rt = tcgv_vec_temp(r);
+tcg_gen_mov_vec(r, tcg_constant_vec(rt->base_type, vece, a));
 }
 
 void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a)
@@ -489,8 +470,8 @@ void tcg_gen_abs_vec(unsigned vece, TCGv_vec r, TCGv_vec a)
 if (tcg_can_emit_vec_op(INDEX_op_sari_vec, type, vece) > 0) {
 tcg_gen_sari_vec(vece, t, a, (8 << vece) - 1);
 } else {
-do_dupi_vec(t, MO_REG, 0);
-tcg_gen_cmp_vec(TCG_COND_LT, vece, t, a, t);
+tcg_gen_cmp_vec(TCG_COND_LT, vece, t, a,
+tcg_constant_vec(type, vece, 0));
 }
 tcg_gen_xor_vec(vece, r, a, t);
 tcg_gen_sub_vec(vece, r, r, t);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 802f0b8a32..ad1348d811 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3539,16 +3539,11 @@ static void temp_load(TCGContext *s, TCGTemp *ts, 
TCGRegSet desired_regs,
  * The targets will, in general, have to do this search anyway,
  * do this generically.
  */
-if (TCG_TARGET_REG_BITS == 32) {
-val = dup_const(MO_32, val);
-vece = MO_32;
-}
 if (val == dup_const(MO_8, val)) {
 vece = MO_8;
 } else if (val == dup_const(MO_16, val)) {
 vece = MO_16;
-} else if (TCG_TARGET_REG_BITS == 64 &&
-   val == dup_const(MO_32, val)) {
+} else if (val == dup_const(MO_32, val)) {
 vece = MO_32;
 }
 
-- 
2.25.1




[PULL 13/24] tcg: Use tcg_constant_i32 with icount expander

2021-01-13 Thread Richard Henderson
We must do this before we adjust tcg_out_movi_i32, lest the
under-the-hood poking that we do for icount be broken.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 include/exec/gen-icount.h | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h
index aa4b44354a..298e01eef4 100644
--- a/include/exec/gen-icount.h
+++ b/include/exec/gen-icount.h
@@ -34,7 +34,7 @@ static inline void gen_io_end(void)
 
 static inline void gen_tb_start(const TranslationBlock *tb)
 {
-TCGv_i32 count, imm;
+TCGv_i32 count;
 
 tcg_ctx->exitreq_label = gen_new_label();
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
@@ -48,15 +48,13 @@ static inline void gen_tb_start(const TranslationBlock *tb)
offsetof(ArchCPU, env));
 
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
-imm = tcg_temp_new_i32();
-/* We emit a movi with a dummy immediate argument. Keep the insn index
- * of the movi so that we later (when we know the actual insn count)
- * can update the immediate argument with the actual insn count.  */
-tcg_gen_movi_i32(imm, 0xdeadbeef);
+/*
+ * We emit a sub with a dummy immediate argument. Keep the insn index
+ * of the sub so that we later (when we know the actual insn count)
+ * can update the argument with the actual insn count.
+ */
+tcg_gen_sub_i32(count, count, tcg_constant_i32(0));
 icount_start_insn = tcg_last_op();
-
-tcg_gen_sub_i32(count, count, imm);
-tcg_temp_free_i32(imm);
 }
 
 tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
@@ -74,9 +72,12 @@ static inline void gen_tb_start(const TranslationBlock *tb)
 static inline void gen_tb_end(const TranslationBlock *tb, int num_insns)
 {
 if (tb_cflags(tb) & CF_USE_ICOUNT) {
-/* Update the num_insn immediate parameter now that we know
- * the actual insn count.  */
-tcg_set_insn_param(icount_start_insn, 1, num_insns);
+/*
+ * Update the num_insn immediate parameter now that we know
+ * the actual insn count.
+ */
+tcg_set_insn_param(icount_start_insn, 2,
+   tcgv_i32_arg(tcg_constant_i32(num_insns)));
 }
 
 gen_set_label(tcg_ctx->exitreq_label);
-- 
2.25.1




[PULL 20/24] tcg/i386: Use tcg_constant_vec with tcg vec expanders

2021-01-13 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.c.inc | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 1706b7c776..050f3cb0b1 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -3486,7 +3486,7 @@ static void expand_vec_rotv(TCGType type, unsigned vece, 
TCGv_vec v0,
 static void expand_vec_mul(TCGType type, unsigned vece,
TCGv_vec v0, TCGv_vec v1, TCGv_vec v2)
 {
-TCGv_vec t1, t2, t3, t4;
+TCGv_vec t1, t2, t3, t4, zero;
 
 tcg_debug_assert(vece == MO_8);
 
@@ -3504,11 +3504,11 @@ static void expand_vec_mul(TCGType type, unsigned vece,
 case TCG_TYPE_V64:
 t1 = tcg_temp_new_vec(TCG_TYPE_V128);
 t2 = tcg_temp_new_vec(TCG_TYPE_V128);
-tcg_gen_dup16i_vec(t2, 0);
+zero = tcg_constant_vec(TCG_TYPE_V128, MO_8, 0);
 vec_gen_3(INDEX_op_x86_punpckl_vec, TCG_TYPE_V128, MO_8,
-  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(t2));
+  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckl_vec, TCG_TYPE_V128, MO_8,
-  tcgv_vec_arg(t2), tcgv_vec_arg(t2), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t2), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 tcg_gen_mul_vec(MO_16, t1, t1, t2);
 tcg_gen_shri_vec(MO_16, t1, t1, 8);
 vec_gen_3(INDEX_op_x86_packus_vec, TCG_TYPE_V128, MO_8,
@@ -3523,15 +3523,15 @@ static void expand_vec_mul(TCGType type, unsigned vece,
 t2 = tcg_temp_new_vec(type);
 t3 = tcg_temp_new_vec(type);
 t4 = tcg_temp_new_vec(type);
-tcg_gen_dup16i_vec(t4, 0);
+zero = tcg_constant_vec(TCG_TYPE_V128, MO_8, 0);
 vec_gen_3(INDEX_op_x86_punpckl_vec, type, MO_8,
-  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(t4));
+  tcgv_vec_arg(t1), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckl_vec, type, MO_8,
-  tcgv_vec_arg(t2), tcgv_vec_arg(t4), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t2), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 vec_gen_3(INDEX_op_x86_punpckh_vec, type, MO_8,
-  tcgv_vec_arg(t3), tcgv_vec_arg(v1), tcgv_vec_arg(t4));
+  tcgv_vec_arg(t3), tcgv_vec_arg(v1), tcgv_vec_arg(zero));
 vec_gen_3(INDEX_op_x86_punpckh_vec, type, MO_8,
-  tcgv_vec_arg(t4), tcgv_vec_arg(t4), tcgv_vec_arg(v2));
+  tcgv_vec_arg(t4), tcgv_vec_arg(zero), tcgv_vec_arg(v2));
 tcg_gen_mul_vec(MO_16, t1, t1, t2);
 tcg_gen_mul_vec(MO_16, t3, t3, t4);
 tcg_gen_shri_vec(MO_16, t1, t1, 8);
@@ -3559,7 +3559,7 @@ static bool expand_vec_cmp_noinv(TCGType type, unsigned 
vece, TCGv_vec v0,
 NEED_UMIN = 8,
 NEED_UMAX = 16,
 };
-TCGv_vec t1, t2;
+TCGv_vec t1, t2, t3;
 uint8_t fixup;
 
 switch (cond) {
@@ -3630,9 +3630,9 @@ static bool expand_vec_cmp_noinv(TCGType type, unsigned 
vece, TCGv_vec v0,
 } else if (fixup & NEED_BIAS) {
 t1 = tcg_temp_new_vec(type);
 t2 = tcg_temp_new_vec(type);
-tcg_gen_dupi_vec(vece, t2, 1ull << ((8 << vece) - 1));
-tcg_gen_sub_vec(vece, t1, v1, t2);
-tcg_gen_sub_vec(vece, t2, v2, t2);
+t3 = tcg_constant_vec(type, vece, 1ull << ((8 << vece) - 1));
+tcg_gen_sub_vec(vece, t1, v1, t3);
+tcg_gen_sub_vec(vece, t2, v2, t3);
 v1 = t1;
 v2 = t2;
 cond = tcg_signed_cond(cond);
-- 
2.25.1




[PULL 18/24] tcg: Remove movi and dupi opcodes

2021-01-13 Thread Richard Henderson
These are now completely covered by mov from a
TYPE_CONST temporary.

Reviewed-by: Alex Bennée 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-opc.h|  3 ---
 tcg/optimize.c   |  4 
 tcg/tcg-op-vec.c |  1 -
 tcg/tcg.c| 18 +-
 tcg/aarch64/tcg-target.c.inc |  3 ---
 tcg/arm/tcg-target.c.inc |  1 -
 tcg/i386/tcg-target.c.inc|  3 ---
 tcg/mips/tcg-target.c.inc|  2 --
 tcg/ppc/tcg-target.c.inc |  3 ---
 tcg/riscv/tcg-target.c.inc   |  2 --
 tcg/s390/tcg-target.c.inc|  2 --
 tcg/sparc/tcg-target.c.inc   |  2 --
 tcg/tci/tcg-target.c.inc |  2 --
 13 files changed, 1 insertion(+), 45 deletions(-)

diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index 43711634f6..900984c005 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -45,7 +45,6 @@ DEF(br, 0, 0, 1, TCG_OPF_BB_END)
 DEF(mb, 0, 0, 1, 0)
 
 DEF(mov_i32, 1, 1, 0, TCG_OPF_NOT_PRESENT)
-DEF(movi_i32, 1, 0, 1, TCG_OPF_NOT_PRESENT)
 DEF(setcond_i32, 1, 2, 1, 0)
 DEF(movcond_i32, 1, 4, 1, IMPL(TCG_TARGET_HAS_movcond_i32))
 /* load/store */
@@ -111,7 +110,6 @@ DEF(ctz_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_ctz_i32))
 DEF(ctpop_i32, 1, 1, 0, IMPL(TCG_TARGET_HAS_ctpop_i32))
 
 DEF(mov_i64, 1, 1, 0, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
-DEF(movi_i64, 1, 0, 1, TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT)
 DEF(setcond_i64, 1, 2, 1, IMPL64)
 DEF(movcond_i64, 1, 4, 1, IMPL64 | IMPL(TCG_TARGET_HAS_movcond_i64))
 /* load/store */
@@ -221,7 +219,6 @@ DEF(qemu_st8_i32, 0, TLADDR_ARGS + 1, 1,
 #define IMPLVEC  TCG_OPF_VECTOR | IMPL(TCG_TARGET_MAYBE_vec)
 
 DEF(mov_vec, 1, 1, 0, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT)
-DEF(dupi_vec, 1, 0, 1, TCG_OPF_VECTOR | TCG_OPF_NOT_PRESENT)
 
 DEF(dup_vec, 1, 1, 0, IMPLVEC)
 DEF(dup2_vec, 1, 2, 0, IMPLVEC | IMPL(TCG_TARGET_REG_BITS == 32))
diff --git a/tcg/optimize.c b/tcg/optimize.c
index dbb03ef96b..37c902283e 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -1103,10 +1103,6 @@ void tcg_optimize(TCGContext *s)
 CASE_OP_32_64_VEC(mov):
 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
 break;
-CASE_OP_32_64(movi):
-case INDEX_op_dupi_vec:
-tcg_opt_gen_movi(s, _used, op, op->args[0], op->args[1]);
-break;
 
 case INDEX_op_dup_vec:
 if (arg_is_const(op->args[1])) {
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
index 9fbed1366c..ce0d2f6e0e 100644
--- a/tcg/tcg-op-vec.c
+++ b/tcg/tcg-op-vec.c
@@ -83,7 +83,6 @@ bool tcg_can_emit_vecop_list(const TCGOpcode *list,
 case INDEX_op_xor_vec:
 case INDEX_op_mov_vec:
 case INDEX_op_dup_vec:
-case INDEX_op_dupi_vec:
 case INDEX_op_dup2_vec:
 case INDEX_op_ld_vec:
 case INDEX_op_st_vec:
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 1cadfe070c..5b0e42be91 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1564,7 +1564,6 @@ bool tcg_op_supported(TCGOpcode op)
 return TCG_TARGET_HAS_goto_ptr;
 
 case INDEX_op_mov_i32:
-case INDEX_op_movi_i32:
 case INDEX_op_setcond_i32:
 case INDEX_op_brcond_i32:
 case INDEX_op_ld8u_i32:
@@ -1658,7 +1657,6 @@ bool tcg_op_supported(TCGOpcode op)
 return TCG_TARGET_REG_BITS == 32;
 
 case INDEX_op_mov_i64:
-case INDEX_op_movi_i64:
 case INDEX_op_setcond_i64:
 case INDEX_op_brcond_i64:
 case INDEX_op_ld8u_i64:
@@ -1764,7 +1762,6 @@ bool tcg_op_supported(TCGOpcode op)
 
 case INDEX_op_mov_vec:
 case INDEX_op_dup_vec:
-case INDEX_op_dupi_vec:
 case INDEX_op_dupm_vec:
 case INDEX_op_ld_vec:
 case INDEX_op_st_vec:
@@ -3670,7 +3667,7 @@ static void tcg_reg_alloc_cbranch(TCGContext *s, 
TCGRegSet allocated_regs)
 }
 
 /*
- * Specialized code generation for INDEX_op_movi_*.
+ * Specialized code generation for INDEX_op_mov_* with a constant.
  */
 static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots,
   tcg_target_ulong val, TCGLifeData arg_life,
@@ -3693,14 +3690,6 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp 
*ots,
 }
 }
 
-static void tcg_reg_alloc_movi(TCGContext *s, const TCGOp *op)
-{
-TCGTemp *ots = arg_temp(op->args[0]);
-tcg_target_ulong val = op->args[1];
-
-tcg_reg_alloc_do_movi(s, ots, val, op->life, op->output_pref[0]);
-}
-
 /*
  * Specialized code generation for INDEX_op_mov_*.
  */
@@ -4481,11 +4470,6 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
 case INDEX_op_mov_vec:
 tcg_reg_alloc_mov(s, op);
 break;
-case INDEX_op_movi_i32:
-case INDEX_op_movi_i64:
-case INDEX_op_dupi_vec:
-tcg_reg_alloc_movi(s, op);
-break;
 case INDEX_op_dup_vec:
 tcg_reg_alloc_dup(s, op);
 break;
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index be6d3ea2a8..e370b7e61c 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ 

[PULL 10/24] tcg/optimize: Adjust TempOptInfo allocation

2021-01-13 Thread Richard Henderson
Do not allocate a large block for indexing.  Instead, allocate
for each temporary as they are seen.

In general, this will use less memory, if we consider that most
TBs do not touch every target register.  This also allows us to
allocate TempOptInfo for new temps created during optimization.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 60 --
 1 file changed, 34 insertions(+), 26 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index e42f9c89a8..49bf1386c7 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -89,35 +89,41 @@ static void reset_temp(TCGArg arg)
 }
 
 /* Initialize and activate a temporary.  */
-static void init_ts_info(TempOptInfo *infos,
- TCGTempSet *temps_used, TCGTemp *ts)
+static void init_ts_info(TCGTempSet *temps_used, TCGTemp *ts)
 {
 size_t idx = temp_idx(ts);
-if (!test_bit(idx, temps_used->l)) {
-TempOptInfo *ti = [idx];
+TempOptInfo *ti;
 
+if (test_bit(idx, temps_used->l)) {
+return;
+}
+set_bit(idx, temps_used->l);
+
+ti = ts->state_ptr;
+if (ti == NULL) {
+ti = tcg_malloc(sizeof(TempOptInfo));
 ts->state_ptr = ti;
-ti->next_copy = ts;
-ti->prev_copy = ts;
-if (ts->kind == TEMP_CONST) {
-ti->is_const = true;
-ti->val = ti->mask = ts->val;
-if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
-/* High bits of a 32-bit quantity are garbage.  */
-ti->mask |= ~0xull;
-}
-} else {
-ti->is_const = false;
-ti->mask = -1;
+}
+
+ti->next_copy = ts;
+ti->prev_copy = ts;
+if (ts->kind == TEMP_CONST) {
+ti->is_const = true;
+ti->val = ts->val;
+ti->mask = ts->val;
+if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
+/* High bits of a 32-bit quantity are garbage.  */
+ti->mask |= ~0xull;
 }
-set_bit(idx, temps_used->l);
+} else {
+ti->is_const = false;
+ti->mask = -1;
 }
 }
 
-static void init_arg_info(TempOptInfo *infos,
-  TCGTempSet *temps_used, TCGArg arg)
+static void init_arg_info(TCGTempSet *temps_used, TCGArg arg)
 {
-init_ts_info(infos, temps_used, arg_temp(arg));
+init_ts_info(temps_used, arg_temp(arg));
 }
 
 static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
@@ -604,9 +610,8 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
 /* Propagate constants and copies, fold constant expressions. */
 void tcg_optimize(TCGContext *s)
 {
-int nb_temps, nb_globals;
+int nb_temps, nb_globals, i;
 TCGOp *op, *op_next, *prev_mb = NULL;
-TempOptInfo *infos;
 TCGTempSet temps_used;
 
 /* Array VALS has an element for each temp.
@@ -616,12 +621,15 @@ void tcg_optimize(TCGContext *s)
 
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
+
 bitmap_zero(temps_used.l, nb_temps);
-infos = tcg_malloc(sizeof(TempOptInfo) * nb_temps);
+for (i = 0; i < nb_temps; ++i) {
+s->temps[i].state_ptr = NULL;
+}
 
 QTAILQ_FOREACH_SAFE(op, >ops, link, op_next) {
 uint64_t mask, partmask, affected, tmp;
-int nb_oargs, nb_iargs, i;
+int nb_oargs, nb_iargs;
 TCGOpcode opc = op->opc;
 const TCGOpDef *def = _op_defs[opc];
 
@@ -633,14 +641,14 @@ void tcg_optimize(TCGContext *s)
 for (i = 0; i < nb_oargs + nb_iargs; i++) {
 TCGTemp *ts = arg_temp(op->args[i]);
 if (ts) {
-init_ts_info(infos, _used, ts);
+init_ts_info(_used, ts);
 }
 }
 } else {
 nb_oargs = def->nb_oargs;
 nb_iargs = def->nb_iargs;
 for (i = 0; i < nb_oargs + nb_iargs; i++) {
-init_arg_info(infos, _used, op->args[i]);
+init_arg_info(_used, op->args[i]);
 }
 }
 
-- 
2.25.1




[PULL 06/24] tcg: Rename struct tcg_temp_info to TempOptInfo

2021-01-13 Thread Richard Henderson
Fix this name vs our coding style.

Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 2f827a9d2d..0da9750b65 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -35,20 +35,20 @@
 glue(glue(case INDEX_op_, x), _i64):\
 glue(glue(case INDEX_op_, x), _vec)
 
-struct tcg_temp_info {
+typedef struct TempOptInfo {
 bool is_const;
 TCGTemp *prev_copy;
 TCGTemp *next_copy;
 tcg_target_ulong val;
 tcg_target_ulong mask;
-};
+} TempOptInfo;
 
-static inline struct tcg_temp_info *ts_info(TCGTemp *ts)
+static inline TempOptInfo *ts_info(TCGTemp *ts)
 {
 return ts->state_ptr;
 }
 
-static inline struct tcg_temp_info *arg_info(TCGArg arg)
+static inline TempOptInfo *arg_info(TCGArg arg)
 {
 return ts_info(arg_temp(arg));
 }
@@ -71,9 +71,9 @@ static inline bool ts_is_copy(TCGTemp *ts)
 /* Reset TEMP's state, possibly removing the temp for the list of copies.  */
 static void reset_ts(TCGTemp *ts)
 {
-struct tcg_temp_info *ti = ts_info(ts);
-struct tcg_temp_info *pi = ts_info(ti->prev_copy);
-struct tcg_temp_info *ni = ts_info(ti->next_copy);
+TempOptInfo *ti = ts_info(ts);
+TempOptInfo *pi = ts_info(ti->prev_copy);
+TempOptInfo *ni = ts_info(ti->next_copy);
 
 ni->prev_copy = ti->prev_copy;
 pi->next_copy = ti->next_copy;
@@ -89,12 +89,12 @@ static void reset_temp(TCGArg arg)
 }
 
 /* Initialize and activate a temporary.  */
-static void init_ts_info(struct tcg_temp_info *infos,
+static void init_ts_info(TempOptInfo *infos,
  TCGTempSet *temps_used, TCGTemp *ts)
 {
 size_t idx = temp_idx(ts);
 if (!test_bit(idx, temps_used->l)) {
-struct tcg_temp_info *ti = [idx];
+TempOptInfo *ti = [idx];
 
 ts->state_ptr = ti;
 ti->next_copy = ts;
@@ -105,7 +105,7 @@ static void init_ts_info(struct tcg_temp_info *infos,
 }
 }
 
-static void init_arg_info(struct tcg_temp_info *infos,
+static void init_arg_info(TempOptInfo *infos,
   TCGTempSet *temps_used, TCGArg arg)
 {
 init_ts_info(infos, temps_used, arg_temp(arg));
@@ -171,7 +171,7 @@ static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg val)
 const TCGOpDef *def;
 TCGOpcode new_op;
 tcg_target_ulong mask;
-struct tcg_temp_info *di = arg_info(dst);
+TempOptInfo *di = arg_info(dst);
 
 def = _op_defs[op->opc];
 if (def->flags & TCG_OPF_VECTOR) {
@@ -202,8 +202,8 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 TCGTemp *dst_ts = arg_temp(dst);
 TCGTemp *src_ts = arg_temp(src);
 const TCGOpDef *def;
-struct tcg_temp_info *di;
-struct tcg_temp_info *si;
+TempOptInfo *di;
+TempOptInfo *si;
 tcg_target_ulong mask;
 TCGOpcode new_op;
 
@@ -236,7 +236,7 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 di->mask = mask;
 
 if (src_ts->type == dst_ts->type) {
-struct tcg_temp_info *ni = ts_info(si->next_copy);
+TempOptInfo *ni = ts_info(si->next_copy);
 
 di->next_copy = si->next_copy;
 di->prev_copy = src_ts;
@@ -599,7 +599,7 @@ void tcg_optimize(TCGContext *s)
 {
 int nb_temps, nb_globals;
 TCGOp *op, *op_next, *prev_mb = NULL;
-struct tcg_temp_info *infos;
+TempOptInfo *infos;
 TCGTempSet temps_used;
 
 /* Array VALS has an element for each temp.
@@ -610,7 +610,7 @@ void tcg_optimize(TCGContext *s)
 nb_temps = s->nb_temps;
 nb_globals = s->nb_globals;
 bitmap_zero(temps_used.l, nb_temps);
-infos = tcg_malloc(sizeof(struct tcg_temp_info) * nb_temps);
+infos = tcg_malloc(sizeof(TempOptInfo) * nb_temps);
 
 QTAILQ_FOREACH_SAFE(op, >ops, link, op_next) {
 tcg_target_ulong mask, partmask, affected;
-- 
2.25.1




[PULL 23/24] tcg/aarch64: Use tcg_constant_vec with tcg vec expanders

2021-01-13 Thread Richard Henderson
Improve rotrv_vec to reduce "t1 = -v2, t2 = t1 + c" to
"t1 = -v2, t2 = c - v2".  This avoids a serial dependency
between t1 and t2.

Signed-off-by: Richard Henderson 
---
 tcg/aarch64/tcg-target.c.inc | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index e370b7e61c..23954ec7cf 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -2516,7 +2516,7 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece,
TCGArg a0, ...)
 {
 va_list va;
-TCGv_vec v0, v1, v2, t1, t2;
+TCGv_vec v0, v1, v2, t1, t2, c1;
 TCGArg a2;
 
 va_start(va, a0);
@@ -2548,8 +2548,8 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece,
 
 case INDEX_op_rotlv_vec:
 t1 = tcg_temp_new_vec(type);
-tcg_gen_dupi_vec(vece, t1, 8 << vece);
-tcg_gen_sub_vec(vece, t1, v2, t1);
+c1 = tcg_constant_vec(type, vece, 8 << vece);
+tcg_gen_sub_vec(vece, t1, v2, c1);
 /* Right shifts are negative left shifts for AArch64.  */
 vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1),
   tcgv_vec_arg(v1), tcgv_vec_arg(t1));
@@ -2562,9 +2562,9 @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, 
unsigned vece,
 case INDEX_op_rotrv_vec:
 t1 = tcg_temp_new_vec(type);
 t2 = tcg_temp_new_vec(type);
+c1 = tcg_constant_vec(type, vece, 8 << vece);
 tcg_gen_neg_vec(vece, t1, v2);
-tcg_gen_dupi_vec(vece, t2, 8 << vece);
-tcg_gen_add_vec(vece, t2, t1, t2);
+tcg_gen_sub_vec(vece, t2, c1, v2);
 /* Right shifts are negative left shifts for AArch64.  */
 vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1),
   tcgv_vec_arg(v1), tcgv_vec_arg(t1));
-- 
2.25.1




[PULL 15/24] tcg: Use tcg_constant_{i32,i64} with tcg plugins

2021-01-13 Thread Richard Henderson
Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 accel/tcg/plugin-gen.c | 49 +++---
 1 file changed, 22 insertions(+), 27 deletions(-)

diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
index 51580d51a0..e5dc9d0ca9 100644
--- a/accel/tcg/plugin-gen.c
+++ b/accel/tcg/plugin-gen.c
@@ -284,8 +284,8 @@ static TCGOp *copy_extu_i32_i64(TCGOp **begin_op, TCGOp *op)
 if (TCG_TARGET_REG_BITS == 32) {
 /* mov_i32 */
 op = copy_op(begin_op, op, INDEX_op_mov_i32);
-/* movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
+/* mov_i32 w/ $0 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
 } else {
 /* extu_i32_i64 */
 op = copy_op(begin_op, op, INDEX_op_extu_i32_i64);
@@ -306,39 +306,34 @@ static TCGOp *copy_mov_i64(TCGOp **begin_op, TCGOp *op)
 return op;
 }
 
-static TCGOp *copy_movi_i64(TCGOp **begin_op, TCGOp *op, uint64_t v)
-{
-if (TCG_TARGET_REG_BITS == 32) {
-/* 2x movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = v;
-
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = v >> 32;
-} else {
-/* movi_i64 */
-op = copy_op(begin_op, op, INDEX_op_movi_i64);
-op->args[1] = v;
-}
-return op;
-}
-
 static TCGOp *copy_const_ptr(TCGOp **begin_op, TCGOp *op, void *ptr)
 {
 if (UINTPTR_MAX == UINT32_MAX) {
-/* movi_i32 */
-op = copy_op(begin_op, op, INDEX_op_movi_i32);
-op->args[1] = (uintptr_t)ptr;
+/* mov_i32 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32((uintptr_t)ptr));
 } else {
-/* movi_i64 */
-op = copy_movi_i64(begin_op, op, (uint64_t)(uintptr_t)ptr);
+/* mov_i64 */
+op = copy_op(begin_op, op, INDEX_op_mov_i64);
+op->args[1] = tcgv_i64_arg(tcg_constant_i64((uintptr_t)ptr));
 }
 return op;
 }
 
 static TCGOp *copy_const_i64(TCGOp **begin_op, TCGOp *op, uint64_t v)
 {
-return copy_movi_i64(begin_op, op, v);
+if (TCG_TARGET_REG_BITS == 32) {
+/* 2x mov_i32 */
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32(v));
+op = copy_op(begin_op, op, INDEX_op_mov_i32);
+op->args[1] = tcgv_i32_arg(tcg_constant_i32(v >> 32));
+} else {
+/* mov_i64 */
+op = copy_op(begin_op, op, INDEX_op_mov_i64);
+op->args[1] = tcgv_i64_arg(tcg_constant_i64(v));
+}
+return op;
 }
 
 static TCGOp *copy_extu_tl_i64(TCGOp **begin_op, TCGOp *op)
@@ -486,8 +481,8 @@ static TCGOp *append_mem_cb(const struct qemu_plugin_dyn_cb 
*cb,
 
 tcg_debug_assert(type == PLUGIN_GEN_CB_MEM);
 
-/* const_i32 == movi_i32 ("info", so it remains as is) */
-op = copy_op(_op, op, INDEX_op_movi_i32);
+/* const_i32 == mov_i32 ("info", so it remains as is) */
+op = copy_op(_op, op, INDEX_op_mov_i32);
 
 /* const_ptr */
 op = copy_const_ptr(_op, op, cb->userp);
-- 
2.25.1




[PULL 09/24] tcg/optimize: Improve find_better_copy

2021-01-13 Thread Richard Henderson
Prefer TEMP_CONST over anything else.

Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 27 ---
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 16b0aa7229..e42f9c89a8 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -122,31 +122,28 @@ static void init_arg_info(TempOptInfo *infos,
 
 static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
 {
-TCGTemp *i;
+TCGTemp *i, *g, *l;
 
-/* If this is already a global, we can't do better. */
-if (ts->kind >= TEMP_GLOBAL) {
+/* If this is already readonly, we can't do better. */
+if (temp_readonly(ts)) {
 return ts;
 }
 
-/* Search for a global first. */
+g = l = NULL;
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->kind >= TEMP_GLOBAL) {
+if (temp_readonly(i)) {
 return i;
-}
-}
-
-/* If it is a temp, search for a temp local. */
-if (ts->kind == TEMP_NORMAL) {
-for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->kind >= TEMP_LOCAL) {
-return i;
+} else if (i->kind > ts->kind) {
+if (i->kind == TEMP_GLOBAL) {
+g = i;
+} else if (i->kind == TEMP_LOCAL) {
+l = i;
 }
 }
 }
 
-/* Failure to find a better representation, return the same temp. */
-return ts;
+/* If we didn't find a better representation, return the same temp. */
+return g ? g : l ? l : ts;
 }
 
 static bool ts_are_copies(TCGTemp *ts1, TCGTemp *ts2)
-- 
2.25.1




[PULL 05/24] tcg: Expand TCGTemp.val to 64-bits

2021-01-13 Thread Richard Henderson
This will reduce the differences between 32-bit and 64-bit hosts,
allowing full 64-bit constants to be created with the same interface.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h | 2 +-
 tcg/tcg.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 2bdaeaa69c..e7adc7e265 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -506,7 +506,7 @@ typedef struct TCGTemp {
 unsigned int mem_allocated:1;
 unsigned int temp_allocated:1;
 
-tcg_target_long val;
+int64_t val;
 struct TCGTemp *mem_base;
 intptr_t mem_offset;
 const char *name;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index e02bb71953..545dd2b0b2 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3176,7 +3176,7 @@ static void dump_regs(TCGContext *s)
tcg_target_reg_names[ts->mem_base->reg]);
 break;
 case TEMP_VAL_CONST:
-printf("$0x%" TCG_PRIlx, ts->val);
+printf("$0x%" PRIx64, ts->val);
 break;
 case TEMP_VAL_DEAD:
 printf("D");
-- 
2.25.1




[PULL 08/24] tcg: Introduce TYPE_CONST temporaries

2021-01-13 Thread Richard Henderson
These will hold a single constant for the duration of the TB.
They are hashed, so that each value has one temp across the TB.

Not used yet, this is all infrastructure.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  24 -
 tcg/optimize.c|  13 ++-
 tcg/tcg.c | 224 --
 3 files changed, 211 insertions(+), 50 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index e7adc7e265..eeeb70ad43 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -492,6 +492,8 @@ typedef enum TCGTempKind {
 TEMP_GLOBAL,
 /* Temp is in a fixed register. */
 TEMP_FIXED,
+/* Temp is a fixed constant. */
+TEMP_CONST,
 } TCGTempKind;
 
 typedef struct TCGTemp {
@@ -665,6 +667,7 @@ struct TCGContext {
 QSIMPLEQ_HEAD(, TCGOp) plugin_ops;
 #endif
 
+GHashTable *const_table[TCG_TYPE_COUNT];
 TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
 TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
 
@@ -681,7 +684,7 @@ struct TCGContext {
 
 static inline bool temp_readonly(TCGTemp *ts)
 {
-return ts->kind == TEMP_FIXED;
+return ts->kind >= TEMP_FIXED;
 }
 
 extern TCGContext tcg_init_ctx;
@@ -1079,6 +1082,7 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, 
TCGOpcode opc);
 
 void tcg_optimize(TCGContext *s);
 
+/* Allocate a new temporary and initialize it with a constant. */
 TCGv_i32 tcg_const_i32(int32_t val);
 TCGv_i64 tcg_const_i64(int64_t val);
 TCGv_i32 tcg_const_local_i32(int32_t val);
@@ -1088,6 +1092,24 @@ TCGv_vec tcg_const_ones_vec(TCGType);
 TCGv_vec tcg_const_zeros_vec_matching(TCGv_vec);
 TCGv_vec tcg_const_ones_vec_matching(TCGv_vec);
 
+/*
+ * Locate or create a read-only temporary that is a constant.
+ * This kind of temporary need not and should not be freed.
+ */
+TCGTemp *tcg_constant_internal(TCGType type, int64_t val);
+
+static inline TCGv_i32 tcg_constant_i32(int32_t val)
+{
+return temp_tcgv_i32(tcg_constant_internal(TCG_TYPE_I32, val));
+}
+
+static inline TCGv_i64 tcg_constant_i64(int64_t val)
+{
+return temp_tcgv_i64(tcg_constant_internal(TCG_TYPE_I64, val));
+}
+
+TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val);
+
 #if UINTPTR_MAX == UINT32_MAX
 # define tcg_const_ptr(x)((TCGv_ptr)tcg_const_i32((intptr_t)(x)))
 # define tcg_const_local_ptr(x)  ((TCGv_ptr)tcg_const_local_i32((intptr_t)(x)))
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 433d2540f4..16b0aa7229 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -99,8 +99,17 @@ static void init_ts_info(TempOptInfo *infos,
 ts->state_ptr = ti;
 ti->next_copy = ts;
 ti->prev_copy = ts;
-ti->is_const = false;
-ti->mask = -1;
+if (ts->kind == TEMP_CONST) {
+ti->is_const = true;
+ti->val = ti->mask = ts->val;
+if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
+/* High bits of a 32-bit quantity are garbage.  */
+ti->mask |= ~0xull;
+}
+} else {
+ti->is_const = false;
+ti->mask = -1;
+}
 set_bit(idx, temps_used->l);
 }
 }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 545dd2b0b2..802f0b8a32 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1184,6 +1184,13 @@ void tcg_func_start(TCGContext *s)
 /* No temps have been previously allocated for size or locality.  */
 memset(s->free_temps, 0, sizeof(s->free_temps));
 
+/* No constant temps have been previously allocated. */
+for (int i = 0; i < TCG_TYPE_COUNT; ++i) {
+if (s->const_table[i]) {
+g_hash_table_remove_all(s->const_table[i]);
+}
+}
+
 s->nb_ops = 0;
 s->nb_labels = 0;
 s->current_frame_offset = s->frame_start;
@@ -1255,13 +1262,19 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 bigendian = 1;
 #endif
 
-if (base_ts->kind != TEMP_FIXED) {
+switch (base_ts->kind) {
+case TEMP_FIXED:
+break;
+case TEMP_GLOBAL:
 /* We do not support double-indirect registers.  */
 tcg_debug_assert(!base_ts->indirect_reg);
 base_ts->indirect_base = 1;
 s->nb_indirects += (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64
 ? 2 : 1);
 indirect_reg = 1;
+break;
+default:
+g_assert_not_reached();
 }
 
 if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
@@ -1386,6 +1399,11 @@ void tcg_temp_free_internal(TCGTemp *ts)
 TCGContext *s = tcg_ctx;
 int k, idx;
 
+/* In order to simplify users of tcg_constant_*, silently ignore free. */
+if (ts->kind == TEMP_CONST) {
+return;
+}
+
 #if defined(CONFIG_DEBUG_TCG)
 s->temps_in_use--;
 if (s->temps_in_use < 0) {
@@ -1402,6 +1420,60 @@ void tcg_temp_free_internal(TCGTemp *ts)
 set_bit(idx, s->free_temps[k].l);
 }
 
+TCGTemp *tcg_constant_internal(TCGType type, int64_t val)
+{
+TCGContext *s = 

[PULL 16/24] tcg: Use tcg_constant_{i32,i64,vec} with gvec expanders

2021-01-13 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |   1 +
 tcg/tcg-op-gvec.c | 129 ++
 tcg/tcg.c |   8 +++
 3 files changed, 60 insertions(+), 78 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index eeeb70ad43..504c5e9bb0 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -1109,6 +1109,7 @@ static inline TCGv_i64 tcg_constant_i64(int64_t val)
 }
 
 TCGv_vec tcg_constant_vec(TCGType type, unsigned vece, int64_t val);
+TCGv_vec tcg_constant_vec_matching(TCGv_vec match, unsigned vece, int64_t val);
 
 #if UINTPTR_MAX == UINT32_MAX
 # define tcg_const_ptr(x)((TCGv_ptr)tcg_const_i32((intptr_t)(x)))
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index 1a41dfa908..498a959839 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -115,7 +115,7 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
 gen_helper_gvec_2 *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -127,7 +127,6 @@ void tcg_gen_gvec_2_ool(uint32_t dofs, uint32_t aofs,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with two vector operands
@@ -137,7 +136,7 @@ void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, 
TCGv_i64 c,
  gen_helper_gvec_2i *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -149,7 +148,6 @@ void tcg_gen_gvec_2i_ool(uint32_t dofs, uint32_t aofs, 
TCGv_i64 c,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands.  */
@@ -158,7 +156,7 @@ void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 gen_helper_gvec_3 *fn)
 {
 TCGv_ptr a0, a1, a2;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -173,7 +171,6 @@ void tcg_gen_gvec_3_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
 tcg_temp_free_ptr(a2);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with four vector operands.  */
@@ -182,7 +179,7 @@ void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 int32_t data, gen_helper_gvec_4 *fn)
 {
 TCGv_ptr a0, a1, a2, a3;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -200,7 +197,6 @@ void tcg_gen_gvec_4_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a1);
 tcg_temp_free_ptr(a2);
 tcg_temp_free_ptr(a3);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with five vector operands.  */
@@ -209,7 +205,7 @@ void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 uint32_t maxsz, int32_t data, gen_helper_gvec_5 *fn)
 {
 TCGv_ptr a0, a1, a2, a3, a4;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -230,7 +226,6 @@ void tcg_gen_gvec_5_ool(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 tcg_temp_free_ptr(a2);
 tcg_temp_free_ptr(a3);
 tcg_temp_free_ptr(a4);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands
@@ -240,7 +235,7 @@ void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
 int32_t data, gen_helper_gvec_2_ptr *fn)
 {
 TCGv_ptr a0, a1;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = tcg_temp_new_ptr();
@@ -252,7 +247,6 @@ void tcg_gen_gvec_2_ptr(uint32_t dofs, uint32_t aofs,
 
 tcg_temp_free_ptr(a0);
 tcg_temp_free_ptr(a1);
-tcg_temp_free_i32(desc);
 }
 
 /* Generate a call to a gvec-style helper with three vector operands
@@ -262,7 +256,7 @@ void tcg_gen_gvec_3_ptr(uint32_t dofs, uint32_t aofs, 
uint32_t bofs,
 int32_t data, gen_helper_gvec_3_ptr *fn)
 {
 TCGv_ptr a0, a1, a2;
-TCGv_i32 desc = tcg_const_i32(simd_desc(oprsz, maxsz, data));
+TCGv_i32 desc = tcg_constant_i32(simd_desc(oprsz, maxsz, data));
 
 a0 = tcg_temp_new_ptr();
 a1 = 

[PULL 07/24] tcg: Expand TempOptInfo to 64-bits

2021-01-13 Thread Richard Henderson
This propagates the extended value of TCGTemp.val that we did before.
In addition, it will be required for vector constants.

Signed-off-by: Richard Henderson 
---
 tcg/optimize.c | 40 +---
 1 file changed, 21 insertions(+), 19 deletions(-)

diff --git a/tcg/optimize.c b/tcg/optimize.c
index 0da9750b65..433d2540f4 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -39,8 +39,8 @@ typedef struct TempOptInfo {
 bool is_const;
 TCGTemp *prev_copy;
 TCGTemp *next_copy;
-tcg_target_ulong val;
-tcg_target_ulong mask;
+uint64_t val;
+uint64_t mask;
 } TempOptInfo;
 
 static inline TempOptInfo *ts_info(TCGTemp *ts)
@@ -166,11 +166,11 @@ static bool args_are_copies(TCGArg arg1, TCGArg arg2)
 return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
 }
 
-static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg val)
+static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, uint64_t 
val)
 {
 const TCGOpDef *def;
 TCGOpcode new_op;
-tcg_target_ulong mask;
+uint64_t mask;
 TempOptInfo *di = arg_info(dst);
 
 def = _op_defs[op->opc];
@@ -204,7 +204,7 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 const TCGOpDef *def;
 TempOptInfo *di;
 TempOptInfo *si;
-tcg_target_ulong mask;
+uint64_t mask;
 TCGOpcode new_op;
 
 if (ts_are_copies(dst_ts, src_ts)) {
@@ -247,7 +247,7 @@ static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, 
TCGArg dst, TCGArg src)
 }
 }
 
-static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
+static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
 {
 uint64_t l64, h64;
 
@@ -410,10 +410,10 @@ static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg 
x, TCGArg y)
 }
 }
 
-static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
+static uint64_t do_constant_folding(TCGOpcode op, uint64_t x, uint64_t y)
 {
 const TCGOpDef *def = _op_defs[op];
-TCGArg res = do_constant_folding_2(op, x, y);
+uint64_t res = do_constant_folding_2(op, x, y);
 if (!(def->flags & TCG_OPF_64BIT)) {
 res = (int32_t)res;
 }
@@ -501,8 +501,9 @@ static bool do_constant_folding_cond_eq(TCGCond c)
 static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
TCGArg y, TCGCond c)
 {
-tcg_target_ulong xv = arg_info(x)->val;
-tcg_target_ulong yv = arg_info(y)->val;
+uint64_t xv = arg_info(x)->val;
+uint64_t yv = arg_info(y)->val;
+
 if (arg_is_const(x) && arg_is_const(y)) {
 const TCGOpDef *def = _op_defs[op];
 tcg_debug_assert(!(def->flags & TCG_OPF_VECTOR));
@@ -613,9 +614,8 @@ void tcg_optimize(TCGContext *s)
 infos = tcg_malloc(sizeof(TempOptInfo) * nb_temps);
 
 QTAILQ_FOREACH_SAFE(op, >ops, link, op_next) {
-tcg_target_ulong mask, partmask, affected;
+uint64_t mask, partmask, affected, tmp;
 int nb_oargs, nb_iargs, i;
-TCGArg tmp;
 TCGOpcode opc = op->opc;
 const TCGOpDef *def = _op_defs[opc];
 
@@ -1225,14 +1225,15 @@ void tcg_optimize(TCGContext *s)
 
 CASE_OP_32_64(extract2):
 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
-TCGArg v1 = arg_info(op->args[1])->val;
-TCGArg v2 = arg_info(op->args[2])->val;
+uint64_t v1 = arg_info(op->args[1])->val;
+uint64_t v2 = arg_info(op->args[2])->val;
+int shr = op->args[3];
 
 if (opc == INDEX_op_extract2_i64) {
-tmp = (v1 >> op->args[3]) | (v2 << (64 - op->args[3]));
+tmp = (v1 >> shr) | (v2 << (64 - shr));
 } else {
-tmp = (int32_t)(((uint32_t)v1 >> op->args[3]) |
-((uint32_t)v2 << (32 - op->args[3])));
+tmp = (int32_t)(((uint32_t)v1 >> shr) |
+((uint32_t)v2 << (32 - shr)));
 }
 tcg_opt_gen_movi(s, op, op->args[0], tmp);
 break;
@@ -1271,9 +1272,10 @@ void tcg_optimize(TCGContext *s)
 break;
 }
 if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) {
-tcg_target_ulong tv = arg_info(op->args[3])->val;
-tcg_target_ulong fv = arg_info(op->args[4])->val;
+uint64_t tv = arg_info(op->args[3])->val;
+uint64_t fv = arg_info(op->args[4])->val;
 TCGCond cond = op->args[5];
+
 if (fv == 1 && tv == 0) {
 cond = tcg_invert_cond(cond);
 } else if (!(tv == 1 && fv == 0)) {
-- 
2.25.1




[PULL 04/24] tcg: Add temp_readonly

2021-01-13 Thread Richard Henderson
In most, but not all, places that we check for TEMP_FIXED,
we are really testing that we do not modify the temporary.

Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  5 +
 tcg/tcg.c | 21 ++---
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 571d4e0fa3..2bdaeaa69c 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -679,6 +679,11 @@ struct TCGContext {
 target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
 };
 
+static inline bool temp_readonly(TCGTemp *ts)
+{
+return ts->kind == TEMP_FIXED;
+}
+
 extern TCGContext tcg_init_ctx;
 extern __thread TCGContext *tcg_ctx;
 extern const void *tcg_code_gen_epilogue;
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 143794a585..e02bb71953 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3254,7 +3254,7 @@ static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, 
TCGRegSet, TCGRegSet);
mark it free; otherwise mark it dead.  */
 static void temp_free_or_dead(TCGContext *s, TCGTemp *ts, int free_or_dead)
 {
-if (ts->kind == TEMP_FIXED) {
+if (temp_readonly(ts)) {
 return;
 }
 if (ts->val_type == TEMP_VAL_REG) {
@@ -3278,7 +3278,7 @@ static inline void temp_dead(TCGContext *s, TCGTemp *ts)
 static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs,
   TCGRegSet preferred_regs, int free_or_dead)
 {
-if (ts->kind == TEMP_FIXED) {
+if (temp_readonly(ts)) {
 return;
 }
 if (!ts->mem_coherent) {
@@ -3461,8 +3461,7 @@ static void temp_save(TCGContext *s, TCGTemp *ts, 
TCGRegSet allocated_regs)
 {
 /* The liveness analysis already ensures that globals are back
in memory. Keep an tcg_debug_assert for safety. */
-tcg_debug_assert(ts->val_type == TEMP_VAL_MEM
- || ts->kind == TEMP_FIXED);
+tcg_debug_assert(ts->val_type == TEMP_VAL_MEM || temp_readonly(ts));
 }
 
 /* save globals to their canonical location and assume they can be
@@ -3542,7 +3541,7 @@ static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp 
*ots,
   TCGRegSet preferred_regs)
 {
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 /* The movi is not explicitly generated here.  */
 if (ots->val_type == TEMP_VAL_REG) {
@@ -3582,7 +3581,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(op->args[1]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 /* Note that otype != itype for no-op truncation.  */
 otype = ots->type;
@@ -3643,7 +3642,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOp 
*op)
  * Store the source register into the destination slot
  * and leave the destination temp as TEMP_VAL_MEM.
  */
-assert(ots->kind != TEMP_FIXED);
+assert(!temp_readonly(ots));
 if (!ts->mem_allocated) {
 temp_allocate_frame(s, ots);
 }
@@ -3680,7 +3679,7 @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp 
*op)
 its = arg_temp(op->args[1]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ots->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ots));
 
 itype = its->type;
 vece = TCGOP_VECE(op);
@@ -3912,7 +3911,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(arg);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 if (arg_ct->oalias && !const_args[arg_ct->alias_index]) {
 reg = new_args[arg_ct->alias_index];
@@ -3953,7 +3952,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp 
*op)
 ts = arg_temp(op->args[i]);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 if (NEED_SYNC_ARG(i)) {
 temp_sync(s, ts, o_allocated_regs, 0, IS_DEAD_ARG(i));
@@ -4085,7 +4084,7 @@ static void tcg_reg_alloc_call(TCGContext *s, TCGOp *op)
 ts = arg_temp(arg);
 
 /* ENV should not be modified.  */
-tcg_debug_assert(ts->kind != TEMP_FIXED);
+tcg_debug_assert(!temp_readonly(ts));
 
 reg = tcg_target_call_oarg_regs[i];
 tcg_debug_assert(s->reg_to_temp[reg] == NULL);
-- 
2.25.1




[PULL 03/24] tcg: Consolidate 3 bits into enum TCGTempKind

2021-01-13 Thread Richard Henderson
The temp_fixed, temp_global, temp_local bits are all related.
Combine them into a single enumeration.

Reviewed-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg.h |  20 +---
 tcg/optimize.c|   8 +--
 tcg/tcg.c | 126 --
 3 files changed, 92 insertions(+), 62 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 95fe5604eb..571d4e0fa3 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -483,23 +483,27 @@ typedef enum TCGTempVal {
 TEMP_VAL_CONST,
 } TCGTempVal;
 
+typedef enum TCGTempKind {
+/* Temp is dead at the end of all basic blocks. */
+TEMP_NORMAL,
+/* Temp is saved across basic blocks but dead at the end of TBs. */
+TEMP_LOCAL,
+/* Temp is saved across both basic blocks and translation blocks. */
+TEMP_GLOBAL,
+/* Temp is in a fixed register. */
+TEMP_FIXED,
+} TCGTempKind;
+
 typedef struct TCGTemp {
 TCGReg reg:8;
 TCGTempVal val_type:8;
 TCGType base_type:8;
 TCGType type:8;
-unsigned int fixed_reg:1;
+TCGTempKind kind:3;
 unsigned int indirect_reg:1;
 unsigned int indirect_base:1;
 unsigned int mem_coherent:1;
 unsigned int mem_allocated:1;
-/* If true, the temp is saved across both basic blocks and
-   translation blocks.  */
-unsigned int temp_global:1;
-/* If true, the temp is saved across basic blocks but dead
-   at the end of translation blocks.  If false, the temp is
-   dead at the end of basic blocks.  */
-unsigned int temp_local:1;
 unsigned int temp_allocated:1;
 
 tcg_target_long val;
diff --git a/tcg/optimize.c b/tcg/optimize.c
index 1fb42eb2a9..2f827a9d2d 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -116,21 +116,21 @@ static TCGTemp *find_better_copy(TCGContext *s, TCGTemp 
*ts)
 TCGTemp *i;
 
 /* If this is already a global, we can't do better. */
-if (ts->temp_global) {
+if (ts->kind >= TEMP_GLOBAL) {
 return ts;
 }
 
 /* Search for a global first. */
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (i->temp_global) {
+if (i->kind >= TEMP_GLOBAL) {
 return i;
 }
 }
 
 /* If it is a temp, search for a temp local. */
-if (!ts->temp_local) {
+if (ts->kind == TEMP_NORMAL) {
 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
-if (ts->temp_local) {
+if (i->kind >= TEMP_LOCAL) {
 return i;
 }
 }
diff --git a/tcg/tcg.c b/tcg/tcg.c
index c73128208c..143794a585 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1211,7 +1211,7 @@ static inline TCGTemp *tcg_global_alloc(TCGContext *s)
 tcg_debug_assert(s->nb_globals == s->nb_temps);
 s->nb_globals++;
 ts = tcg_temp_alloc(s);
-ts->temp_global = 1;
+ts->kind = TEMP_GLOBAL;
 
 return ts;
 }
@@ -1228,7 +1228,7 @@ static TCGTemp *tcg_global_reg_new_internal(TCGContext 
*s, TCGType type,
 ts = tcg_global_alloc(s);
 ts->base_type = type;
 ts->type = type;
-ts->fixed_reg = 1;
+ts->kind = TEMP_FIXED;
 ts->reg = reg;
 ts->name = name;
 tcg_regset_set_reg(s->reserved_regs, reg);
@@ -1255,7 +1255,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 bigendian = 1;
 #endif
 
-if (!base_ts->fixed_reg) {
+if (base_ts->kind != TEMP_FIXED) {
 /* We do not support double-indirect registers.  */
 tcg_debug_assert(!base_ts->indirect_reg);
 base_ts->indirect_base = 1;
@@ -1303,6 +1303,7 @@ TCGTemp *tcg_global_mem_new_internal(TCGType type, 
TCGv_ptr base,
 TCGTemp *tcg_temp_new_internal(TCGType type, bool temp_local)
 {
 TCGContext *s = tcg_ctx;
+TCGTempKind kind = temp_local ? TEMP_LOCAL : TEMP_NORMAL;
 TCGTemp *ts;
 int idx, k;
 
@@ -1315,7 +1316,7 @@ TCGTemp *tcg_temp_new_internal(TCGType type, bool 
temp_local)
 ts = >temps[idx];
 ts->temp_allocated = 1;
 tcg_debug_assert(ts->base_type == type);
-tcg_debug_assert(ts->temp_local == temp_local);
+tcg_debug_assert(ts->kind == kind);
 } else {
 ts = tcg_temp_alloc(s);
 if (TCG_TARGET_REG_BITS == 32 && type == TCG_TYPE_I64) {
@@ -1324,18 +1325,18 @@ TCGTemp *tcg_temp_new_internal(TCGType type, bool 
temp_local)
 ts->base_type = type;
 ts->type = TCG_TYPE_I32;
 ts->temp_allocated = 1;
-ts->temp_local = temp_local;
+ts->kind = kind;
 
 tcg_debug_assert(ts2 == ts + 1);
 ts2->base_type = TCG_TYPE_I64;
 ts2->type = TCG_TYPE_I32;
 ts2->temp_allocated = 1;
-ts2->temp_local = temp_local;
+ts2->kind = kind;
 } else {
 ts->base_type = type;
 ts->type = type;
 ts->temp_allocated = 1;
-ts->temp_local = 

[PULL 02/24] tcg: Increase tcg_out_dupi_vec immediate to int64_t

2021-01-13 Thread Richard Henderson
While we don't store more than tcg_target_long in TCGTemp,
we shouldn't be limited to that for code generation.  We will
be able to use this for INDEX_op_dup2_vec with 2 constants.

Also pass along the minimal vece that may be said to apply
to the constant.  This allows some simplification in the
various backends.

Signed-off-by: Richard Henderson 
---
 tcg/tcg.c| 31 +-
 tcg/aarch64/tcg-target.c.inc | 12 ++--
 tcg/i386/tcg-target.c.inc| 22 -
 tcg/ppc/tcg-target.c.inc | 37 +++-
 4 files changed, 69 insertions(+), 33 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index ded3c928e3..c73128208c 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -117,8 +117,8 @@ static bool tcg_out_dup_vec(TCGContext *s, TCGType type, 
unsigned vece,
 TCGReg dst, TCGReg src);
 static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
  TCGReg dst, TCGReg base, intptr_t offset);
-static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
- TCGReg dst, tcg_target_long arg);
+static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
+ TCGReg dst, int64_t arg);
 static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, unsigned vecl,
unsigned vece, const TCGArg *args,
const int *const_args);
@@ -133,8 +133,8 @@ static inline bool tcg_out_dupm_vec(TCGContext *s, TCGType 
type, unsigned vece,
 {
 g_assert_not_reached();
 }
-static inline void tcg_out_dupi_vec(TCGContext *s, TCGType type,
-TCGReg dst, tcg_target_long arg)
+static inline void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
+TCGReg dst, int64_t arg)
 {
 g_assert_not_reached();
 }
@@ -3390,7 +3390,28 @@ static void temp_load(TCGContext *s, TCGTemp *ts, 
TCGRegSet desired_regs,
 if (ts->type <= TCG_TYPE_I64) {
 tcg_out_movi(s, ts->type, reg, ts->val);
 } else {
-tcg_out_dupi_vec(s, ts->type, reg, ts->val);
+uint64_t val = ts->val;
+MemOp vece = MO_64;
+
+/*
+ * Find the minimal vector element that matches the constant.
+ * The targets will, in general, have to do this search anyway,
+ * do this generically.
+ */
+if (TCG_TARGET_REG_BITS == 32) {
+val = dup_const(MO_32, val);
+vece = MO_32;
+}
+if (val == dup_const(MO_8, val)) {
+vece = MO_8;
+} else if (val == dup_const(MO_16, val)) {
+vece = MO_16;
+} else if (TCG_TARGET_REG_BITS == 64 &&
+   val == dup_const(MO_32, val)) {
+vece = MO_32;
+}
+
+tcg_out_dupi_vec(s, ts->type, vece, reg, ts->val);
 }
 ts->mem_coherent = 0;
 break;
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index a2a588e3aa..be6d3ea2a8 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -857,14 +857,14 @@ static void tcg_out_logicali(TCGContext *s, AArch64Insn 
insn, TCGType ext,
 tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c);
 }
 
-static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
- TCGReg rd, tcg_target_long v64)
+static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
+ TCGReg rd, int64_t v64)
 {
 bool q = type == TCG_TYPE_V128;
 int cmode, imm8, i;
 
 /* Test all bytes equal first.  */
-if (v64 == dup_const(MO_8, v64)) {
+if (vece == MO_8) {
 imm8 = (uint8_t)v64;
 tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0xe, imm8);
 return;
@@ -891,7 +891,7 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
  * cannot find an expansion there's no point checking a larger
  * width because we already know by replication it cannot match.
  */
-if (v64 == dup_const(MO_16, v64)) {
+if (vece == MO_16) {
 uint16_t v16 = v64;
 
 if (is_shimm16(v16, , )) {
@@ -910,7 +910,7 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
 tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0x8, v16 & 0xff);
 tcg_out_insn(s, 3606, ORR, q, rd, 0, 0xa, v16 >> 8);
 return;
-} else if (v64 == dup_const(MO_32, v64)) {
+} else if (vece == MO_32) {
 uint32_t v32 = v64;
 uint32_t n32 = ~v32;
 
@@ -2435,7 +2435,7 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
 tcg_out_insn_3617(s, insn, is_q, vece, a0, a1);
 break;
 }
-tcg_out_dupi_vec(s, type, TCG_VEC_TMP, 0);
+tcg_out_dupi_vec(s, type, MO_8, 

[PULL 01/24] tcg: Use tcg_out_dupi_vec from temp_load

2021-01-13 Thread Richard Henderson
Having dupi pass though movi is confusing and arguably wrong.

Reviewed-by: Alex Bennée 
Signed-off-by: Richard Henderson 
---
 tcg/tcg.c|  6 +++-
 tcg/aarch64/tcg-target.c.inc |  7 
 tcg/i386/tcg-target.c.inc| 63 
 tcg/ppc/tcg-target.c.inc |  6 
 4 files changed, 47 insertions(+), 35 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 472bf1755b..ded3c928e3 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -3387,7 +3387,11 @@ static void temp_load(TCGContext *s, TCGTemp *ts, 
TCGRegSet desired_regs,
 case TEMP_VAL_CONST:
 reg = tcg_reg_alloc(s, desired_regs, allocated_regs,
 preferred_regs, ts->indirect_base);
-tcg_out_movi(s, ts->type, reg, ts->val);
+if (ts->type <= TCG_TYPE_I64) {
+tcg_out_movi(s, ts->type, reg, ts->val);
+} else {
+tcg_out_dupi_vec(s, ts->type, reg, ts->val);
+}
 ts->mem_coherent = 0;
 break;
 case TEMP_VAL_MEM:
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index ab199b143f..a2a588e3aa 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -1011,13 +1011,6 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
TCGReg rd,
 case TCG_TYPE_I64:
 tcg_debug_assert(rd < 32);
 break;
-
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-tcg_debug_assert(rd >= 32);
-tcg_out_dupi_vec(s, type, rd, value);
-return;
-
 default:
 g_assert_not_reached();
 }
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 46e856f442..35554fd1e8 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -975,30 +975,32 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
 }
 }
 
-static void tcg_out_movi(TCGContext *s, TCGType type,
- TCGReg ret, tcg_target_long arg)
+static void tcg_out_movi_vec(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
+{
+if (arg == 0) {
+tcg_out_vex_modrm(s, OPC_PXOR, ret, ret, ret);
+return;
+}
+if (arg == -1) {
+tcg_out_vex_modrm(s, OPC_PCMPEQB, ret, ret, ret);
+return;
+}
+
+int rexw = (type == TCG_TYPE_I32 ? 0 : P_REXW);
+tcg_out_vex_modrm_pool(s, OPC_MOVD_VyEy + rexw, ret);
+if (TCG_TARGET_REG_BITS == 64) {
+new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4);
+} else {
+new_pool_label(s, arg, R_386_32, s->code_ptr - 4, 0);
+}
+}
+
+static void tcg_out_movi_int(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
 {
 tcg_target_long diff;
 
-switch (type) {
-case TCG_TYPE_I32:
-#if TCG_TARGET_REG_BITS == 64
-case TCG_TYPE_I64:
-#endif
-if (ret < 16) {
-break;
-}
-/* fallthru */
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-case TCG_TYPE_V256:
-tcg_debug_assert(ret >= 16);
-tcg_out_dupi_vec(s, type, ret, arg);
-return;
-default:
-g_assert_not_reached();
-}
-
 if (arg == 0) {
 tgen_arithr(s, ARITH_XOR, ret, ret);
 return;
@@ -1027,6 +1029,25 @@ static void tcg_out_movi(TCGContext *s, TCGType type,
 tcg_out64(s, arg);
 }
 
+static void tcg_out_movi(TCGContext *s, TCGType type,
+ TCGReg ret, tcg_target_long arg)
+{
+switch (type) {
+case TCG_TYPE_I32:
+#if TCG_TARGET_REG_BITS == 64
+case TCG_TYPE_I64:
+#endif
+if (ret < 16) {
+tcg_out_movi_int(s, type, ret, arg);
+} else {
+tcg_out_movi_vec(s, type, ret, arg);
+}
+break;
+default:
+g_assert_not_reached();
+}
+}
+
 static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
 {
 if (val == (int8_t)val) {
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 19a4a12f15..a3f1bd41cd 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -987,12 +987,6 @@ static void tcg_out_movi(TCGContext *s, TCGType type, 
TCGReg ret,
 tcg_out_movi_int(s, type, ret, arg, false);
 break;
 
-case TCG_TYPE_V64:
-case TCG_TYPE_V128:
-tcg_debug_assert(ret >= TCG_REG_V0);
-tcg_out_dupi_vec(s, type, ret, arg);
-break;
-
 default:
 g_assert_not_reached();
 }
-- 
2.25.1




[PULL 00/24] tcg patch queue

2021-01-13 Thread Richard Henderson
The following changes since commit 45240eed4f064576d589ea60ebadf3c11d7ab891:

  Merge remote-tracking branch 'remotes/armbru/tags/pull-yank-2021-01-13' into 
staging (2021-01-13 14:19:24 +)

are available in the Git repository at:

  https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20210113

for you to fetch changes up to 4cacecaaa2bbf8af0967bd3eee43297fada475a9:

  decodetree: Open files with encoding='utf-8' (2021-01-13 08:39:08 -1000)


Improvements to tcg constant handling.
Force utf8 for decodetree.


Philippe Mathieu-Daudé (1):
  decodetree: Open files with encoding='utf-8'

Richard Henderson (23):
  tcg: Use tcg_out_dupi_vec from temp_load
  tcg: Increase tcg_out_dupi_vec immediate to int64_t
  tcg: Consolidate 3 bits into enum TCGTempKind
  tcg: Add temp_readonly
  tcg: Expand TCGTemp.val to 64-bits
  tcg: Rename struct tcg_temp_info to TempOptInfo
  tcg: Expand TempOptInfo to 64-bits
  tcg: Introduce TYPE_CONST temporaries
  tcg/optimize: Improve find_better_copy
  tcg/optimize: Adjust TempOptInfo allocation
  tcg/optimize: Use tcg_constant_internal with constant folding
  tcg: Convert tcg_gen_dupi_vec to TCG_CONST
  tcg: Use tcg_constant_i32 with icount expander
  tcg: Use tcg_constant_{i32,i64} with tcg int expanders
  tcg: Use tcg_constant_{i32,i64} with tcg plugins
  tcg: Use tcg_constant_{i32,i64,vec} with gvec expanders
  tcg/tci: Add special tci_movi_{i32,i64} opcodes
  tcg: Remove movi and dupi opcodes
  tcg: Add tcg_reg_alloc_dup2
  tcg/i386: Use tcg_constant_vec with tcg vec expanders
  tcg: Remove tcg_gen_dup{8,16,32,64}i_vec
  tcg/ppc: Use tcg_constant_vec with tcg vec expanders
  tcg/aarch64: Use tcg_constant_vec with tcg vec expanders

 include/exec/gen-icount.h|  25 +--
 include/tcg/tcg-op.h |  17 +-
 include/tcg/tcg-opc.h|  11 +-
 include/tcg/tcg.h|  50 -
 accel/tcg/plugin-gen.c   |  49 ++---
 tcg/optimize.c   | 249 +++---
 tcg/tcg-op-gvec.c| 129 +---
 tcg/tcg-op-vec.c |  52 +
 tcg/tcg-op.c | 227 ++--
 tcg/tcg.c| 488 +--
 tcg/tci.c|   4 +-
 tcg/aarch64/tcg-target.c.inc |  32 +--
 tcg/arm/tcg-target.c.inc |   1 -
 tcg/i386/tcg-target.c.inc| 112 ++
 tcg/mips/tcg-target.c.inc|   2 -
 tcg/ppc/tcg-target.c.inc |  90 
 tcg/riscv/tcg-target.c.inc   |   2 -
 tcg/s390/tcg-target.c.inc|   2 -
 tcg/sparc/tcg-target.c.inc   |   2 -
 tcg/tci/tcg-target.c.inc |   6 +-
 scripts/decodetree.py|   9 +-
 21 files changed, 890 insertions(+), 669 deletions(-)



Re: [PATCH v3] tcg: Fix execution on Apple Silicon

2021-01-13 Thread Joelle van Dyne
No because of macOS weirdness you still have to map with RWX and MAP_JIT
before you can use this. Split w^x is only useful in iOS where they don’t
provide this functionality.

-j

On Wednesday, January 13, 2021, Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 1/12/21 5:28 PM, Roman Bolshakov wrote:
> > Pages can't be both write and executable at the same time on Apple
> > Silicon. macOS provides public API to switch write protection [1] for
> > JIT applications, like TCG.
>
> So... considering that split w^x is now upstream, can we just call this
> once
> per thread to enable write and leave it write?
> Since we have the separate rw mapping.
>
>
> r~
>


[PATCH v2 2/2] hw/mips/loongson3_virt: Add TCG SMP support

2021-01-13 Thread Jiaxun Yang
loongson3_virt has KVM SMP support in kenrel.
This patch adds TCG SMP support by enable IPI controller
for machine.

Note that TCG SMP can only support up to 4 CPUs as we
didn't implement multi-node support.

Signed-off-by: Jiaxun Yang 
---
 hw/mips/loongson3_bootp.h |  1 +
 hw/mips/loongson3_virt.c  | 20 +++-
 hw/mips/Kconfig   |  1 +
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index 09f8480abf..4756aa44f6 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -210,6 +210,7 @@ enum {
 VIRT_PCIE_ECAM,
 VIRT_BIOS_ROM,
 VIRT_UART,
+VIRT_IPIS,
 VIRT_LIOINTC,
 VIRT_PCIE_MMIO,
 VIRT_HIGHMEM
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index d4a82fa536..0684a035b0 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -35,6 +35,7 @@
 #include "hw/boards.h"
 #include "hw/char/serial.h"
 #include "hw/intc/loongson_liointc.h"
+#include "hw/intc/loongson_ipi.h"
 #include "hw/mips/mips.h"
 #include "hw/mips/cpudevs.h"
 #include "hw/mips/fw_cfg.h"
@@ -59,6 +60,7 @@
 
 #define PM_CNTL_MODE  0x10
 
+#define LOONGSON_TCG_MAX_VCPUS  4
 #define LOONGSON_MAX_VCPUS  16
 
 /*
@@ -71,6 +73,7 @@
 #define UART_IRQ0
 #define RTC_IRQ 1
 #define PCIE_IRQ_BASE   2
+#define IPI_REG_SPACE   0x100
 
 const struct MemmapEntry virt_memmap[] = {
 [VIRT_LOWMEM] =  { 0x,0x1000 },
@@ -81,6 +84,7 @@ const struct MemmapEntry virt_memmap[] = {
 [VIRT_PCIE_ECAM] =   { 0x1a00, 0x200 },
 [VIRT_BIOS_ROM] ={ 0x1fc0,  0x20 },
 [VIRT_UART] ={ 0x1fe001e0,   0x8 },
+[VIRT_IPIS] ={ 0x3ff01000, 0x400 },
 [VIRT_LIOINTC] = { 0x3ff01400,  0x64 },
 [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
 [VIRT_HIGHMEM] = { 0x8000,   0x0 }, /* Variable */
@@ -495,6 +499,10 @@ static void mips_loongson3_virt_init(MachineState *machine)
 error_report("Loongson-3/TCG needs cpu type Loongson-3A1000");
 exit(1);
 }
+if (machine->smp.cpus > LOONGSON_TCG_MAX_VCPUS) {
+error_report("Loongson-3/TCG supports up to 4 CPUs");
+exit(1);
+}
 } else {
 if (!machine->cpu_type) {
 machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000");
@@ -545,7 +553,17 @@ static void mips_loongson3_virt_init(MachineState *machine)
 qemu_register_reset(main_cpu_reset, cpu);
 
 if (i >= 4) {
-continue; /* Only node-0 can be connected to LIOINTC */
+continue; /* Only node-0 can be connected to LIOINTC and IPI */
+}
+
+if (!kvm_enabled()) {
+/* IPI is handled by kernel for KVM */
+DeviceState *ipi;
+ipi = qdev_new(TYPE_LOONGSON_IPI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(ipi), 0,
+virt_memmap[VIRT_IPIS].base + IPI_REG_SPACE * i);
+sysbus_connect_irq(SYS_BUS_DEVICE(ipi), 0, cpu->env.irq[6]);
 }
 
 for (ip = 0; ip < 4 ; ip++) {
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index aadd436bf4..4fb0cc49e8 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -39,6 +39,7 @@ config LOONGSON3V
 select SERIAL
 select GOLDFISH_RTC
 select LOONGSON_LIOINTC
+select LOONGSON_IPI if TCG
 select PCI_DEVICES
 select PCI_EXPRESS_GENERIC_BRIDGE
 select MSI_NONBROKEN
-- 
2.30.0




Re: [PATCH v3] tcg: Fix execution on Apple Silicon

2021-01-13 Thread Richard Henderson
On 1/12/21 5:28 PM, Roman Bolshakov wrote:
> Pages can't be both write and executable at the same time on Apple
> Silicon. macOS provides public API to switch write protection [1] for
> JIT applications, like TCG.

So... considering that split w^x is now upstream, can we just call this once
per thread to enable write and leave it write?
Since we have the separate rw mapping.


r~



[PATCH v2 1/2] hw/intc: Add Loongson Inter Processor Interrupt controller

2021-01-13 Thread Jiaxun Yang
Loongson IPI controller is a MMIO based simple level triggered
interrupt controller. It will trigger IRQ to it's upstream
processor when set register is written.

It also has 4 64bit mailboxes to pass boot information to
secondary processor.

Signed-off-by: Jiaxun Yang 
---
 include/hw/intc/loongson_ipi.h |  20 
 hw/intc/loongson_ipi.c | 174 +
 hw/intc/Kconfig|   3 +
 hw/intc/meson.build|   1 +
 hw/intc/trace-events   |   4 +
 5 files changed, 202 insertions(+)
 create mode 100644 include/hw/intc/loongson_ipi.h
 create mode 100644 hw/intc/loongson_ipi.c

diff --git a/include/hw/intc/loongson_ipi.h b/include/hw/intc/loongson_ipi.h
new file mode 100644
index 00..a535c467bf
--- /dev/null
+++ b/include/hw/intc/loongson_ipi.h
@@ -0,0 +1,20 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2020-2021 Jiaxun Yang 
+ *
+ */
+
+#ifndef LOONGSON_IPI_H
+#define LOONGSON_IPI_H
+
+#include "qemu/units.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_LOONGSON_IPI "loongson.ipi"
+#define LOONGSON_IPI(obj) OBJECT_CHECK(struct loongson_ipi, (obj), 
TYPE_LOONGSON_IPI)
+
+#endif /* LOONGSON_IPI_H */
diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
new file mode 100644
index 00..cce1da8fb9
--- /dev/null
+++ b/hw/intc/loongson_ipi.c
@@ -0,0 +1,174 @@
+/*
+ * QEMU Loongson Inter Processor Interrupt Controller
+ *
+ * Copyright (c) 2020-2021 Jiaxun Yang 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+#include "hw/intc/loongson_ipi.h"
+#include "sysemu/reset.h"
+#include "trace.h"
+
+/*
+ * Mailboxes are actually 4 64bit registers but we treat it as 8 32bit
+ * to simplify implementation.
+ */
+#define NUM_MBOX  8
+
+enum {
+R_ISR = 0,
+R_IEN = 1,
+R_SET = 2,
+R_CLR = 3,
+/* No register at 0x10~0x20 */
+R_MBOX0 = 8,
+R_END = R_MBOX0 + NUM_MBOX
+};
+
+struct loongson_ipi {
+SysBusDevice parent_obj;
+
+MemoryRegion mmio;
+qemu_irq parent_irq;
+
+uint32_t isr;
+uint32_t ien;
+uint32_t mbox[NUM_MBOX];
+};
+
+static uint64_t
+ipi_read(void *opaque, hwaddr addr, unsigned int size)
+{
+struct loongson_ipi *p = opaque;
+uint64_t r = 0;
+
+addr >>= 2;
+switch (addr) {
+case R_ISR:
+r = p->isr;
+break;
+case R_IEN:
+r = p->ien;
+break;
+case R_SET:
+case R_CLR:
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Reading write only reg: 0x%" HWADDR_PRIx "\n",
+  __func__, addr);
+break;
+case R_MBOX0 ... (R_END - 1):
+r = p->mbox[addr - R_MBOX0];
+break;
+default:
+break;
+}
+
+trace_loongson_ipi_read(addr, r);
+
+return r;
+}
+
+static void
+ipi_write(void *opaque, hwaddr addr,
+  uint64_t val64, unsigned int size)
+{
+struct loongson_ipi *p = opaque;
+uint32_t value = val64;
+
+addr >>= 2;
+switch (addr) {
+case R_ISR:
+/* Do nothing */
+break;
+case R_IEN:
+p->ien = value;
+break;
+case R_SET:
+p->isr |= value;
+break;
+case R_CLR:
+p->isr &= ~value;
+break;
+case R_MBOX0 ... (R_END - 1):
+p->mbox[addr - R_MBOX0] = value;
+break;
+default:
+break;
+}
+p->isr &= p->ien;
+
+trace_loongson_ipi_write(addr, value);
+
+qemu_set_irq(p->parent_irq, !!p->isr);
+}
+
+static void ipi_reset(void *opaque)
+{
+int i;
+struct loongson_ipi *p = opaque;
+
+p->ien = 0;
+p->isr = 0;
+for (i = 0; i < NUM_MBOX; i++) {
+p->mbox[i] = 0;
+}
+}
+
+static const MemoryRegionOps pic_mmio_ops = {
+.read = ipi_read,
+.write = ipi_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+.min_access_size = 4,
+.max_access_size = 4
+},
+.valid = {
+.min_access_size = 4,
+.max_access_size = 8
+},
+};
+
+static void loongson_ipi_init(Object *obj)
+{
+struct loongson_ipi *p = 

[PATCH v2 0/2] loongson3_virt TCG SMP support

2021-01-13 Thread Jiaxun Yang
v2:
 - Use enum instead of define (f4bug)
 - Comment about num mbox (f4bug)
 - Use trace instead of log (f4bug)
 - Correct register size (f4bug)


Jiaxun Yang (2):
  hw/intc: Add Loongson Inter Processor Interrupt controller
  hw/mips/loongson3_virt: Add TCG SMP support

 hw/mips/loongson3_bootp.h  |   1 +
 include/hw/intc/loongson_ipi.h |  20 
 hw/intc/loongson_ipi.c | 174 +
 hw/mips/loongson3_virt.c   |  20 +++-
 hw/intc/Kconfig|   3 +
 hw/intc/meson.build|   1 +
 hw/intc/trace-events   |   4 +
 hw/mips/Kconfig|   1 +
 8 files changed, 223 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/intc/loongson_ipi.h
 create mode 100644 hw/intc/loongson_ipi.c

-- 
2.30.0




Re: [PATCH v4 2/8] acpi: Fix unmatched expected DSDT.pxb file

2021-01-13 Thread Jiahui Cen
Hi Michael,

On 2021/1/13 22:00, Michael S. Tsirkin wrote:
> On Thu, Jan 07, 2021 at 07:40:37PM +0800, Jiahui Cen wrote:
>> Commit fe1127da11 ("unit-test: Add the binary file and clear diff.h") does 
>> not
>> use the up-to-date expected file for pxb for ARM virt.
>>
>> Fix the expected DSDT.pxb file.
>>
>> Full diff of changed file disassembly:
>>
>> diff -ru /tmp/old/tests/data/acpi/virt/DSDT.pxb.dsl 
>> /tmp/new/tests/data/acpi/virt/DSDT.pxb.dsl
>> --- /tmp/old/tests/data/acpi/virt/DSDT.pxb.dsl  2021-01-07 
>> 17:04:51.246831080 +0800
> 
> This --- sign confuses git am. You shouldn't put this in the commit log
> really ...
> 

Yes, it does confuse. I found there were some patches with commit log
like this, so I did the same :(

So, I'll modify the commit logs and resend them.

Thanks,
Jiahui

> 
>> +++ /tmp/new/tests/data/acpi/virt/DSDT.pxb.dsl  2021-01-07 
>> 17:11:59.566831080 +0800
>> @@ -9,9 +9,9 @@
>>   *
>>   * Original Table Header:
>>   * Signature"DSDT"
>> - * Length   0x1E7A (7802)
>> + * Length   0x1DF9 (7673)
>>   * Revision 0x02
>> - * Checksum 0x57
>> + * Checksum 0x42
>>   * OEM ID   "BOCHS "
>>   * OEM Table ID "BXPCDSDT"
>>   * OEM Revision 0x0001 (1)
>> @@ -45,32 +45,6 @@
>>  })
>>  }
>>
>> -Device (FLS0)
>> -{
>> -Name (_HID, "LNRO0015")  // _HID: Hardware ID
>> -Name (_UID, Zero)  // _UID: Unique ID
>> -Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource 
>> Settings
>> -{
>> -Memory32Fixed (ReadWrite,
>> -0x, // Address Base
>> -0x0400, // Address Length
>> -)
>> -})
>> -}
>> -
>> -Device (FLS1)
>> -{
>> -Name (_HID, "LNRO0015")  // _HID: Hardware ID
>> -Name (_UID, One)  // _UID: Unique ID
>> -Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource 
>> Settings
>> -{
>> -Memory32Fixed (ReadWrite,
>> -0x0400, // Address Base
>> -0x0400, // Address Length
>> -)
>> -})
>> -}
>> -
>>  Device (FWCF)
>>  {
>>  Name (_HID, "QEMU0002")  // _HID: Hardware ID
>> @@ -665,9 +639,6 @@
>>  {
>>  Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware 
>> ID
>>  Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
>> -Name (_ADR, Zero)  // _ADR: Address
>> -Name (_CCA, One)  // _CCA: Cache Coherency Attribute
>> -Name (_SEG, Zero)  // _SEG: PCI Segment
>>  Name (_BBN, 0x80)  // _BBN: BIOS Bus Number
>>  Name (_UID, 0x80)  // _UID: Unique ID
>>  Name (_STR, Unicode ("pxb Device"))  // _STR: Description String
>> @@ -1857,7 +1828,7 @@
>>  Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
>>  Name (_SEG, Zero)  // _SEG: PCI Segment
>>  Name (_BBN, Zero)  // _BBN: BIOS Bus Number
>> -Name (_UID, "PCI0")  // _UID: Unique ID
>> +Name (_UID, Zero)  // _UID: Unique ID
>>  Name (_STR, Unicode ("PCIe 0 Device"))  // _STR: Description 
>> String
>>  Name (_CCA, One)  // _CCA: Cache Coherency Attribute
>>  Name (_PRT, Package (0x80)  // _PRT: PCI Routing Table
>> @@ -2983,41 +2954,37 @@
>>  Return (0x00401000)
>>  }
>>
>> -Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource 
>> Settings
>> +Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource 
>> Settings
>>  {
>> -Return (ResourceTemplate ()
>> -{
>> -WordBusNumber (ResourceProducer, MinFixed, MaxFixed, 
>> PosDecode,
>> -0x, // Granularity
>> -0x, // Range Minimum
>> -0x007F, // Range Maximum
>> -0x, // Translation Offset
>> -0x0080, // Length
>> -,, )
>> -DWordMemory (ResourceProducer, PosDecode, MinFixed, 
>> MaxFixed, NonCacheable, ReadWrite,
>> -0x, // Granularity
>> -0x1000, // Range Minimum
>> -0x3EFE, // Range Maximum
>> -0x, // Translation Offset
>> -0x2EFF, // Length
>> -,, , AddressRangeMemory, TypeStatic)
>> -DWordIO (ResourceProducer, MinFixed, MaxFixed, 
>> PosDecode, EntireRange,
>> -   

Re: [PATCH v2 07/12] qapi/schema: make QAPISourceInfo mandatory

2021-01-13 Thread John Snow

On 1/13/21 7:29 PM, Eduardo Habkost wrote:

On Wed, Jan 13, 2021 at 06:04:29PM -0500, John Snow wrote:

On 1/13/21 11:12 AM, Markus Armbruster wrote:

John Snow  writes:


...



I think we need to, yes; or we probably really, really want to. Making the
info parameter optional really adds a lot of unidiomatic type-checking
confetti when we go to use info, and in many more contexts than just this
sorta-built-in-enum; it will creep badly.


Which methods would require unidiomatic type-checking because of
None/Optional?



Virtually everything that accepts a QAPISourceInfo has to do something 
like this:


def foo(info: Optional[QAPISourceInfo]):
if info is None:
raise Exception("Something very bad has happened!")
...
...


Since the great majority of cases *will* have an info, and we take 
careful pains to make sure this info is preserved, it's less invasive to 
just assert that info isn't Optional.


This is especially true for the QAPISchemaMember initializer, which 
several other classes inherit -- if this is allowed to be 
Optional[QAPISourceInfo], any and all users of a QAPISchemaMember or any 
derived classes will have to check -- on every access -- to see if 
'member.info' is set or not.


Since we expect it to be set 100% of the time for all user-defined code, 
it's a lot less "if member.info is not None" checks everywhere.


Adding a special "built-in" source info object to make this claim helps 
avoid making confusing type signatures for the visitors; i.e.


def visit_thing(info: Optional[QAPISourceInfo]): ...

is misleading, because we actually expect thing to *always* have a 
SourceInfo. To make the documentation be a little more ... statistically 
truthful, it's easier to bend the rules in the other direction and just 
fill in the scant few cases where we don't have a QAPISourceInfo.


--js




Re: [PATCH v2 07/12] qapi/schema: make QAPISourceInfo mandatory

2021-01-13 Thread Eduardo Habkost
On Wed, Jan 13, 2021 at 06:04:29PM -0500, John Snow wrote:
> On 1/13/21 11:12 AM, Markus Armbruster wrote:
> > John Snow  writes:
> > 
> > > Signed-off-by: John Snow 
> > > 
> > > ---
> > > 
> > > The event_enum_members change might become irrelevant after a
> > > forthcoming (?) patch by Markus, but didn't have it in-hand at time of
> > > publishing.
> > 
> > It's in my "[PATCH 00/11] Drop support for QAPIGen without a file name",
> > which includes parts of your v1.  The parts that are new should be
> > injected into your series so they replace your "[PATCH v2 09/12]
> > qapi/gen: move write method to QAPIGenC, make fname a str".  Holler if
> > you need help.
> > 
> > > Signed-off-by: John Snow 
> > > ---
> > >   scripts/qapi/events.py |  2 +-
> > >   scripts/qapi/schema.py | 25 ++---
> > >   scripts/qapi/types.py  |  9 +
> > >   scripts/qapi/visit.py  |  6 +++---
> > >   4 files changed, 23 insertions(+), 19 deletions(-)
> > > 
> > > diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
> > > index 9851653b9d1..9ba4f109028 100644
> > > --- a/scripts/qapi/events.py
> > > +++ b/scripts/qapi/events.py
> > > @@ -225,7 +225,7 @@ def visit_event(self,
> > > self._event_emit_name))
> > >   # Note: we generate the enum member regardless of @ifcond, to
> > >   # keep the enumeration usable in target-independent code.
> > > -self._event_enum_members.append(QAPISchemaEnumMember(name, None))
> > > +self._event_enum_members.append(QAPISchemaEnumMember(name, info))
> > 
> > This "enum" is not supposed to be erroneous.  If it is, it's a bug.
> > 
> > Your patch changes how the code behaves should such a bug bite here.
> > Before, we crash.  Afterwards, we report the bug using @info, which I'd
> > expect to produce utterly confusing error messages.
> > 
> 
> It doesn't change the behavior *here*, though. It changes it whenever this
> info object is used in another context. ... and who knows when or where or
> why it is being used, or by whom.
> 
> I'll have to play with this. I'm not sure there's any way to coax a bug to
> happen here that I am aware of right away. Can you think of how to will one
> into existence?
> 
> > My comments on PATCH 06 apply: how the code should behave here is a
> > design issue that should be kept out of this patch series.
> > 
> > If you need to pass a value other than None to help with static typing,
> > then pass a suitable poison info that will crash right where None
> > crashes now.

I don't understand what would be the point of inventing something
that behaves exactly like None but makes type checking less
useful.

With None/Optional, mypy gives us a way to be 100% sure the
object isn't going to invalid.  With a poison value, mypy can't
tell us anymore if the code risks crashing at runtime.

> > 
> 
> I think we need to, yes; or we probably really, really want to. Making the
> info parameter optional really adds a lot of unidiomatic type-checking
> confetti when we go to use info, and in many more contexts than just this
> sorta-built-in-enum; it will creep badly.

Which methods would require unidiomatic type-checking because of
None/Optional?

> 
> So, I gotta pass ...something here. but what? You want poison, but I think
> it's not right to fundamentally poison all built-ins.
> 
> Mmm. Maybe per-instance poison can be done? We actually share info
> objects, but I can make poisoned copies. Using next_line() as a basis:
> 
> def poison(self: T) -> T:
> info = copy.copy(self)
> info.poisoned = True
> return info
> 
> probably almost anything I do is not going to make a lot of sense unless I
> can actually replicate and test the different error scenarios to prove that
> we didn't make the error spaghetti unknowably worse. I see it as
> functionally inevitable that I have to audit this and make sure we get good
> error messages anyway, so ... maybe I just ought to do that now anyway.
> 
> > >   def gen_events(schema: QAPISchema,
> > > diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
> > > index 720449feee4..0449771dfe5 100644
> > > --- a/scripts/qapi/schema.py
> > > +++ b/scripts/qapi/schema.py
> > > @@ -23,6 +23,7 @@
> > >   from .error import QAPIError, QAPISemError
> > >   from .expr import check_exprs
> > >   from .parser import QAPISchemaParser
> > > +from .source import QAPISourceInfo
> > >   class QAPISchemaEntity:
> > > @@ -36,10 +37,10 @@ def __init__(self, name, info, doc, ifcond=None, 
> > > features=None):
> > >   self.name = name
> > >   self._module = None
> > >   # For explicitly defined entities, info points to the (explicit)
> > > -# definition.  For builtins (and their arrays), info is None.
> > > -# For implicitly defined entities, info points to a place that
> > > -# triggered the implicit definition (there may be more than one
> > > -# such place).
> > > + 

Re: [PATCH v2 3/6] tcg/ppc: Hoist common argument loads in tcg_out_op()

2021-01-13 Thread Richard Henderson
On 1/13/21 7:24 AM, Philippe Mathieu-Daudé wrote:
>  case INDEX_op_ld8s_i32:
>  case INDEX_op_ld8s_i64:
> -tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
> +tcg_out_mem_long(s, LBZ, LBZX, a0, a1, a2);
>  tcg_out32(s, EXTSB | RS(args[0]) | RA(args[0]));

Missed replacements.

> -a0 = args[0], a1 = args[1], a2 = args[2];
>  if (const_args[2]) {

Missed replacement.

>  do_addi_32:
>  tcg_out_mem_long(s, ADDI, ADD, a0, a1, (int32_t)a2);
> @@ -2475,7 +2481,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, 
> const TCGArg *args,
>  }
>  break;
>  case INDEX_op_sub_i32:
> -a0 = args[0], a1 = args[1], a2 = args[2];
>  if (const_args[1]) {
>  if (const_args[2]) {

And again.

Let's just drop the hoisting parts and only do the signature parts for now.
I'd rather think of a way to split up this large function than waste time
optimizing it.


r~



Re: [PATCH 1/2] trace: document how to specify multiple --trace patterns

2021-01-13 Thread John Snow

On 1/13/21 6:45 PM, BALATON Zoltan wrote:


Please don't. That would break all scripts that already call qemu using 
single dash options. Forcing everyone to edit their scripts is not nice. 
How about also accepting single dash in qemu-img for consistency then 
you can use whatever you want in docs as long as single dash still works 
for consistency and backward compatibility.


That's not what I meant -- I meant for documentation purposes. QEMU can 
keep accepting single dash, but we should standardize on the spelling 
for purposes of interactive messages, documentation, etc.


--js




Re: [PATCH v6 10/11] iotests: rewrite check into python

2021-01-13 Thread John Snow

On 1/13/21 6:20 PM, Eric Blake wrote:

On 1/9/21 6:26 AM, Vladimir Sementsov-Ogievskiy wrote:

Just use classes introduced in previous three commits. Behavior
difference is described in these three commits.

Drop group file, as it becomes unused.

Signed-off-by: Vladimir Sementsov-Ogievskiy 
---
  tests/qemu-iotests/check | 994 ++-
  tests/qemu-iotests/group | 321 -
  2 files changed, 28 insertions(+), 1287 deletions(-)
  delete mode 100644 tests/qemu-iotests/group


The bulk of the work was done in the earlier patches, and my python
review is weak; but I can confirm that with this patch applied, my usual
attempts at running ./check still appeared to work for me.  That's not
the same as proving you did 1:1 feature translation (and in fact, your
commit message documented dropping some features like -v), but if 'make
check' and CI tools still run, I'm okay leaving it up to developers to
complain about any other feature that they used but which go missing (or
to implement it).

Tested-by: Eric Blake 



I will *try* to give this a look, but I am still buried under post-PTO 
mail; and I feel comfortable with Kevin's Python review otherwise, so 
don't hold your breath waiting to hear from me.




diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 952762d5ed..48bb3128c3 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -1,7 +1,8 @@
-#!/usr/bin/env bash
+#!/usr/bin/env python3
  #
-# Copyright (C) 2009 Red Hat, Inc.
-# Copyright (c) 2000-2002,2006 Silicon Graphics, Inc.  All Rights Reserved.
+# Configure environment and run group of tests in it.
+#
+# Copyright (c) 2020 Virtuozzo International GmbH


You may want to claim 2021 as well.


+import sys
+import os
+from findtests import find_tests, TestFinder
+from testenv import TestEnv
+from testrunner import TestRunner
+
+if __name__ == '__main__':
+if len(sys.argv) == 2 and sys.argv[1] in ['-h', '--help']:
+print('Usage: ./check [options] [testlist]')
+print()
+TestFinder.get_argparser().print_help()
+print()
+TestEnv.get_argparser().print_help()
+print()
+TestRunner.get_argparser().print_help()
+exit()
+
+env = TestEnv(sys.argv[1:])
+tests, remaining_argv = find_tests(env.remaining_argv,
+   test_dir=env.source_iotests)
+
+with TestRunner(remaining_argv, env) as tr:
+assert not tr.remaining_argv
+tr.run_tests([os.path.join(env.source_iotests, t) for t in tests])


A lot shorter for the main engine ;)


diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
deleted file mode 100644
index bc5bc324fe..00
--- a/tests/qemu-iotests/group
+++ /dev/null
@@ -1,321 +0,0 @@
-#
-# QA groups control file
-# Defines test groups


Happy to see this conflict magnet go!



This rules.

--js




Re: [PATCH 21/22] docs/system: Add RISC-V documentation

2021-01-13 Thread Alistair Francis
On Thu, Dec 31, 2020 at 3:53 AM Bin Meng  wrote:
>
> From: Bin Meng 
>
> Add RISC-V system emulator documentation for generic information.
> `Board-specific documentation` and `RISC-V CPU features` are only
> a placeholder and will be added in the future.
>
> Signed-off-by: Bin Meng 

This is great! Thanks!

Reviewed-by: Alistair Francis 

Alistair

> ---
>
>  docs/system/target-riscv.rst | 62 
>  docs/system/targets.rst  |  1 +
>  2 files changed, 63 insertions(+)
>  create mode 100644 docs/system/target-riscv.rst
>
> diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst
> new file mode 100644
> index 00..978b96cbdb
> --- /dev/null
> +++ b/docs/system/target-riscv.rst
> @@ -0,0 +1,62 @@
> +.. _RISC-V-System-emulator:
> +
> +RISC-V System emulator
> +==
> +
> +QEMU can emulate both 32-bit and 64-bit RISC-V CPUs. Use the
> +``qemu-system-riscv64`` executable to simulate a 64-bit RISC-V machine,
> +``qemu-system-riscv32`` executable to simulate a 32-bit RISC-V machine.
> +
> +QEMU has generally good support for RISC-V guests. It has support for
> +several different machines. The reason we support so many is that
> +RISC-V hardware is much more widely varying than x86 hardware. RISC-V
> +CPUs are generally built into "system-on-chip" (SoC) designs created by
> +many different companies with different devices, and these SoCs are
> +then built into machines which can vary still further even if they use
> +the same SoC.
> +
> +For most boards the CPU type is fixed (matching what the hardware has),
> +so typically you don't need to specify the CPU type by hand, except for
> +special cases like the ``virt`` board.
> +
> +Choosing a board model
> +--
> +
> +For QEMU's RISC-V system emulation, you must specify which board
> +model you want to use with the ``-M`` or ``--machine`` option;
> +there is no default.
> +
> +Because RISC-V systems differ so much and in fundamental ways, typically
> +operating system or firmware images intended to run on one machine
> +will not run at all on any other. This is often surprising for new
> +users who are used to the x86 world where every system looks like a
> +standard PC. (Once the kernel has booted, most userspace software
> +cares much less about the detail of the hardware.)
> +
> +If you already have a system image or a kernel that works on hardware
> +and you want to boot with QEMU, check whether QEMU lists that machine
> +in its ``-machine help`` output. If it is listed, then you can probably
> +use that board model. If it is not listed, then unfortunately your image
> +will almost certainly not boot on QEMU. (You might be able to
> +extract the filesystem and use that with a different kernel which
> +boots on a system that QEMU does emulate.)
> +
> +If you don't care about reproducing the idiosyncrasies of a particular
> +bit of hardware, such as small amount of RAM, no PCI or other hard
> +disk, etc., and just want to run Linux, the best option is to use the
> +``virt`` board. This is a platform which doesn't correspond to any
> +real hardware and is designed for use in virtual machines. You'll
> +need to compile Linux with a suitable configuration for running on
> +the ``virt`` board. ``virt`` supports PCI, virtio, recent CPUs and
> +large amounts of RAM. It also supports 64-bit CPUs.
> +
> +Board-specific documentation
> +
> +
> +Unfortunately many of the RISC-V boards QEMU supports are currently
> +undocumented; you can get a complete list by running
> +``qemu-system-riscv64 --machine help``, or
> +``qemu-system-riscv32 --machine help``.
> +
> +RISC-V CPU features
> +---
> diff --git a/docs/system/targets.rst b/docs/system/targets.rst
> index 564cea9a9b..75ed1087fd 100644
> --- a/docs/system/targets.rst
> +++ b/docs/system/targets.rst
> @@ -19,6 +19,7 @@ Contents:
> target-m68k
> target-mips
> target-ppc
> +   target-riscv
> target-rx
> target-s390x
> target-sparc
> --
> 2.25.1
>
>



[PATCH v7 13/13] s390: Recognize confidential-guest-support option

2021-01-13 Thread David Gibson
At least some s390 cpu models support "Protected Virtualization" (PV),
a mechanism to protect guests from eavesdropping by a compromised
hypervisor.

This is similar in function to other mechanisms like AMD's SEV and
POWER's PEF, which are controlled by the "confidential-guest-support"
machine option.  s390 is a slightly special case, because we already
supported PV, simply by using a CPU model with the required feature
(S390_FEAT_UNPACK).

To integrate this with the option used by other platforms, we
implement the following compromise:

 - When the confidential-guest-support option is set, s390 will
   recognize it, verify that the CPU can support PV (failing if not)
   and set virtio default options necessary for encrypted or protected
   guests, as on other platforms.  i.e. if confidential-guest-support
   is set, we will either create a guest capable of entering PV mode,
   or fail outright.

 - If confidential-guest-support is not set, guests might still be
   able to enter PV mode, if the CPU has the right model.  This may be
   a little surprising, but shouldn't actually be harmful.

To start a guest supporting Protected Virtualization using the new
option use the command line arguments:
-object s390-pv-guest,id=pv0 -machine confidential-guest-support=pv0

Signed-off-by: David Gibson 
---
 docs/confidential-guest-support.txt |  3 ++
 docs/system/s390x/protvirt.rst  | 19 ++---
 hw/s390x/pv.c   | 62 +
 include/hw/s390x/pv.h   |  1 +
 target/s390x/kvm.c  |  3 ++
 5 files changed, 82 insertions(+), 6 deletions(-)

diff --git a/docs/confidential-guest-support.txt 
b/docs/confidential-guest-support.txt
index f0801814ff..50b976a082 100644
--- a/docs/confidential-guest-support.txt
+++ b/docs/confidential-guest-support.txt
@@ -43,4 +43,7 @@ AMD Secure Encrypted Virtualization (SEV)
 POWER Protected Execution Facility (PEF)
 docs/papr-pef.txt
 
+s390x Protected Virtualization (PV)
+docs/system/s390x/protvirt.rst
+
 Other mechanisms may be supported in future.
diff --git a/docs/system/s390x/protvirt.rst b/docs/system/s390x/protvirt.rst
index 712974ad87..0f481043d9 100644
--- a/docs/system/s390x/protvirt.rst
+++ b/docs/system/s390x/protvirt.rst
@@ -22,15 +22,22 @@ If those requirements are met, the capability 
`KVM_CAP_S390_PROTECTED`
 will indicate that KVM can support PVMs on that LPAR.
 
 
-QEMU Settings
--
+Running a Protected Virtual Machine
+---
 
-To indicate to the VM that it can transition into protected mode, the
+To run a PVM you will need to select a CPU model which includes the
 `Unpack facility` (stfle bit 161 represented by the feature
-`unpack`/`S390_FEAT_UNPACK`) needs to be part of the cpu model of
-the VM.
+`unpack`/`S390_FEAT_UNPACK`), and add these options to the command line::
+
+-object s390-pv-guest,id=pv0 \
+-machine confidential-guest-support=pv0
+
+Adding these options will:
+
+* Ensure the `unpack` facility is available
+* Enable the IOMMU by default for all I/O devices
+* Initialize the PV mechanism
 
-All I/O devices need to use the IOMMU.
 Passthrough (vfio) devices are currently not supported.
 
 Host huge page backings are not supported. However guests can use huge
diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c
index ab3a2482aa..319d74dfcf 100644
--- a/hw/s390x/pv.c
+++ b/hw/s390x/pv.c
@@ -14,8 +14,11 @@
 #include 
 
 #include "cpu.h"
+#include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "sysemu/kvm.h"
+#include "qom/object_interfaces.h"
+#include "exec/confidential-guest-support.h"
 #include "hw/s390x/ipl.h"
 #include "hw/s390x/pv.h"
 
@@ -111,3 +114,62 @@ void s390_pv_inject_reset_error(CPUState *cs)
 /* Report that we are unable to enter protected mode */
 env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV;
 }
+
+#define TYPE_S390_PV_GUEST "s390-pv-guest"
+OBJECT_DECLARE_SIMPLE_TYPE(S390PVGuest, S390_PV_GUEST)
+
+/**
+ * S390PVGuest:
+ *
+ * The S390PVGuest object is basically a dummy used to tell the
+ * confidential guest support system to use s390's PV mechanism.
+ *
+ * # $QEMU \
+ * -object s390-pv-guest,id=pv0 \
+ * -machine ...,confidential-guest-support=pv0
+ */
+struct S390PVGuest {
+ConfidentialGuestSupport parent_obj;
+};
+
+typedef struct S390PVGuestClass S390PVGuestClass;
+
+struct S390PVGuestClass {
+ConfidentialGuestSupportClass parent_class;
+};
+
+int s390_pv_init(ConfidentialGuestSupport *cgs, Error **errp)
+{
+if (!object_dynamic_cast(OBJECT(cgs), TYPE_S390_PV_GUEST)) {
+return 0;
+}
+
+if (!s390_has_feat(S390_FEAT_UNPACK)) {
+error_setg(errp,
+   "CPU model does not support Protected Virtualization");
+return -1;
+}
+
+cgs->ready = true;
+
+return 0;
+}
+
+OBJECT_DEFINE_TYPE_WITH_INTERFACES(S390PVGuest,
+   s390_pv_guest,
+   S390_PV_GUEST,
+ 

[PATCH v7 08/13] confidential guest support: Move SEV initialization into arch specific code

2021-01-13 Thread David Gibson
While we've abstracted some (potential) differences between mechanisms for
securing guest memory, the initialization is still specific to SEV.  Given
that, move it into x86's kvm_arch_init() code, rather than the generic
kvm_init() code.

Signed-off-by: David Gibson 
---
 accel/kvm/kvm-all.c   | 14 --
 accel/kvm/sev-stub.c  |  4 ++--
 target/i386/kvm/kvm.c | 12 
 target/i386/sev.c |  7 ++-
 4 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index c5b0750fd0..adf27c1864 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -2177,20 +2177,6 @@ static int kvm_init(MachineState *ms)
 
 kvm_state = s;
 
-/*
- * if memory encryption object is specified then initialize the memory
- * encryption context.
- */
-if (ms->cgs) {
-Error *local_err = NULL;
-/* FIXME handle mechanisms other than SEV */
-ret = sev_kvm_init(ms->cgs, _err);
-if (ret < 0) {
-error_report_err(local_err);
-goto err;
-}
-}
-
 ret = kvm_arch_init(ms, s);
 if (ret < 0) {
 goto err;
diff --git a/accel/kvm/sev-stub.c b/accel/kvm/sev-stub.c
index 512e205f7f..9587d1b2a3 100644
--- a/accel/kvm/sev-stub.c
+++ b/accel/kvm/sev-stub.c
@@ -17,6 +17,6 @@
 
 int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
 {
-/* SEV can't be selected if it's not compiled */
-g_assert_not_reached();
+/* If we get here, cgs must be some non-SEV thing */
+return 0;
 }
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 6dc1ee052d..e8b9dc48a2 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -42,6 +42,7 @@
 #include "hw/i386/intel_iommu.h"
 #include "hw/i386/x86-iommu.h"
 #include "hw/i386/e820_memory_layout.h"
+#include "sysemu/sev.h"
 
 #include "hw/pci/pci.h"
 #include "hw/pci/msi.h"
@@ -2135,6 +2136,17 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 uint64_t shadow_mem;
 int ret;
 struct utsname utsname;
+Error *local_err = NULL;
+
+/*
+ * if memory encryption object is specified then initialize the
+ * memory encryption context (no-op otherwise)
+ */
+ret = sev_kvm_init(ms->cgs, _err);
+if (ret < 0) {
+error_report_err(local_err);
+return ret;
+}
 
 if (!kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
 error_report("kvm: KVM_CAP_IRQ_ROUTING not supported by KVM");
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 3d94635397..aa79cacabe 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -664,13 +664,18 @@ sev_vm_state_change(void *opaque, int running, RunState 
state)
 
 int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
 {
-SevGuestState *sev = SEV_GUEST(cgs);
+SevGuestState *sev
+= (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
 char *devname;
 int ret, fw_error;
 uint32_t ebx;
 uint32_t host_cbitpos;
 struct sev_user_data_status status = {};
 
+if (!sev) {
+return 0;
+}
+
 ret = ram_block_discard_disable(true);
 if (ret) {
 error_report("%s: cannot disable RAM discard", __func__);
-- 
2.29.2




Re: [PATCH 22/22] docs/system: riscv: Add documentation for sifive_u machine

2021-01-13 Thread Alistair Francis
On Thu, Dec 31, 2020 at 3:42 AM Bin Meng  wrote:
>
> From: Bin Meng 
>
> This adds detailed documentation for RISC-V `sifive_u` machine,
> including the following information:
>
> - Supported devices
> - Hardware configuration information
> - Boot options
> - Machine-specific options
> - Running Linux kernel
> - Running VxWorks kernel
> - Running U-Boot, and with an alternate configuration
>
> Signed-off-by: Bin Meng 

Reviewed-by: Alistair Francis 

Alistair

>
> ---
>
>  docs/system/riscv/sifive_u.rst | 336 +
>  docs/system/target-riscv.rst   |  10 +
>  2 files changed, 346 insertions(+)
>  create mode 100644 docs/system/riscv/sifive_u.rst
>
> diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst
> new file mode 100644
> index 00..7e133d8ff3
> --- /dev/null
> +++ b/docs/system/riscv/sifive_u.rst
> @@ -0,0 +1,336 @@
> +SiFive HiFive Unleashed (``sifive_u``)
> +==
> +
> +SiFive HiFive Unleashed Development Board is the ultimate RISC‑V development
> +board featuring the Freedom U540 multi-core RISC‑V processor.
> +
> +Supported devices
> +-
> +
> +The ``sifive_u`` machine supports the following devices:
> +
> + * 1 E51 / E31 core
> + * Up to 4 U54 / U34 cores
> + * Core Level Interruptor (CLINT)
> + * Platform-Level Interrupt Controller (PLIC)
> + * Power, Reset, Clock, Interrupt (PRCI)
> + * L2 Loosely Integrated Memory (L2-LIM)
> + * DDR memory controller
> + * 2 UARTs
> + * 1 GEM ethernet controller
> + * 1 GPIO controller
> + * 1 One-Time Programmable (OTP) memory with stored serial number
> + * 1 DMA controller
> + * 2 QSPI controllers
> + * 1 ISSI 25WP256 flash
> + * 1 SD card in SPI mode
> +
> +Please note the real world HiFive Unleashed board has a fixed configuration 
> of
> +1 E51 core and 4 U54 core combination and the RISC-V core boots in 64-bit 
> mode.
> +With QEMU, one can create a machine with 1 E51 core and up to 4 U54 cores. It
> +is also possible to create a 32-bit variant with the same peripherals execpt
> +that the RISC-V cores are replaced by the 32-bit ones (E31 and U34), to help
> +testing of 32-bit guest software.
> +
> +Hardware configuration information
> +--
> +
> +The ``sifive_u`` machine automatically generates a device tree blob ("dtb")
> +which it passes to the guest. This provides information about the addresses,
> +interrupt lines and other configuration of the various devices in the system.
> +Guest software should discover the devices that are present in the generated
> +DTB instead of using a DTB for the real hardware, as some of the devices are
> +not modeled by QEMU and trying to access these devices may cause unexpected
> +behavior.
> +
> +Boot options
> +
> +
> +The ``sifive_u`` machine can start using the standard -kernel functionality
> +for loading a Linux kernel, a VxWorks kernel, a modified U-Boot bootloader
> +(S-mode) or ELF executable with the default OpenSBI firmware image as the
> +-bios. It also supports booting the unmodified U-Boot bootloader using the
> +standard -bios functionality.
> +
> +Machine-specific options
> +
> +
> +The following machine-specific options are supported:
> +
> +- serial=nnn
> +
> +  The board serial number. When not given, the default serial number 1 is 
> used.
> +
> +  SiFive reserves the first 1 KiB of the 16 KiB OTP memory for internal use.
> +  The current usage is only used to store the serial number of the board at
> +  offset 0xfc. U-Boot reads the serial number from the OTP memory, and uses
> +  it to generate a unique MAC address to be programmed to the on-chip GEM
> +  ethernet controller. When multiple QEMU ``sifive_u`` machines are created
> +  and connected to the same subnet, they all have the same MAC address hence
> +  it creates a unusable network. In such scenario, user should give different
> +  values to serial= when creating different ``sifive_u`` machines.
> +
> +- start-in-flash
> +
> +  When given, QEMU's ROM codes jump to QSPI memory-mapped flash directly.
> +  Otherwise QEMU will jump to DRAM or L2LIM depending on the msel= value.
> +  When not given, it defaults to direct DRAM booting.
> +
> +- msel=[6|11]
> +
> +  Mode Select (MSEL[3:0]) pins value, used to control where to boot from.
> +
> +  The FU540 SoC supports booting from several sources, which are controlled
> +  using the Mode Select pins on the chip. Typically, the boot process runs
> +  through several stages before it begins execution of user-provided 
> programs.
> +  These stages typically include the following:
> +
> +  1. Zeroth Stage Boot Loader (ZSBL), which is contained in an on-chip mask
> + ROM and provided by QEMU. Note QEMU implemented ROM codes are not the
> + same as what is programmed in the hardware. The QEMU one is a simplified
> + version, but it provides the same functionality as the hardware.
> +  2. First Stage Boot Loader 

[PATCH v7 11/13] spapr: PEF: prevent migration

2021-01-13 Thread David Gibson
We haven't yet implemented the fairly involved handshaking that will be
needed to migrate PEF protected guests.  For now, just use a migration
blocker so we get a meaningful error if someone attempts this (this is the
same approach used by AMD SEV).

Signed-off-by: David Gibson 
Reviewed-by: Dr. David Alan Gilbert 
Reviewed-by: Greg Kurz 
---
 hw/ppc/pef.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/ppc/pef.c b/hw/ppc/pef.c
index 02b9b3b460..d7a49ef337 100644
--- a/hw/ppc/pef.c
+++ b/hw/ppc/pef.c
@@ -42,6 +42,8 @@ struct PefGuest {
 };
 
 #ifdef CONFIG_KVM
+static Error *pef_mig_blocker;
+
 static int kvmppc_svm_init(Error **errp)
 {
 if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_SECURE_GUEST)) {
@@ -58,6 +60,11 @@ static int kvmppc_svm_init(Error **errp)
 }
 }
 
+/* add migration blocker */
+error_setg(_mig_blocker, "PEF: Migration is not implemented");
+/* NB: This can fail if --only-migratable is used */
+migrate_add_blocker(pef_mig_blocker, _fatal);
+
 return 0;
 }
 
-- 
2.29.2




Re: Emulation for riscv

2021-01-13 Thread Alistair Francis
On Fri, Nov 6, 2020 at 2:36 AM Alex Bennée  wrote:
>
>
> Palmer Dabbelt  writes:
>
> > On Thu, 22 Oct 2020 17:56:38 PDT (-0700), alistai...@gmail.com wrote:
> >> On Thu, Oct 22, 2020 at 4:58 PM Moises Arreola  
> >> wrote:
> >>>
> >>> Hello everyone, my name is Moses and I'm trying to set up a VM for a 
> >>> risc-v processor, I'm using the Risc-V Getting Started Guide and on the 
> >>> final step I'm getting an error while trying to launch the virtual 
> >>> machine using the cmd:
> >>
> >> Hello,
> >>
> >> Please don't use the RISC-V Getting Started Guide. Pretty much all of
> >> the information there is out of date and wrong. Unfortunately we are
> >> unable to correct it.
> >>
> >> The QEMU wiki is a much better place for information:
> >> https://wiki.qemu.org/Documentation/Platforms/RISCV
> >
> > Ya, everything at riscv.org is useless.  It's best to stick to the open 
> > source
> > documentation, as when that gets out of date we can at least fix it.  Using 
> > a
> > distro helps a lot here, the wiki describes how to run a handful of popular
> > ones that were ported to RISC-V early but if your favorite isn't on the list
> > then it may have its own documentation somewhere else.
>
> Even better if you could submit some .rst pages for QEMU's git:
>
>   docs/system/target-riscv.rst
>   docs/system/riscv/virt.rst (and maybe the other models)
>
> then we could improve the user manual where RiscV is currently a little
> under-represented. A number of the systems have simple example command
> lines or explain the kernel support needed for the model.

Thanks for pointing that out Alex. Bin has sent some patches for this
so RISC-V should have a presence soon.

Alistair

>
> >
> >>> sudo qemu-system-riscv64 -nographic -machine virt \
> >>> -kernel linux/arch/riscv/boot/Image -append "root=/dev/vda ro 
> >>> console=ttyS0" \
> >>> -drive file=busybox,format=raw,id=hd0 \
> >>> -device virtio-blk-device,drive=hd0
> >>>
> >>> But what I get in return is a message telling me that the file I gave 
> >>> wasn't the right one, the actual output is:
> >>>
> >>> qemu-system-riscv64: -drive file=busybox,format=raw,id=hd0: A regular 
> >>> file was expected by the 'file' driver, but something else was given
> >>>
> >>> And I checked the file busybox with de cmd "file" and got the following :
> >>> busybox: ELF 64-bit LSB executable, UCB RISC-V, version 1 (SYSV), 
> >>> dynamically linked, interpreter /lib/ld-linux-riscv64-lp64d.so.1, for 
> >>> GNU/Linux 4.15.0, stripped
> >>
> >> That looks like an ELF, which won't work when attached as a drive.
> >>
> >> How are you building this rootFS?
> >>
> >> Alistair
> >>
> >>>
> >>> So I was wondering if the error message was related to qemu.
> >>> Thanks in advance for answering any suggestions are welcome
>
>
> --
> Alex Bennée



Re: [PATCHv4 2/2] arm-virt: add secure pl061 for reset/power down

2021-01-13 Thread Andrew Jones
On Wed, Jan 13, 2021 at 10:30:47AM +0300, Maxim Uvarov wrote:
> - the same size for secure and non secure gpio. Arm doc says that
> secure memory is also split on 4k pages. So one page here has to be
> ok.

To be clear, does that means 4k pages must be used? I'm not concerned
with the size, but the alignment. If it's possible to use larger page
sizes with secure memory, then we need to align to the maximum page
size that may be used.

Thanks,
drew


> - will add dtb.
> - I think then less options is better. So I will remove
> vmc->secure_gpio flag and keep only vmc flag.
> 
> Regards,
> Maxim.
> 
> On Tue, 12 Jan 2021 at 19:28, Andrew Jones  wrote:
> >
> > On Tue, Jan 12, 2021 at 11:25:30AM -0500, Andrew Jones wrote:
> > > On Tue, Jan 12, 2021 at 04:00:23PM +, Peter Maydell wrote:
> > > > On Tue, 12 Jan 2021 at 15:35, Andrew Jones  wrote:
> > > > >
> > > > > On Tue, Jan 12, 2021 at 05:30:58PM +0300, Maxim Uvarov wrote:
> > > > > > Add secure pl061 for reset/power down machine from
> > > > > > the secure world (Arm Trusted Firmware). Connect it
> > > > > > with gpio-pwr driver.
> > > >
> > > > > > +/* connect secure pl061 to gpio-pwr */
> > > > > > +qdev_connect_gpio_out(pl061_dev, ATF_GPIO_POWEROFF,
> > > > > > +  qdev_get_gpio_in_named(gpio_pwr_dev, 
> > > > > > "reset", 0));
> > > > > > +qdev_connect_gpio_out(pl061_dev, ATF_GPIO_REBOOT,
> > > > > > +  qdev_get_gpio_in_named(gpio_pwr_dev, 
> > > > > > "shutdown", 0));
> > > > >
> > > > > I don't know anything about secure world, but it seems odd that we 
> > > > > don't
> > > > > need to add anything to the DTB.
> > > >
> > > > We should be adding something to the DTB, yes. Look at
> > > > how create_uart() does this -- you set the 'status' and
> > > > 'secure-status' properties to indicate that the device is
> > > > secure-world only.
> > > >
> > > >
> > > >
> > > > > > +if (vmc->no_secure_gpio) {
> > > > > > +vms->secure_gpio = false;
> > > > > > +}  else {
> > > > > > +vms->secure_gpio = true;
> > > > > > +}
> > > > >
> > > > > nit: vms->secure_gpio = !vmc->no_secure_gpio
> > > > >
> > > > > But do we even need vms->secure_gpio? Why not just do
> > > > >
> > > > >  if (vms->secure && !vmc->no_secure_gpio) {
> > > > >  create_gpio_secure(vms, secure_sysmem);
> > > > >  }
> > > > >
> > > > > in machvirt_init() ?
> > > >
> > > > We're just following the same pattern as vmc->no_its/vms->its,
> > > > aren't we ?
> > > >
> > >
> > > 'its' is a property that can be changed on the command line. Unless
> > > we want to be able to manage 'secure-gpio' separately from 'secure',
> > > then I think vmc->its plus 'secure' should be sufficient. We don't
> >
> > I meant to write 'vmc->no_secure_gpio and vms->secure' here.
> >
> > Thanks,
> > drew
> >
> > > always need both vmc and vms state, see 'no_ged'.
> > >
> > > Thanks,
> > > drew
> >
> 




[PATCH v7 07/13] confidential guest support: Introduce cgs "ready" flag

2021-01-13 Thread David Gibson
The platform specific details of mechanisms for implementing
confidential guest support may require setup at various points during
initialization.  Thus, it's not really feasible to have a single cgs
initialization hook, but instead each mechanism needs its own
initialization calls in arch or machine specific code.

However, to make it harder to have a bug where a mechanism isn't
properly initialized under some circumstances, we want to have a
common place, relatively late in boot, where we verify that cgs has
been initialized if it was requested.

This patch introduces a ready flag to the ConfidentialGuestSupport
base type to accomplish this, which we verify just before the machine
specific initialization function.

Signed-off-by: David Gibson 
---
 hw/core/machine.c | 8 
 include/exec/confidential-guest-support.h | 2 ++
 target/i386/sev.c | 2 ++
 3 files changed, 12 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 94194ab82d..5a742b 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -1190,6 +1190,14 @@ void machine_run_board_init(MachineState *machine)
 }
 
 if (machine->cgs) {
+/*
+ * Where confidential guest support is initialized depends on
+ * the specific mechanism in use.  But, we need to make sure
+ * it's ready by now.  If it isn't, that's a bug in the
+ * implementation of that cgs mechanism.
+ */
+assert(machine->cgs->ready);
+
 /*
  * With confidential guests, the host can't see the real
  * contents of RAM, so there's no point in it trying to merge
diff --git a/include/exec/confidential-guest-support.h 
b/include/exec/confidential-guest-support.h
index 5f131023ba..bcaf6c9f49 100644
--- a/include/exec/confidential-guest-support.h
+++ b/include/exec/confidential-guest-support.h
@@ -27,6 +27,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(ConfidentialGuestSupport, 
CONFIDENTIAL_GUEST_SUPPORT)
 
 struct ConfidentialGuestSupport {
 Object parent;
+
+bool ready;
 };
 
 typedef struct ConfidentialGuestSupportClass {
diff --git a/target/i386/sev.c b/target/i386/sev.c
index e2b41ef342..3d94635397 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -737,6 +737,8 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error 
**errp)
 qemu_add_machine_init_done_notifier(_machine_done_notify);
 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
 
+cgs->ready = true;
+
 return 0;
 err:
 sev_guest = NULL;
-- 
2.29.2




[PATCH v7 10/13] spapr: Add PEF based confidential guest support

2021-01-13 Thread David Gibson
Some upcoming POWER machines have a system called PEF (Protected
Execution Facility) which uses a small ultravisor to allow guests to
run in a way that they can't be eavesdropped by the hypervisor.  The
effect is roughly similar to AMD SEV, although the mechanisms are
quite different.

Most of the work of this is done between the guest, KVM and the
ultravisor, with little need for involvement by qemu.  However qemu
does need to tell KVM to allow secure VMs.

Because the availability of secure mode is a guest visible difference
which depends on having the right hardware and firmware, we don't
enable this by default.  In order to run a secure guest you need to
create a "pef-guest" object and set the confidential-guest-support
property to point to it.

Note that this just *allows* secure guests, the architecture of PEF is
such that the guest still needs to talk to the ultravisor to enter
secure mode.  Qemu has no directl way of knowing if the guest is in
secure mode, and certainly can't know until well after machine
creation time.

To start a PEF-capable guest, use the command line options:
-object pef-guest,id=pef0 -machine confidential-guest-support=pef0

Signed-off-by: David Gibson 
---
 docs/confidential-guest-support.txt |   3 +
 docs/papr-pef.txt   |  30 +++
 hw/ppc/meson.build  |   1 +
 hw/ppc/pef.c| 119 
 hw/ppc/spapr.c  |   6 ++
 include/hw/ppc/pef.h|  25 ++
 target/ppc/kvm.c|  18 -
 target/ppc/kvm_ppc.h|   6 --
 8 files changed, 184 insertions(+), 24 deletions(-)
 create mode 100644 docs/papr-pef.txt
 create mode 100644 hw/ppc/pef.c
 create mode 100644 include/hw/ppc/pef.h

diff --git a/docs/confidential-guest-support.txt 
b/docs/confidential-guest-support.txt
index 2790425b38..f0801814ff 100644
--- a/docs/confidential-guest-support.txt
+++ b/docs/confidential-guest-support.txt
@@ -40,4 +40,7 @@ Currently supported confidential guest mechanisms are:
 AMD Secure Encrypted Virtualization (SEV)
 docs/amd-memory-encryption.txt
 
+POWER Protected Execution Facility (PEF)
+docs/papr-pef.txt
+
 Other mechanisms may be supported in future.
diff --git a/docs/papr-pef.txt b/docs/papr-pef.txt
new file mode 100644
index 00..6419e995cf
--- /dev/null
+++ b/docs/papr-pef.txt
@@ -0,0 +1,30 @@
+POWER (PAPR) Protected Execution Facility (PEF)
+===
+
+Protected Execution Facility (PEF), also known as Secure Guest support
+is a feature found on IBM POWER9 and POWER10 processors.
+
+If a suitable firmware including an Ultravisor is installed, it adds
+an extra memory protection mode to the CPU.  The ultravisor manages a
+pool of secure memory which cannot be accessed by the hypervisor.
+
+When this feature is enabled in qemu, a guest can use ultracalls to
+enter "secure mode".  This transfers most of its memory to secure
+memory, where it cannot be eavesdropped by a compromised hypervisor.
+
+Launching
+-
+
+To launch a guest which will be permitted to enter PEF secure mode:
+
+# ${QEMU} \
+-object pef-guest,id=pef0 \
+-machine confidential-guest-support=pef0 \
+...
+
+Live Migration
+
+
+Live migration is not yet implemented for PEF guests.  For
+consistency, we currently prevent migration if the PEF feature is
+enabled, whether or not the guest has actually entered secure mode.
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index ffa2ec37fa..218631c883 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -27,6 +27,7 @@ ppc_ss.add(when: 'CONFIG_PSERIES', if_true: files(
   'spapr_nvdimm.c',
   'spapr_rtas_ddw.c',
   'spapr_numa.c',
+  'pef.c',
 ))
 ppc_ss.add(when: 'CONFIG_SPAPR_RNG', if_true: files('spapr_rng.c'))
 ppc_ss.add(when: ['CONFIG_PSERIES', 'CONFIG_LINUX'], if_true: files(
diff --git a/hw/ppc/pef.c b/hw/ppc/pef.c
new file mode 100644
index 00..02b9b3b460
--- /dev/null
+++ b/hw/ppc/pef.c
@@ -0,0 +1,119 @@
+/*
+ * PEF (Protected Execution Facility) for POWER support
+ *
+ * Copyright David Gibson, Redhat Inc. 2020
+ *
+ * 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 "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "sysemu/kvm.h"
+#include "migration/blocker.h"
+#include "exec/confidential-guest-support.h"
+#include "hw/ppc/pef.h"
+
+#define TYPE_PEF_GUEST "pef-guest"
+OBJECT_DECLARE_SIMPLE_TYPE(PefGuest, PEF_GUEST)
+
+typedef struct PefGuest PefGuest;
+typedef struct PefGuestClass PefGuestClass;
+
+struct PefGuestClass {
+ConfidentialGuestSupportClass parent_class;
+};
+
+/**
+ * PefGuest:
+ *
+ * The PefGuest object is used for creating and managing a PEF
+ * guest.
+ *
+ * # $QEMU \
+ * -object pef-guest,id=pef0 \
+ * -machine ...,confidential-guest-support=pef0
+ 

[PATCH v7 12/13] confidential guest support: Alter virtio default properties for protected guests

2021-01-13 Thread David Gibson
The default behaviour for virtio devices is not to use the platforms normal
DMA paths, but instead to use the fact that it's running in a hypervisor
to directly access guest memory.  That doesn't work if the guest's memory
is protected from hypervisor access, such as with AMD's SEV or POWER's PEF.

So, if a confidential guest mechanism is enabled, then apply the
iommu_platform=on option so it will go through normal DMA mechanisms.
Those will presumably have some way of marking memory as shared with
the hypervisor or hardware so that DMA will work.

Signed-off-by: David Gibson 
Reviewed-by: Dr. David Alan Gilbert 
Reviewed-by: Cornelia Huck 
Reviewed-by: Greg Kurz 
---
 hw/core/machine.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 5a742b..61ae363559 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -33,6 +33,8 @@
 #include "migration/global_state.h"
 #include "migration/vmstate.h"
 #include "exec/confidential-guest-support.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-pci.h"
 
 GlobalProperty hw_compat_5_2[] = {};
 const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
@@ -1204,6 +1206,17 @@ void machine_run_board_init(MachineState *machine)
  * areas.
  */
 machine_set_mem_merge(OBJECT(machine), false, _abort);
+
+/*
+ * Virtio devices can't count on directly accessing guest
+ * memory, so they need iommu_platform=on to use normal DMA
+ * mechanisms.  That requires also disabling legacy virtio
+ * support for those virtio pci devices which allow it.
+ */
+object_register_sugar_prop(TYPE_VIRTIO_PCI, "disable-legacy",
+   "on", true);
+object_register_sugar_prop(TYPE_VIRTIO_DEVICE, "iommu_platform",
+   "on", false);
 }
 
 machine_class->init(machine);
-- 
2.29.2




Re: [PATCH v6 13/13] s390: Recognize confidential-guest-support option

2021-01-13 Thread David Gibson
On Wed, Jan 13, 2021 at 07:57:41AM +0100, Christian Borntraeger wrote:
> 
> 
> On 13.01.21 01:57, David Gibson wrote:
> > On Tue, Jan 12, 2021 at 12:36:07PM +0100, Cornelia Huck wrote:
> > 65;6201;1c> On Tue, 12 Jan 2021 09:15:26 +0100
> >> Christian Borntraeger  wrote:
> >>
> >>> On 12.01.21 05:45, David Gibson wrote:
>  At least some s390 cpu models support "Protected Virtualization" (PV),
>  a mechanism to protect guests from eavesdropping by a compromised
>  hypervisor.
> 
>  This is similar in function to other mechanisms like AMD's SEV and
>  POWER's PEF, which are controlled by the "confidential-guest-support"
>  machine option.  s390 is a slightly special case, because we already
>  supported PV, simply by using a CPU model with the required feature
>  (S390_FEAT_UNPACK).
> 
>  To integrate this with the option used by other platforms, we
>  implement the following compromise:
> 
>   - When the confidential-guest-support option is set, s390 will
> recognize it, verify that the CPU can support PV (failing if not)
> and set virtio default options necessary for encrypted or protected
> guests, as on other platforms.  i.e. if confidential-guest-support
> is set, we will either create a guest capable of entering PV mode,
> or fail outright.
> 
>   - If confidential-guest-support is not set, guests might still be
> able to enter PV mode, if the CPU has the right model.  This may be
> a little surprising, but shouldn't actually be harmful.
> 
>  To start a guest supporting Protected Virtualization using the new
>  option use the command line arguments:
>  -object s390-pv-guest,id=pv0 -machine confidential-guest-support=pv0 
>   
> >>>
> >>>
> >>> This results in
> >>>
> >>> [cborntra@t35lp61 qemu]$ qemu-system-s390x -enable-kvm -nographic -m 2G 
> >>> -kernel ~/full.normal 
> >>> **
> >>> ERROR:../qom/object.c:317:type_initialize: assertion failed: 
> >>> (parent->instance_size <= ti->instance_size)
> >>> Bail out! ERROR:../qom/object.c:317:type_initialize: assertion failed: 
> >>> (parent->instance_size <= ti->instance_size)
> >>> Aborted (core dumped)
> >>>
> >>
>  +static const TypeInfo s390_pv_guest_info = {
>  +.parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
>  +.name = TYPE_S390_PV_GUEST,
>  +.instance_size = sizeof(S390PVGuestState),
>  +.interfaces = (InterfaceInfo[]) {
>  +{ TYPE_USER_CREATABLE },
>  +{ }
>  +}
>  +};
> >>
> >> I think this needs TYPE_OBJECT in .parent and
> >> TYPE_CONFIDENTIAL_GUEST_SUPPORT as an interface to fix the crash.
> > 
> > No, that was true of an earlier revision, but parent is correct in the
> > current version.
> 
> right now parent is obviously wrong as it triggers the above warning (and all 
> other
> variants in the previous patches also use TYPE_OBJECT). It is probably the 
> right
> thing when you fix
> 
> +struct S390PVGuestState {
> +Object parent_obj;
> +};
> +
> 
> and change Object to the proper type I guess. 

Yes, I think so.  In the next spin I've fixed the parent_obj field (as
well as moving to OBJECT_DEFINE_TYPE()) and it's passing the gitlab
CI, at least.

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


signature.asc
Description: PGP signature


[PATCH v7 04/13] confidential guest support: Move side effect out of machine_set_memory_encryption()

2021-01-13 Thread David Gibson
When the "memory-encryption" property is set, we also disable KSM
merging for the guest, since it won't accomplish anything.

We want that, but doing it in the property set function itself is
thereoretically incorrect, in the unlikely event of some configuration
environment that set the property then cleared it again before
constructing the guest.

More importantly, it makes some other cleanups we want more difficult.
So, instead move this logic to machine_run_board_init() conditional on
the final value of the property.

Signed-off-by: David Gibson 
Reviewed-by: Richard Henderson 
Reviewed-by: Greg Kurz 
---
 hw/core/machine.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index de3b8f1b31..8909117d80 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -437,14 +437,6 @@ static void machine_set_memory_encryption(Object *obj, 
const char *value,
 
 g_free(ms->memory_encryption);
 ms->memory_encryption = g_strdup(value);
-
-/*
- * With memory encryption, the host can't see the real contents of RAM,
- * so there's no point in it trying to merge areas.
- */
-if (value) {
-machine_set_mem_merge(obj, false, errp);
-}
 }
 
 static bool machine_get_nvdimm(Object *obj, Error **errp)
@@ -1166,6 +1158,15 @@ void machine_run_board_init(MachineState *machine)
 cc->deprecation_note);
 }
 
+if (machine->memory_encryption) {
+/*
+ * With memory encryption, the host can't see the real
+ * contents of RAM, so there's no point in it trying to merge
+ * areas.
+ */
+machine_set_mem_merge(OBJECT(machine), false, _abort);
+}
+
 machine_class->init(machine);
 phase_advance(PHASE_MACHINE_INITIALIZED);
 }
-- 
2.29.2




[PATCH v7 09/13] confidential guest support: Update documentation

2021-01-13 Thread David Gibson
Now that we've implemented a generic machine option for configuring various
confidential guest support mechanisms:
  1. Update docs/amd-memory-encryption.txt to reference this rather than
 the earlier SEV specific option
  2. Add a docs/confidential-guest-support.txt to cover the generalities of
 the confidential guest support scheme

Signed-off-by: David Gibson 
---
 docs/amd-memory-encryption.txt  |  2 +-
 docs/confidential-guest-support.txt | 43 +
 2 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 docs/confidential-guest-support.txt

diff --git a/docs/amd-memory-encryption.txt b/docs/amd-memory-encryption.txt
index 80b8eb00e9..145896aec7 100644
--- a/docs/amd-memory-encryption.txt
+++ b/docs/amd-memory-encryption.txt
@@ -73,7 +73,7 @@ complete flow chart.
 To launch a SEV guest
 
 # ${QEMU} \
--machine ...,memory-encryption=sev0 \
+-machine ...,confidential-guest-support=sev0 \
 -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1
 
 Debugging
diff --git a/docs/confidential-guest-support.txt 
b/docs/confidential-guest-support.txt
new file mode 100644
index 00..2790425b38
--- /dev/null
+++ b/docs/confidential-guest-support.txt
@@ -0,0 +1,43 @@
+Confidential Guest Support
+==
+
+Traditionally, hypervisors such as qemu have complete access to a
+guest's memory and other state, meaning that a compromised hypervisor
+can compromise any of its guests.  A number of platforms have added
+mechanisms in hardware and/or firmware which give guests at least some
+protection from a compromised hypervisor.  This is obviously
+especially desirable for public cloud environments.
+
+These mechanisms have different names and different modes of
+operation, but are often referred to as Secure Guests or Confidential
+Guests.  We use the term "Confidential Guest Support" to distinguish
+this from other aspects of guest security (such as security against
+attacks from other guests, or from network sources).
+
+Running a Confidential Guest
+
+
+To run a confidential guest you need to add two command line parameters:
+
+1. Use "-object" to create a "confidential guest support" object.  The
+   type and parameters will vary with the specific mechanism to be
+   used
+2. Set the "confidential-guest-support" machine parameter to the ID of
+   the object from (1).
+
+Example (for AMD SEV)::
+
+qemu-system-x86_64 \
+ \
+-machine ...,confidential-guest-support=sev0 \
+-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1
+
+Supported mechanisms
+
+
+Currently supported confidential guest mechanisms are:
+
+AMD Secure Encrypted Virtualization (SEV)
+docs/amd-memory-encryption.txt
+
+Other mechanisms may be supported in future.
-- 
2.29.2




[PATCH v7 06/13] sev: Add Error ** to sev_kvm_init()

2021-01-13 Thread David Gibson
This allows failures to be reported richly and idiomatically.

Signed-off-by: David Gibson 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Cornelia Huck 
---
 accel/kvm/kvm-all.c  |  4 +++-
 accel/kvm/sev-stub.c |  2 +-
 include/sysemu/sev.h |  2 +-
 target/i386/sev.c| 31 +++
 4 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 28ab126f70..c5b0750fd0 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -2182,9 +2182,11 @@ static int kvm_init(MachineState *ms)
  * encryption context.
  */
 if (ms->cgs) {
+Error *local_err = NULL;
 /* FIXME handle mechanisms other than SEV */
-ret = sev_kvm_init(ms->cgs);
+ret = sev_kvm_init(ms->cgs, _err);
 if (ret < 0) {
+error_report_err(local_err);
 goto err;
 }
 }
diff --git a/accel/kvm/sev-stub.c b/accel/kvm/sev-stub.c
index 3d4787ae4a..512e205f7f 100644
--- a/accel/kvm/sev-stub.c
+++ b/accel/kvm/sev-stub.c
@@ -15,7 +15,7 @@
 #include "qemu-common.h"
 #include "sysemu/sev.h"
 
-int sev_kvm_init(ConfidentialGuestSupport *cgs)
+int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
 {
 /* SEV can't be selected if it's not compiled */
 g_assert_not_reached();
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 3b5b1aacf1..5c5a13c6ca 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -16,7 +16,7 @@
 
 #include "sysemu/kvm.h"
 
-int sev_kvm_init(ConfidentialGuestSupport *cgs);
+int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
 int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp);
 int sev_inject_launch_secret(const char *hdr, const char *secret,
  uint64_t gpa, Error **errp);
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 5399a136ad..e2b41ef342 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -662,7 +662,7 @@ sev_vm_state_change(void *opaque, int running, RunState 
state)
 }
 }
 
-int sev_kvm_init(ConfidentialGuestSupport *cgs)
+int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
 {
 SevGuestState *sev = SEV_GUEST(cgs);
 char *devname;
@@ -684,14 +684,14 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs)
 host_cbitpos = ebx & 0x3f;
 
 if (host_cbitpos != sev->cbitpos) {
-error_report("%s: cbitpos check failed, host '%d' requested '%d'",
- __func__, host_cbitpos, sev->cbitpos);
+error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
+   __func__, host_cbitpos, sev->cbitpos);
 goto err;
 }
 
 if (sev->reduced_phys_bits < 1) {
-error_report("%s: reduced_phys_bits check failed, it should be >=1,"
- " requested '%d'", __func__, sev->reduced_phys_bits);
+error_setg(errp, "%s: reduced_phys_bits check failed, it should be 
>=1,"
+   " requested '%d'", __func__, sev->reduced_phys_bits);
 goto err;
 }
 
@@ -700,20 +700,19 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs)
 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
 sev->sev_fd = open(devname, O_RDWR);
 if (sev->sev_fd < 0) {
-error_report("%s: Failed to open %s '%s'", __func__,
- devname, strerror(errno));
-}
-g_free(devname);
-if (sev->sev_fd < 0) {
+error_setg(errp, "%s: Failed to open %s '%s'", __func__,
+   devname, strerror(errno));
+g_free(devname);
 goto err;
 }
+g_free(devname);
 
 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, ,
  _error);
 if (ret) {
-error_report("%s: failed to get platform status ret=%d "
- "fw_error='%d: %s'", __func__, ret, fw_error,
- fw_error_to_str(fw_error));
+error_setg(errp, "%s: failed to get platform status ret=%d "
+   "fw_error='%d: %s'", __func__, ret, fw_error,
+   fw_error_to_str(fw_error));
 goto err;
 }
 sev->build_id = status.build;
@@ -723,14 +722,14 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs)
 trace_kvm_sev_init();
 ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, _error);
 if (ret) {
-error_report("%s: failed to initialize ret=%d fw_error=%d '%s'",
- __func__, ret, fw_error, fw_error_to_str(fw_error));
+error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
+   __func__, ret, fw_error, fw_error_to_str(fw_error));
 goto err;
 }
 
 ret = sev_launch_start(sev);
 if (ret) {
-error_report("%s: failed to create encryption context", __func__);
+error_setg(errp, "%s: failed to create encryption context", __func__);
 goto err;
 }
 
-- 
2.29.2




[PATCH v7 01/13] qom: Allow optional sugar props

2021-01-13 Thread David Gibson
From: Greg Kurz 

Global properties have an @optional field, which allows to apply a given
property to a given type even if one of its subclasses doesn't support
it. This is especially used in the compat code when dealing with the
"disable-modern" and "disable-legacy" properties and the "virtio-pci"
type.

Allow object_register_sugar_prop() to set this field as well.

Signed-off-by: Greg Kurz 
Message-Id: <159738953558.377274.16617742952571083440.st...@bahia.lan>
Signed-off-by: David Gibson 
Reviewed-by: Eduardo Habkost 
Reviewed-by: Cornelia Huck 
Reviewed-by: Philippe Mathieu-Daudé 
---
 include/qom/object.h |  3 ++-
 qom/object.c |  4 +++-
 softmmu/rtc.c|  3 ++-
 softmmu/vl.c | 17 +++--
 4 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/include/qom/object.h b/include/qom/object.h
index d378f13a11..6721cd312e 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -638,7 +638,8 @@ bool object_apply_global_props(Object *obj, const GPtrArray 
*props,
Error **errp);
 void object_set_machine_compat_props(GPtrArray *compat_props);
 void object_set_accelerator_compat_props(GPtrArray *compat_props);
-void object_register_sugar_prop(const char *driver, const char *prop, const 
char *value);
+void object_register_sugar_prop(const char *driver, const char *prop,
+const char *value, bool optional);
 void object_apply_compat_props(Object *obj);
 
 /**
diff --git a/qom/object.c b/qom/object.c
index 2fa0119647..491823db4a 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -442,7 +442,8 @@ static GPtrArray *object_compat_props[3];
  * other than "-global".  These are generally used for syntactic
  * sugar and legacy command line options.
  */
-void object_register_sugar_prop(const char *driver, const char *prop, const 
char *value)
+void object_register_sugar_prop(const char *driver, const char *prop,
+const char *value, bool optional)
 {
 GlobalProperty *g;
 if (!object_compat_props[2]) {
@@ -452,6 +453,7 @@ void object_register_sugar_prop(const char *driver, const 
char *prop, const char
 g->driver = g_strdup(driver);
 g->property = g_strdup(prop);
 g->value = g_strdup(value);
+g->optional = optional;
 g_ptr_array_add(object_compat_props[2], g);
 }
 
diff --git a/softmmu/rtc.c b/softmmu/rtc.c
index e1e15ef613..5632684fc9 100644
--- a/softmmu/rtc.c
+++ b/softmmu/rtc.c
@@ -179,7 +179,8 @@ void configure_rtc(QemuOpts *opts)
 if (!strcmp(value, "slew")) {
 object_register_sugar_prop("mc146818rtc",
"lost_tick_policy",
-   "slew");
+   "slew",
+   false);
 } else if (!strcmp(value, "none")) {
 /* discard is default */
 } else {
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 7ddf405d76..3f7721b83e 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -1663,16 +1663,20 @@ static int machine_set_property(void *opaque,
 return 0;
 }
 if (g_str_equal(qom_name, "igd-passthru")) {
-object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), qom_name, value);
+object_register_sugar_prop(ACCEL_CLASS_NAME("xen"), qom_name, value,
+   false);
 return 0;
 }
 if (g_str_equal(qom_name, "kvm-shadow-mem")) {
-object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value);
+object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value,
+   false);
 return 0;
 }
 if (g_str_equal(qom_name, "kernel-irqchip")) {
-object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value);
-object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), qom_name, value);
+object_register_sugar_prop(ACCEL_CLASS_NAME("kvm"), qom_name, value,
+   false);
+object_register_sugar_prop(ACCEL_CLASS_NAME("whpx"), qom_name, value,
+   false);
 return 0;
 }
 
@@ -2297,9 +2301,10 @@ static void qemu_process_sugar_options(void)
 
 val = g_strdup_printf("%d",
  (uint32_t) 
qemu_opt_get_number(qemu_find_opts_singleton("smp-opts"), "cpus", 1));
-object_register_sugar_prop("memory-backend", "prealloc-threads", val);
+object_register_sugar_prop("memory-backend", "prealloc-threads", val,
+   false);
 g_free(val);
-object_register_sugar_prop("memory-backend", "prealloc", "on");
+object_register_sugar_prop("memory-backend", "prealloc", "on", false);
 }
 
 if (watchdog) {
-- 
2.29.2




[PATCH v7 05/13] confidential guest support: Rework the "memory-encryption" property

2021-01-13 Thread David Gibson
Currently the "memory-encryption" property is only looked at once we
get to kvm_init().  Although protection of guest memory from the
hypervisor isn't something that could really ever work with TCG, it's
not conceptually tied to the KVM accelerator.

In addition, the way the string property is resolved to an object is
almost identical to how a QOM link property is handled.

So, create a new "confidential-guest-support" link property which sets
this QOM interface link directly in the machine.  For compatibility we
keep the "memory-encryption" property, but now implemented in terms of
the new property.

Signed-off-by: David Gibson 
Reviewed-by: Greg Kurz 
---
 accel/kvm/kvm-all.c  |  5 +++--
 accel/kvm/sev-stub.c |  5 +++--
 hw/core/machine.c| 43 +--
 include/hw/boards.h  |  2 +-
 include/sysemu/sev.h |  2 +-
 target/i386/sev.c| 32 ++--
 6 files changed, 47 insertions(+), 42 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 260ed73ffe..28ab126f70 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -2181,8 +2181,9 @@ static int kvm_init(MachineState *ms)
  * if memory encryption object is specified then initialize the memory
  * encryption context.
  */
-if (ms->memory_encryption) {
-ret = sev_guest_init(ms->memory_encryption);
+if (ms->cgs) {
+/* FIXME handle mechanisms other than SEV */
+ret = sev_kvm_init(ms->cgs);
 if (ret < 0) {
 goto err;
 }
diff --git a/accel/kvm/sev-stub.c b/accel/kvm/sev-stub.c
index 5db9ab8f00..3d4787ae4a 100644
--- a/accel/kvm/sev-stub.c
+++ b/accel/kvm/sev-stub.c
@@ -15,7 +15,8 @@
 #include "qemu-common.h"
 #include "sysemu/sev.h"
 
-int sev_guest_init(const char *id)
+int sev_kvm_init(ConfidentialGuestSupport *cgs)
 {
-return -1;
+/* SEV can't be selected if it's not compiled */
+g_assert_not_reached();
 }
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 8909117d80..94194ab82d 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -32,6 +32,7 @@
 #include "hw/mem/nvdimm.h"
 #include "migration/global_state.h"
 #include "migration/vmstate.h"
+#include "exec/confidential-guest-support.h"
 
 GlobalProperty hw_compat_5_2[] = {};
 const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
@@ -427,16 +428,37 @@ static char *machine_get_memory_encryption(Object *obj, 
Error **errp)
 {
 MachineState *ms = MACHINE(obj);
 
-return g_strdup(ms->memory_encryption);
+if (ms->cgs) {
+return g_strdup(object_get_canonical_path_component(OBJECT(ms->cgs)));
+}
+
+return NULL;
 }
 
 static void machine_set_memory_encryption(Object *obj, const char *value,
 Error **errp)
 {
-MachineState *ms = MACHINE(obj);
+Object *cgs =
+object_resolve_path_component(object_get_objects_root(), value);
+
+if (!cgs) {
+error_setg(errp, "No such memory encryption object '%s'", value);
+return;
+}
 
-g_free(ms->memory_encryption);
-ms->memory_encryption = g_strdup(value);
+object_property_set_link(obj, "confidential-guest-support", cgs, errp);
+}
+
+static void machine_check_confidential_guest_support(const Object *obj,
+ const char *name,
+ Object *new_target,
+ Error **errp)
+{
+/*
+ * So far the only constraint is that the target has the
+ * TYPE_CONFIDENTIAL_GUEST_SUPPORT interface, and that's checked
+ * by the QOM core
+ */
 }
 
 static bool machine_get_nvdimm(Object *obj, Error **errp)
@@ -836,6 +858,15 @@ static void machine_class_init(ObjectClass *oc, void *data)
 object_class_property_set_description(oc, "suppress-vmdesc",
 "Set on to disable self-describing migration");
 
+object_class_property_add_link(oc, "confidential-guest-support",
+   TYPE_CONFIDENTIAL_GUEST_SUPPORT,
+   offsetof(MachineState, cgs),
+   machine_check_confidential_guest_support,
+   OBJ_PROP_LINK_STRONG);
+object_class_property_set_description(oc, "confidential-guest-support",
+  "Set confidential guest scheme to 
support");
+
+/* For compatibility */
 object_class_property_add_str(oc, "memory-encryption",
 machine_get_memory_encryption, machine_set_memory_encryption);
 object_class_property_set_description(oc, "memory-encryption",
@@ -1158,9 +1189,9 @@ void machine_run_board_init(MachineState *machine)
 cc->deprecation_note);
 }
 
-if (machine->memory_encryption) {
+if (machine->cgs) {
 /*
- * With memory encryption, the host can't see the real
+ * With confidential guests, the 

[PATCH v7 00/13] Generalize memory encryption models

2021-01-13 Thread David Gibson
A number of hardware platforms are implementing mechanisms whereby the
hypervisor does not have unfettered access to guest memory, in order
to mitigate the security impact of a compromised hypervisor.

AMD's SEV implements this with in-cpu memory encryption, and Intel has
its own memory encryption mechanism.  POWER has an upcoming mechanism
to accomplish this in a different way, using a new memory protection
level plus a small trusted ultravisor.  s390 also has a protected
execution environment.

The current code (committed or draft) for these features has each
platform's version configured entirely differently.  That doesn't seem
ideal for users, or particularly for management layers.

AMD SEV introduces a notionally generic machine option
"machine-encryption", but it doesn't actually cover any cases other
than SEV.

This series is a proposal to at least partially unify configuration
for these mechanisms, by renaming and generalizing AMD's
"memory-encryption" property.  It is replaced by a
"confidential-guest-support" property pointing to a platform specific
object which configures and manages the specific details.

Note to Ram Pai: the documentation I've included for PEF is very
minimal.  If you could send a patch expanding on that, it would be
very helpful.

Changes since v6:
 * Moved to using OBJECT_DECLARE_TYPE and OBJECT_DEFINE_TYPE macros
 * Assorted minor fixes
Changes since v5:
 * Renamed from "securable guest memory" to "confidential guest
   support"
 * Simpler reworking of x86 boot time flash encryption
 * Added a bunch of documentation
 * Fixed some compile errors on POWER
Changes since v4:
 * Renamed from "host trust limitation" to "securable guest memory",
   which I think is marginally more descriptive
 * Re-organized initialization, because the previous model called at
   kvm_init didn't work for s390
 * Assorted fixes to the s390 implementation; rudimentary testing
   (gitlab CI) only
Changes since v3:
 * Rebased
 * Added first cut at handling of s390 protected virtualization
Changes since RFCv2:
 * Rebased
 * Removed preliminary SEV cleanups (they've been merged)
 * Changed name to "host trust limitation"
 * Added migration blocker to the PEF code (based on SEV's version)
Changes since RFCv1:
 * Rebased
 * Fixed some errors pointed out by Dave Gilbert

David Gibson (12):
  confidential guest support: Introduce new confidential guest support
class
  sev: Remove false abstraction of flash encryption
  confidential guest support: Move side effect out of
machine_set_memory_encryption()
  confidential guest support: Rework the "memory-encryption" property
  sev: Add Error ** to sev_kvm_init()
  confidential guest support: Introduce cgs "ready" flag
  confidential guest support: Move SEV initialization into arch specific
code
  confidential guest support: Update documentation
  spapr: Add PEF based confidential guest support
  spapr: PEF: prevent migration
  confidential guest support: Alter virtio default properties for
protected guests
  s390: Recognize confidential-guest-support option

Greg Kurz (1):
  qom: Allow optional sugar props

 accel/kvm/kvm-all.c   |  38 ---
 accel/kvm/sev-stub.c  |  10 +-
 accel/stubs/kvm-stub.c|  10 --
 backends/confidential-guest-support.c |  33 ++
 backends/meson.build  |   1 +
 docs/amd-memory-encryption.txt|   2 +-
 docs/confidential-guest-support.txt   |  49 +
 docs/papr-pef.txt |  30 ++
 docs/system/s390x/protvirt.rst|  19 ++--
 hw/core/machine.c |  71 ++--
 hw/i386/pc_sysfw.c|  17 ++-
 hw/ppc/meson.build|   1 +
 hw/ppc/pef.c  | 126 ++
 hw/ppc/spapr.c|   6 ++
 hw/s390x/pv.c |  62 +++
 include/exec/confidential-guest-support.h |  40 +++
 include/hw/boards.h   |   2 +-
 include/hw/ppc/pef.h  |  25 +
 include/hw/s390x/pv.h |   1 +
 include/qemu/typedefs.h   |   1 +
 include/qom/object.h  |   3 +-
 include/sysemu/kvm.h  |  16 ---
 include/sysemu/sev.h  |   4 +-
 qom/object.c  |   4 +-
 softmmu/rtc.c |   3 +-
 softmmu/vl.c  |  17 +--
 target/i386/kvm/kvm.c |  12 +++
 target/i386/sev-stub.c|   5 +
 target/i386/sev.c |  93 +++-
 target/ppc/kvm.c  |  18 
 target/ppc/kvm_ppc.h  |   6 --
 target/s390x/kvm.c|   3 +
 32 files changed, 539 insertions(+), 189 deletions(-)
 create mode 100644 backends/confidential-guest-support.c
 create mode 

[PATCH v7 03/13] sev: Remove false abstraction of flash encryption

2021-01-13 Thread David Gibson
When AMD's SEV memory encryption is in use, flash memory banks (which are
initialed by pc_system_flash_map()) need to be encrypted with the guest's
key, so that the guest can read them.

That's abstracted via the kvm_memcrypt_encrypt_data() callback in the KVM
state.. except, that it doesn't really abstract much at all.

For starters, the only called is in code specific to the 'pc' family of
machine types, so it's obviously specific to those and to x86 to begin
with.  But it makes a bunch of further assumptions that need not be true
about an arbitrary confidential guest system based on memory encryption,
let alone one based on other mechanisms:

 * it assumes that the flash memory is defined to be encrypted with the
   guest key, rather than being shared with hypervisor
 * it assumes that that hypervisor has some mechanism to encrypt data into
   the guest, even though it can't decrypt it out, since that's the whole
   point
 * the interface assumes that this encrypt can be done in place, which
   implies that the hypervisor can write into a confidential guests's
   memory, even if what it writes isn't meaningful

So really, this "abstraction" is actually pretty specific to the way SEV
works.  So, this patch removes it and instead has the PC flash
initialization code call into a SEV specific callback.

Signed-off-by: David Gibson 
---
 accel/kvm/kvm-all.c| 31 ++-
 accel/kvm/sev-stub.c   |  9 ++---
 accel/stubs/kvm-stub.c | 10 --
 hw/i386/pc_sysfw.c | 17 ++---
 include/sysemu/kvm.h   | 16 
 include/sysemu/sev.h   |  4 ++--
 target/i386/sev-stub.c |  5 +
 target/i386/sev.c  | 24 ++--
 8 files changed, 31 insertions(+), 85 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 389eaace72..260ed73ffe 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -120,10 +120,6 @@ struct KVMState
 KVMMemoryListener memory_listener;
 QLIST_HEAD(, KVMParkedVcpu) kvm_parked_vcpus;
 
-/* memory encryption */
-void *memcrypt_handle;
-int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len);
-
 /* For "info mtree -f" to tell if an MR is registered in KVM */
 int nr_as;
 struct KVMAs {
@@ -222,26 +218,6 @@ int kvm_get_max_memslots(void)
 return s->nr_slots;
 }
 
-bool kvm_memcrypt_enabled(void)
-{
-if (kvm_state && kvm_state->memcrypt_handle) {
-return true;
-}
-
-return false;
-}
-
-int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
-{
-if (kvm_state->memcrypt_handle &&
-kvm_state->memcrypt_encrypt_data) {
-return kvm_state->memcrypt_encrypt_data(kvm_state->memcrypt_handle,
-  ptr, len);
-}
-
-return 1;
-}
-
 /* Called with KVMMemoryListener.slots_lock held */
 static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
 {
@@ -2206,13 +2182,10 @@ static int kvm_init(MachineState *ms)
  * encryption context.
  */
 if (ms->memory_encryption) {
-kvm_state->memcrypt_handle = sev_guest_init(ms->memory_encryption);
-if (!kvm_state->memcrypt_handle) {
-ret = -1;
+ret = sev_guest_init(ms->memory_encryption);
+if (ret < 0) {
 goto err;
 }
-
-kvm_state->memcrypt_encrypt_data = sev_encrypt_data;
 }
 
 ret = kvm_arch_init(ms, s);
diff --git a/accel/kvm/sev-stub.c b/accel/kvm/sev-stub.c
index 4f97452585..5db9ab8f00 100644
--- a/accel/kvm/sev-stub.c
+++ b/accel/kvm/sev-stub.c
@@ -15,12 +15,7 @@
 #include "qemu-common.h"
 #include "sysemu/sev.h"
 
-int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len)
+int sev_guest_init(const char *id)
 {
-abort();
-}
-
-void *sev_guest_init(const char *id)
-{
-return NULL;
+return -1;
 }
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index 680e099463..0f17acfac0 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -81,16 +81,6 @@ int kvm_on_sigbus(int code, void *addr)
 return 1;
 }
 
-bool kvm_memcrypt_enabled(void)
-{
-return false;
-}
-
-int kvm_memcrypt_encrypt_data(uint8_t *ptr, uint64_t len)
-{
-  return 1;
-}
-
 #ifndef CONFIG_USER_ONLY
 int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
 {
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 92e90ff013..11172214f1 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -38,6 +38,7 @@
 #include "sysemu/sysemu.h"
 #include "hw/block/flash.h"
 #include "sysemu/kvm.h"
+#include "sysemu/sev.h"
 
 #define FLASH_SECTOR_SIZE 4096
 
@@ -147,7 +148,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
 PFlashCFI01 *system_flash;
 MemoryRegion *flash_mem;
 void *flash_ptr;
-int ret, flash_size;
+int flash_size;
 
 assert(PC_MACHINE_GET_CLASS(pcms)->pci_enabled);
 
@@ -191,16 +192,10 @@ static void pc_system_flash_map(PCMachineState *pcms,
 flash_mem = 

[PATCH v7 02/13] confidential guest support: Introduce new confidential guest support class

2021-01-13 Thread David Gibson
Several architectures have mechanisms which are designed to protect guest
memory from interference or eavesdropping by a compromised hypervisor.  AMD
SEV does this with in-chip memory encryption and Intel's MKTME can do
similar things.  POWER's Protected Execution Framework (PEF) accomplishes a
similar goal using an ultravisor and new memory protection features,
instead of encryption.

To (partially) unify handling for these, this introduces a new
ConfidentialGuestSupport QOM base class.  "Confidential" is kind of vague,
but "confidential computing" seems to be the buzzword about these schemes,
and "secure" or "protected" are often used in connection to unrelated
things (such as hypervisor-from-guest or guest-from-guest security).

The "support" in the name is significant because in at least some of the
cases it requires the guest to take specific actions in order to protect
itself from hypervisor eavesdropping.

Signed-off-by: David Gibson 
---
 backends/confidential-guest-support.c | 33 
 backends/meson.build  |  1 +
 include/exec/confidential-guest-support.h | 38 +++
 include/qemu/typedefs.h   |  1 +
 target/i386/sev.c |  3 +-
 5 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 backends/confidential-guest-support.c
 create mode 100644 include/exec/confidential-guest-support.h

diff --git a/backends/confidential-guest-support.c 
b/backends/confidential-guest-support.c
new file mode 100644
index 00..9b0ded0db4
--- /dev/null
+++ b/backends/confidential-guest-support.c
@@ -0,0 +1,33 @@
+/*
+ * QEMU Confidential Guest support
+ *
+ * Copyright: David Gibson, Red Hat Inc. 2020
+ *
+ * Authors:
+ *  David Gibson 
+ *
+ * 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 "exec/confidential-guest-support.h"
+
+OBJECT_DEFINE_ABSTRACT_TYPE(ConfidentialGuestSupport,
+confidential_guest_support,
+CONFIDENTIAL_GUEST_SUPPORT,
+OBJECT)
+
+static void confidential_guest_support_class_init(ObjectClass *oc, void *data)
+{
+}
+
+static void confidential_guest_support_init(Object *obj)
+{
+}
+
+static void confidential_guest_support_finalize(Object *obj)
+{
+}
diff --git a/backends/meson.build b/backends/meson.build
index 484456ece7..d4221831fc 100644
--- a/backends/meson.build
+++ b/backends/meson.build
@@ -6,6 +6,7 @@ softmmu_ss.add([files(
   'rng-builtin.c',
   'rng-egd.c',
   'rng.c',
+  'confidential-guest-support.c',
 ), numa])
 
 softmmu_ss.add(when: 'CONFIG_POSIX', if_true: files('rng-random.c'))
diff --git a/include/exec/confidential-guest-support.h 
b/include/exec/confidential-guest-support.h
new file mode 100644
index 00..5f131023ba
--- /dev/null
+++ b/include/exec/confidential-guest-support.h
@@ -0,0 +1,38 @@
+/*
+ * QEMU Confidential Guest support
+ *   This interface describes the common pieces between various
+ *   schemes for protecting guest memory or other state against a
+ *   compromised hypervisor.  This includes memory encryption (AMD's
+ *   SEV and Intel's MKTME) or special protection modes (PEF on POWER,
+ *   or PV on s390x).
+ *
+ * Copyright: David Gibson, Red Hat Inc. 2020
+ *
+ * Authors:
+ *  David Gibson 
+ *
+ * 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_CONFIDENTIAL_GUEST_SUPPORT_H
+#define QEMU_CONFIDENTIAL_GUEST_SUPPORT_H
+
+#ifndef CONFIG_USER_ONLY
+
+#include "qom/object.h"
+
+#define TYPE_CONFIDENTIAL_GUEST_SUPPORT "confidential-guest-support"
+OBJECT_DECLARE_SIMPLE_TYPE(ConfidentialGuestSupport, 
CONFIDENTIAL_GUEST_SUPPORT)
+
+struct ConfidentialGuestSupport {
+Object parent;
+};
+
+typedef struct ConfidentialGuestSupportClass {
+ObjectClass parent;
+} ConfidentialGuestSupportClass;
+
+#endif /* !CONFIG_USER_ONLY */
+
+#endif /* QEMU_CONFIDENTIAL_GUEST_SUPPORT_H */
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 976b529dfb..33685c79ed 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -36,6 +36,7 @@ typedef struct BusState BusState;
 typedef struct Chardev Chardev;
 typedef struct CompatProperty CompatProperty;
 typedef struct CoMutex CoMutex;
+typedef struct ConfidentialGuestSupport ConfidentialGuestSupport;
 typedef struct CPUAddressSpace CPUAddressSpace;
 typedef struct CPUState CPUState;
 typedef struct DeviceListener DeviceListener;
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 1546606811..6b49925f51 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -31,6 +31,7 @@
 #include "qom/object.h"
 #include "exec/address-spaces.h"
 #include "monitor/monitor.h"
+#include "exec/confidential-guest-support.h"
 
 #define TYPE_SEV_GUEST "sev-guest"
 

Re: [PATCH v4 11/11] vfio: Disable only uncoordinated discards

2021-01-13 Thread Alex Williamson
On Thu,  7 Jan 2021 14:34:23 +0100
David Hildenbrand  wrote:

> We support coordinated discarding of RAM using the RamDiscardMgr. Let's
> unlock support for coordinated discards, keeping uncoordinated discards
> (e.g., via virtio-balloon) disabled.
> 
> This unlocks virtio-mem + vfio. Note that vfio used via "nvme://" by the
> block layer has to be implemented/unlocked separately. For now,
> virtio-mem only supports x86-64 - spapr IOMMUs are not tested/affected.

I think SPAPR always uses a vIOMMU, but I won't claim to understand it.
Is there anything other than testing that restricts it to x86-64?  ARM
and S390 will use the same type1 IOMMU backend as far as vfio support
is concerned.  Should we do something more than put it in a commit log
if we really want to prevent it elsewhere?  Thanks,

Alex
 
> Note: The block size of a virtio-mem device has to be set to sane sizes,
> depending on the maximum hotplug size - to not run out of vfio mappings.
> The default virtio-mem block size is usually in the range of a couple of
> MBs. The maximum number of mapping is 64k, shared with other users.
> Assume you want to hotplug 256GB using virtio-mem - the block size would
> have to be set to at least 8 MiB (resulting in 32768 separate mappings).
> 
> Reviewed-by: Pankaj Gupta 
> Cc: Paolo Bonzini 
> Cc: "Michael S. Tsirkin" 
> Cc: Alex Williamson 
> Cc: Dr. David Alan Gilbert 
> Cc: Igor Mammedov 
> Cc: Pankaj Gupta 
> Cc: Peter Xu 
> Cc: Auger Eric 
> Cc: Wei Yang 
> Cc: teawater 
> Cc: Marek Kedzierski 
> Signed-off-by: David Hildenbrand 
> ---
>  hw/vfio/common.c | 10 ++
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index 2b9ba3f8c9..ee7a82524a 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -1976,8 +1976,10 @@ static int vfio_connect_container(VFIOGroup *group, 
> AddressSpace *as,
>   * new memory, it will not yet set ram_block_discard_set_required() and
>   * therefore, neither stops us here or deals with the sudden memory
>   * consumption of inflated memory.
> + *
> + * We do support discarding of memory coordinated via the RamDiscardMgr.
>   */
> -ret = ram_block_discard_disable(true);
> +ret = ram_block_uncoordinated_discard_disable(true);
>  if (ret) {
>  error_setg_errno(errp, -ret, "Cannot set discarding of RAM broken");
>  return ret;
> @@ -2157,7 +2159,7 @@ close_fd_exit:
>  close(fd);
>  
>  put_space_exit:
> -ram_block_discard_disable(false);
> +ram_block_uncoordinated_discard_disable(false);
>  vfio_put_address_space(space);
>  
>  return ret;
> @@ -2279,7 +2281,7 @@ void vfio_put_group(VFIOGroup *group)
>  }
>  
>  if (!group->ram_block_discard_allowed) {
> -ram_block_discard_disable(false);
> +ram_block_uncoordinated_discard_disable(false);
>  }
>  vfio_kvm_device_del_group(group);
>  vfio_disconnect_container(group);
> @@ -2333,7 +2335,7 @@ int vfio_get_device(VFIOGroup *group, const char *name,
>  
>  if (!group->ram_block_discard_allowed) {
>  group->ram_block_discard_allowed = true;
> -ram_block_discard_disable(false);
> +ram_block_uncoordinated_discard_disable(false);
>  }
>  }
>  




Re: [PATCH 1/2] trace: document how to specify multiple --trace patterns

2021-01-13 Thread BALATON Zoltan

On Wed, 13 Jan 2021, John Snow wrote:

On 1/13/21 5:15 PM, Eric Blake wrote:

On 1/13/21 3:42 PM, John Snow wrote:

On 1/13/21 4:48 AM, Stefan Hajnoczi wrote:

QEMU options are single dash with double dash accepted for
compatibility but
help and other docs have single dash so these (and below) should be
-trace.
(Also a bit less typing for otherwise already way too long command
lines.)

Is this documented somewhere?

I was under the impression that '-' is legacy syntax and '--' is the
preferred syntax. There are examples of '--' on the QEMU man page.


Historically, uses of 'getopt_long()' support only double dash, while
'getopt_long_only()' support both single and double.  While qemu does
not use getopt_long_only() (because it rolls its own parser instead), it
certainly tries to behave as if it does.  Meanwhile, our other tools
like qemu-img or qemu-storage-daemon use getopt_long().  I'm in favor of
preferring the double-dash in documentation, even when single-dash
works, especially for any option (like --trace) that is used for more
tools than just qemu proper, because it makes for easier copy-paste
between options that work for all tools in the qemu suite rather than
just qemu.



Yes, this makes sense.



Let's reach agreement, document it, and then make the documentation
consistent.

Stefan


My naive impression was that double-dash is the preferred idiom in
linuxdom in general for any multi-character option.

We might hang on to single-dash for backwards compatibility, but I doubt
we want to enshrine that as our preferred way.

Is there a reasoning I am unaware of?


Continuing to document '-machine' instead of '--machine' for qemu is
debatable because we don't support 'qemu-img --machine' or
'qemu-storage-daemon --machine'; but since 'qemu-img -trace' is an error
while 'qemu-img --trace' works, I'm definitely in favor of preferring
'--trace' everywhere in our docs.



At that point, it's a guessing game as to which binaries support which flags 
and using which spellings -- maybe some will pick up new flags later and so 
on.


Skip the fuss and just insist on the double dash, I think.


Please don't. That would break all scripts that already call qemu using 
single dash options. Forcing everyone to edit their scripts is not nice. 
How about also accepting single dash in qemu-img for consistency then you 
can use whatever you want in docs as long as single dash still works for 
consistency and backward compatibility.


Regards,
BALATON Zoltan



Re: [PATCH v4 06/11] vfio: Sanity check maximum number of DMA mappings with RamDiscardMgr

2021-01-13 Thread Alex Williamson
On Thu,  7 Jan 2021 14:34:18 +0100
David Hildenbrand  wrote:

> Although RamDiscardMgr can handle running into the maximum number of
> DMA mappings by propagating errors when creating a DMA mapping, we want
> to sanity check and warn the user early that there is a theoretical setup
> issue and that virtio-mem might not be able to provide as much memory
> towards a VM as desired.
> 
> As suggested by Alex, let's use the number of KVM memory slots to guess
> how many other mappings we might see over time.
> 
> Cc: Paolo Bonzini 
> Cc: "Michael S. Tsirkin" 
> Cc: Alex Williamson 
> Cc: Dr. David Alan Gilbert 
> Cc: Igor Mammedov 
> Cc: Pankaj Gupta 
> Cc: Peter Xu 
> Cc: Auger Eric 
> Cc: Wei Yang 
> Cc: teawater 
> Cc: Marek Kedzierski 
> Signed-off-by: David Hildenbrand 
> ---
>  hw/vfio/common.c | 43 +++
>  1 file changed, 43 insertions(+)
> 
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index 1babb6bb99..bc20f738ce 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -758,6 +758,49 @@ static void 
> vfio_register_ram_discard_notifier(VFIOContainer *container,
>vfio_ram_discard_notify_discard_all);
>  rdmc->register_listener(rdm, section->mr, >listener);
>  QLIST_INSERT_HEAD(>vrdl_list, vrdl, next);
> +
> +/*
> + * Sanity-check if we have a theoretically problematic setup where we 
> could
> + * exceed the maximum number of possible DMA mappings over time. We 
> assume
> + * that each mapped section in the same address space as a RamDiscardMgr
> + * section consumes exactly one DMA mapping, with the exception of
> + * RamDiscardMgr sections; i.e., we don't expect to have gIOMMU sections 
> in
> + * the same address space as RamDiscardMgr sections.
> + *
> + * We assume that each section in the address space consumes one memslot.
> + * We take the number of KVM memory slots as a best guess for the maximum
> + * number of sections in the address space we could have over time,
> + * also consuming DMA mappings.
> + */
> +if (container->dma_max_mappings) {
> +unsigned int vrdl_count = 0, vrdl_mappings = 0, max_memslots = 512;
> +
> +#ifdef CONFIG_KVM
> +if (kvm_enabled()) {
> +max_memslots = kvm_get_max_memslots();
> +}
> +#endif
> +
> +QLIST_FOREACH(vrdl, >vrdl_list, next) {
> +hwaddr start, end;
> +
> +start = QEMU_ALIGN_DOWN(vrdl->offset_within_address_space,
> +vrdl->granularity);
> +end = ROUND_UP(vrdl->offset_within_address_space + vrdl->size,
> +   vrdl->granularity);
> +vrdl_mappings = (end - start) / vrdl->granularity;

---> += ?


> +vrdl_count++;
> +}
> +
> +if (vrdl_mappings + max_memslots - vrdl_count >
> +container->dma_max_mappings) {
> +warn_report("%s: possibly running out of DMA mappings. E.g., try"
> +" increasing the 'block-size' of virtio-mem devies."
> +" Maximum possible DMA mappings: %d, Maximum 
> possible"
> +" memslots: %d", __func__, 
> container->dma_max_mappings,
> +max_memslots);
> +}
> +}
>  }
>  
>  static void vfio_unregister_ram_discard_listener(VFIOContainer *container,




Re: [PATCH v4 05/11] vfio: Query and store the maximum number of possible DMA mappings

2021-01-13 Thread Alex Williamson
On Thu,  7 Jan 2021 14:34:17 +0100
David Hildenbrand  wrote:

> Let's query the maximum number of possible DMA mappings by querying the
> available mappings when creating the container (before any mappings are
> created). We'll use this informaton soon to perform some sanity checks
> and warn the user.
> 
> Cc: Paolo Bonzini 
> Cc: "Michael S. Tsirkin" 
> Cc: Alex Williamson 
> Cc: Dr. David Alan Gilbert 
> Cc: Igor Mammedov 
> Cc: Pankaj Gupta 
> Cc: Peter Xu 
> Cc: Auger Eric 
> Cc: Wei Yang 
> Cc: teawater 
> Cc: Marek Kedzierski 
> Signed-off-by: David Hildenbrand 
> ---
>  hw/vfio/common.c  | 4 
>  include/hw/vfio/vfio-common.h | 1 +
>  2 files changed, 5 insertions(+)
> 
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index 2bd219cf1d..1babb6bb99 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -1934,6 +1934,7 @@ static int vfio_connect_container(VFIOGroup *group, 
> AddressSpace *as,
>  container->fd = fd;
>  container->error = NULL;
>  container->dirty_pages_supported = false;
> +container->dma_max_mappings = 0;
>  QLIST_INIT(>giommu_list);
>  QLIST_INIT(>hostwin_list);
>  QLIST_INIT(>vrdl_list);
> @@ -1965,7 +1966,10 @@ static int vfio_connect_container(VFIOGroup *group, 
> AddressSpace *as,
>  vfio_host_win_add(container, 0, (hwaddr)-1, info->iova_pgsizes);
>  container->pgsizes = info->iova_pgsizes;
>  
> +/* The default in the kernel ("dma_entry_limit") is 65535. */
> +container->dma_max_mappings = 65535;
>  if (!ret) {
> +vfio_get_info_dma_avail(info, >dma_max_mappings);
>  vfio_get_iommu_info_migration(container, info);
>  }
>  g_free(info);
> diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> index af6f8d1b22..4b28c6e8ac 100644
> --- a/include/hw/vfio/vfio-common.h
> +++ b/include/hw/vfio/vfio-common.h
> @@ -88,6 +88,7 @@ typedef struct VFIOContainer {
>  uint64_t dirty_pgsizes;
>  uint64_t max_dirty_bitmap_size;
>  unsigned long pgsizes;
> +unsigned int dma_max_mappings;
>  QLIST_HEAD(, VFIOGuestIOMMU) giommu_list;
>  QLIST_HEAD(, VFIOHostDMAWindow) hostwin_list;
>  QLIST_HEAD(, VFIOGroup) group_list;

Reviewed-by: Alex Williamson 
Acked-by: Alex Williamson 




Re: [PATCH 0/2] MAINTAINERS cleanups

2021-01-13 Thread Philippe Mathieu-Daudé
Cc'ing qemu-trivial@

On 1/13/21 11:08 PM, John Snow wrote:
> On 10/30/20 11:34 AM, John Snow wrote:
>>
>>
>> John Snow (2):
>>    MAINTAINERS: Remove Ben Warren
>>    MAINTAINERS: Make status spellings consistent
>>
>>   MAINTAINERS | 13 ++---
>>   1 file changed, 6 insertions(+), 7 deletions(-)
>>
> 
> A little late for 5.2 now, but ... ping?




Re: [PATCH v4 04/11] vfio: Support for RamDiscardMgr in the !vIOMMU case

2021-01-13 Thread Alex Williamson
On Thu,  7 Jan 2021 14:34:16 +0100
David Hildenbrand  wrote:

> Implement support for RamDiscardMgr, to prepare for virtio-mem
> support. Instead of mapping the whole memory section, we only map
> "populated" parts and update the mapping when notified about
> discarding/population of memory via the RamDiscardListener. Similarly, when
> syncing the dirty bitmaps, sync only the actually mapped (populated) parts
> by replaying via the notifier.
> 
> Using virtio-mem with vfio is still blocked via
> ram_block_discard_disable()/ram_block_discard_require() after this patch.
> 
> Cc: Paolo Bonzini 
> Cc: "Michael S. Tsirkin" 
> Cc: Alex Williamson 
> Cc: Dr. David Alan Gilbert 
> Cc: Igor Mammedov 
> Cc: Pankaj Gupta 
> Cc: Peter Xu 
> Cc: Auger Eric 
> Cc: Wei Yang 
> Cc: teawater 
> Cc: Marek Kedzierski 
> Signed-off-by: David Hildenbrand 
> ---
>  hw/vfio/common.c  | 200 ++
>  include/hw/vfio/vfio-common.h |  12 ++
>  2 files changed, 212 insertions(+)
> 
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index 6ff1daa763..2bd219cf1d 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -654,6 +654,136 @@ out:
>  rcu_read_unlock();
>  }
>  
> +static void vfio_ram_discard_notify_discard(RamDiscardListener *rdl,
> +const MemoryRegion *mr,
> +ram_addr_t offset, ram_addr_t 
> size)
> +{
> +VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
> +listener);
> +const hwaddr mr_start = MAX(offset, vrdl->offset_within_region);
> +const hwaddr mr_end = MIN(offset + size,
> +  vrdl->offset_within_region + vrdl->size);
> +const hwaddr iova = mr_start - vrdl->offset_within_region +
> +vrdl->offset_within_address_space;
> +int ret;
> +
> +if (mr_start >= mr_end) {
> +return;
> +}
> +
> +/* Unmap with a single call. */
> +ret = vfio_dma_unmap(vrdl->container, iova, mr_end - mr_start, NULL);
> +if (ret) {
> +error_report("%s: vfio_dma_unmap() failed: %s", __func__,
> + strerror(-ret));
> +}
> +}
> +
> +static int vfio_ram_discard_notify_populate(RamDiscardListener *rdl,
> +const MemoryRegion *mr,
> +ram_addr_t offset, ram_addr_t 
> size)
> +{
> +VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
> +listener);
> +const hwaddr mr_end = MIN(offset + size,
> +  vrdl->offset_within_region + vrdl->size);
> +hwaddr mr_start = MAX(offset, vrdl->offset_within_region);
> +hwaddr mr_next, iova;
> +void *vaddr;
> +int ret;
> +
> +/*
> + * Map in (aligned within memory region) minimum granularity, so we can
> + * unmap in minimum granularity later.
> + */
> +for (; mr_start < mr_end; mr_start = mr_next) {
> +mr_next = ROUND_UP(mr_start + 1, vrdl->granularity);
> +mr_next = MIN(mr_next, mr_end);
> +
> +iova = mr_start - vrdl->offset_within_region +
> +   vrdl->offset_within_address_space;
> +vaddr = memory_region_get_ram_ptr(vrdl->mr) + mr_start;
> +
> +ret = vfio_dma_map(vrdl->container, iova, mr_next - mr_start,
> +   vaddr, mr->readonly);
> +if (ret) {
> +/* Rollback */
> +vfio_ram_discard_notify_discard(rdl, mr, offset, size);
> +return ret;
> +}
> +}
> +return 0;
> +}
> +
> +static void vfio_ram_discard_notify_discard_all(RamDiscardListener *rdl,
> +const MemoryRegion *mr)
> +{
> +VFIORamDiscardListener *vrdl = container_of(rdl, VFIORamDiscardListener,
> +listener);
> +int ret;
> +
> +/* Unmap with a single call. */
> +ret = vfio_dma_unmap(vrdl->container, vrdl->offset_within_address_space,
> + vrdl->size, NULL);
> +if (ret) {
> +error_report("%s: vfio_dma_unmap() failed: %s", __func__,
> + strerror(-ret));
> +}
> +}
> +
> +static void vfio_register_ram_discard_notifier(VFIOContainer *container,
> +   MemoryRegionSection *section)
> +{
> +RamDiscardMgr *rdm = memory_region_get_ram_discard_mgr(section->mr);
> +RamDiscardMgrClass *rdmc = RAM_DISCARD_MGR_GET_CLASS(rdm);
> +VFIORamDiscardListener *vrdl;
> +
> +vrdl = g_new0(VFIORamDiscardListener, 1);
> +vrdl->container = container;
> +vrdl->mr = section->mr;
> +vrdl->offset_within_region = section->offset_within_region;
> +vrdl->offset_within_address_space = section->offset_within_address_space;
> +vrdl->size = int128_get64(section->size);

Re: [PATCH] tests/acceptance: Test PMON with Loongson-3A1000 CPU

2021-01-13 Thread Philippe Mathieu-Daudé
On 1/12/21 3:05 PM, Wainer dos Santos Moschetta wrote:
> Hi,
> 
> On 1/11/21 11:07 PM, Jiaxun Yang wrote:
>> Test booting of PMON bootloader on loongson3-virt platform.
>>
>> $ (venv) AVOCADO_ALLOW_UNTRUSTED_CODE=1 \
>>  avocado --show=app,console \
>>    run -t machine:loongson3-virt tests/acceptance
>> Fetching asset from
>> tests/acceptance/machine_mips_loongson3v.py:MipsLoongson3v.test_pmon_serial_console
>>
>> JOB ID : 8e202b3727847c9104d0d3d6546ed225d35f6706
>> JOB LOG    :
>> /home/flygoat/avocado/job-results/job-2021-01-12T10.02-8e202b3/job.log
>>   (1/1)
>> tests/acceptance/machine_mips_loongson3v.py:MipsLoongson3v.test_pmon_serial_console:
>>  
>> console: PMON2000 MIPS Initializing. Standby...
>> console: Jump to 9fc
> 
>> Signed-off-by: Jiaxun Yang 
>> ---
>>   MAINTAINERS |  1 +
>>   tests/acceptance/machine_mips_loongson3v.py | 39 +
>>   2 files changed, 40 insertions(+)
>>   create mode 100644 tests/acceptance/machine_mips_loongson3v.py
> 
> Allow me to use this new test as an example to start a discussion about
> the organization of the acceptance files.
> 
> The mips64le tests currently are:
> 
> $ ./venv/bin/avocado list -t arch:mips64el acceptance/
> 
> INSTRUMENTED
> acceptance/boot_linux_console.py:BootLinuxConsole.test_mips64el_malta
> INSTRUMENTED
> acceptance/boot_linux_console.py:BootLinuxConsole.test_mips64el_fuloong2e
> INSTRUMENTED
> acceptance/boot_linux_console.py:BootLinuxConsole.test_mips64el_malta_5KEc_cpio
> 
> INSTRUMENTED
> acceptance/linux_ssh_mips_malta.py:LinuxSSH.test_mips_malta64el_kernel3_2_0
> INSTRUMENTED
> acceptance/machine_mips_loongson3v.py:MipsLoongson3v.test_pmon_serial_console
> 
> INSTRUMENTED
> acceptance/machine_mips_malta.py:MaltaMachineFramebuffer.test_mips_malta_i6400_framebuffer_logo_1core
> 
> INSTRUMENTED
> acceptance/machine_mips_malta.py:MaltaMachineFramebuffer.test_mips_malta_i6400_framebuffer_logo_7cores
> 
> INSTRUMENTED
> acceptance/machine_mips_malta.py:MaltaMachineFramebuffer.test_mips_malta_i6400_framebuffer_logo_8cores
> 
> INSTRUMENTED
> acceptance/replay_kernel.py:ReplayKernelNormal.test_mips64el_malta
> INSTRUMENTED
> acceptance/replay_kernel.py:ReplayKernelSlow.test_mips64el_malta_5KEc_cpio
> 
> Most of them are simple "boot linux (or firmware) and check the console"
> tests. The replay_kernel.py contain tests for a given feature and happen
> to be testing on mips64el as well. So on tests/acceptance directory
> we've got boot tests spread across files and mixed with "generic"
> feature tests.
> 
> I think we should find a home for those boot tests. Maybe throw them all
> in a sub-directory called "boot_tests", or in arch-oriented directories
> (boot_tests/mips64el, boot_tests/x86_64, ...) which would make easier to
> reference them in the MAINTAINERS file.
> 
> Any thought?

[thread hijack...]

A tests might be multi-arch. If you think it is easier to have the
tests sorted in subfolders, go ahead :) Where is a test is not a
problem. The problem we have to solve is how to relate a test with
its maintainers / developers interested in it.

We once said what really matters are Avocado tags. This might be an
underused feature of Avocado. Maybe what we need is a script to
relate test tags with MAINTAINERS?

Let's say we use the 'A' tag for that:

-- >8 --
diff --git a/MAINTAINERS b/MAINTAINERS
index cb0656aec3d..a484d429d78 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -646,6 +646,7 @@ M: Anup Patel 
 M: Alistair Francis 
 L: qemu-ri...@nongnu.org
 S: Maintained
+A: device:goldfish_rtc
 F: hw/rtc/goldfish_rtc.c
 F: include/hw/rtc/goldfish_rtc.h

@@ -1160,6 +1161,11 @@ Loongson-3 virtual platforms
 M: Huacai Chen 
 R: Jiaxun Yang 
 S: Maintained
+A: machine:loongson3-virt
+A: cpu:Loongson-3A1000
+A: device:liointc
+A: device:goldfish_rtc
 F: hw/intc/loongson_liointc.c
 F: hw/mips/loongson3_bootp.c
 F: hw/mips/loongson3_bootp.h
---

If this test fails, it should list the maintainers of the
loongson3-virt machine and the goldfish RTC.

Maintainers add their tags of interest, and can Ack when a
developer add a tag to their MAINTAINERS entry.

Thought? :)




Re: [PATCH v6 10/11] iotests: rewrite check into python

2021-01-13 Thread Eric Blake
On 1/9/21 6:26 AM, Vladimir Sementsov-Ogievskiy wrote:
> Just use classes introduced in previous three commits. Behavior
> difference is described in these three commits.
> 
> Drop group file, as it becomes unused.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  tests/qemu-iotests/check | 994 ++-
>  tests/qemu-iotests/group | 321 -
>  2 files changed, 28 insertions(+), 1287 deletions(-)
>  delete mode 100644 tests/qemu-iotests/group

The bulk of the work was done in the earlier patches, and my python
review is weak; but I can confirm that with this patch applied, my usual
attempts at running ./check still appeared to work for me.  That's not
the same as proving you did 1:1 feature translation (and in fact, your
commit message documented dropping some features like -v), but if 'make
check' and CI tools still run, I'm okay leaving it up to developers to
complain about any other feature that they used but which go missing (or
to implement it).

Tested-by: Eric Blake 

> 
> diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
> index 952762d5ed..48bb3128c3 100755
> --- a/tests/qemu-iotests/check
> +++ b/tests/qemu-iotests/check
> @@ -1,7 +1,8 @@
> -#!/usr/bin/env bash
> +#!/usr/bin/env python3
>  #
> -# Copyright (C) 2009 Red Hat, Inc.
> -# Copyright (c) 2000-2002,2006 Silicon Graphics, Inc.  All Rights Reserved.
> +# Configure environment and run group of tests in it.
> +#
> +# Copyright (c) 2020 Virtuozzo International GmbH

You may want to claim 2021 as well.

> +import sys
> +import os
> +from findtests import find_tests, TestFinder
> +from testenv import TestEnv
> +from testrunner import TestRunner
> +
> +if __name__ == '__main__':
> +if len(sys.argv) == 2 and sys.argv[1] in ['-h', '--help']:
> +print('Usage: ./check [options] [testlist]')
> +print()
> +TestFinder.get_argparser().print_help()
> +print()
> +TestEnv.get_argparser().print_help()
> +print()
> +TestRunner.get_argparser().print_help()
> +exit()
> +
> +env = TestEnv(sys.argv[1:])
> +tests, remaining_argv = find_tests(env.remaining_argv,
> +   test_dir=env.source_iotests)
> +
> +with TestRunner(remaining_argv, env) as tr:
> +assert not tr.remaining_argv
> +tr.run_tests([os.path.join(env.source_iotests, t) for t in tests])

A lot shorter for the main engine ;)

> diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
> deleted file mode 100644
> index bc5bc324fe..00
> --- a/tests/qemu-iotests/group
> +++ /dev/null
> @@ -1,321 +0,0 @@
> -#
> -# QA groups control file
> -# Defines test groups

Happy to see this conflict magnet go!

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




Re: [PATCH v6 07/11] iotests: add findtests.py

2021-01-13 Thread Eric Blake
On 1/9/21 6:26 AM, Vladimir Sementsov-Ogievskiy wrote:
> Add python script with new logic of searching for tests:
> 
> Current ./check behavior:
>  - tests are named [0-9][0-9][0-9]
>  - tests must be registered in group file (even if test doesn't belong
>to any group, like 142)
> 

> 
> This commit don't update check behavior (which will be don in further

done

> commit), still, the documentation changed like new behavior is already
> here.  Let's live with this small inconsistency for the following few
> commits, until final change.
> 
> The file findtests.py is self-executable and may be used for debugging
> purposes.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  docs/devel/testing.rst  |  50 ++-
>  tests/qemu-iotests/findtests.py | 229 
>  2 files changed, 278 insertions(+), 1 deletion(-)
>  create mode 100755 tests/qemu-iotests/findtests.py

In addition to Kevin's review,


> +Additional way of defining groups is creating tests/qemu-iotests/group.local
> +file. This should be used only for downstream (this file should never appear
> +in upstream). This file may be used for defining some downstream test groups
> +or for temporary disable tests, like this:

Kevin suggested s/disable/disabling/; I'd go one step further:
/temporary disable/temporarily disabling/


> +
> +- quick : Tests in this group should finish within some few seconds.

s/some/a/

Also, for each group name, the space before ':' looks odd.

> +++ b/tests/qemu-iotests/findtests.py
> @@ -0,0 +1,229 @@
> +#!/usr/bin/env python3
> +#
> +# Parse command line options to define set of tests to run.
> +#
> +# Copyright (c) 2020 Virtuozzo International GmbH

Worth claiming 2021 as well?

Otherwise, my python review is weak, but I didn't spot anything
blatantly wrong.

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




Re: [PATCH 1/2] trace: document how to specify multiple --trace patterns

2021-01-13 Thread John Snow

On 1/13/21 5:15 PM, Eric Blake wrote:

On 1/13/21 3:42 PM, John Snow wrote:

On 1/13/21 4:48 AM, Stefan Hajnoczi wrote:

QEMU options are single dash with double dash accepted for
compatibility but
help and other docs have single dash so these (and below) should be
-trace.
(Also a bit less typing for otherwise already way too long command
lines.)

Is this documented somewhere?

I was under the impression that '-' is legacy syntax and '--' is the
preferred syntax. There are examples of '--' on the QEMU man page.


Historically, uses of 'getopt_long()' support only double dash, while
'getopt_long_only()' support both single and double.  While qemu does
not use getopt_long_only() (because it rolls its own parser instead), it
certainly tries to behave as if it does.  Meanwhile, our other tools
like qemu-img or qemu-storage-daemon use getopt_long().  I'm in favor of
preferring the double-dash in documentation, even when single-dash
works, especially for any option (like --trace) that is used for more
tools than just qemu proper, because it makes for easier copy-paste
between options that work for all tools in the qemu suite rather than
just qemu.



Yes, this makes sense.



Let's reach agreement, document it, and then make the documentation
consistent.

Stefan


My naive impression was that double-dash is the preferred idiom in
linuxdom in general for any multi-character option.

We might hang on to single-dash for backwards compatibility, but I doubt
we want to enshrine that as our preferred way.

Is there a reasoning I am unaware of?


Continuing to document '-machine' instead of '--machine' for qemu is
debatable because we don't support 'qemu-img --machine' or
'qemu-storage-daemon --machine'; but since 'qemu-img -trace' is an error
while 'qemu-img --trace' works, I'm definitely in favor of preferring
'--trace' everywhere in our docs.



At that point, it's a guessing game as to which binaries support which 
flags and using which spellings -- maybe some will pick up new flags 
later and so on.


Skip the fuss and just insist on the double dash, I think.

--js




Re: [PATCH 1/2] hw/intc: Add Loongson Inter Processor Interrupt controller

2021-01-13 Thread Philippe Mathieu-Daudé
Hi Jiaxun,

On 1/12/21 4:32 AM, Jiaxun Yang wrote:
> Loongson IPI controller is a MMIO based simple level triggered
> interrupt controller. It will trigger IRQ to it's upstream
> processor when set register is written.
> 
> It also has 8 32bit mailboxes to pass boot information to
> secondary processor.

Hmm the datasheet describe them as 4 64bit mailboxes (also
accessible in 32bit).

I have no problem modelling this device as 8x32 to simplify,
but the documentation should be accurate. Along with a comment
describing NUM_MBOX value.

> Signed-off-by: Jiaxun Yang 
> ---
>  hw/intc/Kconfig|   3 +
>  hw/intc/loongson_ipi.c | 146 +
>  hw/intc/meson.build|   1 +
>  include/hw/intc/loongson_ipi.h |  20 +
>  4 files changed, 170 insertions(+)
>  create mode 100644 hw/intc/loongson_ipi.c
>  create mode 100644 include/hw/intc/loongson_ipi.h
> 
> diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
> index c18d11142a..0e15102662 100644
> --- a/hw/intc/Kconfig
> +++ b/hw/intc/Kconfig
> @@ -59,6 +59,9 @@ config RX_ICU
>  config LOONGSON_LIOINTC
>  bool
>  
> +config LOONGSON_IPI
> +bool
> +
>  config SIFIVE_CLINT
>  bool
>  
> diff --git a/hw/intc/loongson_ipi.c b/hw/intc/loongson_ipi.c
> new file mode 100644
> index 00..7246f05f9e
> --- /dev/null
> +++ b/hw/intc/loongson_ipi.c
> @@ -0,0 +1,146 @@
> +/*
> + * QEMU Loongson Inter Processor Interrupt Controller
> + *
> + * Copyright (c) 2020-2021 Jiaxun Yang 
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see .
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "qemu/module.h"
> +#include "qemu/log.h"
> +#include "hw/irq.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/intc/loongson_ipi.h"
> +
> +#define R_ISR   0
> +#define R_IEN   1
> +#define R_SET   2
> +#define R_CLR   3
> +/* No register between 0x10~0x20 */
> +#define R_MBOX0 8
> +#define NUM_MBOX8
> +#define R_END   16

Can you use an enum please?

> +
> +struct loongson_ipi {
> +SysBusDevice parent_obj;
> +
> +MemoryRegion mmio;
> +qemu_irq parent_irq;
> +
> +uint32_t isr;
> +uint32_t ien;
> +uint32_t mbox[NUM_MBOX];
> +};
> +
> +static uint64_t
> +ipi_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> +struct loongson_ipi *p = opaque;
> +uint64_t r = 0;
> +
> +addr >>= 2;
> +switch (addr) {
> +case R_ISR:
> +r = p->isr;
> +break;
> +case R_IEN:
> +r = p->ien;
> +break;
> +case R_MBOX0 ... (R_END - 1):
> +r = p->mbox[addr - R_MBOX0];
> +break;

Logging here write-only registers (R_SET, R_CLR) as LOG_GUEST_ERROR
might result useful.

> +default:
> +break;
> +}
> +
> +qemu_log_mask(CPU_LOG_INT,
> +  "%s: size=%d, addr=%"HWADDR_PRIx", val=%"PRIx64"\n",
> +  __func__, size, addr, r);

CPU_LOG_INT is used for the architectural part (within GS464V).
For hardware we use trace events. Do you mind changing?

> +
> +return r;
> +}
> +
> +static void
> +ipi_write(void *opaque, hwaddr addr,
> +  uint64_t val64, unsigned int size)
> +{
> +struct loongson_ipi *p = opaque;
> +uint32_t value = val64;
> +
> +addr >>= 2;
> +switch (addr) {
> +case R_ISR:
> +/* Do nothing */
> +break;
> +case R_IEN:
> +p->ien = value;
> +break;
> +case R_SET:
> +p->isr |= value;
> +break;
> +case R_CLR:
> +p->isr &= ~value;
> +break;
> +case R_MBOX0 ... (R_END - 1):
> +p->mbox[addr - R_MBOX0] = value;
> +break;
> +default:
> +break;
> +}
> +p->isr &= p->ien;
> +
> +qemu_log_mask(CPU_LOG_INT,
> +  "%s: size=%d, addr=%"HWADDR_PRIx", val=%"PRIx32"\n",
> +  __func__, size, addr, value);

Ditto.

> +
> +qemu_set_irq(p->parent_irq, !!p->isr);
> +}
> +
> +static const MemoryRegionOps pic_ops = {
> +.read = ipi_read,
> +.write = ipi_write,
> +.endianness = DEVICE_NATIVE_ENDIAN,
> +.valid = {
> +.min_access_size = 4,
> +.max_access_size = 4
> +}

64-bit access are valid. You probably want:

   .impl = {
   .min_access_size = 4,
   .max_access_size = 4
   },
   .valid = {
   

Re: [PATCH v2 07/12] qapi/schema: make QAPISourceInfo mandatory

2021-01-13 Thread John Snow

On 1/13/21 11:12 AM, Markus Armbruster wrote:

John Snow  writes:


Signed-off-by: John Snow 

---

The event_enum_members change might become irrelevant after a
forthcoming (?) patch by Markus, but didn't have it in-hand at time of
publishing.


It's in my "[PATCH 00/11] Drop support for QAPIGen without a file name",
which includes parts of your v1.  The parts that are new should be
injected into your series so they replace your "[PATCH v2 09/12]
qapi/gen: move write method to QAPIGenC, make fname a str".  Holler if
you need help.


Signed-off-by: John Snow 
---
  scripts/qapi/events.py |  2 +-
  scripts/qapi/schema.py | 25 ++---
  scripts/qapi/types.py  |  9 +
  scripts/qapi/visit.py  |  6 +++---
  4 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 9851653b9d1..9ba4f109028 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -225,7 +225,7 @@ def visit_event(self,
self._event_emit_name))
  # Note: we generate the enum member regardless of @ifcond, to
  # keep the enumeration usable in target-independent code.
-self._event_enum_members.append(QAPISchemaEnumMember(name, None))
+self._event_enum_members.append(QAPISchemaEnumMember(name, info))


This "enum" is not supposed to be erroneous.  If it is, it's a bug.

Your patch changes how the code behaves should such a bug bite here.
Before, we crash.  Afterwards, we report the bug using @info, which I'd
expect to produce utterly confusing error messages.



It doesn't change the behavior *here*, though. It changes it whenever 
this info object is used in another context. ... and who knows when or 
where or why it is being used, or by whom.


I'll have to play with this. I'm not sure there's any way to coax a bug 
to happen here that I am aware of right away. Can you think of how to 
will one into existence?



My comments on PATCH 06 apply: how the code should behave here is a
design issue that should be kept out of this patch series.

If you need to pass a value other than None to help with static typing,
then pass a suitable poison info that will crash right where None
crashes now.



I think we need to, yes; or we probably really, really want to. Making 
the info parameter optional really adds a lot of unidiomatic 
type-checking confetti when we go to use info, and in many more contexts 
than just this sorta-built-in-enum; it will creep badly.


So, I gotta pass ...something here. but what? You want poison, but I 
think it's not right to fundamentally poison all built-ins.


Mmm. Maybe per-instance poison can be done? We actually share info 
objects, but I can make poisoned copies. Using next_line() as a basis:


def poison(self: T) -> T:
info = copy.copy(self)
info.poisoned = True
return info

probably almost anything I do is not going to make a lot of sense unless 
I can actually replicate and test the different error scenarios to prove 
that we didn't make the error spaghetti unknowably worse. I see it as 
functionally inevitable that I have to audit this and make sure we get 
good error messages anyway, so ... maybe I just ought to do that now anyway.



  def gen_events(schema: QAPISchema,
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index 720449feee4..0449771dfe5 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -23,6 +23,7 @@
  from .error import QAPIError, QAPISemError
  from .expr import check_exprs
  from .parser import QAPISchemaParser
+from .source import QAPISourceInfo
  
  
  class QAPISchemaEntity:

@@ -36,10 +37,10 @@ def __init__(self, name, info, doc, ifcond=None, 
features=None):
  self.name = name
  self._module = None
  # For explicitly defined entities, info points to the (explicit)
-# definition.  For builtins (and their arrays), info is None.
-# For implicitly defined entities, info points to a place that
-# triggered the implicit definition (there may be more than one
-# such place).
+# definition. For built-in types (and their arrays), info is a
+# special object that evaluates to False. For implicitly defined
+# entities, info points to a place that triggered the implicit
+# definition (there may be more than one such place).
  self.info = info
  self.doc = doc
  self._ifcond = ifcond or []
@@ -68,7 +69,7 @@ def check_doc(self):
  
  def _set_module(self, schema, info):

  assert self._checked
-self._module = schema.module_by_fname(info and info.fname)
+self._module = schema.module_by_fname(info.fname if info else None)


Looks unrelated.



Hmm, it sorta is. I have apparently edited this patch since I sent it, 
but there was some tomfoolery over how "x and y" statements behave and 
this edit was necessary at the time.


"info and info.fname" 

Re: [PATCH v6 06/11] iotests: define group in each iotest

2021-01-13 Thread Eric Blake
On 1/9/21 6:26 AM, Vladimir Sementsov-Ogievskiy wrote:
> We are going to drop group file. Define group in tests as a preparatory
> step.
> 
> The patch is generated by
> 
> cd tests/qemu-iotests
> 
> grep '^[0-9]\{3\} ' group | while read line; do
> file=$(awk '{print $1}' <<< "$line");
> groups=$(sed -e 's/^... //' <<< "$line");
> awk "NR==2{print \"# group: $groups\"}1" $file > tmp;
> cat tmp > $file;
> done
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---

>  291 files changed, 291 insertions(+)

May need rebasing, but your reproduction formula works (requires bash,
but that's fine since the tests themselves do as well).

> +++ b/tests/qemu-iotests/312
> @@ -1,4 +1,5 @@
>  #!/usr/bin/env bash
> +# group: rw quick
>  #
>  # Test drive-mirror with quorum
>  #

I like how it looks.

Reviewed-by: Eric Blake 

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




Re: [PATCH v6 05/11] iotests/294: add shebang line

2021-01-13 Thread Eric Blake
On 1/9/21 6:26 AM, Vladimir Sementsov-Ogievskiy wrote:
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  tests/qemu-iotests/294 | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Eric Blake 

> 
> diff --git a/tests/qemu-iotests/294 b/tests/qemu-iotests/294
> index 87da35db49..4c375ed609 100755
> --- a/tests/qemu-iotests/294
> +++ b/tests/qemu-iotests/294
> @@ -1,3 +1,4 @@
> +#!/usr/bin/env bash
>  #
>  # Copyright (C) 2019 Red Hat, Inc.
>  #
> 

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




Re: [PATCH v6 04/11] iotests: make tests executable

2021-01-13 Thread Eric Blake
On 1/9/21 6:26 AM, Vladimir Sementsov-Ogievskiy wrote:
> All other test files are executable. Fix these.
> 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> ---
>  tests/qemu-iotests/283 | 0
>  tests/qemu-iotests/298 | 0
>  tests/qemu-iotests/299 | 0
>  3 files changed, 0 insertions(+), 0 deletions(-)
>  mode change 100644 => 100755 tests/qemu-iotests/283
>  mode change 100644 => 100755 tests/qemu-iotests/298
>  mode change 100644 => 100755 tests/qemu-iotests/299

Reviewed-by: Eric Blake 

> 
> diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283
> old mode 100644
> new mode 100755
> diff --git a/tests/qemu-iotests/298 b/tests/qemu-iotests/298
> old mode 100644
> new mode 100755
> diff --git a/tests/qemu-iotests/299 b/tests/qemu-iotests/299
> old mode 100644
> new mode 100755
> 

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




  1   2   3   4   5   >