Re: [PATCH] udmabuf: revert 'Add support for mapping hugepages (v4)'

2023-06-08 Thread Greg Kroah-Hartman
On Thu, Jun 08, 2023 at 01:49:27PM -0700, Mike Kravetz wrote:
> This effectively reverts commit 16c243e99d33 ("udmabuf: Add support
> for mapping hugepages (v4)").  Recently, Junxiao Chang found a BUG
> with page map counting as described here [1].  This issue pointed out
> that the udmabuf driver was making direct use of subpages of hugetlb
> pages.  This is not a good idea, and no other mm code attempts such use.
> In addition to the mapcount issue, this also causes issues with hugetlb
> vmemmap optimization and page poisoning.
> 
> For now, remove hugetlb support.
> 
> If udmabuf wants to be used on hugetlb mappings, it should be changed to
> only use complete hugetlb pages.  This will require different alignment
> and size requirements on the UDMABUF_CREATE API.
> 
> [1] 
> https://lore.kernel.org/linux-mm/20230512072036.1027784-1-junxiao.ch...@intel.com/
> 
> Fixes: 16c243e99d33 ("udmabuf: Add support for mapping hugepages (v4)")
> Cc: 
> Signed-off-by: Mike Kravetz 

Acked-by: Greg Kroah-Hartman 



[PATCH] hw/intc: If mmsiaddrcfgh.L == 1, smsiaddrcfg and smsiaddrcfgh are read-only.

2023-06-08 Thread Tommy Wu
According to the `The RISC-V Advanced Interrupt Architecture`
document, if register `mmsiaddrcfgh` of the domain has bit L set
to one, then `smsiaddrcfg` and `smsiaddrcfgh` are locked as
read-only alongside `mmsiaddrcfg` and `mmsiaddrcfgh`.

Signed-off-by: Tommy Wu 
Reviewed-by: Frank Chang 
---
 hw/intc/riscv_aplic.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index afc5b54dbb..4bdc6a5d1a 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -688,13 +688,13 @@ static void riscv_aplic_write(void *opaque, hwaddr addr, 
uint64_t value,
  * domains).
  */
 if (aplic->num_children &&
-!(aplic->smsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
+!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
 aplic->smsicfgaddr = value;
 }
 } else if (aplic->mmode && aplic->msimode &&
(addr == APLIC_SMSICFGADDRH)) {
 if (aplic->num_children &&
-!(aplic->smsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
+!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
 aplic->smsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK;
 }
 } else if ((APLIC_SETIP_BASE <= addr) &&
-- 
2.31.1




RE: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary UNMAP calls

2023-06-08 Thread Duan, Zhenzhong


>-Original Message-
>From: Peter Xu 
>Sent: Friday, June 9, 2023 3:53 AM
>To: Jason Gunthorpe 
>Cc: Liu, Yi L ; Duan, Zhenzhong
>; qemu-devel@nongnu.org; m...@redhat.com;
>jasow...@redhat.com; pbonz...@redhat.com;
>richard.hender...@linaro.org; edua...@habkost.net;
>marcel.apfelb...@gmail.com; alex.william...@redhat.com;
>c...@redhat.com; da...@redhat.com; phi...@linaro.org;
>kwankh...@nvidia.com; c...@nvidia.com; Peng, Chao P
>
>Subject: Re: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary
>UNMAP calls
>
>On Thu, Jun 08, 2023 at 01:27:50PM -0300, Jason Gunthorpe wrote:
>> On Thu, Jun 08, 2023 at 11:40:55AM -0400, Peter Xu wrote:
>>
>> > > But if there is the proper locks to prevent a map/unmap race, then
>> > > there should also be the proper locks to check that there is no map in
>> > > the first place and avoid the kernel call..
>> >
>> > The problem is IIRC guest iommu driver can do smart things like batching
>> > invalidations, it means when QEMU gets it from the guest OS it may
>already
>> > not matching one mapped objects.
>>
>> qemu has to fix it. The kernel API is object based, not paged
>> based. You cannot unmap partions of a prior mapping.
>>
>> I assume for this kind of emulation it is doing 4k objects because
>> it has no idea what size of mapping the client will use?
>
>MAP is fine, before notify() to VFIO or anything, qemu scans the pgtable
>and handles it in page size or huge page size, so it can be >4K but always
>guest iommu pgsize aligned.
>
>I think we rely on guest behaving right, so it should also always operate
>on that size minimum when mapped huge.  It shouldn't violate the
>"per-object" protocol of iommufd.
>
>IIUC the same to vfio type1v2 from that aspect.
>
>It's more about UNMAP batching, but I assume iommufd is fine if it's fine
>with holes inside for that case.  The only difference of "not exist" of
>-ENOENT seems to be just same as before as long as QEMU treats it as 0 like
>before.
>
>Though that does look slightly special, because the whole empty UNMAP
>region can be seen as a hole too; not sure when that -ENOENT will be useful
>if qemu should always bypass it anyway.  Indeed not a problem to qemu.
>
>>
>> > We can definitely lookup every single object and explicitly unmap, but it
>> > loses partial of the point of batching that guest OS does.
>>
>> You don't need every single object, but it would be faster to check
>> where things are mapped and then call the kernel correctly instead of
>> trying to iterate with the unmapped reults.
>
>Maybe yes.  If so, It'll be great if Zhenzhong could just attach some proof
>on that, meanwhile drop the "iommufd UNMAP warnings" section in the commit
>message.

Seems vtd_page_walk_one() already works in above way, checking mapping
changes and calling kernel for changed entries?

Thanks
Zhenzhong


Re: [RFC v2 6/6] linux-user: Add '-native-bypass' option

2023-06-08 Thread Manos Pitsidianakis

On Wed, 07 Jun 2023 19:47, Yeqi Fu  wrote:

--- a/linux-user/main.c
+++ b/linux-user/main.c
+/* Set the library for native bypass  */
+if (native_lib != NULL) {
+char *token = malloc(strlen(native_lib) + 12);


malloc() can fail (in rare circumstances). Check for the return value 
here. Or use g_malloc() which terminates on alloc failure.



+strcpy(token, "LD_PRELOAD=");
+strcat(token, native_lib);


(You could alternatively use snprintf() here)



diff --git a/util/envlist.c b/util/envlist.c
index db937c0427..713d52497e 100644
+int
+envlist_appendenv(envlist_t *envlist, const char *env, const char *separator)
+{
+struct envlist_entry *entry = NULL;
+const char *eq_sign;
+size_t envname_len;
+
+if ((envlist == NULL) || (env == NULL)) {


separator must not be NULL as well.


+return (EINVAL);


Unnecessary parentheses here and in later returns.


+}
+
+/* find out first equals sign in given env */
+eq_sign = strchr(env, '=');
+if (eq_sign == NULL) {


Perhaps you can return an error message to the user here also, and 
explain why it failed. You can do that by passing an error message 
pointer with the function arguments.


By the way, if strchr(strchr(env, '='), '=') != NULL, shouldn't this 
fail also?




Re: [RFC v2 1/6] build: Add configure options for native calls

2023-06-08 Thread Manos Pitsidianakis

On Wed, 07 Jun 2023 19:47, Yeqi Fu  wrote:

+have_user_native_call = get_option('user_native_call') \
+.require(have_user, error_message: 'user_native_call requires user') \
+.require(targetos == 'linux', error_message: 'user_native_call requires 
Linux') \
+.allowed()



Is there a check for accepting user_native_call only for supported CPU 
user targets?




By the way, a question, would native calls be possible on BSD? I assume 
if yes it'd be a task for another time.




RE: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary UNMAP calls

2023-06-08 Thread Duan, Zhenzhong


>-Original Message-
>From: Peter Xu 
>Sent: Thursday, June 8, 2023 11:41 PM
>To: Jason Gunthorpe ; Liu, Yi L ; Duan,
>Zhenzhong 
>Cc: Duan, Zhenzhong ; qemu-
>de...@nongnu.org; m...@redhat.com; jasow...@redhat.com;
>pbonz...@redhat.com; richard.hender...@linaro.org; edua...@habkost.net;
>marcel.apfelb...@gmail.com; alex.william...@redhat.com;
>c...@redhat.com; da...@redhat.com; phi...@linaro.org;
>kwankh...@nvidia.com; c...@nvidia.com; Liu, Yi L ; Peng,
>Chao P 
>Subject: Re: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary
>UNMAP calls
>
>On Thu, Jun 08, 2023 at 11:11:15AM -0300, Jason Gunthorpe wrote:
>> On Thu, Jun 08, 2023 at 10:05:08AM -0400, Peter Xu wrote:
>>
>> > IIUC what VFIO does here is it returns succeed if unmap over nothing
>rather
>> > than failing like iommufd.  Curious (like JasonW) on why that retval?  I'd
>> > assume for returning "how much unmapped" we can at least still return 0
>for
>> > nothing.
>>
>> In iommufd maps are objects, you can only map or unmap entire
>> objects. The ability to batch unmap objects by specifying an range
>> that spans many is something that was easy to do and that VFIO had,
>> but I'm not sure it is actually usefull..
>>
>> So asking to unmap an object that is already known not to be mapped is
>> actually possibly racy, especially if you consider iommufd's support
>> for kernel-side IOVA allocation. It should not be done, or if it is
>> done, with user space locking to protect it.
>>
>> For VFIO, long long ago, VFIO could unmap IOVA page at a time - ie it
>> wasn't objects. In this world it made some sense that the unmap would
>> 'succeed' as the end result was unmapped.
>>
>> > Are you probably suggesting that we can probably handle that in QEMU
>side
>> > on -ENOENT here for iommufd only (a question to Yi?).
>>
>> Yes, this can be done, ENOENT is reliably returned and qemu doesn't
>> use the kernel-side IOVA allocator.
>>
>> But if there is the proper locks to prevent a map/unmap race, then
>> there should also be the proper locks to check that there is no map in
>> the first place and avoid the kernel call..
>
>The problem is IIRC guest iommu driver can do smart things like batching
>invalidations, it means when QEMU gets it from the guest OS it may already
>not matching one mapped objects.
>
>We can definitely lookup every single object and explicitly unmap, but it
>loses partial of the point of batching that guest OS does.  Logically QEMU
>can redirect that batched invalidation into one ioctl() to the host, rather
>than a lot of smaller ones.
>
>While for this specific patch - Zhenzhong/Yi, do you agree that we should
>just handle -ENOENT in the iommufd series (I assume it's still under work),
>then for this specific patch it's only about performance difference?

Yes, that make sense.

Thanks
Zhenzhong


RE: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary UNMAP calls

2023-06-08 Thread Duan, Zhenzhong


>-Original Message-
>From: Peter Xu 
>Sent: Friday, June 9, 2023 4:34 AM
>To: Duan, Zhenzhong 
>Cc: qemu-devel@nongnu.org; m...@redhat.com; jasow...@redhat.com;
>pbonz...@redhat.com; richard.hender...@linaro.org; edua...@habkost.net;
>marcel.apfelb...@gmail.com; alex.william...@redhat.com;
>c...@redhat.com; da...@redhat.com; phi...@linaro.org;
>kwankh...@nvidia.com; c...@nvidia.com; Liu, Yi L ; Peng,
>Chao P 
>Subject: Re: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary
>UNMAP calls
>
>On Thu, Jun 08, 2023 at 05:52:31PM +0800, Zhenzhong Duan wrote:
>>  while (remain >= VTD_PAGE_SIZE) {
>> -IOMMUTLBEvent event;
>>  uint64_t mask = dma_aligned_pow2_mask(start, end, s->aw_bits);
>>  uint64_t size = mask + 1;
>>
>>  assert(size);
>>
>> -event.type = IOMMU_NOTIFIER_UNMAP;
>> -event.entry.iova = start;
>> -event.entry.addr_mask = mask;
>> -event.entry.target_as = &address_space_memory;
>> -event.entry.perm = IOMMU_NONE;
>> -/* This field is meaningless for unmap */
>> -event.entry.translated_addr = 0;
>> -
>> -memory_region_notify_iommu_one(n, &event);
>> +map.iova = start;
>> +map.size = mask;
>> +if (iova_tree_find(as->iova_tree, &map)) {
>> +event.entry.iova = start;
>> +event.entry.addr_mask = mask;
>> +memory_region_notify_iommu_one(n, &event);
>> +}
>
>Ah one more thing: I think this path can also be triggered by notifiers without
>MAP event registered, whose iova tree will always be empty.  So we may only
>do this for MAP, then I'm not sure whether it'll be worthwhile..

Hmm, yes, my change will lead to vhost missed to receive some invalidation 
request in device-tlb disabled case as iova tree is empty. Thanks for point out.

Let me collect time diff spent in unmap AS for you to decide if it still worth 
or not.

Thanks
Zhenzhong
 


Re: [QEMU PATCH 1/1] virtgpu: do not destroy resources when guest suspend

2023-06-08 Thread Chen, Jiqian
On 2023/6/9 00:41, Robert Beckett wrote:
> 
> On 08/06/2023 03:56, Jiqian Chen wrote:
>> After suspending and resuming guest VM, you will get
>> a black screen, and the display can't come back.
>>
>> This is because when guest did suspending, it called
>> into qemu to call virtio_gpu_gl_reset. In function
>> virtio_gpu_gl_reset, it destroyed resources and reset
>> renderer, which were used for display. As a result,
>> guest's screen can't come back to the time when it was
>> suspended and only showed black.
>>
>> So, this patch adds a new ctrl message
>> VIRTIO_GPU_CMD_STATUS_FREEZING to get notification from
>> guest. If guest is during suspending, it sets freezing
>> status of virtgpu to true, this will prevent destroying
>> resources and resetting renderer when guest calls into
>> virtio_gpu_gl_reset. If guest is during resuming, it sets
>> freezing to false, and then virtio_gpu_gl_reset will keep
>> its origin actions and has no other impaction.
>>
>> Signed-off-by: Jiqian Chen 
>> ---
>>   hw/display/virtio-gpu-gl.c  |  9 ++-
>>   hw/display/virtio-gpu-virgl.c   |  3 +++
>>   hw/display/virtio-gpu.c | 26 +++--
>>   include/hw/virtio/virtio-gpu.h  |  3 +++
>>   include/standard-headers/linux/virtio_gpu.h |  9 +++
>>   5 files changed, 47 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
>> index e06be60dfb..e11ad233eb 100644
>> --- a/hw/display/virtio-gpu-gl.c
>> +++ b/hw/display/virtio-gpu-gl.c
>> @@ -100,7 +100,14 @@ static void virtio_gpu_gl_reset(VirtIODevice *vdev)
>>    */
>>   if (gl->renderer_inited && !gl->renderer_reset) {
>>   virtio_gpu_virgl_reset_scanout(g);
>> -    gl->renderer_reset = true;
>> +    /*
>> + * If guest is suspending, we shouldn't reset renderer,
>> + * otherwise, the display can't come back to the time when
>> + * it was suspended after guest resumed.
>> + */
>> +    if (!g->freezing) {
>> +    gl->renderer_reset = true;
>> +    }
>>   }
>>   }
>>   diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
>> index 73cb92c8d5..183ec92d53 100644
>> --- a/hw/display/virtio-gpu-virgl.c
>> +++ b/hw/display/virtio-gpu-virgl.c
>> @@ -464,6 +464,9 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
>>   case VIRTIO_GPU_CMD_GET_EDID:
>>   virtio_gpu_get_edid(g, cmd);
>>   break;
>> +    case VIRTIO_GPU_CMD_STATUS_FREEZING:
>> +    virtio_gpu_cmd_status_freezing(g, cmd);
>> +    break;
>>   default:
>>   cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
>>   break;
>> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
>> index 5e15c79b94..8f235d7848 100644
>> --- a/hw/display/virtio-gpu.c
>> +++ b/hw/display/virtio-gpu.c
>> @@ -373,6 +373,16 @@ static void virtio_gpu_resource_create_blob(VirtIOGPU 
>> *g,
>>   QTAILQ_INSERT_HEAD(&g->reslist, res, next);
>>   }
>>   +void virtio_gpu_cmd_status_freezing(VirtIOGPU *g,
>> + struct virtio_gpu_ctrl_command *cmd)
>> +{
>> +    struct virtio_gpu_status_freezing sf;
>> +
>> +    VIRTIO_GPU_FILL_CMD(sf);
>> +    virtio_gpu_bswap_32(&sf, sizeof(sf));
>> +    g->freezing = sf.freezing;
>> +}
>> +
>>   static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
>>   {
>>   struct virtio_gpu_scanout *scanout = 
>> &g->parent_obj.scanout[scanout_id];
>> @@ -986,6 +996,9 @@ void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
>>   case VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING:
>>   virtio_gpu_resource_detach_backing(g, cmd);
>>   break;
>> +    case VIRTIO_GPU_CMD_STATUS_FREEZING:
>> +    virtio_gpu_cmd_status_freezing(g, cmd);
>> +    break;
>>   default:
>>   cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
>>   break;
>> @@ -1344,6 +1357,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, 
>> Error **errp)
>>   QTAILQ_INIT(&g->reslist);
>>   QTAILQ_INIT(&g->cmdq);
>>   QTAILQ_INIT(&g->fenceq);
>> +
>> +    g->freezing = false;
>>   }
>>     void virtio_gpu_reset(VirtIODevice *vdev)
>> @@ -1352,8 +1367,15 @@ void virtio_gpu_reset(VirtIODevice *vdev)
>>   struct virtio_gpu_simple_resource *res, *tmp;
>>   struct virtio_gpu_ctrl_command *cmd;
>>   -    QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) {
>> -    virtio_gpu_resource_destroy(g, res);
>> +    /*
>> + * If guest is suspending, we shouldn't destroy resources,
>> + * otherwise, the display can't come back to the time when
>> + * it was suspended after guest resumed.
>> + */
> 
> 
> What should happen if qemu is torn down while the guest is suspended.
> Currently there is no other place where the resources will be destroyed. 
> While it is likely viable to rely on process auto tear down of mem and files 
> from the host cleanup point of view, it feels bad to rely on that.
> Perhaps an inverted co

RE: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary UNMAP calls

2023-06-08 Thread Duan, Zhenzhong

>-Original Message-
>From: Peter Xu 
>Sent: Thursday, June 8, 2023 10:05 PM
>To: Duan, Zhenzhong ; Jason Gunthorpe
>
>Cc: qemu-devel@nongnu.org; m...@redhat.com; jasow...@redhat.com;
>pbonz...@redhat.com; richard.hender...@linaro.org; edua...@habkost.net;
>marcel.apfelb...@gmail.com; alex.william...@redhat.com;
>c...@redhat.com; da...@redhat.com; phi...@linaro.org;
>kwankh...@nvidia.com; c...@nvidia.com; Liu, Yi L ; Peng,
>Chao P 
>Subject: Re: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary
>UNMAP calls
>
>On Thu, Jun 08, 2023 at 05:52:31PM +0800, Zhenzhong Duan wrote:
>> Commit 63b88968f1 ("intel-iommu: rework the page walk logic") adds
>> logic to record mapped IOVA ranges so we only need to send MAP or
>> UNMAP when necessary. But there is still a corner case of unnecessary
>UNMAP.
>>
>> During invalidation, either domain or device selective, we only need
>> to unmap when there are recorded mapped IOVA ranges, presuming most
>of
>> OSes allocating IOVA range continuously, e.g. on x86, linux sets up
>> mapping from 0x downwards.
>>
>> Strace shows UNMAP ioctl taking 0.14us and we have 28 such ioctl()
>> in one invalidation, as two notifiers in x86 are split into power of 2
>> pieces.
>>
>> ioctl(48, VFIO_IOMMU_UNMAP_DMA, 0x7d5c42f0) = 0 <0.14>
>
>Thanks for the numbers, but for a fair comparison IMHO it needs to be a
>comparison of before/after on the whole time used for unmap AS.  It'll be
>great to have finer granule measurements like each ioctl, but the total time
>used should be more important (especially to contain "after"). Side
>note: I don't think the UNMAP ioctl will take the same time; it should matter
>on whether there's mapping exist).

Yes, but what we want to optimize out is the unmapping no-existent range case.
Will show the time diff spent in unmap AS.

>
>Actually it's hard to tell because this also depends on what's in the iova 
>tree..
>but still at least we know how it works in some cases.
>
>>
>> The other purpose of this patch is to eliminate noisy error log when
>> we work with IOMMUFD. It looks the duplicate UNMAP call will fail with
>> IOMMUFD while always succeed with legacy container. This behavior
>> difference leads to below error log for IOMMUFD:
>>
>> IOMMU_IOAS_UNMAP failed: No such file or directory
>> vfio_container_dma_unmap(0x562012d6b6d0, 0x0, 0x8000) = -2 (No
>> such file or directory) IOMMU_IOAS_UNMAP failed: No such file or
>> directory vfio_container_dma_unmap(0x562012d6b6d0, 0x8000,
>> 0x4000) = -2 (No such file or directory) ...
>
>My gut feeling is the major motivation is actually this (not the perf).
>tens of some 14us ioctls is really nothing on a rare event..

To be honest, yes.

Thanks
Zhenzhong

>
>Jason Wang raised a question in previous version and I think JasonG's reply is
>here:
>
>https://lore.kernel.org/r/zhtaqxd3zybmh...@nvidia.com
>
>JasonG: sorry I know zero on iommufd api yet, but you said:
>
>The VFIO emulation functions should do whatever VFIO does, is there
>a mistake there?
>
>IIUC what VFIO does here is it returns succeed if unmap over nothing rather
>than failing like iommufd.  Curious (like JasonW) on why that retval?  I'd
>assume for returning "how much unmapped" we can at least still return 0 for
>nothing.
>
>Are you probably suggesting that we can probably handle that in QEMU side
>on -ENOENT here for iommufd only (a question to Yi?).
>
>If that's already a kernel abi, not sure whether it's even discussable, but 
>just to
>raise this up.
>
>--
>Peter Xu



RE: [PATCH v3 0/5] Optimize UNMAP call and bug fix

2023-06-08 Thread Duan, Zhenzhong
>-Original Message-
>From: Peter Xu 
>Sent: Thursday, June 8, 2023 11:54 PM
>To: Duan, Zhenzhong 
>Cc: qemu-devel@nongnu.org; m...@redhat.com; jasow...@redhat.com;
>pbonz...@redhat.com; richard.hender...@linaro.org; edua...@habkost.net;
>marcel.apfelb...@gmail.com; alex.william...@redhat.com;
>c...@redhat.com; da...@redhat.com; phi...@linaro.org;
>kwankh...@nvidia.com; c...@nvidia.com; Liu, Yi L ; Peng,
>Chao P 
>Subject: Re: [PATCH v3 0/5] Optimize UNMAP call and bug fix
>
>On Thu, Jun 08, 2023 at 05:52:26PM +0800, Zhenzhong Duan wrote:
>> Hi All,
>>
>> This patchset includes some fixes on VFIO dirty sync and vIOMMU.
>> PATCH1 isn't needed now as dependent changes in PATCH2 is removed, but
>> as Peter has given Reviewed-by, leave it to maintainer to decide if
>> pick or not.
>
>Let's drop patch 1 until it's really used.  Thanks,

Will drop it in next version.

Thanks
Zhenzhong


RE: [PATCH v3 4/5] intel_iommu: Fix address space unmap

2023-06-08 Thread Duan, Zhenzhong


>-Original Message-
>From: Peter Xu 
>Sent: Thursday, June 8, 2023 9:48 PM
>To: Duan, Zhenzhong 
>Cc: qemu-devel@nongnu.org; m...@redhat.com; jasow...@redhat.com;
>pbonz...@redhat.com; richard.hender...@linaro.org; edua...@habkost.net;
>marcel.apfelb...@gmail.com; alex.william...@redhat.com;
>c...@redhat.com; da...@redhat.com; phi...@linaro.org;
>kwankh...@nvidia.com; c...@nvidia.com; Liu, Yi L ; Peng,
>Chao P 
>Subject: Re: [PATCH v3 4/5] intel_iommu: Fix address space unmap
>
>On Thu, Jun 08, 2023 at 05:52:30PM +0800, Zhenzhong Duan wrote:
>> During address space unmap, corresponding IOVA tree entries are also
>> removed. But DMAMap is set beyond notifier's scope by 1, so in theory
>> there is possibility to remove a continuous entry above the notifier's
>> scope but falling in adjacent notifier's scope.
>
>This function is only called in "loop over all notifiers" case (or replay() 
>that just
>got removed, but even so there'll be only 1 notifier normally iiuc at least for
>vt-d), hopefully it means no bug exist (no Fixes needed, no backport needed
>either), but still worth fixing it up.

Not two notifiers as vtd-ir splits for vt-d?

Thanks
Zhenzhong
>
>>
>> There is no issue currently as no use cases allocate notifiers
>> continuously, but let's be robust.
>>
>> Signed-off-by: Zhenzhong Duan 
>
>Reviewed-by: Peter Xu 
>
>--
>Peter Xu



Re: Reducing vdpa migration downtime because of memory pin / maps

2023-06-08 Thread Jason Wang
On Fri, Jun 9, 2023 at 6:39 AM Si-Wei Liu  wrote:
>
>
> On 6/7/23 01:08, Eugenio Perez Martin wrote:
> > On Wed, Jun 7, 2023 at 12:43 AM Si-Wei Liu  wrote:
> >> Sorry for reviving this old thread, I lost the best timing to follow up
> >> on this while I was on vacation. I have been working on this and found
> >> out some discrepancy, please see below.
> >>
> >> On 4/5/23 04:37, Eugenio Perez Martin wrote:
> >>> Hi!
> >>>
> >>> As mentioned in the last upstream virtio-networking meeting, one of
> >>> the factors that adds more downtime to migration is the handling of
> >>> the guest memory (pin, map, etc). At this moment this handling is
> >>> bound to the virtio life cycle (DRIVER_OK, RESET). In that sense, the
> >>> destination device waits until all the guest memory / state is
> >>> migrated to start pinning all the memory.
> >>>
> >>> The proposal is to bind it to the char device life cycle (open vs
> >>> close),
> >> Hmmm, really? If it's the life cycle for char device, the next guest /
> >> qemu launch on the same vhost-vdpa device node won't make it work.
> >>
> > Maybe my sentence was not accurate, but I think we're on the same page here.
> >
> > Two qemu instances opening the same char device at the same time are
> > not allowed, and vhost_vdpa_release clean all the maps. So the next
> > qemu that opens the char device should see a clean device anyway.
>
> I mean the pin can't be done at the time of char device open, where the
> user address space is not known/bound yet. The earliest point possible
> for pinning would be until the vhost_attach_mm() call from SET_OWNER is
> done. Actually I think the counterpart vhost_detach_mm() only gets
> handled in vhost_vdpa_release() at device close time is a resulting
> artifact and amiss of today's vhost protocol - the opposite RESET_OWNER
> call is not made mandatory hence only seen implemented in vhost-net
> device today. One qemu instance could well exec(3) another new qemu
> instance to live upgrade itself while keeping all emulated devices and
> guest alive. The current vhost design simply prohibits this from happening.

I'm not sure I fully understand the issue you mention here. What is
missed and can iommufd help anyhow?

>
>
> >
> >>>so all the guest memory can be pinned for all the guest / qemu
> >>> lifecycle.
> >> I think to tie pinning to guest / qemu process life cycle makes more
> >> sense. Essentially this pinning part needs to be decoupled from the
> >> iotlb mapping abstraction layer, and can / should work as a standalone
> >> uAPI. Such that QEMU at the destination may launch and pin all guest's
> >> memory as needed without having to start the device, while awaiting any
> >> incoming migration request. Though problem is, there's no existing vhost
> >> uAPI that could properly serve as the vehicle for that. SET_OWNER /
> >> SET_MEM_TABLE / RESET_OWNER seems a remote fit.. Any objection against
> >> introducing a new but clean vhost uAPI for pinning guest pages, subject
> >> to guest's life cycle?
> >>
> > I think that to pin or not pin memory maps should be a kernel
> > decision, not to be driven by qemu.
>
> It's kernel decision for sure. I am with this part.
>
> > I'm not against it if needed, but
> > let me know if the current "clean at close" address your concerns.
>
> To better facilitate QEMU exec (live update) case, I propose we add new
> vhost uAPI pair for explicit pinning request - which would live with
> user mm's, or more precisely qemu instance's lifecycle.

Is this something similar to iommufd?

Btw, I'm not sure whether or not it's good to expose pinning to the
userspace. For example, vhost allows virtual mapping instead of dma
mapping which doesn't require pinning at all.

Thanks

>
> >
> >> Another concern is the use_va stuff, originally it tags to the device
> >> level and is made static at the time of device instantiation, which is
> >> fine. But others to come just find a new home at per-group level or
> >> per-vq level struct. Hard to tell whether or not pinning is actually
> >> needed for the latter use_va friends, as they are essentially tied to
> >> the virtio life cycle or feature negotiation. While guest / Qemu starts
> >> way earlier than that. Perhaps just ignore those sub-device level use_va
> >> usages? Presumably !use_va at the device level is sufficient to infer
> >> the need of pinning for device?
> >>
> > I don't follow this. But I have the feeling that the subject of my
> > original mail is way more accurate if I would have said just "memory
> > maps".
>
> I think the iotlb layer in vhost-vdpa just provides the abstraction for
> mapping, not pinning. Although in some case mapping implicitly relies on
> pinning for DMA purpose, it doesn't have to tie to that in uAPI
> semantics. We can do explicit on-demand pinning for cases for e.g.
> warming up device at live migration destination.
>
>
> >
> > I still consider the way to fix it is to actually delegate that to the
> > kernel vdpa, so it can choose if a

Re: [PATCH] vdpa: dont check vhost_vdpa->suspended when unsupported

2023-06-08 Thread Jason Wang
On Wed, Jun 7, 2023 at 11:37 PM Eugenio Perez Martin
 wrote:
>
> On Wed, Jun 7, 2023 at 11:09 AM Zhu Lingshan  wrote:
> >
> > When read the state of a virtqueue, vhost_vdpa need
> > to check whether the device is suspended.
> >
> > This commit verifies whether VHOST_BACKEND_F_SUSPEND is
> > negotiated when checking vhost_vdpa->suspended.
> >
>
> I'll add: Otherwise, qemu prints XXX error message.
>
> On second thought, not returning an error prevents the caller
> (vhost.c:vhost_virtqueue_stop) from recovering used idx from the
> guest.
>
> I'm not sure about the right fix for this, should we call
> virtio_queue_restore_last_avail_idx here?

It should be the duty of the caller:

E.g in vhost_virtqueue_stop() we had:

=>  r = dev->vhost_ops->vhost_get_vring_base(dev, &state);
if (r < 0) {
VHOST_OPS_DEBUG(r, "vhost VQ %u ring restore failed: %d", idx, r);
/* Connection to the backend is broken, so let's sync internal
 * last avail idx to the device used idx.
 */
virtio_queue_restore_last_avail_idx(vdev, idx);
} else {
virtio_queue_set_last_avail_idx(vdev, idx, state.num);

Thansk

> Communicate that the backend
> cannot suspend so vhost.c can print a better error message?
>
> Thanks!
>
> > Signed-off-by: Zhu Lingshan 
> > ---
> >  hw/virtio/vhost-vdpa.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
> > index b3094e8a8b..ae176c06dd 100644
> > --- a/hw/virtio/vhost-vdpa.c
> > +++ b/hw/virtio/vhost-vdpa.c
> > @@ -1397,7 +1397,7 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev 
> > *dev,
> >  return 0;
> >  }
> >
> > -if (!v->suspended) {
> > +if ((dev->backend_cap & BIT_ULL(VHOST_BACKEND_F_SUSPEND)) && 
> > (!v->suspended)) {
> >  /*
> >   * Cannot trust in value returned by device, let vhost recover used
> >   * idx from guest.
> > --
> > 2.39.1
> >
>




Re: [PATCH v3 5/5] gitlab: support disabling job auto-run in upstream

2023-06-08 Thread Richard Henderson

On 6/8/23 09:40, Daniel P. Berrangé wrote:

In forks QEMU_CI=1 can be used to create a pipeline but not auto-run any
jobs. In upstream jobs always auto-run, which is equiv of QEMU_CI=2.

This supports setting QEMU_CI=1 in upstream, to disable job auto-run.
This can be used to preserve CI minutes if repushing a branch to staging
with a specific fix that only needs testing in limited scenarios.

Signed-off-by: Daniel P. Berrangé
---
  .gitlab-ci.d/base.yml | 10 ++
  1 file changed, 10 insertions(+)


Reviewed-by: Richard Henderson 

r~



[PATCH v2 03/38] tests/multiarch: Add test-aes

2023-06-08 Thread Richard Henderson
Use a shared driver and backends for i386, aarch64, ppc64, riscv64.

Signed-off-by: Richard Henderson 
---
 tests/tcg/aarch64/test-aes.c|  58 
 tests/tcg/i386/test-aes.c   |  68 +
 tests/tcg/ppc64/test-aes.c  | 116 +++
 tests/tcg/riscv64/test-aes.c|  76 ++
 tests/tcg/multiarch/test-aes-main.c.inc | 183 
 tests/tcg/aarch64/Makefile.target   |   4 +
 tests/tcg/i386/Makefile.target  |   4 +
 tests/tcg/ppc64/Makefile.target |   1 +
 tests/tcg/riscv64/Makefile.target   |   4 +
 9 files changed, 514 insertions(+)
 create mode 100644 tests/tcg/aarch64/test-aes.c
 create mode 100644 tests/tcg/i386/test-aes.c
 create mode 100644 tests/tcg/ppc64/test-aes.c
 create mode 100644 tests/tcg/riscv64/test-aes.c
 create mode 100644 tests/tcg/multiarch/test-aes-main.c.inc

diff --git a/tests/tcg/aarch64/test-aes.c b/tests/tcg/aarch64/test-aes.c
new file mode 100644
index 00..2cd324f09b
--- /dev/null
+++ b/tests/tcg/aarch64/test-aes.c
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "../multiarch/test-aes-main.c.inc"
+
+bool test_SB_SR(uint8_t *o, const uint8_t *i)
+{
+/* aese also adds round key, so supply zero. */
+asm("ld1 { v0.16b }, [%1]\n\t"
+"movi v1.16b, #0\n\t"
+"aese v0.16b, v1.16b\n\t"
+"st1 { v0.16b }, [%0]"
+: : "r"(o), "r"(i) : "v0", "v1", "memory");
+return true;
+}
+
+bool test_MC(uint8_t *o, const uint8_t *i)
+{
+asm("ld1 { v0.16b }, [%1]\n\t"
+"aesmc v0.16b, v0.16b\n\t"
+"st1 { v0.16b }, [%0]"
+: : "r"(o), "r"(i) : "v0", "memory");
+return true;
+}
+
+bool test_SB_SR_MC_AK(uint8_t *o, const uint8_t *i, const uint8_t *k)
+{
+return false;
+}
+
+bool test_ISB_ISR(uint8_t *o, const uint8_t *i)
+{
+/* aesd also adds round key, so supply zero. */
+asm("ld1 { v0.16b }, [%1]\n\t"
+"movi v1.16b, #0\n\t"
+"aesd v0.16b, v1.16b\n\t"
+"st1 { v0.16b }, [%0]"
+: : "r"(o), "r"(i) : "v0", "v1", "memory");
+return true;
+}
+
+bool test_IMC(uint8_t *o, const uint8_t *i)
+{
+asm("ld1 { v0.16b }, [%1]\n\t"
+"aesimc v0.16b, v0.16b\n\t"
+"st1 { v0.16b }, [%0]"
+: : "r"(o), "r"(i) : "v0", "memory");
+return true;
+}
+
+bool test_ISB_ISR_AK_IMC(uint8_t *o, const uint8_t *i, const uint8_t *k)
+{
+return false;
+}
+
+bool test_ISB_ISR_IMC_AK(uint8_t *o, const uint8_t *i, const uint8_t *k)
+{
+return false;
+}
diff --git a/tests/tcg/i386/test-aes.c b/tests/tcg/i386/test-aes.c
new file mode 100644
index 00..199395e6cc
--- /dev/null
+++ b/tests/tcg/i386/test-aes.c
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "../multiarch/test-aes-main.c.inc"
+#include 
+
+static bool test_SB_SR(uint8_t *o, const uint8_t *i)
+{
+__m128i vi = _mm_loadu_si128((const __m128i_u *)i);
+
+/* aesenclast also adds round key, so supply zero. */
+vi = _mm_aesenclast_si128(vi, _mm_setzero_si128());
+
+_mm_storeu_si128((__m128i_u *)o, vi);
+return true;
+}
+
+static bool test_MC(uint8_t *o, const uint8_t *i)
+{
+return false;
+}
+
+static bool test_SB_SR_MC_AK(uint8_t *o, const uint8_t *i, const uint8_t *k)
+{
+__m128i vi = _mm_loadu_si128((const __m128i_u *)i);
+__m128i vk = _mm_loadu_si128((const __m128i_u *)k);
+
+vi = _mm_aesenc_si128(vi, vk);
+
+_mm_storeu_si128((__m128i_u *)o, vi);
+return true;
+}
+
+static bool test_ISB_ISR(uint8_t *o, const uint8_t *i)
+{
+__m128i vi = _mm_loadu_si128((const __m128i_u *)i);
+
+/* aesdeclast also adds round key, so supply zero. */
+vi = _mm_aesdeclast_si128(vi, _mm_setzero_si128());
+
+_mm_storeu_si128((__m128i_u *)o, vi);
+return true;
+}
+
+static bool test_IMC(uint8_t *o, const uint8_t *i)
+{
+__m128i vi = _mm_loadu_si128((const __m128i_u *)i);
+
+vi = _mm_aesimc_si128(vi);
+
+_mm_storeu_si128((__m128i_u *)o, vi);
+return true;
+}
+
+static bool test_ISB_ISR_AK_IMC(uint8_t *o, const uint8_t *i, const uint8_t *k)
+{
+return false;
+}
+
+static bool test_ISB_ISR_IMC_AK(uint8_t *o, const uint8_t *i, const uint8_t *k)
+{
+__m128i vi = _mm_loadu_si128((const __m128i_u *)i);
+__m128i vk = _mm_loadu_si128((const __m128i_u *)k);
+
+vi = _mm_aesdec_si128(vi, vk);
+
+_mm_storeu_si128((__m128i_u *)o, vi);
+return true;
+}
diff --git a/tests/tcg/ppc64/test-aes.c b/tests/tcg/ppc64/test-aes.c
new file mode 100644
index 00..1d2be488e9
--- /dev/null
+++ b/tests/tcg/ppc64/test-aes.c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "../multiarch/test-aes-main.c.inc"
+
+#undef BIG_ENDIAN
+#define BIG_ENDIAN  (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+
+static unsigned char bswap_le[16] __attribute__((aligned(16))) = {
+8,9,10,11,12,13,14,15,
+0,1,2,3,4,5,6,7
+};
+
+bool test_SB_SR(uint8_t *o, const uint8_t *i)
+{
+/* vciph

[PATCH v2 32/38] crypto: Remove AES_shifts, AES_ishifts

2023-06-08 Thread Richard Henderson
These arrays are no longer used, replaced by AES_SH_*, AES_ISH_*.

Signed-off-by: Richard Henderson 
---
 include/crypto/aes.h |  4 
 crypto/aes.c | 14 --
 2 files changed, 18 deletions(-)

diff --git a/include/crypto/aes.h b/include/crypto/aes.h
index 24b073d569..aa8b54065d 100644
--- a/include/crypto/aes.h
+++ b/include/crypto/aes.h
@@ -30,10 +30,6 @@ void AES_decrypt(const unsigned char *in, unsigned char *out,
 extern const uint8_t AES_sbox[256];
 extern const uint8_t AES_isbox[256];
 
-/* AES ShiftRows and InvShiftRows */
-extern const uint8_t AES_shifts[16];
-extern const uint8_t AES_ishifts[16];
-
 /* AES MixColumns, for use with rot32. */
 extern const uint32_t AES_mc_rot[256];
 
diff --git a/crypto/aes.c b/crypto/aes.c
index f0721ad4a2..7b8a22fe3e 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -131,13 +131,6 @@ enum {
 AES_SH_F = 0xb,
 };
 
-const uint8_t AES_shifts[16] = {
-AES_SH_0, AES_SH_1, AES_SH_2, AES_SH_3,
-AES_SH_4, AES_SH_5, AES_SH_6, AES_SH_7,
-AES_SH_8, AES_SH_9, AES_SH_A, AES_SH_B,
-AES_SH_C, AES_SH_D, AES_SH_E, AES_SH_F,
-};
-
 /* AES InvShiftRows, for complete unrolling. */
 enum {
 AES_ISH_0 = 0x0,
@@ -158,13 +151,6 @@ enum {
 AES_ISH_F = 0x3,
 };
 
-const uint8_t AES_ishifts[16] = {
-AES_ISH_0, AES_ISH_1, AES_ISH_2, AES_ISH_3,
-AES_ISH_4, AES_ISH_5, AES_ISH_6, AES_ISH_7,
-AES_ISH_8, AES_ISH_9, AES_ISH_A, AES_ISH_B,
-AES_ISH_C, AES_ISH_D, AES_ISH_E, AES_ISH_F,
-};
-
 /*
  * MixColumns lookup table, for use with rot32.
  */
-- 
2.34.1




[PATCH v2 04/38] target/arm: Move aesmc and aesimc tables to crypto/aes.c

2023-06-08 Thread Richard Henderson
We do not currently have a table in crypto/ for just MixColumns.
Move both tables for consistency.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/crypto/aes.h   |   6 ++
 crypto/aes.c   | 140 
 target/arm/tcg/crypto_helper.c | 143 ++---
 3 files changed, 151 insertions(+), 138 deletions(-)

diff --git a/include/crypto/aes.h b/include/crypto/aes.h
index 822d64588c..24b073d569 100644
--- a/include/crypto/aes.h
+++ b/include/crypto/aes.h
@@ -34,6 +34,12 @@ extern const uint8_t AES_isbox[256];
 extern const uint8_t AES_shifts[16];
 extern const uint8_t AES_ishifts[16];
 
+/* AES MixColumns, for use with rot32. */
+extern const uint32_t AES_mc_rot[256];
+
+/* AES InvMixColumns, for use with rot32. */
+extern const uint32_t AES_imc_rot[256];
+
 /* AES InvMixColumns */
 /* AES_imc[x][0] = [x].[0e, 09, 0d, 0b]; */
 /* AES_imc[x][1] = [x].[0b, 0e, 09, 0d]; */
diff --git a/crypto/aes.c b/crypto/aes.c
index af72ff7779..67bb74b8e3 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -116,6 +116,146 @@ const uint8_t AES_ishifts[16] = {
 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
 };
 
+/*
+ * MixColumns lookup table, for use with rot32.
+ */
+const uint32_t AES_mc_rot[256] = {
+0x, 0x03010102, 0x06020204, 0x05030306,
+0x0c040408, 0x0f05050a, 0x0a06060c, 0x0907070e,
+0x18080810, 0x1b090912, 0x1e0a0a14, 0x1d0b0b16,
+0x140c0c18, 0x170d0d1a, 0x120e0e1c, 0x110f0f1e,
+0x30101020, 0x3322, 0x36121224, 0x35131326,
+0x3c141428, 0x3f15152a, 0x3a16162c, 0x3917172e,
+0x28181830, 0x2b191932, 0x2e1a1a34, 0x2d1b1b36,
+0x241c1c38, 0x271d1d3a, 0x221e1e3c, 0x211f1f3e,
+0x60202040, 0x63212142, 0x6644, 0x65232346,
+0x6c242448, 0x6f25254a, 0x6a26264c, 0x6927274e,
+0x78282850, 0x7b292952, 0x7e2a2a54, 0x7d2b2b56,
+0x742c2c58, 0x772d2d5a, 0x722e2e5c, 0x712f2f5e,
+0x50303060, 0x53313162, 0x56323264, 0x5566,
+0x5c343468, 0x5f35356a, 0x5a36366c, 0x5937376e,
+0x48383870, 0x4b393972, 0x4e3a3a74, 0x4d3b3b76,
+0x443c3c78, 0x473d3d7a, 0x423e3e7c, 0x413f3f7e,
+0xc0404080, 0xc3414182, 0xc6424284, 0xc5434386,
+0xcc88, 0xcf45458a, 0xca46468c, 0xc947478e,
+0xd8484890, 0xdb494992, 0xde4a4a94, 0xdd4b4b96,
+0xd44c4c98, 0xd74d4d9a, 0xd24e4e9c, 0xd14f4f9e,
+0xf05050a0, 0xf35151a2, 0xf65252a4, 0xf55353a6,
+0xfc5454a8, 0xffaa, 0xfa5656ac, 0xf95757ae,
+0xe85858b0, 0xeb5959b2, 0xee5a5ab4, 0xed5b5bb6,
+0xe45c5cb8, 0xe75d5dba, 0xe25e5ebc, 0xe15f5fbe,
+0xa06060c0, 0xa36161c2, 0xa66262c4, 0xa56363c6,
+0xac6464c8, 0xaf6565ca, 0xaacc, 0xa96767ce,
+0xb86868d0, 0xbb6969d2, 0xbe6a6ad4, 0xbd6b6bd6,
+0xb46c6cd8, 0xb76d6dda, 0xb26e6edc, 0xb16f6fde,
+0x907070e0, 0x937171e2, 0x967272e4, 0x957373e6,
+0x9c7474e8, 0x9f7575ea, 0x9a7676ec, 0x99ee,
+0x887878f0, 0x8b7979f2, 0x8e7a7af4, 0x8d7b7bf6,
+0x847c7cf8, 0x877d7dfa, 0x827e7efc, 0x817f7ffe,
+0x9b80801b, 0x98818119, 0x9d82821f, 0x9e83831d,
+0x97848413, 0x94858511, 0x91868617, 0x92878715,
+0x830b, 0x80898909, 0x858a8a0f, 0x868b8b0d,
+0x8f8c8c03, 0x8c8d8d01, 0x898e8e07, 0x8a8f8f05,
+0xab90903b, 0xa8919139, 0xad92923f, 0xae93933d,
+0xa7949433, 0xa4959531, 0xa1969637, 0xa2979735,
+0xb398982b, 0xb029, 0xb59a9a2f, 0xb69b9b2d,
+0xbf9c9c23, 0xbc9d9d21, 0xb99e9e27, 0xba9f9f25,
+0xfba0a05b, 0xf8a1a159, 0xfda2a25f, 0xfea3a35d,
+0xf7a4a453, 0xf4a5a551, 0xf1a6a657, 0xf2a7a755,
+0xe3a8a84b, 0xe0a9a949, 0xe54f, 0xe6abab4d,
+0xefacac43, 0xecadad41, 0xe9aeae47, 0xeaafaf45,
+0xcbb0b07b, 0xc8b1b179, 0xcdb2b27f, 0xceb3b37d,
+0xc7b4b473, 0xc4b5b571, 0xc1b6b677, 0xc2b7b775,
+0xd3b8b86b, 0xd0b9b969, 0xd5baba6f, 0xd66d,
+0xdfbcbc63, 0xdcbdbd61, 0xd9bebe67, 0xdabfbf65,
+0x5bc0c09b, 0x58c1c199, 0x5dc2c29f, 0x5ec3c39d,
+0x57c4c493, 0x54c5c591, 0x51c6c697, 0x52c7c795,
+0x43c8c88b, 0x40c9c989, 0x45caca8f, 0x46cbcb8d,
+0x4f83, 0x4ccdcd81, 0x49cece87, 0x4acfcf85,
+0x6bd0d0bb, 0x68d1d1b9, 0x6dd2d2bf, 0x6ed3d3bd,
+0x67d4d4b3, 0x64d5d5b1, 0x61d6d6b7, 0x62d7d7b5,
+0x73d8d8ab, 0x70d9d9a9, 0x75dadaaf, 0x76dbdbad,
+0x7fdcdca3, 0x7ca1, 0x79dedea7, 0x7adfdfa5,
+0x3be0e0db, 0x38e1e1d9, 0x3de2e2df, 0x3ee3e3dd,
+0x37e4e4d3, 0x34e5e5d1, 0x31e6e6d7, 0x32e7e7d5,
+0x23e8e8cb, 0x20e9e9c9, 0x25eaeacf, 0x26ebebcd,
+0x2fececc3, 0x2cededc1, 0x29c7, 0x2aefefc5,
+0x0bf0f0fb, 0x08f1f1f9, 0x0df2f2ff, 0x0ef3f3fd,
+0x07f4f4f3, 0x04f5f5f1, 0x01f6f6f7, 0x02f7f7f5,
+0x13f8f8eb, 0x10f9f9e9, 0x15fafaef, 0x16fbfbed,
+0x1ffcfce3, 0x1cfdfde1, 0x19fefee7, 0x1ae5,
+};
+
+/*
+ * Inverse MixColumns lookup table, for use with rot32.
+ */
+const uint32_t AES_imc_rot[256] = {
+0x, 0x0b0d090e, 0x161a121c, 0x1d171b12,
+0x2c342438, 0x27392d36, 0x3a2e3624, 0x31233f2a,
+0x58684870, 0x5365417e, 0x4e725a6c, 0x457f5362,
+0x745c6c48, 0x7f5165

[PATCH v2 08/38] target/arm: Demultiplex AESE and AESMC

2023-06-08 Thread Richard Henderson
Split these helpers so that we are not passing 'decrypt'
within the simd descriptor.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/arm/helper.h |  2 ++
 target/arm/tcg/sve.decode   |  4 ++--
 target/arm/tcg/crypto_helper.c  | 37 +++--
 target/arm/tcg/translate-a64.c  | 13 
 target/arm/tcg/translate-neon.c |  4 ++--
 target/arm/tcg/translate-sve.c  |  8 ---
 6 files changed, 41 insertions(+), 27 deletions(-)

diff --git a/target/arm/helper.h b/target/arm/helper.h
index 3335c2b10b..95e32a697a 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -552,7 +552,9 @@ DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, 
ptr)
 DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
 
 DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(crypto_aesd, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(crypto_aesimc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
 
 DEF_HELPER_FLAGS_4(crypto_sha1su0, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
 DEF_HELPER_FLAGS_4(crypto_sha1c, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
diff --git a/target/arm/tcg/sve.decode b/target/arm/tcg/sve.decode
index 14b3a69c36..04b6fcc0cf 100644
--- a/target/arm/tcg/sve.decode
+++ b/target/arm/tcg/sve.decode
@@ -1629,8 +1629,8 @@ STNT1_zprz  1110010 .. 10 . 001 ... . . \
 ### SVE2 Crypto Extensions
 
 # SVE2 crypto unary operations
-# AESMC and AESIMC
-AESMC   01000101 00 1011100 decrypt:1 0 rd:5
+AESMC   01000101 00 1011100 0 0 rd:5
+AESIMC  01000101 00 1011100 1 0 rd:5
 
 # SVE2 crypto destructive binary operations
 AESE01000101 00 10001 0 11100 0 . .  @rdn_rm_e0
diff --git a/target/arm/tcg/crypto_helper.c b/target/arm/tcg/crypto_helper.c
index 06254939d2..75882d9ea3 100644
--- a/target/arm/tcg/crypto_helper.c
+++ b/target/arm/tcg/crypto_helper.c
@@ -45,11 +45,9 @@ static void clear_tail_16(void *vd, uint32_t desc)
 clear_tail(vd, opr_sz, max_sz);
 }
 
-static void do_crypto_aese(uint64_t *rd, uint64_t *rn,
-   uint64_t *rm, bool decrypt)
+static void do_crypto_aese(uint64_t *rd, uint64_t *rn, uint64_t *rm,
+   const uint8_t *sbox, const uint8_t *shift)
 {
-static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
-static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
 union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } };
 union CRYPTO_STATE st = { .l = { rn[0], rn[1] } };
 int i;
@@ -60,7 +58,7 @@ static void do_crypto_aese(uint64_t *rd, uint64_t *rn,
 
 /* combine ShiftRows operation and sbox substitution */
 for (i = 0; i < 16; i++) {
-CR_ST_BYTE(st, i) = sbox[decrypt][CR_ST_BYTE(rk, shift[decrypt][i])];
+CR_ST_BYTE(st, i) = sbox[CR_ST_BYTE(rk, shift[i])];
 }
 
 rd[0] = st.l[0];
@@ -70,18 +68,26 @@ static void do_crypto_aese(uint64_t *rd, uint64_t *rn,
 void HELPER(crypto_aese)(void *vd, void *vn, void *vm, uint32_t desc)
 {
 intptr_t i, opr_sz = simd_oprsz(desc);
-bool decrypt = simd_data(desc);
 
 for (i = 0; i < opr_sz; i += 16) {
-do_crypto_aese(vd + i, vn + i, vm + i, decrypt);
+do_crypto_aese(vd + i, vn + i, vm + i, AES_sbox, AES_shifts);
 }
 clear_tail(vd, opr_sz, simd_maxsz(desc));
 }
 
-static void do_crypto_aesmc(uint64_t *rd, uint64_t *rm, bool decrypt)
+void HELPER(crypto_aesd)(void *vd, void *vn, void *vm, uint32_t desc)
+{
+intptr_t i, opr_sz = simd_oprsz(desc);
+
+for (i = 0; i < opr_sz; i += 16) {
+do_crypto_aese(vd + i, vn + i, vm + i, AES_isbox, AES_ishifts);
+}
+clear_tail(vd, opr_sz, simd_maxsz(desc));
+}
+
+static void do_crypto_aesmc(uint64_t *rd, uint64_t *rm, const uint32_t *mc)
 {
 union CRYPTO_STATE st = { .l = { rm[0], rm[1] } };
-const uint32_t *mc = decrypt ? AES_imc_rot : AES_mc_rot;
 int i;
 
 for (i = 0; i < 16; i += 4) {
@@ -99,10 +105,19 @@ static void do_crypto_aesmc(uint64_t *rd, uint64_t *rm, 
bool decrypt)
 void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t desc)
 {
 intptr_t i, opr_sz = simd_oprsz(desc);
-bool decrypt = simd_data(desc);
 
 for (i = 0; i < opr_sz; i += 16) {
-do_crypto_aesmc(vd + i, vm + i, decrypt);
+do_crypto_aesmc(vd + i, vm + i, AES_mc_rot);
+}
+clear_tail(vd, opr_sz, simd_maxsz(desc));
+}
+
+void HELPER(crypto_aesimc)(void *vd, void *vm, uint32_t desc)
+{
+intptr_t i, opr_sz = simd_oprsz(desc);
+
+for (i = 0; i < opr_sz; i += 16) {
+do_crypto_aesmc(vd + i, vm + i, AES_imc_rot);
 }
 clear_tail(vd, opr_sz, simd_maxsz(desc));
 }
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index aa93f37e21..8b7337ad01 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a6

[PATCH v2 31/38] target/ppc: Use aesdec_ISB_ISR_AK_IMC

2023-06-08 Thread Richard Henderson
This implements the VNCIPHER instruction.

Signed-off-by: Richard Henderson 
---
 target/ppc/int_helper.c | 19 ---
 1 file changed, 4 insertions(+), 15 deletions(-)

diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 1e477924b7..834da80fe3 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2947,22 +2947,11 @@ void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b)
 
 void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-/* This differs from what is written in ISA V2.07.  The RTL is */
-/* incorrect and will be fixed in V2.07B.  */
-int i;
-ppc_avr_t tmp;
+AESState *ad = (AESState *)r;
+AESState *st = (AESState *)a;
+AESState *rk = (AESState *)b;
 
-VECTOR_FOR_INORDER_I(i, u8) {
-tmp.VsrB(i) = b->VsrB(i) ^ AES_isbox[a->VsrB(AES_ishifts[i])];
-}
-
-VECTOR_FOR_INORDER_I(i, u32) {
-r->VsrW(i) =
-AES_imc[tmp.VsrB(4 * i + 0)][0] ^
-AES_imc[tmp.VsrB(4 * i + 1)][1] ^
-AES_imc[tmp.VsrB(4 * i + 2)][2] ^
-AES_imc[tmp.VsrB(4 * i + 3)][3];
-}
+aesdec_ISB_ISR_AK_IMC(ad, st, rk, true);
 }
 
 void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
-- 
2.34.1




[PATCH v2 12/38] crypto: Add aesdec_ISB_ISR_AK

2023-06-08 Thread Richard Henderson
Add a primitive for InvSubBytes + InvShiftRows + AddRoundKey.

Signed-off-by: Richard Henderson 
---
 host/include/generic/host/aes-round.h |  4 +++
 include/crypto/aes-round.h| 21 +
 crypto/aes.c  | 43 +++
 3 files changed, 68 insertions(+)

diff --git a/host/include/generic/host/aes-round.h 
b/host/include/generic/host/aes-round.h
index 19c8505e2b..e8f6bb0b99 100644
--- a/host/include/generic/host/aes-round.h
+++ b/host/include/generic/host/aes-round.h
@@ -13,4 +13,8 @@ void aesenc_SB_SR_AK_accel(AESState *, const AESState *,
const AESState *, bool)
 QEMU_ERROR("unsupported accel");
 
+void aesdec_ISB_ISR_AK_accel(AESState *, const AESState *,
+ const AESState *, bool)
+QEMU_ERROR("unsupported accel");
+
 #endif
diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h
index 15ea1f42bc..56376cc83b 100644
--- a/include/crypto/aes-round.h
+++ b/include/crypto/aes-round.h
@@ -41,4 +41,25 @@ static inline void aesenc_SB_SR_AK(AESState *r, const 
AESState *st,
 }
 }
 
+/*
+ * Perform InvSubBytes + InvShiftRows.
+ */
+
+void aesdec_ISB_ISR_AK_gen(AESState *ret, const AESState *st,
+   const AESState *rk);
+void aesdec_ISB_ISR_AK_genrev(AESState *ret, const AESState *st,
+  const AESState *rk);
+
+static inline void aesdec_ISB_ISR_AK(AESState *r, const AESState *st,
+ const AESState *rk, bool be)
+{
+if (HAVE_AES_ACCEL) {
+aesdec_ISB_ISR_AK_accel(r, st, rk, be);
+} else if (HOST_BIG_ENDIAN == be) {
+aesdec_ISB_ISR_AK_gen(r, st, rk);
+} else {
+aesdec_ISB_ISR_AK_genrev(r, st, rk);
+}
+}
+
 #endif /* CRYPTO_AES_ROUND_H */
diff --git a/crypto/aes.c b/crypto/aes.c
index 896f6f44f1..767930223c 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -1293,6 +1293,49 @@ void aesenc_SB_SR_AK_genrev(AESState *r, const AESState 
*s, const AESState *k)
 aesenc_SB_SR_AK_swap(r, s, k, true);
 }
 
+/* Perform InvSubBytes + InvShiftRows. */
+static inline void
+aesdec_ISB_ISR_AK_swap(AESState *ret, const AESState *st,
+   const AESState *rk, bool swap)
+{
+const int swap_b = swap ? 15 : 0;
+AESState t;
+
+t.b[swap_b ^ 0x0] = AES_isbox[st->b[swap_b ^ AES_ISH_0]];
+t.b[swap_b ^ 0x1] = AES_isbox[st->b[swap_b ^ AES_ISH_1]];
+t.b[swap_b ^ 0x2] = AES_isbox[st->b[swap_b ^ AES_ISH_2]];
+t.b[swap_b ^ 0x3] = AES_isbox[st->b[swap_b ^ AES_ISH_3]];
+t.b[swap_b ^ 0x4] = AES_isbox[st->b[swap_b ^ AES_ISH_4]];
+t.b[swap_b ^ 0x5] = AES_isbox[st->b[swap_b ^ AES_ISH_5]];
+t.b[swap_b ^ 0x6] = AES_isbox[st->b[swap_b ^ AES_ISH_6]];
+t.b[swap_b ^ 0x7] = AES_isbox[st->b[swap_b ^ AES_ISH_7]];
+t.b[swap_b ^ 0x8] = AES_isbox[st->b[swap_b ^ AES_ISH_8]];
+t.b[swap_b ^ 0x9] = AES_isbox[st->b[swap_b ^ AES_ISH_9]];
+t.b[swap_b ^ 0xa] = AES_isbox[st->b[swap_b ^ AES_ISH_A]];
+t.b[swap_b ^ 0xb] = AES_isbox[st->b[swap_b ^ AES_ISH_B]];
+t.b[swap_b ^ 0xc] = AES_isbox[st->b[swap_b ^ AES_ISH_C]];
+t.b[swap_b ^ 0xd] = AES_isbox[st->b[swap_b ^ AES_ISH_D]];
+t.b[swap_b ^ 0xe] = AES_isbox[st->b[swap_b ^ AES_ISH_E]];
+t.b[swap_b ^ 0xf] = AES_isbox[st->b[swap_b ^ AES_ISH_F]];
+
+/*
+ * Perform the AddRoundKey with generic vectors.
+ * This may be expanded to either host integer or host vector code.
+ * The key and output endianness match, so no bswap required.
+ */
+ret->v = t.v ^ rk->v;
+}
+
+void aesdec_ISB_ISR_AK_gen(AESState *r, const AESState *s, const AESState *k)
+{
+aesdec_ISB_ISR_AK_swap(r, s, k, false);
+}
+
+void aesdec_ISB_ISR_AK_genrev(AESState *r, const AESState *s, const AESState 
*k)
+{
+aesdec_ISB_ISR_AK_swap(r, s, k, true);
+}
+
 /**
  * Expand the cipher key into the encryption key schedule.
  */
-- 
2.34.1




[PATCH v2 07/38] target/i386: Use aesenc_SB_SR_AK

2023-06-08 Thread Richard Henderson
This implements the AESENCLAST instruction.

Signed-off-by: Richard Henderson 
---
 target/i386/ops_sse.h | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index fb63af7afa..63fdecbe03 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -19,6 +19,7 @@
  */
 
 #include "crypto/aes.h"
+#include "crypto/aes-round.h"
 
 #if SHIFT == 0
 #define Reg MMXReg
@@ -2202,12 +2203,12 @@ void glue(helper_aesenc, SUFFIX)(CPUX86State *env, Reg 
*d, Reg *v, Reg *s)
 
 void glue(helper_aesenclast, SUFFIX)(CPUX86State *env, Reg *d, Reg *v, Reg *s)
 {
-int i;
-Reg st = *v;
-Reg rk = *s;
+for (int i = 0; i < SHIFT; i++) {
+AESState *ad = (AESState *)&d->ZMM_X(i);
+AESState *st = (AESState *)&v->ZMM_X(i);
+AESState *rk = (AESState *)&s->ZMM_X(i);
 
-for (i = 0; i < 8 << SHIFT; i++) {
-d->B(i) = rk.B(i) ^ (AES_sbox[st.B(AES_shifts[i & 15] + (i & ~15))]);
+aesenc_SB_SR_AK(ad, st, rk, false);
 }
 }
 
-- 
2.34.1




[PATCH v2 21/38] target/arm: Use aesdec_IMC

2023-06-08 Thread Richard Henderson
This implements the AESIMC instruction.  We have converted everything
to crypto/aes-round.h; crypto/aes.h is no longer needed.

Signed-off-by: Richard Henderson 
---
 target/arm/tcg/crypto_helper.c | 33 ++---
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/target/arm/tcg/crypto_helper.c b/target/arm/tcg/crypto_helper.c
index 1952aaac58..fdd70abbfd 100644
--- a/target/arm/tcg/crypto_helper.c
+++ b/target/arm/tcg/crypto_helper.c
@@ -14,7 +14,6 @@
 #include "cpu.h"
 #include "exec/helper-proto.h"
 #include "tcg/tcg-gvec-desc.h"
-#include "crypto/aes.h"
 #include "crypto/aes-round.h"
 #include "crypto/sm4.h"
 #include "vec_internal.h"
@@ -102,23 +101,6 @@ void HELPER(crypto_aesd)(void *vd, void *vn, void *vm, 
uint32_t desc)
 clear_tail(vd, opr_sz, simd_maxsz(desc));
 }
 
-static void do_crypto_aesmc(uint64_t *rd, uint64_t *rm, const uint32_t *mc)
-{
-union CRYPTO_STATE st = { .l = { rm[0], rm[1] } };
-int i;
-
-for (i = 0; i < 16; i += 4) {
-CR_ST_WORD(st, i >> 2) =
-mc[CR_ST_BYTE(st, i)] ^
-rol32(mc[CR_ST_BYTE(st, i + 1)], 8) ^
-rol32(mc[CR_ST_BYTE(st, i + 2)], 16) ^
-rol32(mc[CR_ST_BYTE(st, i + 3)], 24);
-}
-
-rd[0] = st.l[0];
-rd[1] = st.l[1];
-}
-
 void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t desc)
 {
 intptr_t i, opr_sz = simd_oprsz(desc);
@@ -147,7 +129,20 @@ void HELPER(crypto_aesimc)(void *vd, void *vm, uint32_t 
desc)
 intptr_t i, opr_sz = simd_oprsz(desc);
 
 for (i = 0; i < opr_sz; i += 16) {
-do_crypto_aesmc(vd + i, vm + i, AES_imc_rot);
+AESState *ad = (AESState *)(vd + i);
+AESState *st = (AESState *)(vm + i);
+AESState t;
+
+/* Our uint64_t are in the wrong order for big-endian. */
+if (HOST_BIG_ENDIAN) {
+t.d[0] = st->d[1];
+t.d[1] = st->d[0];
+aesdec_IMC(&t, &t, false);
+ad->d[0] = t.d[1];
+ad->d[1] = t.d[0];
+} else {
+aesdec_IMC(ad, st, false);
+}
 }
 clear_tail(vd, opr_sz, simd_maxsz(desc));
 }
-- 
2.34.1




[PATCH v2 29/38] target/riscv: Use aesdec_ISB_ISR_IMC_AK

2023-06-08 Thread Richard Henderson
This implements the AES64DSM instruction.  This was the last use
of aes64_operation and its support macros, so remove them all.

Signed-off-by: Richard Henderson 
---
 target/riscv/crypto_helper.c | 101 ---
 1 file changed, 10 insertions(+), 91 deletions(-)

diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
index c036fe8632..99d85a6188 100644
--- a/target/riscv/crypto_helper.c
+++ b/target/riscv/crypto_helper.c
@@ -104,98 +104,8 @@ target_ulong HELPER(aes32dsi)(target_ulong rs1, 
target_ulong rs2,
 return aes32_operation(shamt, rs1, rs2, false, false);
 }
 
-#define BY(X, I) ((X >> (8 * I)) & 0xFF)
-
-#define AES_SHIFROWS_LO(RS1, RS2) ( \
-(((RS1 >> 24) & 0xFF) << 56) | (((RS2 >> 48) & 0xFF) << 48) | \
-(((RS2 >> 8) & 0xFF) << 40) | (((RS1 >> 32) & 0xFF) << 32) | \
-(((RS2 >> 56) & 0xFF) << 24) | (((RS2 >> 16) & 0xFF) << 16) | \
-(((RS1 >> 40) & 0xFF) << 8) | (((RS1 >> 0) & 0xFF) << 0))
-
-#define AES_INVSHIFROWS_LO(RS1, RS2) ( \
-(((RS2 >> 24) & 0xFF) << 56) | (((RS2 >> 48) & 0xFF) << 48) | \
-(((RS1 >> 8) & 0xFF) << 40) | (((RS1 >> 32) & 0xFF) << 32) | \
-(((RS1 >> 56) & 0xFF) << 24) | (((RS2 >> 16) & 0xFF) << 16) | \
-(((RS2 >> 40) & 0xFF) << 8) | (((RS1 >> 0) & 0xFF) << 0))
-
-#define AES_MIXBYTE(COL, B0, B1, B2, B3) ( \
-BY(COL, B3) ^ BY(COL, B2) ^ AES_GFMUL(BY(COL, B1), 3) ^ \
-AES_GFMUL(BY(COL, B0), 2))
-
-#define AES_MIXCOLUMN(COL) ( \
-AES_MIXBYTE(COL, 3, 0, 1, 2) << 24 | \
-AES_MIXBYTE(COL, 2, 3, 0, 1) << 16 | \
-AES_MIXBYTE(COL, 1, 2, 3, 0) << 8 | AES_MIXBYTE(COL, 0, 1, 2, 3) << 0)
-
-#define AES_INVMIXBYTE(COL, B0, B1, B2, B3) ( \
-AES_GFMUL(BY(COL, B3), 0x9) ^ AES_GFMUL(BY(COL, B2), 0xd) ^ \
-AES_GFMUL(BY(COL, B1), 0xb) ^ AES_GFMUL(BY(COL, B0), 0xe))
-
-#define AES_INVMIXCOLUMN(COL) ( \
-AES_INVMIXBYTE(COL, 3, 0, 1, 2) << 24 | \
-AES_INVMIXBYTE(COL, 2, 3, 0, 1) << 16 | \
-AES_INVMIXBYTE(COL, 1, 2, 3, 0) << 8 | \
-AES_INVMIXBYTE(COL, 0, 1, 2, 3) << 0)
-
 static const AESState aes_zero = { };
 
-static inline target_ulong aes64_operation(target_ulong rs1, target_ulong rs2,
-   bool enc, bool mix)
-{
-uint64_t RS1 = rs1;
-uint64_t RS2 = rs2;
-uint64_t result;
-uint64_t temp;
-uint32_t col_0;
-uint32_t col_1;
-
-if (enc) {
-temp = AES_SHIFROWS_LO(RS1, RS2);
-temp = (((uint64_t)AES_sbox[(temp >> 0) & 0xFF] << 0) |
-((uint64_t)AES_sbox[(temp >> 8) & 0xFF] << 8) |
-((uint64_t)AES_sbox[(temp >> 16) & 0xFF] << 16) |
-((uint64_t)AES_sbox[(temp >> 24) & 0xFF] << 24) |
-((uint64_t)AES_sbox[(temp >> 32) & 0xFF] << 32) |
-((uint64_t)AES_sbox[(temp >> 40) & 0xFF] << 40) |
-((uint64_t)AES_sbox[(temp >> 48) & 0xFF] << 48) |
-((uint64_t)AES_sbox[(temp >> 56) & 0xFF] << 56));
-if (mix) {
-col_0 = temp & 0x;
-col_1 = temp >> 32;
-
-col_0 = AES_MIXCOLUMN(col_0);
-col_1 = AES_MIXCOLUMN(col_1);
-
-result = ((uint64_t)col_1 << 32) | col_0;
-} else {
-result = temp;
-}
-} else {
-temp = AES_INVSHIFROWS_LO(RS1, RS2);
-temp = (((uint64_t)AES_isbox[(temp >> 0) & 0xFF] << 0) |
-((uint64_t)AES_isbox[(temp >> 8) & 0xFF] << 8) |
-((uint64_t)AES_isbox[(temp >> 16) & 0xFF] << 16) |
-((uint64_t)AES_isbox[(temp >> 24) & 0xFF] << 24) |
-((uint64_t)AES_isbox[(temp >> 32) & 0xFF] << 32) |
-((uint64_t)AES_isbox[(temp >> 40) & 0xFF] << 40) |
-((uint64_t)AES_isbox[(temp >> 48) & 0xFF] << 48) |
-((uint64_t)AES_isbox[(temp >> 56) & 0xFF] << 56));
-if (mix) {
-col_0 = temp & 0x;
-col_1 = temp >> 32;
-
-col_0 = AES_INVMIXCOLUMN(col_0);
-col_1 = AES_INVMIXCOLUMN(col_1);
-
-result = ((uint64_t)col_1 << 32) | col_0;
-} else {
-result = temp;
-}
-}
-
-return result;
-}
-
 target_ulong HELPER(aes64esm)(target_ulong rs1, target_ulong rs2)
 {
 AESState t;
@@ -228,7 +138,16 @@ target_ulong HELPER(aes64ds)(target_ulong rs1, 
target_ulong rs2)
 
 target_ulong HELPER(aes64dsm)(target_ulong rs1, target_ulong rs2)
 {
-return aes64_operation(rs1, rs2, false, true);
+AESState t, z = { };
+
+/*
+ * This instruction does not include a round key,
+ * so supply a zero to our primitive.
+ */
+t.d[HOST_BIG_ENDIAN] = rs1;
+t.d[!HOST_BIG_ENDIAN] = rs2;
+aesdec_ISB_ISR_IMC_AK(&t, &t, &z, false);
+return t.d[HOST_BIG_ENDIAN];
 }
 
 target_ulong HELPER(aes64ks2)(target_ulong rs1, target_ulong rs2)
-- 
2.34.1




[PATCH v2 35/38] crypto: Unexport AES_*_rot, AES_TeN, AES_TdN

2023-06-08 Thread Richard Henderson
These arrays are no longer used outside of aes.c.

Signed-off-by: Richard Henderson 
---
 include/crypto/aes.h | 25 -
 crypto/aes.c | 33 +
 2 files changed, 21 insertions(+), 37 deletions(-)

diff --git a/include/crypto/aes.h b/include/crypto/aes.h
index 99209f51b9..709d4d226b 100644
--- a/include/crypto/aes.h
+++ b/include/crypto/aes.h
@@ -30,29 +30,4 @@ void AES_decrypt(const unsigned char *in, unsigned char *out,
 extern const uint8_t AES_sbox[256];
 extern const uint8_t AES_isbox[256];
 
-/* AES MixColumns, for use with rot32. */
-extern const uint32_t AES_mc_rot[256];
-
-/* AES InvMixColumns, for use with rot32. */
-extern const uint32_t AES_imc_rot[256];
-
-/*
-AES_Te0[x] = S [x].[02, 01, 01, 03];
-AES_Te1[x] = S [x].[03, 02, 01, 01];
-AES_Te2[x] = S [x].[01, 03, 02, 01];
-AES_Te3[x] = S [x].[01, 01, 03, 02];
-AES_Te4[x] = S [x].[01, 01, 01, 01];
-
-AES_Td0[x] = Si[x].[0e, 09, 0d, 0b];
-AES_Td1[x] = Si[x].[0b, 0e, 09, 0d];
-AES_Td2[x] = Si[x].[0d, 0b, 0e, 09];
-AES_Td3[x] = Si[x].[09, 0d, 0b, 0e];
-AES_Td4[x] = Si[x].[01, 01, 01, 01];
-*/
-
-extern const uint32_t AES_Te0[256], AES_Te1[256], AES_Te2[256],
-  AES_Te3[256], AES_Te4[256];
-extern const uint32_t AES_Td0[256], AES_Td1[256], AES_Td2[256],
-  AES_Td3[256], AES_Td4[256];
-
 #endif
diff --git a/crypto/aes.c b/crypto/aes.c
index a18267b9f8..30ed2303db 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -154,7 +154,7 @@ enum {
 /*
  * MixColumns lookup table, for use with rot32.
  */
-const uint32_t AES_mc_rot[256] = {
+static const uint32_t AES_mc_rot[256] = {
 0x, 0x03010102, 0x06020204, 0x05030306,
 0x0c040408, 0x0f05050a, 0x0a06060c, 0x0907070e,
 0x18080810, 0x1b090912, 0x1e0a0a14, 0x1d0b0b16,
@@ -224,7 +224,7 @@ const uint32_t AES_mc_rot[256] = {
 /*
  * Inverse MixColumns lookup table, for use with rot32.
  */
-const uint32_t AES_imc_rot[256] = {
+static const uint32_t AES_imc_rot[256] = {
 0x, 0x0b0d090e, 0x161a121c, 0x1d171b12,
 0x2c342438, 0x27392d36, 0x3a2e3624, 0x31233f2a,
 0x58684870, 0x5365417e, 0x4e725a6c, 0x457f5362,
@@ -306,7 +306,7 @@ AES_Td3[x] = Si[x].[09, 0d, 0b, 0e];
 AES_Td4[x] = Si[x].[01, 01, 01, 01];
 */
 
-const uint32_t AES_Te0[256] = {
+static const uint32_t AES_Te0[256] = {
 0xc66363a5U, 0xf87c7c84U, 0xee99U, 0xf67b7b8dU,
 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
@@ -372,7 +372,8 @@ const uint32_t AES_Te0[256] = {
 0x824141c3U, 0x29b0U, 0x5a2d2d77U, 0x1e0f0f11U,
 0x7bb0b0cbU, 0xa85454fcU, 0x6dd6U, 0x2c16163aU,
 };
-const uint32_t AES_Te1[256] = {
+
+static const uint32_t AES_Te1[256] = {
 0xa5c66363U, 0x84f87c7cU, 0x99eeU, 0x8df67b7bU,
 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
@@ -438,7 +439,8 @@ const uint32_t AES_Te1[256] = {
 0xc3824141U, 0xb029U, 0x775a2d2dU, 0x111e0f0fU,
 0xcb7bb0b0U, 0xfca85454U, 0xd66dU, 0x3a2c1616U,
 };
-const uint32_t AES_Te2[256] = {
+
+static const uint32_t AES_Te2[256] = {
 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
@@ -504,8 +506,8 @@ const uint32_t AES_Te2[256] = {
 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
 };
-const uint32_t AES_Te3[256] = {
 
+static const uint32_t AES_Te3[256] = {
 0x6363a5c6U, 0x7c7c84f8U, 0x99eeU, 0x7b7b8df6U,
 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
@@ -571,7 +573,8 @@ const uint32_t AES_Te3[256] = {
 0x4141c382U, 0xb029U, 0x2d2d775aU, 0x0f0f111eU,
 0xb0b0cb7bU, 0x5454fca8U, 0xd66dU, 0x16163a2cU,
 };
-const uint32_t AES_Te4[256] = {
+
+static const uint32_t AES_Te4[256] = {
 0x63636363U, 0x7c7c7c7cU, 0xU, 0x7b7b7b7bU,
 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
@@ -637,7 +640,8 @@ const uint32_t AES_Te4[256] = {
 0x41414141U, 0xU, 0x2d2d2d2dU, 0x0f0f0f0fU,
 0xb0b0b0b0U, 0x54545454U, 0xU, 0x16161616U,
 };
-const uint32_t AES_Td0[256] = {
+
+static const uint32_t AES_Td0[256] = {
 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
@@ -703,7 +707,8 @@ const uint32_t AES_Td0[256] = {
 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
 };
-const uint32_t AES_Td1[256] = {
+
+static const uint32_t AES_Td1[256] = {
 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x2

[PATCH v2 09/38] target/arm: Use aesenc_SB_SR_AK

2023-06-08 Thread Richard Henderson
This implements the AESE instruction.

Signed-off-by: Richard Henderson 
---
 target/arm/tcg/crypto_helper.c | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/target/arm/tcg/crypto_helper.c b/target/arm/tcg/crypto_helper.c
index 75882d9ea3..00f3b21507 100644
--- a/target/arm/tcg/crypto_helper.c
+++ b/target/arm/tcg/crypto_helper.c
@@ -15,6 +15,7 @@
 #include "exec/helper-proto.h"
 #include "tcg/tcg-gvec-desc.h"
 #include "crypto/aes.h"
+#include "crypto/aes-round.h"
 #include "crypto/sm4.h"
 #include "vec_internal.h"
 
@@ -45,6 +46,8 @@ static void clear_tail_16(void *vd, uint32_t desc)
 clear_tail(vd, opr_sz, max_sz);
 }
 
+static const AESState aes_zero = { };
+
 static void do_crypto_aese(uint64_t *rd, uint64_t *rn, uint64_t *rm,
const uint8_t *sbox, const uint8_t *shift)
 {
@@ -70,7 +73,26 @@ void HELPER(crypto_aese)(void *vd, void *vn, void *vm, 
uint32_t desc)
 intptr_t i, opr_sz = simd_oprsz(desc);
 
 for (i = 0; i < opr_sz; i += 16) {
-do_crypto_aese(vd + i, vn + i, vm + i, AES_sbox, AES_shifts);
+AESState *ad = (AESState *)(vd + i);
+AESState *st = (AESState *)(vn + i);
+AESState *rk = (AESState *)(vm + i);
+AESState t;
+
+/*
+ * Our uint64_t are in the wrong order for big-endian.
+ * The Arm AddRoundKey comes first, while the API AddRoundKey
+ * comes last: perform the xor here, and provide zero to API.
+ */
+if (HOST_BIG_ENDIAN) {
+t.d[0] = st->d[1] ^ rk->d[1];
+t.d[1] = st->d[0] ^ rk->d[0];
+aesenc_SB_SR_AK(&t, &t, &aes_zero, false);
+ad->d[0] = t.d[1];
+ad->d[1] = t.d[0];
+} else {
+t.v = st->v ^ rk->v;
+aesenc_SB_SR_AK(ad, &t, &aes_zero, false);
+}
 }
 clear_tail(vd, opr_sz, simd_maxsz(desc));
 }
-- 
2.34.1




[PATCH v2 33/38] crypto: Implement aesdec_IMC with AES_imc_rot

2023-06-08 Thread Richard Henderson
This method uses one uint32_t * 256 table instead of 4,
which means its data cache overhead is less.

Signed-off-by: Richard Henderson 
---
 crypto/aes.c | 42 +-
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/crypto/aes.c b/crypto/aes.c
index 7b8a22fe3e..4da2cd7077 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -1446,39 +1446,39 @@ aesdec_IMC_swap(AESState *r, const AESState *st, bool 
swap)
 bool be = HOST_BIG_ENDIAN ^ swap;
 uint32_t t;
 
-/* Note that AES_imc is encoded for big-endian. */
-t = (AES_imc[st->b[swap_b ^ 0x0]][0] ^
- AES_imc[st->b[swap_b ^ 0x1]][1] ^
- AES_imc[st->b[swap_b ^ 0x2]][2] ^
- AES_imc[st->b[swap_b ^ 0x3]][3]);
-if (!be) {
+/* Note that AES_imc_rot is encoded for little-endian. */
+t = (  AES_imc_rot[st->b[swap_b ^ 0x0]] ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0x1]], 8) ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0x2]], 16) ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0x3]], 24));
+if (be) {
 t = bswap32(t);
 }
 r->w[swap_w ^ 0] = t;
 
-t = (AES_imc[st->b[swap_b ^ 0x4]][0] ^
- AES_imc[st->b[swap_b ^ 0x5]][1] ^
- AES_imc[st->b[swap_b ^ 0x6]][2] ^
- AES_imc[st->b[swap_b ^ 0x7]][3]);
-if (!be) {
+t = (  AES_imc_rot[st->b[swap_b ^ 0x4]] ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0x5]], 8) ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0x6]], 16) ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0x7]], 24));
+if (be) {
 t = bswap32(t);
 }
 r->w[swap_w ^ 1] = t;
 
-t = (AES_imc[st->b[swap_b ^ 0x8]][0] ^
- AES_imc[st->b[swap_b ^ 0x9]][1] ^
- AES_imc[st->b[swap_b ^ 0xA]][2] ^
- AES_imc[st->b[swap_b ^ 0xB]][3]);
-if (!be) {
+t = (  AES_imc_rot[st->b[swap_b ^ 0x8]] ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0x9]], 8) ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0xA]], 16) ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0xB]], 24));
+if (be) {
 t = bswap32(t);
 }
 r->w[swap_w ^ 2] = t;
 
-t = (AES_imc[st->b[swap_b ^ 0xC]][0] ^
- AES_imc[st->b[swap_b ^ 0xD]][1] ^
- AES_imc[st->b[swap_b ^ 0xE]][2] ^
- AES_imc[st->b[swap_b ^ 0xF]][3]);
-if (!be) {
+t = (  AES_imc_rot[st->b[swap_b ^ 0xC]] ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0xD]], 8) ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0xE]], 16) ^
+ rol32(AES_imc_rot[st->b[swap_b ^ 0xF]], 24));
+if (be) {
 t = bswap32(t);
 }
 r->w[swap_w ^ 3] = t;
-- 
2.34.1




[PATCH v2 11/38] target/riscv: Use aesenc_SB_SR_AK

2023-06-08 Thread Richard Henderson
This implements the AES64ES instruction.

Signed-off-by: Richard Henderson 
---
 target/riscv/crypto_helper.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
index 2ef30281b1..b072fed3e2 100644
--- a/target/riscv/crypto_helper.c
+++ b/target/riscv/crypto_helper.c
@@ -22,6 +22,7 @@
 #include "exec/exec-all.h"
 #include "exec/helper-proto.h"
 #include "crypto/aes.h"
+#include "crypto/aes-round.h"
 #include "crypto/sm4.h"
 
 #define AES_XTIME(a) \
@@ -136,6 +137,8 @@ target_ulong HELPER(aes32dsi)(target_ulong rs1, 
target_ulong rs2,
 AES_INVMIXBYTE(COL, 1, 2, 3, 0) << 8 | \
 AES_INVMIXBYTE(COL, 0, 1, 2, 3) << 0)
 
+static const AESState aes_zero = { };
+
 static inline target_ulong aes64_operation(target_ulong rs1, target_ulong rs2,
bool enc, bool mix)
 {
@@ -200,7 +203,12 @@ target_ulong HELPER(aes64esm)(target_ulong rs1, 
target_ulong rs2)
 
 target_ulong HELPER(aes64es)(target_ulong rs1, target_ulong rs2)
 {
-return aes64_operation(rs1, rs2, true, false);
+AESState t;
+
+t.d[HOST_BIG_ENDIAN] = rs1;
+t.d[!HOST_BIG_ENDIAN] = rs2;
+aesenc_SB_SR_AK(&t, &t, &aes_zero, false);
+return t.d[HOST_BIG_ENDIAN];
 }
 
 target_ulong HELPER(aes64ds)(target_ulong rs1, target_ulong rs2)
-- 
2.34.1




[PATCH v2 15/38] target/ppc: Use aesdec_ISB_ISR_AK

2023-06-08 Thread Richard Henderson
This implements the VNCIPHERLAST instruction.

Signed-off-by: Richard Henderson 
---
 target/ppc/int_helper.c | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 34257e9d76..15f07fca2b 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2973,13 +2973,7 @@ void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b)
 
 void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-ppc_avr_t result;
-int i;
-
-VECTOR_FOR_INORDER_I(i, u8) {
-result.VsrB(i) = b->VsrB(i) ^ (AES_isbox[a->VsrB(AES_ishifts[i])]);
-}
-*r = result;
+aesdec_ISB_ISR_AK((AESState *)r, (AESState *)a, (AESState *)b, true);
 }
 
 void helper_vshasigmaw(ppc_avr_t *r,  ppc_avr_t *a, uint32_t st_six)
-- 
2.34.1




[PATCH v2 19/38] crypto: Add aesdec_IMC

2023-06-08 Thread Richard Henderson
Add a primitive for InvMixColumns.

Signed-off-by: Richard Henderson 
---
 host/include/generic/host/aes-round.h |  2 +
 include/crypto/aes-round.h| 18 +
 crypto/aes.c  | 57 +++
 3 files changed, 77 insertions(+)

diff --git a/host/include/generic/host/aes-round.h 
b/host/include/generic/host/aes-round.h
index b00e9b50b1..34068afe40 100644
--- a/host/include/generic/host/aes-round.h
+++ b/host/include/generic/host/aes-round.h
@@ -15,6 +15,8 @@ void aesenc_SB_SR_AK_accel(AESState *, const AESState *,
const AESState *, bool)
 QEMU_ERROR("unsupported accel");
 
+void aesdec_IMC_accel(AESState *, const AESState *, bool)
+QEMU_ERROR("unsupported accel");
 void aesdec_ISB_ISR_AK_accel(AESState *, const AESState *,
  const AESState *, bool)
 QEMU_ERROR("unsupported accel");
diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h
index 9f263ca726..b80d4de664 100644
--- a/include/crypto/aes-round.h
+++ b/include/crypto/aes-round.h
@@ -59,6 +59,24 @@ static inline void aesenc_SB_SR_AK(AESState *r, const 
AESState *st,
 }
 }
 
+/*
+ * Perform InvMixColumns.
+ */
+
+void aesdec_IMC_gen(AESState *ret, const AESState *st);
+void aesdec_IMC_genrev(AESState *ret, const AESState *st);
+
+static inline void aesdec_IMC(AESState *r, const AESState *st, bool be)
+{
+if (HAVE_AES_ACCEL) {
+aesdec_IMC_accel(r, st, be);
+} else if (HOST_BIG_ENDIAN == be) {
+aesdec_IMC_gen(r, st);
+} else {
+aesdec_IMC_genrev(r, st);
+}
+}
+
 /*
  * Perform InvSubBytes + InvShiftRows.
  */
diff --git a/crypto/aes.c b/crypto/aes.c
index 89de8e8db4..bfd41e3fb9 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -1395,6 +1395,63 @@ void aesdec_ISB_ISR_AK_genrev(AESState *r, const 
AESState *s, const AESState *k)
 aesdec_ISB_ISR_AK_swap(r, s, k, true);
 }
 
+/* Perform InvMixColumns. */
+static inline void
+aesdec_IMC_swap(AESState *r, const AESState *st, bool swap)
+{
+int swap_b = swap * 0xf;
+int swap_w = swap * 0x3;
+bool be = HOST_BIG_ENDIAN ^ swap;
+uint32_t t;
+
+/* Note that AES_imc is encoded for big-endian. */
+t = (AES_imc[st->b[swap_b ^ 0x0]][0] ^
+ AES_imc[st->b[swap_b ^ 0x1]][1] ^
+ AES_imc[st->b[swap_b ^ 0x2]][2] ^
+ AES_imc[st->b[swap_b ^ 0x3]][3]);
+if (!be) {
+t = bswap32(t);
+}
+r->w[swap_w ^ 0] = t;
+
+t = (AES_imc[st->b[swap_b ^ 0x4]][0] ^
+ AES_imc[st->b[swap_b ^ 0x5]][1] ^
+ AES_imc[st->b[swap_b ^ 0x6]][2] ^
+ AES_imc[st->b[swap_b ^ 0x7]][3]);
+if (!be) {
+t = bswap32(t);
+}
+r->w[swap_w ^ 1] = t;
+
+t = (AES_imc[st->b[swap_b ^ 0x8]][0] ^
+ AES_imc[st->b[swap_b ^ 0x9]][1] ^
+ AES_imc[st->b[swap_b ^ 0xA]][2] ^
+ AES_imc[st->b[swap_b ^ 0xB]][3]);
+if (!be) {
+t = bswap32(t);
+}
+r->w[swap_w ^ 2] = t;
+
+t = (AES_imc[st->b[swap_b ^ 0xC]][0] ^
+ AES_imc[st->b[swap_b ^ 0xD]][1] ^
+ AES_imc[st->b[swap_b ^ 0xE]][2] ^
+ AES_imc[st->b[swap_b ^ 0xF]][3]);
+if (!be) {
+t = bswap32(t);
+}
+r->w[swap_w ^ 3] = t;
+}
+
+void aesdec_IMC_gen(AESState *r, const AESState *st)
+{
+aesdec_IMC_swap(r, st, false);
+}
+
+void aesdec_IMC_genrev(AESState *r, const AESState *st)
+{
+aesdec_IMC_swap(r, st, true);
+}
+
 /**
  * Expand the cipher key into the encryption key schedule.
  */
-- 
2.34.1




[PATCH v2 14/38] target/arm: Use aesdec_ISB_ISR_AK

2023-06-08 Thread Richard Henderson
This implements the AESD instruction.

Signed-off-by: Richard Henderson 
---
 target/arm/tcg/crypto_helper.c | 37 +++---
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/target/arm/tcg/crypto_helper.c b/target/arm/tcg/crypto_helper.c
index 00f3b21507..d2cb74e7fc 100644
--- a/target/arm/tcg/crypto_helper.c
+++ b/target/arm/tcg/crypto_helper.c
@@ -48,26 +48,6 @@ static void clear_tail_16(void *vd, uint32_t desc)
 
 static const AESState aes_zero = { };
 
-static void do_crypto_aese(uint64_t *rd, uint64_t *rn, uint64_t *rm,
-   const uint8_t *sbox, const uint8_t *shift)
-{
-union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } };
-union CRYPTO_STATE st = { .l = { rn[0], rn[1] } };
-int i;
-
-/* xor state vector with round key */
-rk.l[0] ^= st.l[0];
-rk.l[1] ^= st.l[1];
-
-/* combine ShiftRows operation and sbox substitution */
-for (i = 0; i < 16; i++) {
-CR_ST_BYTE(st, i) = sbox[CR_ST_BYTE(rk, shift[i])];
-}
-
-rd[0] = st.l[0];
-rd[1] = st.l[1];
-}
-
 void HELPER(crypto_aese)(void *vd, void *vn, void *vm, uint32_t desc)
 {
 intptr_t i, opr_sz = simd_oprsz(desc);
@@ -102,7 +82,22 @@ void HELPER(crypto_aesd)(void *vd, void *vn, void *vm, 
uint32_t desc)
 intptr_t i, opr_sz = simd_oprsz(desc);
 
 for (i = 0; i < opr_sz; i += 16) {
-do_crypto_aese(vd + i, vn + i, vm + i, AES_isbox, AES_ishifts);
+AESState *ad = (AESState *)(vd + i);
+AESState *st = (AESState *)(vn + i);
+AESState *rk = (AESState *)(vm + i);
+AESState t;
+
+/* Our uint64_t are in the wrong order for big-endian. */
+if (HOST_BIG_ENDIAN) {
+t.d[0] = st->d[1] ^ rk->d[1];
+t.d[1] = st->d[0] ^ rk->d[0];
+aesdec_ISB_ISR_AK(&t, &t, &aes_zero, false);
+ad->d[0] = t.d[1];
+ad->d[1] = t.d[0];
+} else {
+t.v = st->v ^ rk->v;
+aesdec_ISB_ISR_AK(ad, &t, &aes_zero, false);
+}
 }
 clear_tail(vd, opr_sz, simd_maxsz(desc));
 }
-- 
2.34.1




[PATCH v2 22/38] target/riscv: Use aesdec_IMC

2023-06-08 Thread Richard Henderson
This implements the AES64IM instruction.

Signed-off-by: Richard Henderson 
---
 target/riscv/crypto_helper.c | 15 +--
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
index e61f7fe1e5..505166ce5a 100644
--- a/target/riscv/crypto_helper.c
+++ b/target/riscv/crypto_helper.c
@@ -272,17 +272,12 @@ target_ulong HELPER(aes64ks1i)(target_ulong rs1, 
target_ulong rnum)
 
 target_ulong HELPER(aes64im)(target_ulong rs1)
 {
-uint64_t RS1 = rs1;
-uint32_t col_0 = RS1 & 0x;
-uint32_t col_1 = RS1 >> 32;
-target_ulong result;
+AESState t;
 
-col_0 = AES_INVMIXCOLUMN(col_0);
-col_1 = AES_INVMIXCOLUMN(col_1);
-
-result = ((uint64_t)col_1 << 32) | col_0;
-
-return result;
+t.d[HOST_BIG_ENDIAN] = rs1;
+t.d[!HOST_BIG_ENDIAN] = 0;
+aesdec_IMC(&t, &t, false);
+return t.d[HOST_BIG_ENDIAN];
 }
 
 target_ulong HELPER(sm4ed)(target_ulong rs1, target_ulong rs2,
-- 
2.34.1




[PATCH v2 34/38] crypto: Remove AES_imc

2023-06-08 Thread Richard Henderson
This array is no longer used.

Signed-off-by: Richard Henderson 
---
 include/crypto/aes.h |   7 --
 crypto/aes.c | 264 ---
 2 files changed, 271 deletions(-)

diff --git a/include/crypto/aes.h b/include/crypto/aes.h
index aa8b54065d..99209f51b9 100644
--- a/include/crypto/aes.h
+++ b/include/crypto/aes.h
@@ -36,13 +36,6 @@ extern const uint32_t AES_mc_rot[256];
 /* AES InvMixColumns, for use with rot32. */
 extern const uint32_t AES_imc_rot[256];
 
-/* AES InvMixColumns */
-/* AES_imc[x][0] = [x].[0e, 09, 0d, 0b]; */
-/* AES_imc[x][1] = [x].[0b, 0e, 09, 0d]; */
-/* AES_imc[x][2] = [x].[0d, 0b, 0e, 09]; */
-/* AES_imc[x][3] = [x].[09, 0d, 0b, 0e]; */
-extern const uint32_t AES_imc[256][4];
-
 /*
 AES_Te0[x] = S [x].[02, 01, 01, 03];
 AES_Te1[x] = S [x].[03, 02, 01, 01];
diff --git a/crypto/aes.c b/crypto/aes.c
index 4da2cd7077..a18267b9f8 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -291,270 +291,6 @@ const uint32_t AES_imc_rot[256] = {
 0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d,
 };
 
-/* AES_imc[x][0] = [x].[0e, 09, 0d, 0b]; */
-/* AES_imc[x][1] = [x].[0b, 0e, 09, 0d]; */
-/* AES_imc[x][2] = [x].[0d, 0b, 0e, 09]; */
-/* AES_imc[x][3] = [x].[09, 0d, 0b, 0e]; */
-const uint32_t AES_imc[256][4] = {
-{ 0x, 0x, 0x, 0x, }, /* x=00 */
-{ 0x0E090D0B, 0x0B0E090D, 0x0D0B0E09, 0x090D0B0E, }, /* x=01 */
-{ 0x1C121A16, 0x161C121A, 0x1A161C12, 0x121A161C, }, /* x=02 */
-{ 0x121B171D, 0x1D121B17, 0x171D121B, 0x1B171D12, }, /* x=03 */
-{ 0x3824342C, 0x2C382434, 0x342C3824, 0x24342C38, }, /* x=04 */
-{ 0x362D3927, 0x27362D39, 0x3927362D, 0x2D392736, }, /* x=05 */
-{ 0x24362E3A, 0x3A24362E, 0x2E3A2436, 0x362E3A24, }, /* x=06 */
-{ 0x2A3F2331, 0x312A3F23, 0x23312A3F, 0x3F23312A, }, /* x=07 */
-{ 0x70486858, 0x58704868, 0x68587048, 0x48685870, }, /* x=08 */
-{ 0x7E416553, 0x537E4165, 0x65537E41, 0x4165537E, }, /* x=09 */
-{ 0x6C5A724E, 0x4E6C5A72, 0x724E6C5A, 0x5A724E6C, }, /* x=0A */
-{ 0x62537F45, 0x4562537F, 0x7F456253, 0x537F4562, }, /* x=0B */
-{ 0x486C5C74, 0x74486C5C, 0x5C74486C, 0x6C5C7448, }, /* x=0C */
-{ 0x4665517F, 0x7F466551, 0x517F4665, 0x65517F46, }, /* x=0D */
-{ 0x547E4662, 0x62547E46, 0x4662547E, 0x7E466254, }, /* x=0E */
-{ 0x5A774B69, 0x695A774B, 0x4B695A77, 0x774B695A, }, /* x=0F */
-{ 0xE090D0B0, 0xB0E090D0, 0xD0B0E090, 0x90D0B0E0, }, /* x=10 */
-{ 0xEE99DDBB, 0xBBEE99DD, 0xDDBBEE99, 0x99DDBBEE, }, /* x=11 */
-{ 0xFC82CAA6, 0xA6FC82CA, 0xCAA6FC82, 0x82CAA6FC, }, /* x=12 */
-{ 0xF28BC7AD, 0xADF28BC7, 0xC7ADF28B, 0x8BC7ADF2, }, /* x=13 */
-{ 0xD8B4E49C, 0x9CD8B4E4, 0xE49CD8B4, 0xB4E49CD8, }, /* x=14 */
-{ 0xD6BDE997, 0x97D6BDE9, 0xE997D6BD, 0xBDE997D6, }, /* x=15 */
-{ 0xC4A6FE8A, 0x8AC4A6FE, 0xFE8AC4A6, 0xA6FE8AC4, }, /* x=16 */
-{ 0xCAAFF381, 0x81CAAFF3, 0xF381CAAF, 0xAFF381CA, }, /* x=17 */
-{ 0x90D8B8E8, 0xE890D8B8, 0xB8E890D8, 0xD8B8E890, }, /* x=18 */
-{ 0x9ED1B5E3, 0xE39ED1B5, 0xB5E39ED1, 0xD1B5E39E, }, /* x=19 */
-{ 0x8CCAA2FE, 0xFE8CCAA2, 0xA2FE8CCA, 0xCAA2FE8C, }, /* x=1A */
-{ 0x82C3AFF5, 0xF582C3AF, 0xAFF582C3, 0xC3AFF582, }, /* x=1B */
-{ 0xA8FC8CC4, 0xC4A8FC8C, 0x8CC4A8FC, 0xFC8CC4A8, }, /* x=1C */
-{ 0xA6F581CF, 0xCFA6F581, 0x81CFA6F5, 0xF581CFA6, }, /* x=1D */
-{ 0xB4EE96D2, 0xD2B4EE96, 0x96D2B4EE, 0xEE96D2B4, }, /* x=1E */
-{ 0xBAE79BD9, 0xD9BAE79B, 0x9BD9BAE7, 0xE79BD9BA, }, /* x=1F */
-{ 0xDB3BBB7B, 0x7BDB3BBB, 0xBB7BDB3B, 0x3BBB7BDB, }, /* x=20 */
-{ 0xD532B670, 0x70D532B6, 0xB670D532, 0x32B670D5, }, /* x=21 */
-{ 0xC729A16D, 0x6DC729A1, 0xA16DC729, 0x29A16DC7, }, /* x=22 */
-{ 0xC920AC66, 0x66C920AC, 0xAC66C920, 0x20AC66C9, }, /* x=23 */
-{ 0xE31F8F57, 0x57E31F8F, 0x8F57E31F, 0x1F8F57E3, }, /* x=24 */
-{ 0xED16825C, 0x5CED1682, 0x825CED16, 0x16825CED, }, /* x=25 */
-{ 0xFF0D9541, 0x41FF0D95, 0x9541FF0D, 0x0D9541FF, }, /* x=26 */
-{ 0xF104984A, 0x4AF10498, 0x984AF104, 0x04984AF1, }, /* x=27 */
-{ 0xAB73D323, 0x23AB73D3, 0xD323AB73, 0x73D323AB, }, /* x=28 */
-{ 0xA57ADE28, 0x28A57ADE, 0xDE28A57A, 0x7ADE28A5, }, /* x=29 */
-{ 0xB761C935, 0x35B761C9, 0xC935B761, 0x61C935B7, }, /* x=2A */
-{ 0xB968C43E, 0x3EB968C4, 0xC43EB968, 0x68C43EB9, }, /* x=2B */
-{ 0x9357E70F, 0x0F9357E7, 0xE70F9357, 0x57E70F93, }, /* x=2C */
-{ 0x9D5EEA04, 0x049D5EEA, 0xEA049D5E, 0x5EEA049D, }, /* x=2D */
-{ 0x8F45FD19, 0x198F45FD, 0xFD198F45, 0x45FD198F, }, /* x=2E */
-{ 0x814CF012, 0x12814CF0, 0xF012814C, 0x4CF01281, }, /* x=2F */
-{ 0x3BAB6BCB, 0xCB3BAB6B, 0x6BCB3BAB, 0xAB6BCB3B, }, /* x=30 */
-{ 0x35A266C0, 0xC035A266, 0x66C035A2, 0xA266C035, }, /* x=31 */
-{ 0x27B971DD, 0xDD27B971, 0x71DD27B9, 0xB971DD27, }, /* x=32 */
-{ 0x29B07CD6, 0xD629B07C, 0x7CD629B0, 0xB07CD629, }, /* x=33 */
-{ 0x038F5FE7, 0xE7038F5F, 0x5FE7038F, 0x8F5FE703, }, /* x=34 */
-{ 0x0D8652EC, 0xEC0D8652, 0x52EC0D86, 0x8652EC0D, }, /* x=35

[PATCH v2 38/38] host/include/ppc: Implement aes-round.h

2023-06-08 Thread Richard Henderson
Detect CRYPTO in cpuinfo; implement the accel hooks.

Signed-off-by: Richard Henderson 
---
 host/include/ppc/host/aes-round.h   | 181 
 host/include/ppc/host/cpuinfo.h |   1 +
 host/include/ppc64/host/aes-round.h |   1 +
 util/cpuinfo-ppc.c  |   8 ++
 4 files changed, 191 insertions(+)
 create mode 100644 host/include/ppc/host/aes-round.h
 create mode 100644 host/include/ppc64/host/aes-round.h

diff --git a/host/include/ppc/host/aes-round.h 
b/host/include/ppc/host/aes-round.h
new file mode 100644
index 00..9b5a15d1e5
--- /dev/null
+++ b/host/include/ppc/host/aes-round.h
@@ -0,0 +1,181 @@
+/*
+ * Power v2.07 specific aes acceleration.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef PPC_HOST_AES_ROUND_H
+#define PPC_HOST_AES_ROUND_H
+
+#ifndef __ALTIVEC__
+/* Without ALTIVEC, we can't even write inline assembly. */
+#include "host/include/generic/host/aes-round.h"
+#else
+#include "host/cpuinfo.h"
+
+#ifdef __CRYPTO__
+# define HAVE_AES_ACCEL  true
+#else
+# define HAVE_AES_ACCEL  likely(cpuinfo & CPUINFO_CRYPTO)
+#endif
+#define ATTR_AES_ACCEL
+
+/*
+ * While there is , both gcc and clang "aid" with the
+ * endianness issues in different ways. Just use inline asm instead.
+ */
+
+/* Bytes in memory are host-endian; bytes in register are @be. */
+static inline AESStateVec aes_accel_ld(const AESState *p, bool be)
+{
+AESStateVec r;
+
+if (be) {
+asm("lvx %0, 0, %1" : "=v"(r) : "r"(p), "m"(*p));
+} else if (HOST_BIG_ENDIAN) {
+AESStateVec rev = {
+15, 14, 13, 12, 11, 10, 9, 8, 7,  6,  5,  4,  3,  2,  1,  0,
+};
+asm("lvx %0, 0, %1\n\t"
+"vperm %0, %0, %0, %2"
+: "=v"(r) : "r"(p), "v"(rev), "m"(*p));
+} else {
+#ifdef __POWER9_VECTOR__
+asm("lxvb16x %x0, 0, %1" : "=v"(r) : "r"(p), "m"(*p));
+#else
+asm("lxvd2x %x0, 0, %1\n\t"
+"xxpermdi %x0, %x0, %x0, 2"
+: "=v"(r) : "r"(p), "m"(*p));
+#endif
+}
+return r;
+}
+
+static void aes_accel_st(AESState *p, AESStateVec r, bool be)
+{
+if (be) {
+asm("stvx %1, 0, %2" : "=m"(*p) : "v"(r), "r"(p));
+} else if (HOST_BIG_ENDIAN) {
+AESStateVec rev = {
+15, 14, 13, 12, 11, 10, 9, 8, 7,  6,  5,  4,  3,  2,  1,  0,
+};
+asm("vperm %1, %1, %1, %2\n\t"
+"stvx %1, 0, %3"
+: "=m"(*p), "+v"(r) : "v"(rev), "r"(p));
+} else {
+#ifdef __POWER9_VECTOR__
+asm("stxvb16x %x1, 0, %2" : "=m"(*p) : "v"(r), "r"(p));
+#else
+asm("xxpermdi %x1, %x1, %x1, 2\n\t"
+"stxvd2x %x1, 0, %2"
+: "=m"(*p), "+v"(r) : "r"(p));
+#endif
+}
+}
+
+static inline AESStateVec aes_accel_vcipher(AESStateVec d, AESStateVec k)
+{
+asm("vcipher %0, %0, %1" : "+v"(d) : "v"(k));
+return d;
+}
+
+static inline AESStateVec aes_accel_vncipher(AESStateVec d, AESStateVec k)
+{
+asm("vncipher %0, %0, %1" : "+v"(d) : "v"(k));
+return d;
+}
+
+static inline AESStateVec aes_accel_vcipherlast(AESStateVec d, AESStateVec k)
+{
+asm("vcipherlast %0, %0, %1" : "+v"(d) : "v"(k));
+return d;
+}
+
+static inline AESStateVec aes_accel_vncipherlast(AESStateVec d, AESStateVec k)
+{
+asm("vncipherlast %0, %0, %1" : "+v"(d) : "v"(k));
+return d;
+}
+
+static inline void
+aesenc_MC_accel(AESState *ret, const AESState *st, bool be)
+{
+AESStateVec t, z = { };
+
+t = aes_accel_ld(st, be);
+t = aes_accel_vncipherlast(t, z);
+t = aes_accel_vcipher(t, z);
+aes_accel_st(ret, t, be);
+}
+
+static inline void
+aesenc_SB_SR_AK_accel(AESState *ret, const AESState *st,
+  const AESState *rk, bool be)
+{
+AESStateVec t, k;
+
+t = aes_accel_ld(st, be);
+k = aes_accel_ld(rk, be);
+t = aes_accel_vcipherlast(t, k);
+aes_accel_st(ret, t, be);
+}
+
+static inline void
+aesenc_SB_SR_MC_AK_accel(AESState *ret, const AESState *st,
+ const AESState *rk, bool be)
+{
+AESStateVec t, k;
+
+t = aes_accel_ld(st, be);
+k = aes_accel_ld(rk, be);
+t = aes_accel_vcipher(t, k);
+aes_accel_st(ret, t, be);
+}
+
+static inline void
+aesdec_IMC_accel(AESState *ret, const AESState *st, bool be)
+{
+AESStateVec t, z = { };
+
+t = aes_accel_ld(st, be);
+t = aes_accel_vcipherlast(t, z);
+t = aes_accel_vncipher(t, z);
+aes_accel_st(ret, t, be);
+}
+
+static inline void
+aesdec_ISB_ISR_AK_accel(AESState *ret, const AESState *st,
+const AESState *rk, bool be)
+{
+AESStateVec t, k;
+
+t = aes_accel_ld(st, be);
+k = aes_accel_ld(rk, be);
+t = aes_accel_vncipherlast(t, k);
+aes_accel_st(ret, t, be);
+}
+
+static inline void
+aesdec_ISB_ISR_AK_IMC_accel(AESState *ret, const AESState *st,
+const AESState *rk, bool be)
+{
+AESStateVec t, k;
+
+t = aes_accel_ld(st, be);
+k = aes_accel_ld(rk, be);
+t = aes_accel_vncipher(t, k);
+   

[PATCH v2 06/38] crypto: Add aesenc_SB_SR_AK

2023-06-08 Thread Richard Henderson
Start adding infrastructure for accelerating guest AES.
Begin with a SubBytes + ShiftRows + AddRoundKey primitive.

Signed-off-by: Richard Henderson 
---
 host/include/generic/host/aes-round.h | 16 ++
 include/crypto/aes-round.h| 44 +++
 crypto/aes.c  | 44 +++
 3 files changed, 104 insertions(+)
 create mode 100644 host/include/generic/host/aes-round.h
 create mode 100644 include/crypto/aes-round.h

diff --git a/host/include/generic/host/aes-round.h 
b/host/include/generic/host/aes-round.h
new file mode 100644
index 00..19c8505e2b
--- /dev/null
+++ b/host/include/generic/host/aes-round.h
@@ -0,0 +1,16 @@
+/*
+ * No host specific aes acceleration.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef GENERIC_HOST_AES_ROUND_H
+#define GENERIC_HOST_AES_ROUND_H
+
+#define HAVE_AES_ACCEL  false
+#define ATTR_AES_ACCEL
+
+void aesenc_SB_SR_AK_accel(AESState *, const AESState *,
+   const AESState *, bool)
+QEMU_ERROR("unsupported accel");
+
+#endif
diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h
new file mode 100644
index 00..15ea1f42bc
--- /dev/null
+++ b/include/crypto/aes-round.h
@@ -0,0 +1,44 @@
+/*
+ * AES round fragments, generic version
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Copyright (C) 2023 Linaro, Ltd.
+ */
+
+#ifndef CRYPTO_AES_ROUND_H
+#define CRYPTO_AES_ROUND_H
+
+/* Hosts with acceleration will usually need a 16-byte vector type. */
+typedef uint8_t AESStateVec __attribute__((vector_size(16)));
+
+typedef union {
+uint8_t b[16];
+uint32_t w[4];
+uint64_t d[4];
+AESStateVec v;
+} AESState;
+
+#include "host/aes-round.h"
+
+/*
+ * Perform SubBytes + ShiftRows.
+ */
+
+void aesenc_SB_SR_AK_gen(AESState *ret, const AESState *st,
+ const AESState *rk);
+void aesenc_SB_SR_AK_genrev(AESState *ret, const AESState *st,
+const AESState *rk);
+
+static inline void aesenc_SB_SR_AK(AESState *r, const AESState *st,
+   const AESState *rk, bool be)
+{
+if (HAVE_AES_ACCEL) {
+aesenc_SB_SR_AK_accel(r, st, rk, be);
+} else if (HOST_BIG_ENDIAN == be) {
+aesenc_SB_SR_AK_gen(r, st, rk);
+} else {
+aesenc_SB_SR_AK_genrev(r, st, rk);
+}
+}
+
+#endif /* CRYPTO_AES_ROUND_H */
diff --git a/crypto/aes.c b/crypto/aes.c
index cdf937883d..896f6f44f1 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -29,6 +29,7 @@
  */
 #include "qemu/osdep.h"
 #include "crypto/aes.h"
+#include "crypto/aes-round.h"
 
 typedef uint32_t u32;
 typedef uint8_t u8;
@@ -1249,6 +1250,49 @@ static const u32 rcon[] = {
 0x1B00, 0x3600, /* for 128-bit blocks, Rijndael never uses 
more than 10 rcon values */
 };
 
+/* Perform SubBytes + ShiftRows + AddRoundKey. */
+static inline void
+aesenc_SB_SR_AK_swap(AESState *ret, const AESState *st,
+ const AESState *rk, bool swap)
+{
+const int swap_b = swap ? 15 : 0;
+AESState t;
+
+t.b[swap_b ^ 0x0] = AES_sbox[st->b[swap_b ^ AES_SH_0]];
+t.b[swap_b ^ 0x1] = AES_sbox[st->b[swap_b ^ AES_SH_1]];
+t.b[swap_b ^ 0x2] = AES_sbox[st->b[swap_b ^ AES_SH_2]];
+t.b[swap_b ^ 0x3] = AES_sbox[st->b[swap_b ^ AES_SH_3]];
+t.b[swap_b ^ 0x4] = AES_sbox[st->b[swap_b ^ AES_SH_4]];
+t.b[swap_b ^ 0x5] = AES_sbox[st->b[swap_b ^ AES_SH_5]];
+t.b[swap_b ^ 0x6] = AES_sbox[st->b[swap_b ^ AES_SH_6]];
+t.b[swap_b ^ 0x7] = AES_sbox[st->b[swap_b ^ AES_SH_7]];
+t.b[swap_b ^ 0x8] = AES_sbox[st->b[swap_b ^ AES_SH_8]];
+t.b[swap_b ^ 0x9] = AES_sbox[st->b[swap_b ^ AES_SH_9]];
+t.b[swap_b ^ 0xa] = AES_sbox[st->b[swap_b ^ AES_SH_A]];
+t.b[swap_b ^ 0xb] = AES_sbox[st->b[swap_b ^ AES_SH_B]];
+t.b[swap_b ^ 0xc] = AES_sbox[st->b[swap_b ^ AES_SH_C]];
+t.b[swap_b ^ 0xd] = AES_sbox[st->b[swap_b ^ AES_SH_D]];
+t.b[swap_b ^ 0xe] = AES_sbox[st->b[swap_b ^ AES_SH_E]];
+t.b[swap_b ^ 0xf] = AES_sbox[st->b[swap_b ^ AES_SH_F]];
+
+/*
+ * Perform the AddRoundKey with generic vectors.
+ * This may be expanded to either host integer or host vector code.
+ * The key and output endianness match, so no bswap required.
+ */
+ret->v = t.v ^ rk->v;
+}
+
+void aesenc_SB_SR_AK_gen(AESState *r, const AESState *s, const AESState *k)
+{
+aesenc_SB_SR_AK_swap(r, s, k, false);
+}
+
+void aesenc_SB_SR_AK_genrev(AESState *r, const AESState *s, const AESState *k)
+{
+aesenc_SB_SR_AK_swap(r, s, k, true);
+}
+
 /**
  * Expand the cipher key into the encryption key schedule.
  */
-- 
2.34.1




[PATCH v2 01/38] tcg/ppc: Define _CALL_AIX for clang on ppc64(be)

2023-06-08 Thread Richard Henderson
Restructure the ifdef ladder, separating 64-bit from 32-bit,
and ensure _CALL_AIX is set for ELF v1.  Fixes the build for
ppc64 big-endian host with clang.

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

diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 507fe6cda8..5c8378f8f6 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -29,15 +29,24 @@
 /*
  * Standardize on the _CALL_FOO symbols used by GCC:
  * Apple XCode does not define _CALL_DARWIN.
- * Clang defines _CALL_ELF (64-bit) but not _CALL_SYSV (32-bit).
+ * Clang defines _CALL_ELF (64-bit) but not _CALL_SYSV or _CALL_AIX.
  */
-#if !defined(_CALL_SYSV) && \
-!defined(_CALL_DARWIN) && \
-!defined(_CALL_AIX) && \
-!defined(_CALL_ELF)
-# if defined(__APPLE__)
+#if TCG_TARGET_REG_BITS == 64
+# ifdef _CALL_AIX
+/* ok */
+# elif defined(_CALL_ELF) && _CALL_ELF == 1
+#  define _CALL_AIX
+# elif defined(_CALL_ELF) && _CALL_ELF == 2
+/* ok */
+# else
+#  error "Unknown ABI"
+# endif
+#else
+# if defined(_CALL_SYSV) || defined(_CALL_DARWIN)
+/* ok */
+# elif defined(__APPLE__)
 #  define _CALL_DARWIN
-# elif defined(__ELF__) && TCG_TARGET_REG_BITS == 32
+# elif defined(__ELF__)
 #  define _CALL_SYSV
 # else
 #  error "Unknown ABI"
-- 
2.34.1




[PATCH v2 26/38] target/riscv: Use aesenc_SB_SR_MC_AK

2023-06-08 Thread Richard Henderson
This implements the AES64ESM instruction.

Signed-off-by: Richard Henderson 
---
 target/riscv/crypto_helper.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
index 505166ce5a..c036fe8632 100644
--- a/target/riscv/crypto_helper.c
+++ b/target/riscv/crypto_helper.c
@@ -198,7 +198,12 @@ static inline target_ulong aes64_operation(target_ulong 
rs1, target_ulong rs2,
 
 target_ulong HELPER(aes64esm)(target_ulong rs1, target_ulong rs2)
 {
-return aes64_operation(rs1, rs2, true, true);
+AESState t;
+
+t.d[HOST_BIG_ENDIAN] = rs1;
+t.d[!HOST_BIG_ENDIAN] = rs2;
+aesenc_SB_SR_MC_AK(&t, &t, &aes_zero, false);
+return t.d[HOST_BIG_ENDIAN];
 }
 
 target_ulong HELPER(aes64es)(target_ulong rs1, target_ulong rs2)
-- 
2.34.1




[PATCH v2 24/38] target/i386: Use aesenc_SB_SR_MC_AK

2023-06-08 Thread Richard Henderson
This implements the AESENC instruction.

Signed-off-by: Richard Henderson 
---
 target/i386/ops_sse.h | 14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 893913ebf8..93a4e0cf16 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -2188,16 +2188,12 @@ void glue(helper_aesdeclast, SUFFIX)(CPUX86State *env, 
Reg *d, Reg *v, Reg *s)
 
 void glue(helper_aesenc, SUFFIX)(CPUX86State *env, Reg *d, Reg *v, Reg *s)
 {
-int i;
-Reg st = *v;
-Reg rk = *s;
+for (int i = 0; i < SHIFT; i++) {
+AESState *ad = (AESState *)&d->ZMM_X(i);
+AESState *st = (AESState *)&v->ZMM_X(i);
+AESState *rk = (AESState *)&s->ZMM_X(i);
 
-for (i = 0 ; i < 2 << SHIFT ; i++) {
-int j = i & 3;
-d->L(i) = rk.L(i) ^ bswap32(AES_Te0[st.B(AES_shifts[4 * j + 0])] ^
-AES_Te1[st.B(AES_shifts[4 * j + 1])] ^
-AES_Te2[st.B(AES_shifts[4 * j + 2])] ^
-AES_Te3[st.B(AES_shifts[4 * j + 3])]);
+aesenc_SB_SR_MC_AK(ad, st, rk, false);
 }
 }
 
-- 
2.34.1




[PATCH v2 28/38] target/i386: Use aesdec_ISB_ISR_IMC_AK

2023-06-08 Thread Richard Henderson
This implements the AESDEC instruction.

Signed-off-by: Richard Henderson 
---
 target/i386/ops_sse.h | 14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 93a4e0cf16..a0e425733f 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -2162,16 +2162,12 @@ void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, 
Reg *d, Reg *v, Reg *s,
 
 void glue(helper_aesdec, SUFFIX)(CPUX86State *env, Reg *d, Reg *v, Reg *s)
 {
-int i;
-Reg st = *v;
-Reg rk = *s;
+for (int i = 0; i < SHIFT; i++) {
+AESState *ad = (AESState *)&d->ZMM_X(i);
+AESState *st = (AESState *)&v->ZMM_X(i);
+AESState *rk = (AESState *)&s->ZMM_X(i);
 
-for (i = 0 ; i < 2 << SHIFT ; i++) {
-int j = i & 3;
-d->L(i) = rk.L(i) ^ bswap32(AES_Td0[st.B(AES_ishifts[4 * j + 0])] ^
-AES_Td1[st.B(AES_ishifts[4 * j + 1])] ^
-AES_Td2[st.B(AES_ishifts[4 * j + 2])] ^
-AES_Td3[st.B(AES_ishifts[4 * j + 3])]);
+aesdec_ISB_ISR_IMC_AK(ad, st, rk, false);
 }
 }
 
-- 
2.34.1




[PATCH v2 23/38] crypto: Add aesenc_SB_SR_MC_AK

2023-06-08 Thread Richard Henderson
Add a primitive for SubBytes + ShiftRows + MixColumns + AddRoundKey.

Signed-off-by: Richard Henderson 
---
 host/include/generic/host/aes-round.h |  3 ++
 include/crypto/aes-round.h| 21 ++
 crypto/aes.c  | 56 +++
 3 files changed, 80 insertions(+)

diff --git a/host/include/generic/host/aes-round.h 
b/host/include/generic/host/aes-round.h
index 34068afe40..ee64db32fa 100644
--- a/host/include/generic/host/aes-round.h
+++ b/host/include/generic/host/aes-round.h
@@ -14,6 +14,9 @@ void aesenc_MC_accel(AESState *, const AESState *, bool)
 void aesenc_SB_SR_AK_accel(AESState *, const AESState *,
const AESState *, bool)
 QEMU_ERROR("unsupported accel");
+void aesenc_SB_SR_MC_AK_accel(AESState *, const AESState *,
+  const AESState *, bool)
+QEMU_ERROR("unsupported accel");
 
 void aesdec_IMC_accel(AESState *, const AESState *, bool)
 QEMU_ERROR("unsupported accel");
diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h
index b80d4de664..9e10c3ee9e 100644
--- a/include/crypto/aes-round.h
+++ b/include/crypto/aes-round.h
@@ -77,6 +77,27 @@ static inline void aesdec_IMC(AESState *r, const AESState 
*st, bool be)
 }
 }
 
+/*
+ * Perform SubBytes + ShiftRows + MixColumns + AddRoundKey.
+ */
+
+void aesenc_SB_SR_MC_AK_gen(AESState *ret, const AESState *st,
+const AESState *rk);
+void aesenc_SB_SR_MC_AK_genrev(AESState *ret, const AESState *st,
+   const AESState *rk);
+
+static inline void aesenc_SB_SR_MC_AK(AESState *r, const AESState *st,
+  const AESState *rk, bool be)
+{
+if (HAVE_AES_ACCEL) {
+aesenc_SB_SR_MC_AK_accel(r, st, rk, be);
+} else if (HOST_BIG_ENDIAN == be) {
+aesenc_SB_SR_MC_AK_gen(r, st, rk);
+} else {
+aesenc_SB_SR_MC_AK_genrev(r, st, rk);
+}
+}
+
 /*
  * Perform InvSubBytes + InvShiftRows.
  */
diff --git a/crypto/aes.c b/crypto/aes.c
index bfd41e3fb9..0c281472aa 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -1352,6 +1352,62 @@ void aesenc_MC_genrev(AESState *r, const AESState *st)
 aesenc_MC_swap(r, st, true);
 }
 
+/* Perform SubBytes + ShiftRows + MixColumns + AddRoundKey. */
+static inline void
+aesenc_SB_SR_MC_AK_swap(AESState *r, const AESState *st,
+const AESState *rk, bool swap)
+{
+int swap_b = swap * 0xf;
+int swap_w = swap * 0x3;
+bool be = HOST_BIG_ENDIAN ^ swap;
+uint32_t w0, w1, w2, w3;
+
+w0 = (AES_Te0[st->b[swap_b ^ AES_SH_0]] ^
+  AES_Te1[st->b[swap_b ^ AES_SH_1]] ^
+  AES_Te2[st->b[swap_b ^ AES_SH_2]] ^
+  AES_Te3[st->b[swap_b ^ AES_SH_3]]);
+
+w1 = (AES_Te0[st->b[swap_b ^ AES_SH_4]] ^
+  AES_Te1[st->b[swap_b ^ AES_SH_5]] ^
+  AES_Te2[st->b[swap_b ^ AES_SH_6]] ^
+  AES_Te3[st->b[swap_b ^ AES_SH_7]]);
+
+w2 = (AES_Te0[st->b[swap_b ^ AES_SH_8]] ^
+  AES_Te1[st->b[swap_b ^ AES_SH_9]] ^
+  AES_Te2[st->b[swap_b ^ AES_SH_A]] ^
+  AES_Te3[st->b[swap_b ^ AES_SH_B]]);
+
+w3 = (AES_Te0[st->b[swap_b ^ AES_SH_C]] ^
+  AES_Te1[st->b[swap_b ^ AES_SH_D]] ^
+  AES_Te2[st->b[swap_b ^ AES_SH_E]] ^
+  AES_Te3[st->b[swap_b ^ AES_SH_F]]);
+
+/* Note that AES_TeX is encoded for big-endian. */
+if (!be) {
+w0 = bswap32(w0);
+w1 = bswap32(w1);
+w2 = bswap32(w2);
+w3 = bswap32(w3);
+}
+
+r->w[swap_w ^ 0] = rk->w[swap_w ^ 0] ^ w0;
+r->w[swap_w ^ 1] = rk->w[swap_w ^ 1] ^ w1;
+r->w[swap_w ^ 2] = rk->w[swap_w ^ 2] ^ w2;
+r->w[swap_w ^ 3] = rk->w[swap_w ^ 3] ^ w3;
+}
+
+void aesenc_SB_SR_MC_AK_gen(AESState *r, const AESState *st,
+const AESState *rk)
+{
+aesenc_SB_SR_MC_AK_swap(r, st, rk, false);
+}
+
+void aesenc_SB_SR_MC_AK_genrev(AESState *r, const AESState *st,
+   const AESState *rk)
+{
+aesenc_SB_SR_MC_AK_swap(r, st, rk, true);
+}
+
 /* Perform InvSubBytes + InvShiftRows. */
 static inline void
 aesdec_ISB_ISR_AK_swap(AESState *ret, const AESState *st,
-- 
2.34.1




[PATCH v2 27/38] crypto: Add aesdec_ISB_ISR_IMC_AK

2023-06-08 Thread Richard Henderson
Add a primitive for InvSubBytes + InvShiftRows +
InvMixColumns + AddRoundKey.

Signed-off-by: Richard Henderson 
---
 host/include/generic/host/aes-round.h |  3 ++
 include/crypto/aes-round.h| 21 ++
 crypto/aes.c  | 56 +++
 3 files changed, 80 insertions(+)

diff --git a/host/include/generic/host/aes-round.h 
b/host/include/generic/host/aes-round.h
index ee64db32fa..16b4447831 100644
--- a/host/include/generic/host/aes-round.h
+++ b/host/include/generic/host/aes-round.h
@@ -23,5 +23,8 @@ void aesdec_IMC_accel(AESState *, const AESState *, bool)
 void aesdec_ISB_ISR_AK_accel(AESState *, const AESState *,
  const AESState *, bool)
 QEMU_ERROR("unsupported accel");
+void aesdec_ISB_ISR_IMC_AK_accel(AESState *, const AESState *,
+ const AESState *, bool)
+QEMU_ERROR("unsupported accel");
 
 #endif
diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h
index 9e10c3ee9e..31c5f10df6 100644
--- a/include/crypto/aes-round.h
+++ b/include/crypto/aes-round.h
@@ -119,4 +119,25 @@ static inline void aesdec_ISB_ISR_AK(AESState *r, const 
AESState *st,
 }
 }
 
+/*
+ * Perform InvSubBytes + InvShiftRows + InvMixColumns + AddRoundKey.
+ */
+
+void aesdec_ISB_ISR_IMC_AK_gen(AESState *ret, const AESState *st,
+   const AESState *rk);
+void aesdec_ISB_ISR_IMC_AK_genrev(AESState *ret, const AESState *st,
+  const AESState *rk);
+
+static inline void aesdec_ISB_ISR_IMC_AK(AESState *r, const AESState *st,
+ const AESState *rk, bool be)
+{
+if (HAVE_AES_ACCEL) {
+aesdec_ISB_ISR_IMC_AK_accel(r, st, rk, be);
+} else if (HOST_BIG_ENDIAN == be) {
+aesdec_ISB_ISR_IMC_AK_gen(r, st, rk);
+} else {
+aesdec_ISB_ISR_IMC_AK_genrev(r, st, rk);
+}
+}
+
 #endif /* CRYPTO_AES_ROUND_H */
diff --git a/crypto/aes.c b/crypto/aes.c
index 0c281472aa..b671a3a6fb 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -1508,6 +1508,62 @@ void aesdec_IMC_genrev(AESState *r, const AESState *st)
 aesdec_IMC_swap(r, st, true);
 }
 
+/* Perform InvSubBytes + InvShiftRows + InvMixColumns + AddRoundKey. */
+static inline void
+aesdec_ISB_ISR_IMC_AK_swap(AESState *r, const AESState *st,
+   const AESState *rk, bool swap)
+{
+int swap_b = swap * 0xf;
+int swap_w = swap * 0x3;
+bool be = HOST_BIG_ENDIAN ^ swap;
+uint32_t w0, w1, w2, w3;
+
+w0 = (AES_Td0[st->b[swap_b ^ AES_ISH_0]] ^
+  AES_Td1[st->b[swap_b ^ AES_ISH_1]] ^
+  AES_Td2[st->b[swap_b ^ AES_ISH_2]] ^
+  AES_Td3[st->b[swap_b ^ AES_ISH_3]]);
+
+w1 = (AES_Td0[st->b[swap_b ^ AES_ISH_4]] ^
+  AES_Td1[st->b[swap_b ^ AES_ISH_5]] ^
+  AES_Td2[st->b[swap_b ^ AES_ISH_6]] ^
+  AES_Td3[st->b[swap_b ^ AES_ISH_7]]);
+
+w2 = (AES_Td0[st->b[swap_b ^ AES_ISH_8]] ^
+  AES_Td1[st->b[swap_b ^ AES_ISH_9]] ^
+  AES_Td2[st->b[swap_b ^ AES_ISH_A]] ^
+  AES_Td3[st->b[swap_b ^ AES_ISH_B]]);
+
+w3 = (AES_Td0[st->b[swap_b ^ AES_ISH_C]] ^
+  AES_Td1[st->b[swap_b ^ AES_ISH_D]] ^
+  AES_Td2[st->b[swap_b ^ AES_ISH_E]] ^
+  AES_Td3[st->b[swap_b ^ AES_ISH_F]]);
+
+/* Note that AES_TdX is encoded for big-endian. */
+if (!be) {
+w0 = bswap32(w0);
+w1 = bswap32(w1);
+w2 = bswap32(w2);
+w3 = bswap32(w3);
+}
+
+r->w[swap_w ^ 0] = rk->w[swap_w ^ 0] ^ w0;
+r->w[swap_w ^ 1] = rk->w[swap_w ^ 1] ^ w1;
+r->w[swap_w ^ 2] = rk->w[swap_w ^ 2] ^ w2;
+r->w[swap_w ^ 3] = rk->w[swap_w ^ 3] ^ w3;
+}
+
+void aesdec_ISB_ISR_IMC_AK_gen(AESState *r, const AESState *st,
+   const AESState *rk)
+{
+aesdec_ISB_ISR_IMC_AK_swap(r, st, rk, false);
+}
+
+void aesdec_ISB_ISR_IMC_AK_genrev(AESState *r, const AESState *st,
+  const AESState *rk)
+{
+aesdec_ISB_ISR_IMC_AK_swap(r, st, rk, true);
+}
+
 /**
  * Expand the cipher key into the encryption key schedule.
  */
-- 
2.34.1




[PATCH v2 30/38] crypto: Add aesdec_ISB_ISR_AK_IMC

2023-06-08 Thread Richard Henderson
Add a primitive for InvSubBytes + InvShiftRows +
AddRoundKey + InvMixColumns.

Signed-off-by: Richard Henderson 
---
 host/include/generic/host/aes-round.h |  3 +++
 include/crypto/aes-round.h| 21 +
 crypto/aes.c  | 14 ++
 3 files changed, 38 insertions(+)

diff --git a/host/include/generic/host/aes-round.h 
b/host/include/generic/host/aes-round.h
index 16b4447831..c52fea936f 100644
--- a/host/include/generic/host/aes-round.h
+++ b/host/include/generic/host/aes-round.h
@@ -23,6 +23,9 @@ void aesdec_IMC_accel(AESState *, const AESState *, bool)
 void aesdec_ISB_ISR_AK_accel(AESState *, const AESState *,
  const AESState *, bool)
 QEMU_ERROR("unsupported accel");
+void aesdec_ISB_ISR_AK_IMC_accel(AESState *, const AESState *,
+ const AESState *, bool)
+QEMU_ERROR("unsupported accel");
 void aesdec_ISB_ISR_IMC_AK_accel(AESState *, const AESState *,
  const AESState *, bool)
 QEMU_ERROR("unsupported accel");
diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h
index 31c5f10df6..dd8f49becb 100644
--- a/include/crypto/aes-round.h
+++ b/include/crypto/aes-round.h
@@ -119,6 +119,27 @@ static inline void aesdec_ISB_ISR_AK(AESState *r, const 
AESState *st,
 }
 }
 
+/*
+ * Perform InvSubBytes + InvShiftRows + AddRoundKey + InvMixColumns.
+ */
+
+void aesdec_ISB_ISR_AK_IMC_gen(AESState *ret, const AESState *st,
+   const AESState *rk);
+void aesdec_ISB_ISR_AK_IMC_genrev(AESState *ret, const AESState *st,
+  const AESState *rk);
+
+static inline void aesdec_ISB_ISR_AK_IMC(AESState *r, const AESState *st,
+ const AESState *rk, bool be)
+{
+if (HAVE_AES_ACCEL) {
+aesdec_ISB_ISR_AK_IMC_accel(r, st, rk, be);
+} else if (HOST_BIG_ENDIAN == be) {
+aesdec_ISB_ISR_AK_IMC_gen(r, st, rk);
+} else {
+aesdec_ISB_ISR_AK_IMC_genrev(r, st, rk);
+}
+}
+
 /*
  * Perform InvSubBytes + InvShiftRows + InvMixColumns + AddRoundKey.
  */
diff --git a/crypto/aes.c b/crypto/aes.c
index b671a3a6fb..f0721ad4a2 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -1564,6 +1564,20 @@ void aesdec_ISB_ISR_IMC_AK_genrev(AESState *r, const 
AESState *st,
 aesdec_ISB_ISR_IMC_AK_swap(r, st, rk, true);
 }
 
+void aesdec_ISB_ISR_AK_IMC_gen(AESState *ret, const AESState *st,
+   const AESState *rk)
+{
+aesdec_ISB_ISR_AK_gen(ret, st, rk);
+aesdec_IMC_gen(ret, ret);
+}
+
+void aesdec_ISB_ISR_AK_IMC_genrev(AESState *ret, const AESState *st,
+  const AESState *rk)
+{
+aesdec_ISB_ISR_AK_genrev(ret, st, rk);
+aesdec_IMC_genrev(ret, ret);
+}
+
 /**
  * Expand the cipher key into the encryption key schedule.
  */
-- 
2.34.1




[PATCH v2 18/38] target/arm: Use aesenc_MC

2023-06-08 Thread Richard Henderson
This implements the AESMC instruction.

Signed-off-by: Richard Henderson 
---
 target/arm/tcg/crypto_helper.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/target/arm/tcg/crypto_helper.c b/target/arm/tcg/crypto_helper.c
index d2cb74e7fc..1952aaac58 100644
--- a/target/arm/tcg/crypto_helper.c
+++ b/target/arm/tcg/crypto_helper.c
@@ -124,7 +124,20 @@ void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t 
desc)
 intptr_t i, opr_sz = simd_oprsz(desc);
 
 for (i = 0; i < opr_sz; i += 16) {
-do_crypto_aesmc(vd + i, vm + i, AES_mc_rot);
+AESState *ad = (AESState *)(vd + i);
+AESState *st = (AESState *)(vm + i);
+AESState t;
+
+/* Our uint64_t are in the wrong order for big-endian. */
+if (HOST_BIG_ENDIAN) {
+t.d[0] = st->d[1];
+t.d[1] = st->d[0];
+aesenc_MC(&t, &t, false);
+ad->d[0] = t.d[1];
+ad->d[1] = t.d[0];
+} else {
+aesenc_MC(ad, st, false);
+}
 }
 clear_tail(vd, opr_sz, simd_maxsz(desc));
 }
-- 
2.34.1




[PATCH v2 36/38] host/include/i386: Implement aes-round.h

2023-06-08 Thread Richard Henderson
Detect AES in cpuinfo; implement the accel hooks.

Signed-off-by: Richard Henderson 
---
 host/include/i386/host/aes-round.h   | 152 +++
 host/include/i386/host/cpuinfo.h |   1 +
 host/include/x86_64/host/aes-round.h |   1 +
 util/cpuinfo-i386.c  |   3 +
 4 files changed, 157 insertions(+)
 create mode 100644 host/include/i386/host/aes-round.h
 create mode 100644 host/include/x86_64/host/aes-round.h

diff --git a/host/include/i386/host/aes-round.h 
b/host/include/i386/host/aes-round.h
new file mode 100644
index 00..f9abb7c352
--- /dev/null
+++ b/host/include/i386/host/aes-round.h
@@ -0,0 +1,152 @@
+/*
+ * x86 specific aes acceleration.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HOST_AES_ROUND_H
+#define HOST_AES_ROUND_H
+
+#include "host/cpuinfo.h"
+#include 
+
+#if defined(__AES__) && defined(__SSSE3__)
+# define HAVE_AES_ACCEL  true
+# define ATTR_AES_ACCEL
+#else
+# define HAVE_AES_ACCEL  likely(cpuinfo & CPUINFO_AES)
+# define ATTR_AES_ACCEL  __attribute__((target("aes,ssse3")))
+#endif
+
+static inline __m128i ATTR_AES_ACCEL
+aes_accel_bswap(__m128i x)
+{
+return _mm_shuffle_epi8(x, _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8,
+9, 10, 11, 12, 13, 14, 15));
+}
+
+static inline void ATTR_AES_ACCEL
+aesenc_MC_accel(AESState *ret, const AESState *st, bool be)
+{
+__m128i t = (__m128i)st->v;
+__m128i z = _mm_setzero_si128();
+
+if (be) {
+t = aes_accel_bswap(t);
+t = _mm_aesdeclast_si128(t, z);
+t = _mm_aesenc_si128(t, z);
+t = aes_accel_bswap(t);
+} else {
+t = _mm_aesdeclast_si128(t, z);
+t = _mm_aesenc_si128(t, z);
+}
+ret->v = (AESStateVec)t;
+}
+
+static inline void ATTR_AES_ACCEL
+aesenc_SB_SR_AK_accel(AESState *ret, const AESState *st,
+  const AESState *rk, bool be)
+{
+__m128i t = (__m128i)st->v;
+__m128i k = (__m128i)rk->v;
+
+if (be) {
+t = aes_accel_bswap(t);
+k = aes_accel_bswap(k);
+t = _mm_aesenclast_si128(t, k);
+t = aes_accel_bswap(t);
+} else {
+t = _mm_aesenclast_si128(t, k);
+}
+ret->v = (AESStateVec)t;
+}
+
+static inline void ATTR_AES_ACCEL
+aesenc_SB_SR_MC_AK_accel(AESState *ret, const AESState *st,
+ const AESState *rk, bool be)
+{
+__m128i t = (__m128i)st->v;
+__m128i k = (__m128i)rk->v;
+
+if (be) {
+t = aes_accel_bswap(t);
+k = aes_accel_bswap(k);
+t = _mm_aesenc_si128(t, k);
+t = aes_accel_bswap(t);
+} else {
+t = _mm_aesenc_si128(t, k);
+}
+ret->v = (AESStateVec)t;
+}
+
+static inline void ATTR_AES_ACCEL
+aesdec_IMC_accel(AESState *ret, const AESState *st, bool be)
+{
+__m128i t = (__m128i)st->v;
+
+if (be) {
+t = aes_accel_bswap(t);
+t = _mm_aesimc_si128(t);
+t = aes_accel_bswap(t);
+} else {
+t = _mm_aesimc_si128(t);
+}
+ret->v = (AESStateVec)t;
+}
+
+static inline void ATTR_AES_ACCEL
+aesdec_ISB_ISR_AK_accel(AESState *ret, const AESState *st,
+const AESState *rk, bool be)
+{
+__m128i t = (__m128i)st->v;
+__m128i k = (__m128i)rk->v;
+
+if (be) {
+t = aes_accel_bswap(t);
+k = aes_accel_bswap(k);
+t = _mm_aesdeclast_si128(t, k);
+t = aes_accel_bswap(t);
+} else {
+t = _mm_aesdeclast_si128(t, k);
+}
+ret->v = (AESStateVec)t;
+}
+
+static inline void ATTR_AES_ACCEL
+aesdec_ISB_ISR_AK_IMC_accel(AESState *ret, const AESState *st,
+const AESState *rk, bool be)
+{
+__m128i t = (__m128i)st->v;
+__m128i k = (__m128i)rk->v;
+
+if (be) {
+t = aes_accel_bswap(t);
+k = aes_accel_bswap(k);
+t = _mm_aesdeclast_si128(t, k);
+t = _mm_aesimc_si128(t);
+t = aes_accel_bswap(t);
+} else {
+t = _mm_aesdeclast_si128(t, k);
+t = _mm_aesimc_si128(t);
+}
+ret->v = (AESStateVec)t;
+}
+
+static inline void ATTR_AES_ACCEL
+aesdec_ISB_ISR_IMC_AK_accel(AESState *ret, const AESState *st,
+const AESState *rk, bool be)
+{
+__m128i t = (__m128i)st->v;
+__m128i k = (__m128i)rk->v;
+
+if (be) {
+t = aes_accel_bswap(t);
+k = aes_accel_bswap(k);
+t = _mm_aesdec_si128(t, k);
+t = aes_accel_bswap(t);
+} else {
+t = _mm_aesdec_si128(t, k);
+}
+ret->v = (AESStateVec)t;
+}
+
+#endif
diff --git a/host/include/i386/host/cpuinfo.h b/host/include/i386/host/cpuinfo.h
index a6537123cf..073d0a426f 100644
--- a/host/include/i386/host/cpuinfo.h
+++ b/host/include/i386/host/cpuinfo.h
@@ -26,6 +26,7 @@
 #define CPUINFO_AVX512VBMI2 (1u << 15)
 #define CPUINFO_ATOMIC_VMOVDQA  (1u << 16)
 #define CPUINFO_ATOMIC_VMOVDQU  (1u << 17)
+#define CPUINFO_AES (1u << 18)
 
 /* Initialized with a constructor. */
 extern unsigned cpuinfo;
diff 

[PATCH v2 16/38] target/riscv: Use aesdec_ISB_ISR_AK

2023-06-08 Thread Richard Henderson
This implements the AES64DS instruction.

Signed-off-by: Richard Henderson 
---
 target/riscv/crypto_helper.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
index b072fed3e2..e61f7fe1e5 100644
--- a/target/riscv/crypto_helper.c
+++ b/target/riscv/crypto_helper.c
@@ -213,7 +213,12 @@ target_ulong HELPER(aes64es)(target_ulong rs1, 
target_ulong rs2)
 
 target_ulong HELPER(aes64ds)(target_ulong rs1, target_ulong rs2)
 {
-return aes64_operation(rs1, rs2, false, false);
+AESState t;
+
+t.d[HOST_BIG_ENDIAN] = rs1;
+t.d[!HOST_BIG_ENDIAN] = rs2;
+aesdec_ISB_ISR_AK(&t, &t, &aes_zero, false);
+return t.d[HOST_BIG_ENDIAN];
 }
 
 target_ulong HELPER(aes64dsm)(target_ulong rs1, target_ulong rs2)
-- 
2.34.1




[PATCH v2 37/38] host/include/aarch64: Implement aes-round.h

2023-06-08 Thread Richard Henderson
Detect AES in cpuinfo; implement the accel hooks.

Signed-off-by: Richard Henderson 
---
 meson.build   |   9 ++
 host/include/aarch64/host/aes-round.h | 205 ++
 host/include/aarch64/host/cpuinfo.h   |   1 +
 util/cpuinfo-aarch64.c|   2 +
 4 files changed, 217 insertions(+)
 create mode 100644 host/include/aarch64/host/aes-round.h

diff --git a/meson.build b/meson.build
index 34306a6205..d622e54bef 100644
--- a/meson.build
+++ b/meson.build
@@ -2665,6 +2665,15 @@ config_host_data.set('CONFIG_AVX512BW_OPT', 
get_option('avx512bw') \
 int main(int argc, char *argv[]) { return bar(argv[0]); }
   '''), error_message: 'AVX512BW not available').allowed())
 
+# For both AArch64 and AArch32, detect if builtins are available.
+config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
+#include 
+#ifndef __ARM_FEATURE_AES
+__attribute__((target("+crypto")))
+#endif
+void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
+  '''))
+
 have_pvrdma = get_option('pvrdma') \
   .require(rdma.found(), error_message: 'PVRDMA requires OpenFabrics 
libraries') \
   .require(cc.compiles(gnu_source_prefix + '''
diff --git a/host/include/aarch64/host/aes-round.h 
b/host/include/aarch64/host/aes-round.h
new file mode 100644
index 00..6c126c3e89
--- /dev/null
+++ b/host/include/aarch64/host/aes-round.h
@@ -0,0 +1,205 @@
+/*
+ * AArch64 specific aes acceleration.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HOST_AES_ROUND_H
+#define HOST_AES_ROUND_H
+
+#include "host/cpuinfo.h"
+#include 
+
+#ifdef __ARM_FEATURE_AES
+# define HAVE_AES_ACCEL  true
+#else
+# define HAVE_AES_ACCEL  likely(cpuinfo & CPUINFO_AES)
+#endif
+#if !defined(__ARM_FEATURE_AES) && defined(CONFIG_ARM_AES_BUILTIN)
+# define ATTR_AES_ACCEL  __attribute__((target("+crypto")))
+#else
+# define ATTR_AES_ACCEL
+#endif
+
+static inline uint8x16_t aes_accel_bswap(uint8x16_t x)
+{
+return vqtbl1q_u8(x, (uint8x16_t){ 15, 14, 13, 12, 11, 10, 9, 8,
+7,  6,  5,  4,  3,  2, 1, 0, });
+}
+
+#ifdef CONFIG_ARM_AES_BUILTIN
+# define aes_accel_aesdvaesdq_u8
+# define aes_accel_aesevaeseq_u8
+# define aes_accel_aesmc   vaesmcq_u8
+# define aes_accel_aesimc  vaesimcq_u8
+# define aes_accel_aesd_imc(S, K)  vaesimcq_u8(vaesdq_u8(S, K))
+# define aes_accel_aese_mc(S, K)   vaesmcq_u8(vaeseq_u8(S, K))
+#else
+static inline uint8x16_t aes_accel_aesd(uint8x16_t d, uint8x16_t k)
+{
+asm(".arch_extension aes\n\t"
+"aesd %0.16b, %1.16b" : "+w"(d) : "w"(k));
+return d;
+}
+
+static inline uint8x16_t aes_accel_aese(uint8x16_t d, uint8x16_t k)
+{
+asm(".arch_extension aes\n\t"
+"aese %0.16b, %1.16b" : "+w"(d) : "w"(k));
+return d;
+}
+
+static inline uint8x16_t aes_accel_aesmc(uint8x16_t d)
+{
+asm(".arch_extension aes\n\t"
+"aesmc %0.16b, %1.16b" : "=w"(d) : "w"(d));
+return d;
+}
+
+static inline uint8x16_t aes_accel_aesimc(uint8x16_t d)
+{
+asm(".arch_extension aes\n\t"
+"aesimc %0.16b, %1.16b" : "=w"(d) : "w"(d));
+return d;
+}
+
+/* Most CPUs fuse AESD+AESIMC in the execution pipeline. */
+static inline uint8x16_t aes_accel_aesd_imc(uint8x16_t d, uint8x16_t k)
+{
+asm(".arch_extension aes\n\t"
+"aesd %0.16b, %1.16b\n\t"
+"aesimc %0.16b, %0.16b" : "+w"(d) : "w"(k));
+return d;
+}
+
+/* Most CPUs fuse AESE+AESMC in the execution pipeline. */
+static inline uint8x16_t aes_accel_aese_mc(uint8x16_t d, uint8x16_t k)
+{
+asm(".arch_extension aes\n\t"
+"aese %0.16b, %1.16b\n\t"
+"aesmc %0.16b, %0.16b" : "+w"(d) : "w"(k));
+return d;
+}
+#endif /* CONFIG_ARM_AES_BUILTIN */
+
+static inline void ATTR_AES_ACCEL
+aesenc_MC_accel(AESState *ret, const AESState *st, bool be)
+{
+uint8x16_t t = (uint8x16_t)st->v;
+
+if (be) {
+t = aes_accel_bswap(t);
+t = aes_accel_aesmc(t);
+t = aes_accel_bswap(t);
+} else {
+t = aes_accel_aesmc(t);
+}
+ret->v = (AESStateVec)t;
+}
+
+static inline void ATTR_AES_ACCEL
+aesenc_SB_SR_AK_accel(AESState *ret, const AESState *st,
+  const AESState *rk, bool be)
+{
+uint8x16_t t = (uint8x16_t)st->v;
+uint8x16_t z = { };
+
+if (be) {
+t = aes_accel_bswap(t);
+t = aes_accel_aese(t, z);
+t = aes_accel_bswap(t);
+} else {
+t = aes_accel_aese(t, z);
+}
+ret->v = (AESStateVec)t ^ rk->v;
+}
+
+static inline void ATTR_AES_ACCEL
+aesenc_SB_SR_MC_AK_accel(AESState *ret, const AESState *st,
+ const AESState *rk, bool be)
+{
+uint8x16_t t = (uint8x16_t)st->v;
+uint8x16_t z = { };
+
+if (be) {
+t = aes_accel_bswap(t);
+t = aes_accel_aese_mc(t, z);
+t = aes_accel_bswap(t);
+} else {
+t = aes_accel_aese_mc(t, z);
+}
+ret->v = (AESStateVec)t ^ rk->v;
+}
+
+static inline void ATTR_AES_ACCEL

[PATCH v2 17/38] crypto: Add aesenc_MC

2023-06-08 Thread Richard Henderson
Add a primitive for MixColumns.

Signed-off-by: Richard Henderson 
---
 host/include/generic/host/aes-round.h |  2 +
 include/crypto/aes-round.h| 18 
 crypto/aes.c  | 59 +++
 3 files changed, 79 insertions(+)

diff --git a/host/include/generic/host/aes-round.h 
b/host/include/generic/host/aes-round.h
index e8f6bb0b99..b00e9b50b1 100644
--- a/host/include/generic/host/aes-round.h
+++ b/host/include/generic/host/aes-round.h
@@ -9,6 +9,8 @@
 #define HAVE_AES_ACCEL  false
 #define ATTR_AES_ACCEL
 
+void aesenc_MC_accel(AESState *, const AESState *, bool)
+QEMU_ERROR("unsupported accel");
 void aesenc_SB_SR_AK_accel(AESState *, const AESState *,
const AESState *, bool)
 QEMU_ERROR("unsupported accel");
diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h
index 56376cc83b..9f263ca726 100644
--- a/include/crypto/aes-round.h
+++ b/include/crypto/aes-round.h
@@ -20,6 +20,24 @@ typedef union {
 
 #include "host/aes-round.h"
 
+/*
+ * Perform MixColumns.
+ */
+
+void aesenc_MC_gen(AESState *ret, const AESState *st);
+void aesenc_MC_genrev(AESState *ret, const AESState *st);
+
+static inline void aesenc_MC(AESState *r, const AESState *st, bool be)
+{
+if (HAVE_AES_ACCEL) {
+aesenc_MC_accel(r, st, be);
+} else if (HOST_BIG_ENDIAN == be) {
+aesenc_MC_gen(r, st);
+} else {
+aesenc_MC_genrev(r, st);
+}
+}
+
 /*
  * Perform SubBytes + ShiftRows.
  */
diff --git a/crypto/aes.c b/crypto/aes.c
index 767930223c..89de8e8db4 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -28,6 +28,8 @@
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "qemu/osdep.h"
+#include "qemu/bswap.h"
+#include "qemu/bitops.h"
 #include "crypto/aes.h"
 #include "crypto/aes-round.h"
 
@@ -1293,6 +1295,63 @@ void aesenc_SB_SR_AK_genrev(AESState *r, const AESState 
*s, const AESState *k)
 aesenc_SB_SR_AK_swap(r, s, k, true);
 }
 
+/* Perform MixColumns. */
+static inline void
+aesenc_MC_swap(AESState *r, const AESState *st, bool swap)
+{
+int swap_b = swap * 0xf;
+int swap_w = swap * 0x3;
+bool be = HOST_BIG_ENDIAN ^ swap;
+uint32_t t;
+
+/* Note that AES_mc_rot is encoded for little-endian. */
+t = (  AES_mc_rot[st->b[swap_b ^ 0x0]] ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0x1]], 8) ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0x2]], 16) ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0x3]], 24));
+if (be) {
+t = bswap32(t);
+}
+r->w[swap_w ^ 0] = t;
+
+t = (  AES_mc_rot[st->b[swap_b ^ 0x4]] ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0x5]], 8) ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0x6]], 16) ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0x7]], 24));
+if (be) {
+t = bswap32(t);
+}
+r->w[swap_w ^ 1] = t;
+
+t = (  AES_mc_rot[st->b[swap_b ^ 0x8]] ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0x9]], 8) ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0xA]], 16) ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0xB]], 24));
+if (be) {
+t = bswap32(t);
+}
+r->w[swap_w ^ 2] = t;
+
+t = (  AES_mc_rot[st->b[swap_b ^ 0xC]] ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0xD]], 8) ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0xE]], 16) ^
+ rol32(AES_mc_rot[st->b[swap_b ^ 0xF]], 24));
+if (be) {
+t = bswap32(t);
+}
+r->w[swap_w ^ 3] = t;
+}
+
+void aesenc_MC_gen(AESState *r, const AESState *st)
+{
+aesenc_MC_swap(r, st, false);
+}
+
+void aesenc_MC_genrev(AESState *r, const AESState *st)
+{
+aesenc_MC_swap(r, st, true);
+}
+
 /* Perform InvSubBytes + InvShiftRows. */
 static inline void
 aesdec_ISB_ISR_AK_swap(AESState *ret, const AESState *st,
-- 
2.34.1




[PATCH v2 10/38] target/ppc: Use aesenc_SB_SR_AK

2023-06-08 Thread Richard Henderson
This implements the VCIPHERLAST instruction.

Signed-off-by: Richard Henderson 
---
 target/ppc/int_helper.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index d97a7f1f28..34257e9d76 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -25,6 +25,7 @@
 #include "qemu/log.h"
 #include "exec/helper-proto.h"
 #include "crypto/aes.h"
+#include "crypto/aes-round.h"
 #include "fpu/softfloat.h"
 #include "qapi/error.h"
 #include "qemu/guest-random.h"
@@ -2947,13 +2948,7 @@ void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, 
ppc_avr_t *b)
 
 void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-ppc_avr_t result;
-int i;
-
-VECTOR_FOR_INORDER_I(i, u8) {
-result.VsrB(i) = b->VsrB(i) ^ (AES_sbox[a->VsrB(AES_shifts[i])]);
-}
-*r = result;
+aesenc_SB_SR_AK((AESState *)r, (AESState *)a, (AESState *)b, true);
 }
 
 void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
-- 
2.34.1




[PATCH v2 20/38] target/i386: Use aesdec_IMC

2023-06-08 Thread Richard Henderson
This implements the AESIMC instruction.

Signed-off-by: Richard Henderson 
---
 target/i386/ops_sse.h | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 0a37bde595..893913ebf8 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -2215,15 +2215,10 @@ void glue(helper_aesenclast, SUFFIX)(CPUX86State *env, 
Reg *d, Reg *v, Reg *s)
 #if SHIFT == 1
 void glue(helper_aesimc, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
 {
-int i;
-Reg tmp = *s;
+AESState *ad = (AESState *)&d->ZMM_X(0);
+AESState *st = (AESState *)&s->ZMM_X(0);
 
-for (i = 0 ; i < 4 ; i++) {
-d->L(i) = bswap32(AES_imc[tmp.B(4 * i + 0)][0] ^
-  AES_imc[tmp.B(4 * i + 1)][1] ^
-  AES_imc[tmp.B(4 * i + 2)][2] ^
-  AES_imc[tmp.B(4 * i + 3)][3]);
-}
+aesdec_IMC(ad, st, false);
 }
 
 void glue(helper_aeskeygenassist, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
-- 
2.34.1




[PATCH v2 25/38] target/ppc: Use aesenc_SB_SR_MC_AK

2023-06-08 Thread Richard Henderson
This implements the VCIPHER instruction.

Signed-off-by: Richard Henderson 
---
 target/ppc/int_helper.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 15f07fca2b..1e477924b7 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -2933,17 +2933,11 @@ void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
 
 void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-ppc_avr_t result;
-int i;
+AESState *ad = (AESState *)r;
+AESState *st = (AESState *)a;
+AESState *rk = (AESState *)b;
 
-VECTOR_FOR_INORDER_I(i, u32) {
-result.VsrW(i) = b->VsrW(i) ^
-(AES_Te0[a->VsrB(AES_shifts[4 * i + 0])] ^
- AES_Te1[a->VsrB(AES_shifts[4 * i + 1])] ^
- AES_Te2[a->VsrB(AES_shifts[4 * i + 2])] ^
- AES_Te3[a->VsrB(AES_shifts[4 * i + 3])]);
-}
-*r = result;
+aesenc_SB_SR_MC_AK(ad, st, rk, true);
 }
 
 void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
-- 
2.34.1




[PATCH v2 13/38] target/i386: Use aesdec_ISB_ISR_AK

2023-06-08 Thread Richard Henderson
This implements the AESDECLAST instruction.

Signed-off-by: Richard Henderson 
---
 target/i386/ops_sse.h | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 63fdecbe03..0a37bde595 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -2177,12 +2177,12 @@ void glue(helper_aesdec, SUFFIX)(CPUX86State *env, Reg 
*d, Reg *v, Reg *s)
 
 void glue(helper_aesdeclast, SUFFIX)(CPUX86State *env, Reg *d, Reg *v, Reg *s)
 {
-int i;
-Reg st = *v;
-Reg rk = *s;
+for (int i = 0; i < SHIFT; i++) {
+AESState *ad = (AESState *)&d->ZMM_X(i);
+AESState *st = (AESState *)&v->ZMM_X(i);
+AESState *rk = (AESState *)&s->ZMM_X(i);
 
-for (i = 0; i < 8 << SHIFT; i++) {
-d->B(i) = rk.B(i) ^ (AES_isbox[st.B(AES_ishifts[i & 15] + (i & ~15))]);
+aesdec_ISB_ISR_AK(ad, st, rk, false);
 }
 }
 
-- 
2.34.1




[PATCH v2 00/38] crypto: Provide aes-round.h and host accel

2023-06-08 Thread Richard Henderson
Inspired by Ard Biesheuvel's RFC patches for accelerating AES
under emulation, provide a set of primitives that maps between
the guest and host fragments.

There is a small guest correctness test case.

I think the end result is quite a bit cleaner, since the logic
is now centralized, rather than spread across 4 different guests.

Further work could clean up crypto/aes.c itself to use these
instead of the tables directly.  I'm sure that's just an ultimate
fallback when an appropriate system library is not available, and
so not terribly important, but it could still significantly reduce
the amount of code we carry.

I would imagine structuring a polynomial multiplication header
in a similar way.  There are 4 or 5 versions of those spread across
the different guests.

Changes for v2:
  * Change aesenc_SB_SR -> aesenc_SB_SR_AK
  * Change aesdec_ISB_ISR -> aesdec_ISB_ISR_AK

  Both of these because if we have to provide a zero to x86 and ppc
  hosts, we can do that at the guest level just as easily as the host.
  Which allows x86 and ppc guests to provide the key their key.

  * Add aesdec_ISB_ISR_AK_IMC

  Provide a variation for the Power8 primitive.  Easy enough to do
  with two x86 instructions.

  * Add ppc host support.

  Nasty issues with , fighting with builtins vs bswap,
  so everything is in inline asm.


r~


Richard Henderson (38):
  tcg/ppc: Define _CALL_AIX for clang on ppc64(be)
  util: Add cpuinfo-ppc.c
  tests/multiarch: Add test-aes
  target/arm: Move aesmc and aesimc tables to crypto/aes.c
  crypto/aes: Add constants for ShiftRows, InvShiftRows
  crypto: Add aesenc_SB_SR_AK
  target/i386: Use aesenc_SB_SR_AK
  target/arm: Demultiplex AESE and AESMC
  target/arm: Use aesenc_SB_SR_AK
  target/ppc: Use aesenc_SB_SR_AK
  target/riscv: Use aesenc_SB_SR_AK
  crypto: Add aesdec_ISB_ISR_AK
  target/i386: Use aesdec_ISB_ISR_AK
  target/arm: Use aesdec_ISB_ISR_AK
  target/ppc: Use aesdec_ISB_ISR_AK
  target/riscv: Use aesdec_ISB_ISR_AK
  crypto: Add aesenc_MC
  target/arm: Use aesenc_MC
  crypto: Add aesdec_IMC
  target/i386: Use aesdec_IMC
  target/arm: Use aesdec_IMC
  target/riscv: Use aesdec_IMC
  crypto: Add aesenc_SB_SR_MC_AK
  target/i386: Use aesenc_SB_SR_MC_AK
  target/ppc: Use aesenc_SB_SR_MC_AK
  target/riscv: Use aesenc_SB_SR_MC_AK
  crypto: Add aesdec_ISB_ISR_IMC_AK
  target/i386: Use aesdec_ISB_ISR_IMC_AK
  target/riscv: Use aesdec_ISB_ISR_IMC_AK
  crypto: Add aesdec_ISB_ISR_AK_IMC
  target/ppc: Use aesdec_ISB_ISR_AK_IMC
  crypto: Remove AES_shifts, AES_ishifts
  crypto: Implement aesdec_IMC with AES_imc_rot
  crypto: Remove AES_imc
  crypto: Unexport AES_*_rot, AES_TeN, AES_TdN
  host/include/i386: Implement aes-round.h
  host/include/aarch64: Implement aes-round.h
  host/include/ppc: Implement aes-round.h

 meson.build |   9 +
 host/include/aarch64/host/aes-round.h   | 205 ++
 host/include/aarch64/host/cpuinfo.h |   1 +
 host/include/generic/host/aes-round.h   |  33 +
 host/include/i386/host/aes-round.h  | 152 +
 host/include/i386/host/cpuinfo.h|   1 +
 host/include/ppc/host/aes-round.h   | 181 ++
 host/include/ppc/host/cpuinfo.h |  30 +
 host/include/ppc64/host/aes-round.h |   1 +
 host/include/ppc64/host/cpuinfo.h   |   1 +
 host/include/x86_64/host/aes-round.h|   1 +
 include/crypto/aes-round.h  | 164 +
 include/crypto/aes.h|  30 -
 target/arm/helper.h |   2 +
 target/i386/ops_sse.h   |  60 +-
 tcg/ppc/tcg-target.h|  16 +-
 target/arm/tcg/sve.decode   |   4 +-
 crypto/aes.c| 796 
 target/arm/tcg/crypto_helper.c  | 249 +++-
 target/arm/tcg/translate-a64.c  |  13 +-
 target/arm/tcg/translate-neon.c |   4 +-
 target/arm/tcg/translate-sve.c  |   8 +-
 target/ppc/int_helper.c |  50 +-
 target/riscv/crypto_helper.c| 138 ++--
 tests/tcg/aarch64/test-aes.c|  58 ++
 tests/tcg/i386/test-aes.c   |  68 ++
 tests/tcg/ppc64/test-aes.c  | 116 
 tests/tcg/riscv64/test-aes.c|  76 +++
 util/cpuinfo-aarch64.c  |   2 +
 util/cpuinfo-i386.c |   3 +
 util/cpuinfo-ppc.c  |  65 ++
 tcg/ppc/tcg-target.c.inc|  67 +-
 tests/tcg/multiarch/test-aes-main.c.inc | 183 ++
 tests/tcg/aarch64/Makefile.target   |   4 +
 tests/tcg/i386/Makefile.target  |   4 +
 tests/tcg/ppc64/Makefile.target |   1 +
 tests/tcg/riscv64/Makefile.target   |   4 +
 util/meson.build|   2 +
 38 files changed, 2074 insertions(+), 728 deletions(-)
 create mode 100644 host/include/aarch64/host/aes-round.h
 create mode 100644 host/include/generic/host/aes-round.h
 create mode 100644 host/include/i386/host/aes-round.h
 create mode 100644 host/include/ppc/host/aes-round.h
 creat

[PATCH v2 02/38] util: Add cpuinfo-ppc.c

2023-06-08 Thread Richard Henderson
Move the code from tcg/.  Fix a bug in that PPC_FEATURE2_ARCH_3_10
is actually spelled PPC_FEATURE2_ARCH_3_1.

Signed-off-by: Richard Henderson 
---
 host/include/ppc/host/cpuinfo.h   | 29 
 host/include/ppc64/host/cpuinfo.h |  1 +
 tcg/ppc/tcg-target.h  | 16 -
 util/cpuinfo-ppc.c| 57 +++
 tcg/ppc/tcg-target.c.inc  | 44 +---
 util/meson.build  |  2 ++
 6 files changed, 98 insertions(+), 51 deletions(-)
 create mode 100644 host/include/ppc/host/cpuinfo.h
 create mode 100644 host/include/ppc64/host/cpuinfo.h
 create mode 100644 util/cpuinfo-ppc.c

diff --git a/host/include/ppc/host/cpuinfo.h b/host/include/ppc/host/cpuinfo.h
new file mode 100644
index 00..7ec252ef52
--- /dev/null
+++ b/host/include/ppc/host/cpuinfo.h
@@ -0,0 +1,29 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Host specific cpu indentification for ppc.
+ */
+
+#ifndef HOST_CPUINFO_H
+#define HOST_CPUINFO_H
+
+/* Digested version of  */
+
+#define CPUINFO_ALWAYS  (1u << 0)  /* so cpuinfo is nonzero */
+#define CPUINFO_V2_06   (1u << 1)
+#define CPUINFO_V2_07   (1u << 2)
+#define CPUINFO_V3_00   (1u << 3)
+#define CPUINFO_V3_10   (1u << 4)
+#define CPUINFO_ISEL(1u << 5)
+#define CPUINFO_ALTIVEC (1u << 6)
+#define CPUINFO_VSX (1u << 7)
+
+/* Initialized with a constructor. */
+extern unsigned cpuinfo;
+
+/*
+ * We cannot rely on constructor ordering, so other constructors must
+ * use the function interface rather than the variable above.
+ */
+unsigned cpuinfo_init(void);
+
+#endif /* HOST_CPUINFO_H */
diff --git a/host/include/ppc64/host/cpuinfo.h 
b/host/include/ppc64/host/cpuinfo.h
new file mode 100644
index 00..2f036a0627
--- /dev/null
+++ b/host/include/ppc64/host/cpuinfo.h
@@ -0,0 +1 @@
+#include "host/include/ppc/host/cpuinfo.h"
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index c7552b6391..b632a5a647 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -25,6 +25,8 @@
 #ifndef PPC_TCG_TARGET_H
 #define PPC_TCG_TARGET_H
 
+#include "host/cpuinfo.h"
+
 #define MAX_CODE_GEN_BUFFER_SIZE  ((size_t)-1)
 
 #define TCG_TARGET_NB_REGS 64
@@ -61,14 +63,12 @@ typedef enum {
 tcg_isa_3_10,
 } TCGPowerISA;
 
-extern TCGPowerISA have_isa;
-extern bool have_altivec;
-extern bool have_vsx;
-
-#define have_isa_2_06  (have_isa >= tcg_isa_2_06)
-#define have_isa_2_07  (have_isa >= tcg_isa_2_07)
-#define have_isa_3_00  (have_isa >= tcg_isa_3_00)
-#define have_isa_3_10  (have_isa >= tcg_isa_3_10)
+#define have_isa_2_06  (cpuinfo & CPUINFO_V2_06)
+#define have_isa_2_07  (cpuinfo & CPUINFO_V2_07)
+#define have_isa_3_00  (cpuinfo & CPUINFO_V3_00)
+#define have_isa_3_10  (cpuinfo & CPUINFO_V3_10)
+#define have_altivec   (cpuinfo & CPUINFO_ALTIVEC)
+#define have_vsx   (cpuinfo & CPUINFO_VSX)
 
 /* optional instructions automatically implemented */
 #define TCG_TARGET_HAS_ext8u_i320 /* andi */
diff --git a/util/cpuinfo-ppc.c b/util/cpuinfo-ppc.c
new file mode 100644
index 00..ee761de33a
--- /dev/null
+++ b/util/cpuinfo-ppc.c
@@ -0,0 +1,57 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Host specific cpu indentification for ppc.
+ */
+
+#include "qemu/osdep.h"
+#include "host/cpuinfo.h"
+
+#ifdef CONFIG_GETAUXVAL
+# include 
+#else
+# include 
+# include "elf.h"
+#endif
+
+unsigned cpuinfo;
+
+/* Called both as constructor and (possibly) via other constructors. */
+unsigned __attribute__((constructor)) cpuinfo_init(void)
+{
+unsigned info = cpuinfo;
+unsigned long hwcap, hwcap2;
+
+if (info) {
+return info;
+}
+
+hwcap = qemu_getauxval(AT_HWCAP);
+hwcap2 = qemu_getauxval(AT_HWCAP2);
+info = CPUINFO_ALWAYS;
+
+if (hwcap & PPC_FEATURE_ARCH_2_06) {
+info |= CPUINFO_V2_06;
+}
+if (hwcap2 & PPC_FEATURE2_ARCH_2_07) {
+info |= CPUINFO_V2_07;
+}
+if (hwcap2 & PPC_FEATURE2_ARCH_3_00) {
+info |= CPUINFO_V3_00;
+}
+if (hwcap2 & PPC_FEATURE2_ARCH_3_1) {
+info |= CPUINFO_V3_10;
+}
+if (hwcap2 & PPC_FEATURE2_HAS_ISEL) {
+info |= CPUINFO_ISEL;
+}
+if (hwcap & PPC_FEATURE_HAS_ALTIVEC) {
+info |= CPUINFO_ALTIVEC;
+/* We only care about the portion of VSX that overlaps Altivec. */
+if (hwcap & PPC_FEATURE_HAS_VSX) {
+info |= CPUINFO_VSX;
+}
+}
+
+cpuinfo = info;
+return info;
+}
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 5c8378f8f6..c866f2c997 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -101,10 +101,7 @@
 #define ALL_GENERAL_REGS  0xu
 #define ALL_VECTOR_REGS   0xull
 
-TCGPowerISA have_isa;
-static bool have_isel;
-bool have_altivec;
-bool have_vsx;
+#define have_isel  (cpuinfo & CPUINFO_ISEL)
 
 #ifndef CONFIG_SOFTMMU
 #define TCG_GUEST_BASE_REG 30
@@ -387

[PATCH v2 05/38] crypto/aes: Add constants for ShiftRows, InvShiftRows

2023-06-08 Thread Richard Henderson
These symbols will avoid the indirection through memory
when fully unrolling some new primitives.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 crypto/aes.c | 50 --
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/crypto/aes.c b/crypto/aes.c
index 67bb74b8e3..cdf937883d 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -108,12 +108,58 @@ const uint8_t AES_isbox[256] = {
 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D,
 };
 
+/* AES ShiftRows, for complete unrolling. */
+enum {
+AES_SH_0 = 0x0,
+AES_SH_1 = 0x5,
+AES_SH_2 = 0xa,
+AES_SH_3 = 0xf,
+AES_SH_4 = 0x4,
+AES_SH_5 = 0x9,
+AES_SH_6 = 0xe,
+AES_SH_7 = 0x3,
+AES_SH_8 = 0x8,
+AES_SH_9 = 0xd,
+AES_SH_A = 0x2,
+AES_SH_B = 0x7,
+AES_SH_C = 0xc,
+AES_SH_D = 0x1,
+AES_SH_E = 0x6,
+AES_SH_F = 0xb,
+};
+
 const uint8_t AES_shifts[16] = {
-0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
+AES_SH_0, AES_SH_1, AES_SH_2, AES_SH_3,
+AES_SH_4, AES_SH_5, AES_SH_6, AES_SH_7,
+AES_SH_8, AES_SH_9, AES_SH_A, AES_SH_B,
+AES_SH_C, AES_SH_D, AES_SH_E, AES_SH_F,
+};
+
+/* AES InvShiftRows, for complete unrolling. */
+enum {
+AES_ISH_0 = 0x0,
+AES_ISH_1 = 0xd,
+AES_ISH_2 = 0xa,
+AES_ISH_3 = 0x7,
+AES_ISH_4 = 0x4,
+AES_ISH_5 = 0x1,
+AES_ISH_6 = 0xe,
+AES_ISH_7 = 0xb,
+AES_ISH_8 = 0x8,
+AES_ISH_9 = 0x5,
+AES_ISH_A = 0x2,
+AES_ISH_B = 0xf,
+AES_ISH_C = 0xc,
+AES_ISH_D = 0x9,
+AES_ISH_E = 0x6,
+AES_ISH_F = 0x3,
 };
 
 const uint8_t AES_ishifts[16] = {
-0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
+AES_ISH_0, AES_ISH_1, AES_ISH_2, AES_ISH_3,
+AES_ISH_4, AES_ISH_5, AES_ISH_6, AES_ISH_7,
+AES_ISH_8, AES_ISH_9, AES_ISH_A, AES_ISH_B,
+AES_ISH_C, AES_ISH_D, AES_ISH_E, AES_ISH_F,
 };
 
 /*
-- 
2.34.1




Re: [PATCH 3/9] disas/riscv: Move types/constants to new header file

2023-06-08 Thread LIU Zhiwei



On 2023/5/30 21:18, Christoph Muellner wrote:

From: Christoph Müllner 

In order to enable vendor disassembler support, we need to
move types and constants into a header file so that other
compilation units can use them as well.

This patch does not introduce any functional changes.

Signed-off-by: Christoph Müllner 


Reviewed-by: LIU Zhiwei 

Zhiwei


---
  disas/riscv.c | 270 +---
  disas/riscv.h | 280 ++
  2 files changed, 281 insertions(+), 269 deletions(-)
  create mode 100644 disas/riscv.h

diff --git a/disas/riscv.c b/disas/riscv.c
index d597161d46..a062fb48cc 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -19,158 +19,7 @@
  
  #include "qemu/osdep.h"

  #include "disas/dis-asm.h"
-
-
-/* types */
-
-typedef uint64_t rv_inst;
-typedef uint16_t rv_opcode;
-
-/* enums */
-
-typedef enum {
-rv32,
-rv64,
-rv128
-} rv_isa;
-
-typedef enum {
-rv_rm_rne = 0,
-rv_rm_rtz = 1,
-rv_rm_rdn = 2,
-rv_rm_rup = 3,
-rv_rm_rmm = 4,
-rv_rm_dyn = 7,
-} rv_rm;
-
-typedef enum {
-rv_fence_i = 8,
-rv_fence_o = 4,
-rv_fence_r = 2,
-rv_fence_w = 1,
-} rv_fence;
-
-typedef enum {
-rv_ireg_zero,
-rv_ireg_ra,
-rv_ireg_sp,
-rv_ireg_gp,
-rv_ireg_tp,
-rv_ireg_t0,
-rv_ireg_t1,
-rv_ireg_t2,
-rv_ireg_s0,
-rv_ireg_s1,
-rv_ireg_a0,
-rv_ireg_a1,
-rv_ireg_a2,
-rv_ireg_a3,
-rv_ireg_a4,
-rv_ireg_a5,
-rv_ireg_a6,
-rv_ireg_a7,
-rv_ireg_s2,
-rv_ireg_s3,
-rv_ireg_s4,
-rv_ireg_s5,
-rv_ireg_s6,
-rv_ireg_s7,
-rv_ireg_s8,
-rv_ireg_s9,
-rv_ireg_s10,
-rv_ireg_s11,
-rv_ireg_t3,
-rv_ireg_t4,
-rv_ireg_t5,
-rv_ireg_t6,
-} rv_ireg;
-
-typedef enum {
-rvc_end,
-rvc_rd_eq_ra,
-rvc_rd_eq_x0,
-rvc_rs1_eq_x0,
-rvc_rs2_eq_x0,
-rvc_rs2_eq_rs1,
-rvc_rs1_eq_ra,
-rvc_imm_eq_zero,
-rvc_imm_eq_n1,
-rvc_imm_eq_p1,
-rvc_csr_eq_0x001,
-rvc_csr_eq_0x002,
-rvc_csr_eq_0x003,
-rvc_csr_eq_0xc00,
-rvc_csr_eq_0xc01,
-rvc_csr_eq_0xc02,
-rvc_csr_eq_0xc80,
-rvc_csr_eq_0xc81,
-rvc_csr_eq_0xc82,
-} rvc_constraint;
-
-typedef enum {
-rv_codec_illegal,
-rv_codec_none,
-rv_codec_u,
-rv_codec_uj,
-rv_codec_i,
-rv_codec_i_sh5,
-rv_codec_i_sh6,
-rv_codec_i_sh7,
-rv_codec_i_csr,
-rv_codec_s,
-rv_codec_sb,
-rv_codec_r,
-rv_codec_r_m,
-rv_codec_r4_m,
-rv_codec_r_a,
-rv_codec_r_l,
-rv_codec_r_f,
-rv_codec_cb,
-rv_codec_cb_imm,
-rv_codec_cb_sh5,
-rv_codec_cb_sh6,
-rv_codec_ci,
-rv_codec_ci_sh5,
-rv_codec_ci_sh6,
-rv_codec_ci_16sp,
-rv_codec_ci_lwsp,
-rv_codec_ci_ldsp,
-rv_codec_ci_lqsp,
-rv_codec_ci_li,
-rv_codec_ci_lui,
-rv_codec_ci_none,
-rv_codec_ciw_4spn,
-rv_codec_cj,
-rv_codec_cj_jal,
-rv_codec_cl_lw,
-rv_codec_cl_ld,
-rv_codec_cl_lq,
-rv_codec_cr,
-rv_codec_cr_mv,
-rv_codec_cr_jalr,
-rv_codec_cr_jr,
-rv_codec_cs,
-rv_codec_cs_sw,
-rv_codec_cs_sd,
-rv_codec_cs_sq,
-rv_codec_css_swsp,
-rv_codec_css_sdsp,
-rv_codec_css_sqsp,
-rv_codec_k_bs,
-rv_codec_k_rnum,
-rv_codec_v_r,
-rv_codec_v_ldst,
-rv_codec_v_i,
-rv_codec_vsetvli,
-rv_codec_vsetivli,
-rv_codec_zcb_ext,
-rv_codec_zcb_mul,
-rv_codec_zcb_lb,
-rv_codec_zcb_lh,
-rv_codec_zcmp_cm_pushpop,
-rv_codec_zcmp_cm_mv,
-rv_codec_zcmt_jt,
-} rv_codec;
+#include "disas/riscv.h"
  
  typedef enum {

  rv_op_illegal = 0,
@@ -966,50 +815,6 @@ typedef enum {
  rv_op_czero_nez = 790,
  } rv_op;
  
-/* structures */

-
-typedef struct {
-uint64_t  pc;
-uint64_t  inst;
-int32_t   imm;
-uint16_t  op;
-uint8_t   codec;
-uint8_t   rd;
-uint8_t   rs1;
-uint8_t   rs2;
-uint8_t   rs3;
-uint8_t   rm;
-uint8_t   pred;
-uint8_t   succ;
-uint8_t   aq;
-uint8_t   rl;
-uint8_t   bs;
-uint8_t   rnum;
-uint8_t   vm;
-uint32_t  vzimm;
-uint8_t   rlist;
-} rv_decode;
-
-typedef struct {
-const int op;
-const rvc_constraint *constraints;
-} rv_comp_data;
-
-enum {
-rvcd_imm_nz = 0x1
-};
-
-typedef struct {
-const char * const name;
-const rv_codec codec;
-const char * const format;
-const rv_comp_data *pseudo;
-const short decomp_rv32;
-const short decomp_rv64;
-const short decomp_rv128;
-const short decomp_data;
-} rv_opcode_data;
-
  /* register names */
  
  static const char rv_ireg_name_sym[32][5] = {

@@ -1033,79 +838,6 @@ static const char rv_vreg_name_sym[32][4] = {
  "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
  };
  
-/* instruction formats */

-
-#define rv_fmt_none   "O\t"
-#define rv_fmt_rs1"O\t1"
-#define rv_fmt_offset "O\to"
-#define rv_fmt_pred_succ  "O\tp

Fwd: QEMU AVR Patch - Correct handling of AVR interrupts

2023-06-08 Thread Adecy
-- Forwarded message -
De : Adecy 
Date: jeu. 1 juin 2023 à 21:34
Subject: QEMU AVR Patch - Correct handling of AVR interrupts
To: 


Hello,

I would like to submit the attached patch.

Best regards
From c872c0f164a5ab595cf347d098430301e628b741 Mon Sep 17 00:00:00 2001
From: Lucas Dietrich 
Date: Thu, 1 Jun 2023 23:26:33 +0200
Subject: [PATCH] Fix handling of AVR interrupts above 33 by switching ctz32 to
 ctz64

This commit addresses a bug in the AVR interrupt handling code.
The modification involves replacing the usage of the ctz32 function
with ctz64 to ensure proper handling of interrupts above 33 in the AVR
target.

Previously, timers 3, 4, and 5 interrupts were not functioning correctly
because most of their interrupt vectors are numbered above 33.

Signed-off-by: Lucas Dietrich 
---
 target/avr/helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/avr/helper.c b/target/avr/helper.c
index c27f702901..db338a8761 100644
--- a/target/avr/helper.c
+++ b/target/avr/helper.c
@@ -45,7 +45,7 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 }
 if (interrupt_request & CPU_INTERRUPT_HARD) {
 if (cpu_interrupts_enabled(env) && env->intsrc != 0) {
-int index = ctz32(env->intsrc);
+int index = ctz64(env->intsrc);
 cs->exception_index = EXCP_INT(index);
 cc->tcg_ops->do_interrupt(cs);
 
@@ -73,7 +73,7 @@ void avr_cpu_do_interrupt(CPUState *cs)
 if (cs->exception_index == EXCP_RESET) {
 vector = 0;
 } else if (env->intsrc != 0) {
-vector = ctz32(env->intsrc) + 1;
+vector = ctz64(env->intsrc) + 1;
 }
 
 if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) {
-- 
2.39.1



Re: [PATCH v3 5/5] intel_iommu: Optimize out some unnecessary UNMAP calls

2023-06-08 Thread Jason Gunthorpe
On Thu, Jun 08, 2023 at 03:53:23PM -0400, Peter Xu wrote:
> Though that does look slightly special, because the whole empty UNMAP
> region can be seen as a hole too; not sure when that -ENOENT will be useful
> if qemu should always bypass it anyway.  Indeed not a problem to qemu.

It sounds like it might be good to have a flag to unmap the whole
range regardless of contiguity

Jason



Re: [PATCH v4 0/7] Resolve TYPE_PIIX3_XEN_DEVICE

2023-06-08 Thread Stefano Stabellini
On Thu, 8 Jun 2023, Stefano Stabellini wrote:
> On Mon, 5 Jun 2023, Bernhard Beschow wrote:
> > Am 22. Mai 2023 15:42:03 UTC schrieb Bernhard Beschow :
> > >
> > >
> > >Am 15. Mai 2023 20:52:40 UTC schrieb Stefano Stabellini 
> > >:
> > >>On Sat, 13 May 2023, Bernhard Beschow wrote:
> > >>> Am 21. April 2023 07:38:10 UTC schrieb "Michael S. Tsirkin" 
> > >>> :
> > >>> >On Mon, Apr 03, 2023 at 09:41:17AM +0200, Bernhard Beschow wrote:
> > >>> >> There is currently a dedicated PIIX3 device model for use under Xen. 
> > >>> >> By reusing
> > >>> >> existing PCI API during initialization this device model can be 
> > >>> >> eliminated and
> > >>> >> the plain PIIX3 device model can be used instead.
> > >>> >> 
> > >>> >> Resolving TYPE_PIIX3_XEN_DEVICE results in less code while also 
> > >>> >> making Xen
> > >>> >> agnostic towards the precise south bridge being used in the PC 
> > >>> >> machine. The
> > >>> >> latter might become particularily interesting once PIIX4 becomes 
> > >>> >> usable in the
> > >>> >> PC machine, avoiding the "Frankenstein" use of PIIX4_ACPI in PIIX3.
> > >>> >
> > >>> >xen stuff so I assume that tree?
> > >>> 
> > >>> Ping
> > >>
> > >>I am OK either way. Michael, what do you prefer?
> > >>
> > >>Normally I would suggest for you to pick up the patches. But as it
> > >>happens I'll have to likely send another pull request in a week or two
> > >>and I can add these patches to it.
> > >>
> > >>Let me know your preference and I am happy to follow it.
> > >
> > >Hi Stefano,
> > >
> > >Michael's PR was merged last week. How about including this series into 
> > >your PR then?
> > 
> > Ping
> 
> Sorry for the late reply, it looks like patch #3 breaks the build:

I noticed now that this patch series got committed (the right version
without the build failure), thanks Anthony for sending the pull request!



Re: [EXT] Re: Concept of LD-ID in QEMU

2023-06-08 Thread Shesha Bhushan Sreenivasamurthy
Hi,

Thinking a bit more, LD in CXL are PCIe endpoint functions. Therefore 1-1 
mapping of cxl-i2c device per PCIe device is sufficient, and we use function 
number in BDF as the LD-ID. Does it makes sense ?

From: Jonathan Cameron 
Sent: Thursday, June 8, 2023 3:36 AM
To: Shesha Bhushan Sreenivasamurthy 
Cc: linux-...@vger.kernel.org ; 
<"qemu-devel@nongnu.org" 
Subject: [EXT] Re: Concept of LD-ID in QEMU 
 
External Email

--

Shesha,

You've sent an email with the 'In-reply-to' set to one of Terry's patches.
Please check why that happened and make sure you don't do that in future as
it hides your unrelated thread in email clients and the archives!

See
https://urldefense.proofpoint.com/v2/url?u=https-3A__lore.kernel.org_linux-2Dcxl_20230607221651.2454764-2D1-2Dterry.bowman-40amd.com_T_-23t&d=DwIFAw&c=nKjWec2b6R0mOyPaz7xtfQ&r=Zta64bwn4nurTRpD4LY2OGr8KklkMRPn7Z_Qy0o4unU&m=ZMaAF9tkNCKfk8gYXMiPERZeIhavaQ7MdKtqCbShRF6w5ISrgHqAl6XDOONYbprZ&s=ERVX40JlAgnvRvPLm8sYZalsYDbpUU7YAqI0Ol0faPI&e=
  
for example

ss - Apologies. Will be careful.

Jonathan

On Thu, 8 Jun 2023 11:31:53 +0100
Jonathan Cameron  wrote:

> On Wed, 7 Jun 2023 23:01:11 +
> Shesha Bhushan Sreenivasamurthy  wrote:
> 
> > Hi,
> > For DCD sideband there needs to be LD-ID. Is the following approach 
> > acceptable?  
> 
> QEMU question so +CC qemu-devel
> 
> > 
> >  -device 
> > cxl-type3,bus=swport0,volatile-memdev=vmem0,dc-memdev=vmem1,id=cxl-vmem0,num-dc-regions=2,ldid=0
> >  \
> >  -device 
> > cxl-type3,bus=swport0,volatile-memdev=vmem1,dc-memdev=vmem2,id=cxl-vmem1,num-dc-regions=2,ldid=1
> >  \  
> 
> Those will be PCI functions at this level so you can't do this until we have 
> more advanced switch support
> (it has to know about multiple VHs - right now we only support fixed config 
> switches).  You could connect them
> to different switch ports - effectively that will be what it looks like when 
> we do emulate a configurable switch.
> 
> >  -device 
> > i2c_mctp_cxl,bus=aspeed.i2c.bus.0,address=24,target=cxl-vmem0,cxl-vmem1")
> > 
> > With this configuration, the same i2c device is handing both LDs and in 
> > FMAPI commands we use the LDID specified above.  
> 
> This effectively becomes a partial implementation of either an MLD or an 
> MH-SLD
> To manage the actual memory access, those will almost certainly need a bunch 
> of other shared
> infrastructure.  So I'd ultimately expect the i2c_mctp_cxl device to target 
> whatever
> device represents that shared infrastructure - it might be a separate device 
> or a 'lead' type 3 device.
> 
> So I'm not sure how this will fit together longer term.  We need same 
> infrastructure
> to work for a mailbox CCI on a MH-SLD/MLD as well and in that case there 
> isn't a separate
> device to which we can provide multiple targets as you've done in your 
> proposal here.
> 
> So I think we need to work out how to handle all of (I've probably forgotten 
> something)
> X marks done or in progress.
> 
> X 1) i2c_mctp_cxl to an SLD (no PCI Mailbox definition for this one)
>   2) i2c_mctp_cxl directly to an MLD (your case)
> X 3) i2c_mctp_cxl to a fixed config switch (single fixed VH no MLD capable 
> ports)
> X 4) PCI mailbox via switch CCI device that fixed config switch (no MLD 
> capable ports)
>    Even with this simple design some fun things you can do.
>   5) i2c_mctp_cxl to a configurable switch (probably a separate as yet to be 
>defined management interface - that messes with hotplug)
>   6) PCI mailbox via switch CCI to configurable switch (again to defined 
>management interface).
>   7) i2c_mctp_cxl to an MH-SLD - probably to which ever device also has 
>support for
>  tunneling to the FM owned LD via the PCI mailbox.
> X 8) PCI mailbox on MH-SLD tunneling to the FM owned LD.
>   9) i2c_mctp_cxl to an MH-MLD - similar to above - this one isn't that much 
>more complex than MH-SLD case.
> X 10) PCI mailbox to MH-MLD - similar to above.
>   11) Tunneling via the switch CCI (then over PCI-VDM - though that detail 
>isn't visible in QEMU) to an SLD
>   12) Tunneling via the switch CCI (then PCI-VDM) to an MH-SLD and on to he 
>FM owned LD.
>   13) Tunneling via the switch CCI (then over PCI-VDM) to an MLD / MH-MLD
>  
> Current i2c_mctp_cxl covers 1 and 3
> I'm part way through the tunnelling support for (8 and 100) - need to revisit 
> and wire up the switch CCI PoC
> properly which will give us 4.
> 
> 2 needs MLD support in general which we could maybe make work with a static 
> binding in a switch but that
>   would be odd - so we probably need to emulate a configurable switch for that
> 5,6 need configurable switch
> 7 needs same as 2 plus tunneling part similar to 4
> 9 again probably configurable switch for the MLD part to make sense
> 11 is fairly straight forward - but not done yet.
> 12 also not too bad, but needs the MH-SLD part to be fleshed out (some work 
> on going )
> 13 needs pretty much everything

Re: [QEMU][PATCH v6 4/4] tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

2023-06-08 Thread Vikram Garhwal

Hi Peter,
Thanks for sharing the details. I will fix these and send a follow up 
patch soon.


On 6/8/23 2:42 AM, Peter Maydell wrote:

On Tue, 30 May 2023 at 22:23, Vikram Garhwal  wrote:

The QTests perform three tests on the Xilinx VERSAL CANFD controller:
 Tests the CANFD controllers in loopback.
 Tests the CANFD controllers in normal mode with CAN frame.
 Tests the CANFD controllers in normal mode with CANFD frame.

Signed-off-by: Vikram Garhwal 
Acked-by: Thomas Huth 
Reviewed-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 

Hi; Coverity has spotted some issues with this test code; could
you investigate and send followup patches, please ?



+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
+ bool is_canfd_frame)
+{
+uint16_t size = 0;
+uint8_t len = CAN_FRAME_SIZE;
+
+if (is_canfd_frame) {
+len = CANFD_FRAME_SIZE;
+}

Here len is either 4 (if !is_canfd_frame) or 18 (if is_canfd_frame)...


+
+while (size < len) {

...and we loop with size always less than len...


+if (R_RX0_ID_OFFSET + 4 * size == R_RX0_DLC_OFFSET)  {
+g_assert_cmpint((buf_rx[size] & DLC_FD_BIT_MASK), ==,
+(buf_tx[size] & DLC_FD_BIT_MASK));
+} else {
+if (!is_canfd_frame && size == 4) {

...so here this condition can never be true: if !is_canfd_frame
then we know size is less than 4.

What was the intention here ?

(CID 1512900)


+break;
+}
+
+g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
+}
+
+size++;
+}
+}
+/*
+ * Xilinx CANFD supports both CAN and CANFD frames. This test will be
+ * transferring CAN frame i.e. 8 bytes of data from CANFD0 and CANFD1 through
+ * canbus. CANFD0 initiate the data transfer to can-bus, CANFD1 receives the
+ * data. Test compares the can frame data sent from CANFD0 and received on
+ * CANFD1.
+ */
+static void test_can_data_transfer(void)
+{
+uint32_t buf_tx[CAN_FRAME_SIZE] = { 0x5a5bb9a4, 0x8000,
+0x12345678, 0x87654321 };
+uint32_t buf_rx[CAN_FRAME_SIZE] = { 0x00, 0x00, 0x00, 0x00 };

The buf_rx[] array here is only 4 bytes long...


+uint32_t status = 0;
+
+generate_random_data(buf_tx, false);
+
+QTestState *qts = qtest_init("-machine xlnx-versal-virt"
+" -object can-bus,id=canbus"
+" -machine canbus0=canbus"
+" -machine canbus1=canbus"
+);
+
+configure_canfd(qts, MSR_NORMAL_MODE);
+
+/* Check if CANFD0 and CANFD1 are in Normal mode. */
+status = qtest_readl(qts, CANFD0_BASE_ADDR + R_SR_OFFSET);
+status = status & STATUS_REG_MASK;
+g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
+
+status = qtest_readl(qts, CANFD1_BASE_ADDR + R_SR_OFFSET);
+status = status & STATUS_REG_MASK;
+g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
+
+write_data(qts, CANFD0_BASE_ADDR, buf_tx, false);
+
+send_data(qts, CANFD0_BASE_ADDR);
+read_data(qts, CANFD1_BASE_ADDR, buf_rx);

...but read_data() will write up to 17 bytes of data to the buffer,
if the incoming data from the device claims it to be a canfd frame.
The device shouldn't really do that, but the point of a test is
that the device might not be functioning correctly, so we should
size buf_rx[] large enough to fit whatever read_data() writes to it.

(CID 1512899)


+match_rx_tx_data(buf_tx, buf_rx, false);
+
+qtest_quit(qts);
+}

thanks
-- PMM





[PATCH 27/42] migration-test: Create guest_extra_opts()

2023-06-08 Thread Juan Quintela
If a guest has extra command line options, add it with this.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 28 
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 0130a00707..b9b11ebb0f 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -156,6 +156,7 @@ typedef struct {
 gchar *arch_opts;
 gchar *arch_source;
 gchar *arch_target;
+const gchar *extra_opts;
 gchar *kvm_opts;
 const gchar *memory_size;
 /*
@@ -243,6 +244,12 @@ static void guest_use_shmem(GuestState *vm)
 vm->memory_size, vm->shmem_path);
 }
 
+static void guest_extra_opts(GuestState *vm, const gchar *opts)
+{
+g_assert(vm->extra_opts == NULL);
+vm->extra_opts = opts;
+}
+
 /*
  * Wait for some output in the serial output file,
  * we get an 'A' followed by an endless string of 'B's
@@ -640,8 +647,6 @@ typedef struct {
 bool hide_stderr;
 /* only launch the target process */
 bool only_target;
-const char *opts_source;
-const char *opts_target;
 } MigrateStart;
 
 /*
@@ -764,7 +769,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
  from->arch_opts ? from->arch_opts : "",
  from->arch_source ? from->arch_source : "",
  from->shmem_opts ? from->shmem_opts : "",
- args->opts_source ? args->opts_source : "",
+ from->extra_opts ? from->extra_opts : "",
  ignore_stderr ? ignore_stderr : "");
 
 if (!args->only_target) {
@@ -788,7 +793,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
  to->arch_opts ? to->arch_opts : "",
  to->arch_target ? to->arch_target : "",
  to->shmem_opts ? to->shmem_opts : "",
- args->opts_target ? args->opts_target : "",
+ to->extra_opts ? to->extra_opts : "",
  ignore_stderr ? ignore_stderr : "");
 to->qs = qtest_init(cmd_target);
 qtest_qmp_set_event_callback(to->qs,
@@ -1996,11 +2001,10 @@ static void test_validate_uuid(void)
 {
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
-MigrateStart args = {
-.opts_source = "-uuid ----",
-.opts_target = "-uuid ----",
-};
+MigrateStart args = { };
 
+guest_extra_opts(from, "-uuid ----");
+guest_extra_opts(to, "-uuid ----");
 do_test_validate_uuid(from, to, &args, false);
 }
 
@@ -2009,11 +2013,11 @@ static void test_validate_uuid_error(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateStart args = {
-.opts_source = "-uuid ----",
-.opts_target = "-uuid ----",
 .hide_stderr = true,
 };
 
+guest_extra_opts(from, "-uuid ----");
+guest_extra_opts(to, "-uuid ----");
 do_test_validate_uuid(from, to, &args, true);
 }
 
@@ -2022,10 +2026,10 @@ static void test_validate_uuid_src_not_set(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateStart args = {
-.opts_target = "-uuid ----",
 .hide_stderr = true,
 };
 
+guest_extra_opts(to, "-uuid ----");
 do_test_validate_uuid(from, to, &args, false);
 }
 
@@ -2034,10 +2038,10 @@ static void test_validate_uuid_dst_not_set(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateStart args = {
-.opts_source = "-uuid ----",
 .hide_stderr = true,
 };
 
+guest_extra_opts(from, "-uuid ----");
 do_test_validate_uuid(from, to, &args, false);
 }
 
-- 
2.40.1




[PATCH 25/42] migration-test: We were not waiting for "target" to finish

2023-06-08 Thread Juan Quintela
This could create the problem that we start the "second" target before
the first one has removed the serial socket.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 9f86d9bc80..933000ad81 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -2432,6 +2432,8 @@ static void test_multifd_tcp_cancel(void)
 qtest_set_expected_status(to->qs, EXIT_FAILURE);
 qtest_wait_qemu(to->qs);
 
+guest_destroy(to);
+
 args = (MigrateStart){
 .only_target = true,
 };
-- 
2.40.1




[PATCH 26/42] migration-test: create guest_use_shmem()

2023-06-08 Thread Juan Quintela
So now this is the same that everything else.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 46 +---
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 933000ad81..0130a00707 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -164,6 +164,8 @@ typedef struct {
  */
 const gchar *name;
 gchar *serial_path;
+gchar *shmem_opts;
+gchar *shmem_path;
 unsigned start_address;
 unsigned end_address;
 } GuestState;
@@ -217,6 +219,9 @@ static void guest_destroy(GuestState *vm)
 g_free(vm->kvm_opts);
 unlink(vm->serial_path);
 g_free(vm->serial_path);
+g_free(vm->shmem_opts);
+unlink(vm->shmem_path);
+g_free(vm->shmem_path);
 g_free(vm);
 }
 
@@ -226,6 +231,18 @@ static void guest_use_dirty_ring(GuestState *vm)
 vm->kvm_opts = g_strdup(",dirty-ring-size=4096");
 }
 
+static void guest_use_shmem(GuestState *vm)
+{
+g_assert(vm->shmem_opts == NULL);
+g_assert(vm->shmem_path == NULL);
+
+vm->shmem_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
+vm->shmem_opts = g_strdup_printf(
+"-object memory-backend-file,id=mem0,size=%s"
+",mem-path=%s,share=on -numa node,memdev=mem0",
+vm->memory_size, vm->shmem_path);
+}
+
 /*
  * Wait for some output in the serial output file,
  * we get an 'A' followed by an endless string of 'B's
@@ -621,7 +638,6 @@ typedef struct {
  * unconditionally, because it means the user would like to be verbose.
  */
 bool hide_stderr;
-bool use_shmem;
 /* only launch the target process */
 bool only_target;
 const char *opts_source;
@@ -720,8 +736,6 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
 const gchar *ignore_stderr = NULL;
-g_autofree char *shmem_opts = NULL;
-g_autofree char *shmem_path = NULL;
 
 got_src_stop = false;
 got_dst_resume = false;
@@ -738,14 +752,6 @@ static void test_migrate_start(GuestState *from, 
GuestState *to,
 #endif
 }
 
-if (args->use_shmem) {
-shmem_path = g_strdup_printf("/dev/shm/qemu-%d", getpid());
-shmem_opts = g_strdup_printf(
-"-object memory-backend-file,id=mem0,size=%s"
-",mem-path=%s,share=on -numa node,memdev=mem0",
-from->memory_size, shmem_path);
-}
-
 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name %s,debug-threads=on "
  "-m %s "
@@ -757,7 +763,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
  from->serial_path,
  from->arch_opts ? from->arch_opts : "",
  from->arch_source ? from->arch_source : "",
- shmem_opts ? shmem_opts : "",
+ from->shmem_opts ? from->shmem_opts : "",
  args->opts_source ? args->opts_source : "",
  ignore_stderr ? ignore_stderr : "");
 
@@ -781,21 +787,13 @@ static void test_migrate_start(GuestState *from, 
GuestState *to,
  uri,
  to->arch_opts ? to->arch_opts : "",
  to->arch_target ? to->arch_target : "",
- shmem_opts ? shmem_opts : "",
+ to->shmem_opts ? to->shmem_opts : "",
  args->opts_target ? args->opts_target : "",
  ignore_stderr ? ignore_stderr : "");
 to->qs = qtest_init(cmd_target);
 qtest_qmp_set_event_callback(to->qs,
  migrate_watch_for_resume,
  &got_dst_resume);
-
-/*
- * Remove shmem file immediately to avoid memory leak in test failed case.
- * It's valid becase QEMU has already opened this file
- */
-if (args->use_shmem) {
-unlink(shmem_path);
-}
 }
 
 static void test_migrate_end(GuestState *from, GuestState *to, bool test_dest)
@@ -1637,10 +1635,10 @@ static void test_ignore_shared(void)
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
-MigrateStart args = {
-.use_shmem = true
-};
+MigrateStart args = { };
 
+guest_use_shmem(from);
+guest_use_shmem(to);
 test_migrate_start(from, to, uri, &args);
 
 migrate_set_capability(from->qs, "x-ignore-shared", true);
-- 
2.40.1




[PATCH 19/42] migration-test: Create guest before calling test_precopy_common()

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 122 +--
 1 file changed, 89 insertions(+), 33 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 14f4fd579b..528dc571ef 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1419,11 +1419,9 @@ static void test_baddest(void)
 test_migrate_end(from, to, false);
 }
 
-static void test_precopy_common(MigrateCommon *args)
+static void test_precopy_common(GuestState *from, GuestState *to,
+MigrateCommon *args)
 {
-GuestState *from = guest_create("source");
-GuestState *to = guest_create("target");
-
 void *data_hook = NULL;
 
 test_migrate_start(from, to, args->listen_uri, &args->start);
@@ -1521,6 +1519,8 @@ static void test_precopy_common(MigrateCommon *args)
 static void test_precopy_unix_plain(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .listen_uri = uri,
 .connect_uri = uri,
@@ -1531,13 +1531,15 @@ static void test_precopy_unix_plain(void)
 .live = true,
 };
 
-test_precopy_common(&args);
+test_precopy_common(from, to, &args);
 }
 
 
 static void test_precopy_unix_dirty_ring(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .start = {
 .use_dirty_ring = true,
@@ -1551,13 +1553,15 @@ static void test_precopy_unix_dirty_ring(void)
 .live = true,
 };
 
-test_precopy_common(&args);
+test_precopy_common(from, to, &args);
 }
 
 #ifdef CONFIG_GNUTLS
 static void test_precopy_unix_tls_psk(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .connect_uri = uri,
 .listen_uri = uri,
@@ -1565,13 +1569,15 @@ static void test_precopy_unix_tls_psk(void)
 .finish_hook = test_migrate_tls_psk_finish,
 };
 
-test_precopy_common(&args);
+test_precopy_common(from, to, &args);
 }
 
 #ifdef CONFIG_TASN1
 static void test_precopy_unix_tls_x509_default_host(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .start = {
 .hide_stderr = true,
@@ -1583,12 +1589,14 @@ static void 
test_precopy_unix_tls_x509_default_host(void)
 .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
 };
 
-test_precopy_common(&args);
+test_precopy_common(from, to, &args);
 }
 
 static void test_precopy_unix_tls_x509_override_host(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .connect_uri = uri,
 .listen_uri = uri,
@@ -1596,7 +1604,7 @@ static void test_precopy_unix_tls_x509_override_host(void)
 .finish_hook = test_migrate_tls_x509_finish,
 };
 
-test_precopy_common(&args);
+test_precopy_common(from, to, &args);
 }
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
@@ -1653,6 +1661,8 @@ test_migrate_xbzrle_start(QTestState *from,
 static void test_precopy_unix_xbzrle(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .connect_uri = uri,
 .listen_uri = uri,
@@ -1665,12 +1675,14 @@ static void test_precopy_unix_xbzrle(void)
 .live = true,
 };
 
-test_precopy_common(&args);
+test_precopy_common(from, to, &args);
 }
 
 static void test_precopy_unix_compress(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .connect_uri = uri,
 .listen_uri = uri,
@@ -1688,12 +1700,14 @@ static void test_precopy_unix_compress(void)
 .live = true,
 };
 
-test_precopy_common(&args);
+test_precopy_common(from, to, &args);
 }
 
 static void test_precopy_unix_compress_nowait(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .connect_uri = uri,
 .listen_uri = uri,
@@ -1707,32 +1721,38 @@ static void test_precopy_unix_compress_nowait(void)
 .live = true,
 };
 
-test_precopy_c

[PATCH 33/42] migration-test: Remove connect_uri

2023-06-08 Thread Juan Quintela
We are using to->uri in everywhere know.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 52 +---
 1 file changed, 13 insertions(+), 39 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index f029258f67..3b1b76fe6f 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -671,24 +671,14 @@ static void migrate_postcopy_start(GuestState *from, 
GuestState *to)
 qtest_qmp_eventwait(to->qs, "RESUME");
 }
 
-static void do_migrate(GuestState *from, GuestState *to, const gchar *uri)
+static void do_migrate(GuestState *from, GuestState *to)
 {
-if (to->uri) {
-if (strncmp(to->uri, "tcp:", strlen("tcp:")) == 0) {
-g_autofree char *tcp_uri =
-migrate_get_socket_address(to->qs, "socket-address");
-migrate_qmp(from->qs, tcp_uri, "{}");
-} else {
-migrate_qmp(from->qs, to->uri, "{}");
-}
+if (!to->uri || strncmp(to->uri, "tcp:", strlen("tcp:")) == 0) {
+g_autofree char *tcp_uri =
+migrate_get_socket_address(to->qs, "socket-address");
+migrate_qmp(from->qs, tcp_uri, "{}");
 } else {
-if (!uri) {
-g_autofree char *tcp_uri =
-migrate_get_socket_address(to->qs, "socket-address");
-migrate_qmp(from->qs, tcp_uri, "{}");
-} else {
-migrate_qmp(from->qs, uri, "{}");
-}
+migrate_qmp(from->qs, to->uri, "{}");
 }
 }
 
@@ -726,14 +716,6 @@ typedef struct {
 /* Required: the URI for the dst QEMU to listen on */
 const char *listen_uri;
 
-/*
- * Optional: the URI for the src QEMU to connect to
- * If NULL, then it will query the dst QEMU for its actual
- * listening address and use that as the connect address.
- * This allows for dynamically picking a free TCP port.
- */
-const char *connect_uri;
-
 /* Optional: callback to run at start to set migration parameters */
 TestMigrateStartHook start_hook;
 /* Optional: callback to run at finish to cleanup */
@@ -1239,7 +1221,7 @@ static void migrate_postcopy_prepare(GuestState *from,
 /* Wait for the first serial output from the source */
 wait_for_serial(from);
 
-do_migrate(from, to, to->uri);
+do_migrate(from, to);
 
 wait_for_migration_pass(from->qs);
 }
@@ -1500,7 +1482,7 @@ static void test_precopy_common(GuestState *from, 
GuestState *to,
 }
 }
 
-do_migrate(from, to, args->connect_uri);
+do_migrate(from, to);
 
 if (args->result != MIG_TEST_SUCCEED) {
 bool allow_active = args->result == MIG_TEST_FAIL;
@@ -1563,7 +1545,6 @@ static void test_precopy_unix_plain(void)
 GuestState *to = guest_create("target");
 MigrateCommon args = {
 .listen_uri = uri,
-.connect_uri = uri,
 /*
  * The simplest use case of precopy, covering smoke tests of
  * get-dirty-log dirty tracking.
@@ -1582,7 +1563,6 @@ static void test_precopy_unix_dirty_ring(void)
 GuestState *to = guest_create("target");
 MigrateCommon args = {
 .listen_uri = uri,
-.connect_uri = uri,
 /*
  * Besides the precopy/unix basic test, cover dirty ring interface
  * rather than get-dirty-log.
@@ -1602,7 +1582,6 @@ static void test_precopy_unix_tls_psk(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.connect_uri = uri,
 .listen_uri = uri,
 .start_hook = test_migrate_tls_psk_start_match,
 .finish_hook = test_migrate_tls_psk_finish,
@@ -1618,7 +1597,6 @@ static void test_precopy_unix_tls_x509_default_host(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.connect_uri = uri,
 .listen_uri = uri,
 .start_hook = test_migrate_tls_x509_start_default_host,
 .finish_hook = test_migrate_tls_x509_finish,
@@ -1636,7 +1614,6 @@ static void test_precopy_unix_tls_x509_override_host(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.connect_uri = uri,
 .listen_uri = uri,
 .start_hook = test_migrate_tls_x509_start_override_host,
 .finish_hook = test_migrate_tls_x509_finish,
@@ -1664,7 +1641,7 @@ static void test_ignore_shared(void)
 /* Wait for the first serial output from the source */
 wait_for_serial(from);
 
-do_migrate(from, to, to->uri);
+do_migrate(from, to);
 
 wait_for_migration_pass(from->qs);
 
@@ -1701,7 +1678,6 @@ static void test_precopy_unix_xbzrle(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.connect_uri = uri,
 .listen_uri = uri,
 .start_hook = test_migrate_xbzrle_start,
 

[PATCH 03/42] migration-test: simplify shmem_opts handling

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 73b2f01427..95ccc9bce7 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -681,9 +681,6 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 "-object memory-backend-file,id=mem0,size=%s"
 ",mem-path=%s,share=on -numa node,memdev=mem0",
 memory_size, shmem_path);
-} else {
-shmem_path = NULL;
-shmem_opts = g_strdup("");
 }
 
 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg%s%s "
@@ -696,7 +693,8 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  machine_opts ? " -machine " : "",
  machine_opts ? machine_opts : "",
  memory_size, tmpfs,
- arch_source, shmem_opts,
+ arch_source,
+ shmem_opts ? shmem_opts : "",
  args->opts_source ? args->opts_source : "",
  ignore_stderr ? ignore_stderr : "");
 
@@ -718,7 +716,8 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  machine_opts ? " -machine " : "",
  machine_opts ? machine_opts : "",
  memory_size, tmpfs, uri,
- arch_target, shmem_opts,
+ arch_target,
+ shmem_opts ? shmem_opts : "",
  args->opts_target ? args->opts_target : "",
  ignore_stderr ? ignore_stderr : "");
 *to = qtest_init(cmd_target);
-- 
2.40.1




[PATCH 41/42] migration-test: Move functions to migration-helpers.c

2023-06-08 Thread Juan Quintela
This will help on next patch to split vcpu-dirty-limit-test.c

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-helpers.h |  39 +
 tests/qtest/migration-helpers.c | 242 +
 tests/qtest/migration-test.c| 260 
 3 files changed, 281 insertions(+), 260 deletions(-)

diff --git a/tests/qtest/migration-helpers.h b/tests/qtest/migration-helpers.h
index 009e250e90..6096ffd82a 100644
--- a/tests/qtest/migration-helpers.h
+++ b/tests/qtest/migration-helpers.h
@@ -15,6 +15,8 @@
 
 #include "libqtest.h"
 
+extern char *tmpfs;
+
 bool migrate_watch_for_stop(QTestState *who, const char *name,
 QDict *event, void *opaque);
 bool migrate_watch_for_resume(QTestState *who, const char *name,
@@ -33,4 +35,41 @@ void wait_for_migration_complete(QTestState *who);
 
 void wait_for_migration_fail(QTestState *from, bool allow_active);
 
+typedef struct {
+QTestState *qs;
+/* options for source and target */
+gchar *arch_opts;
+gchar *arch_source;
+gchar *arch_target;
+const gchar *extra_opts;
+const gchar *hide_stderr;
+gchar *kvm_opts;
+const gchar *memory_size;
+/*
+ * name must *not* contain "target" if it is the target of a
+ * migration.
+ */
+const gchar *name;
+gchar *serial_path;
+gchar *shmem_opts;
+gchar *shmem_path;
+gchar *unix_socket;
+gchar *uri;
+unsigned start_address;
+unsigned end_address;
+bool got_event;
+} GuestState;
+
+GuestState *guest_create(const char *name);
+void guest_destroy(GuestState *vm);
+void guest_realize(GuestState *who);
+void guest_use_dirty_ring(GuestState *vm);
+
+void wait_for_serial(GuestState *vm);
+
+void bootfile_create(char *dir);
+void bootfile_delete(void);
+
+bool kvm_dirty_ring_supported(void);
+
 #endif /* MIGRATION_HELPERS_H */
diff --git a/tests/qtest/migration-helpers.c b/tests/qtest/migration-helpers.c
index be00c52d00..ffdc689a88 100644
--- a/tests/qtest/migration-helpers.c
+++ b/tests/qtest/migration-helpers.c
@@ -13,8 +13,23 @@
 #include "qemu/osdep.h"
 #include "qapi/qmp/qjson.h"
 
+#include "tests/migration/migration-test.h"
 #include "migration-helpers.h"
 
+#if defined(__linux__)
+#include 
+#include 
+#include 
+#endif
+
+/* For dirty ring test; so far only x86_64 is supported */
+#if defined(__linux__) && defined(HOST_X86_64)
+#include "linux/kvm.h"
+#endif
+
+char *tmpfs;
+static char *bootpath;
+
 /*
  * Number of seconds we wait when looking for migration
  * status changes, to avoid test suite hanging forever
@@ -180,3 +195,230 @@ void wait_for_migration_fail(QTestState *from, bool 
allow_active)
 g_assert(qdict_get_bool(rsp_return, "running"));
 qobject_unref(rsp_return);
 }
+
+/* The boot file modifies memory area in [start_address, end_address)
+ * repeatedly. It outputs a 'B' at a fixed rate while it's still running.
+ */
+#include "tests/migration/i386/a-b-bootblock.h"
+#include "tests/migration/aarch64/a-b-kernel.h"
+#include "tests/migration/s390x/a-b-bios.h"
+
+void bootfile_create(char *dir)
+{
+const char *arch = qtest_get_arch();
+unsigned char *content;
+size_t len;
+
+bootpath = g_strdup_printf("%s/bootsect", dir);
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+/* the assembled x86 boot sector should be exactly one sector large */
+g_assert(sizeof(x86_bootsect) == 512);
+content = x86_bootsect;
+len = sizeof(x86_bootsect);
+} else if (g_str_equal(arch, "s390x")) {
+content = s390x_elf;
+len = sizeof(s390x_elf);
+} else if (strcmp(arch, "ppc64") == 0) {
+/*
+ * sane architectures can be programmed at the boot prompt
+ */
+return;
+} else if (strcmp(arch, "aarch64") == 0) {
+content = aarch64_kernel;
+len = sizeof(aarch64_kernel);
+g_assert(sizeof(aarch64_kernel) <= ARM_TEST_MAX_KERNEL_SIZE);
+} else {
+g_assert_not_reached();
+}
+
+FILE *bootfile = fopen(bootpath, "wb");
+
+g_assert_cmpint(fwrite(content, len, 1, bootfile), ==, 1);
+fclose(bootfile);
+}
+
+void bootfile_delete(void)
+{
+unlink(bootpath);
+g_free(bootpath);
+bootpath = NULL;
+}
+
+GuestState *guest_create(const char *name)
+{
+GuestState *vm = g_new0(GuestState, 1);
+const char *arch = qtest_get_arch();
+
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+vm->memory_size = "150M";
+vm->arch_opts = g_strdup_printf("-drive file=%s,format=raw", bootpath);
+vm->start_address = X86_TEST_MEM_START;
+vm->end_address = X86_TEST_MEM_END;
+} else if (g_str_equal(arch, "s390x")) {
+vm->memory_size = "128M";
+vm->arch_opts = g_strdup_printf("-bios %s", bootpath);
+vm->start_address = S390_TEST_MEM_START;
+vm->end_address = S390_TEST_MEM_END;
+} else if (strcmp(arch, "ppc64") == 0) {
+vm->memory_size = "256

[PATCH 13/42] migration-test: Check for shared memory like for everything else

2023-06-08 Thread Juan Quintela
Makes things easier and cleaner.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index daaf5cd71a..5837060138 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -645,13 +645,6 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 const char *arch = qtest_get_arch();
 const char *memory_size;
 
-if (args->use_shmem) {
-if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
-g_test_skip("/dev/shm is not supported");
-return -1;
-}
-}
-
 got_src_stop = false;
 got_dst_resume = false;
 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
@@ -2639,6 +2632,15 @@ static bool kvm_dirty_ring_supported(void)
 #endif
 }
 
+static bool shm_supported(void)
+{
+if (g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
+return true;
+}
+g_test_message("Skipping test: shared memory not available");
+return false;
+}
+
 int main(int argc, char **argv)
 {
 bool has_kvm, has_tcg;
@@ -2768,7 +2770,9 @@ int main(int argc, char **argv)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-qtest_add_func("/migration/ignore_shared", test_ignore_shared);
+if (shm_supported()) {
+qtest_add_func("/migration/ignore_shared", test_ignore_shared);
+}
 #ifndef _WIN32
 qtest_add_func("/migration/fd_proto", test_migrate_fd_proto);
 #endif
-- 
2.40.1




[PATCH 21/42] migration-test: Move common guest code to guest_create()

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 104 ++-
 1 file changed, 55 insertions(+), 49 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index a18b3ce1e2..9671c4c6e5 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -40,8 +40,6 @@
 #include "linux/kvm.h"
 #endif
 
-unsigned start_address;
-unsigned end_address;
 static bool uffd_feature_thread_id;
 static bool got_src_stop;
 static bool got_dst_resume;
@@ -154,12 +152,50 @@ static void bootfile_delete(void)
 
 typedef struct {
 QTestState *qs;
+/* options for source and target */
+gchar *arch_opts;
+gchar *arch_source;
+gchar *arch_target;
+const gchar *memory_size;
 const gchar *name;
+unsigned start_address;
+unsigned end_address;
 } GuestState;
 
 static GuestState *guest_create(const char *name)
 {
 GuestState *vm = g_new0(GuestState, 1);
+const char *arch = qtest_get_arch();
+
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+vm->memory_size = "150M";
+vm->arch_opts = g_strdup_printf("-drive file=%s,format=raw", bootpath);
+vm->start_address = X86_TEST_MEM_START;
+vm->end_address = X86_TEST_MEM_END;
+} else if (g_str_equal(arch, "s390x")) {
+vm->memory_size = "128M";
+vm->arch_opts = g_strdup_printf("-bios %s", bootpath);
+vm->start_address = S390_TEST_MEM_START;
+vm->end_address = S390_TEST_MEM_END;
+} else if (strcmp(arch, "ppc64") == 0) {
+vm->memory_size = "256M";
+vm->start_address = PPC_TEST_MEM_START;
+vm->end_address = PPC_TEST_MEM_END;
+vm->arch_source = g_strdup_printf(
+"-prom-env 'use-nvramrc?=true' -prom-env "
+"'nvramrc=hex .\" _\" begin %x %x "
+"do i c@ 1 + i c! 1000 +loop .\" B\" 0 "
+"until'", vm->end_address, vm->start_address);
+vm->arch_opts = g_strdup("-nodefaults -machine vsmt=8");
+} else if (strcmp(arch, "aarch64") == 0) {
+vm->memory_size = "150M";
+vm->arch_opts = g_strdup_printf(
+"-machine virt,gic-version=max -cpu max -kernel %s", bootpath);
+vm->start_address = ARM_TEST_MEM_START;
+vm->end_address = ARM_TEST_MEM_END;
+} else {
+g_assert_not_reached();
+}
 
 vm->name = name;
 
@@ -169,6 +205,9 @@ static GuestState *guest_create(const char *name)
 static void guest_destroy(GuestState *vm)
 {
 qtest_quit(vm->qs);
+g_free(vm->arch_opts);
+g_free(vm->arch_source);
+g_free(vm->arch_target);
 g_free(vm);
 }
 
@@ -307,10 +346,11 @@ static void check_guests_ram(GuestState *who)
 bool hit_edge = false;
 int bad = 0;
 
-qtest_memread(who->qs, start_address, &first_byte, 1);
+qtest_memread(who->qs, who->start_address, &first_byte, 1);
 last_byte = first_byte;
 
-for (address = start_address + TEST_MEM_PAGE_SIZE; address < end_address;
+for (address = who->start_address + TEST_MEM_PAGE_SIZE;
+ address < who->end_address;
  address += TEST_MEM_PAGE_SIZE)
 {
 uint8_t b;
@@ -663,49 +703,15 @@ typedef struct {
 static void test_migrate_start(GuestState *from, GuestState *to,
const char *uri, MigrateStart *args)
 {
-g_autofree gchar *arch_source = NULL;
-g_autofree gchar *arch_target = NULL;
-/* options for source and target */
-g_autofree gchar *arch_opts = NULL;
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
 const gchar *ignore_stderr = NULL;
 g_autofree char *shmem_opts = NULL;
 g_autofree char *shmem_path = NULL;
 const char *kvm_opts = NULL;
-const char *arch = qtest_get_arch();
-const char *memory_size;
 
 got_src_stop = false;
 got_dst_resume = false;
-if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
-memory_size = "150M";
-arch_opts = g_strdup_printf("-drive file=%s,format=raw", bootpath);
-start_address = X86_TEST_MEM_START;
-end_address = X86_TEST_MEM_END;
-} else if (g_str_equal(arch, "s390x")) {
-memory_size = "128M";
-arch_opts = g_strdup_printf("-bios %s", bootpath);
-start_address = S390_TEST_MEM_START;
-end_address = S390_TEST_MEM_END;
-} else if (strcmp(arch, "ppc64") == 0) {
-memory_size = "256M";
-start_address = PPC_TEST_MEM_START;
-end_address = PPC_TEST_MEM_END;
-arch_source = g_strdup_printf("-prom-env 'use-nvramrc?=true' -prom-env 
"
-  "'nvramrc=hex .\" _\" begin %x %x "
-  "do i c@ 1 + i c! 1000 +loop .\" B\" 0 "
-  "until'", end_address, start_address);
-arch_opts = g_strdup("-nodefaults -machine vsmt=8");
-} else if (strcmp(arch, "aarch64") == 0) {
-memory_size = "15

[PATCH 36/42] migration-test: Remove unused listen_uri

2023-06-08 Thread Juan Quintela
Only remaining use was to transfer "defer".  But we make "defer" the
default if no uri is given.  Once there Remove the uri parameter to
test_migrate_start().

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 34 ++
 1 file changed, 10 insertions(+), 24 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 8d497d0940..95b7c9ed73 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -706,9 +706,6 @@ typedef struct {
 /* Optional: fine tune start parameters */
 MigrateStart start;
 
-/* Required: the URI for the dst QEMU to listen on */
-const char *listen_uri;
-
 /* Optional: callback to run at start to set migration parameters */
 TestMigrateStartHook start_hook;
 /* Optional: callback to run at finish to cleanup */
@@ -757,7 +754,7 @@ typedef struct {
 } MigrateCommon;
 
 static void test_migrate_start(GuestState *from, GuestState *to,
-   const char *uri, MigrateStart *args)
+   MigrateStart *args)
 {
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
@@ -797,7 +794,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
  to->name,
  to->memory_size,
  to->serial_path,
- to->uri ? to->uri : uri,
+ to->uri ? to->uri : "defer",
  to->arch_opts ? to->arch_opts : "",
  to->arch_target ? to->arch_target : "",
  to->shmem_opts ? to->shmem_opts : "",
@@ -1192,7 +1189,7 @@ static void migrate_postcopy_prepare(GuestState *from,
  MigrateCommon *args)
 {
 guest_listen_unix_socket(to);
-test_migrate_start(from, to, NULL, &args->start);
+test_migrate_start(from, to, &args->start);
 
 if (args->start_hook) {
 args->postcopy_data = args->start_hook(from, to);
@@ -1424,7 +1421,7 @@ static void test_baddest(void)
 guest_hide_stderr(from);
 guest_hide_stderr(to);
 guest_set_uri(to, "tcp:127.0.0.1:0");
-test_migrate_start(from, to, NULL, &args);
+test_migrate_start(from, to, &args);
 /*
  * Don't change to do_migrate(). We are using a wrong uri on purpose.
  */
@@ -1438,7 +1435,7 @@ static void test_precopy_common(GuestState *from, 
GuestState *to,
 {
 void *data_hook = NULL;
 
-test_migrate_start(from, to, args->listen_uri, &args->start);
+test_migrate_start(from, to, &args->start);
 
 if (args->start_hook) {
 data_hook = args->start_hook(from, to);
@@ -1620,7 +1617,7 @@ static void test_ignore_shared(void)
 guest_use_shmem(from);
 guest_use_shmem(to);
 guest_listen_unix_socket(to);
-test_migrate_start(from, to, NULL, &args);
+test_migrate_start(from, to, &args);
 
 migrate_set_capability(from->qs, "x-ignore-shared", true);
 migrate_set_capability(to->qs, "x-ignore-shared", true);
@@ -1921,7 +1918,6 @@ static void test_migrate_fd_proto(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "defer",
 .start_hook = test_migrate_fd_start_hook,
 .finish_hook = test_migrate_fd_finish_hook
 };
@@ -1933,7 +1929,7 @@ static void do_test_validate_uuid(GuestState *from, 
GuestState *to,
   MigrateStart *args, bool should_fail)
 {
 guest_listen_unix_socket(to);
-test_migrate_start(from, to, NULL, args);
+test_migrate_start(from, to, args);
 
 /*
  * UUID validation is at the begin of migration. So, the main process of
@@ -2036,7 +2032,7 @@ static void test_migrate_auto_converge(void)
 const int64_t init_pct = 5, inc_pct = 25, max_pct = 95;
 
 guest_listen_unix_socket(to);
-test_migrate_start(from, to, NULL, &args);
+test_migrate_start(from, to, &args);
 
 migrate_set_capability(from->qs, "auto-converge", true);
 migrate_set_parameter_int(from->qs, "cpu-throttle-initial", init_pct);
@@ -2138,7 +2134,6 @@ static void test_multifd_tcp_none(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "defer",
 .start_hook = test_migrate_precopy_tcp_multifd_start,
 /*
  * Multifd is more complicated than most of the features, it
@@ -2155,7 +2150,6 @@ static void test_multifd_tcp_zlib(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "defer",
 .start_hook = test_migrate_precopy_tcp_multifd_zlib_start,
 };
 test_precopy_common(from, to, &args);
@@ -2167,7 +2161,6 @@ static void test_multifd

[PATCH 12/42] migration-test: Enable back ignore-shared test

2023-06-08 Thread Juan Quintela
It failed on aarch64 tcg, lets see if that is still the case.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 7178c8e679..daaf5cd71a 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1591,8 +1591,6 @@ static void test_precopy_unix_tls_x509_override_host(void)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-#if 0
-/* Currently upset on aarch64 TCG */
 static void test_ignore_shared(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
@@ -1629,7 +1627,6 @@ static void test_ignore_shared(void)
 
 test_migrate_end(from, to, true);
 }
-#endif
 
 static void *
 test_migrate_xbzrle_start(QTestState *from,
@@ -2771,7 +2768,7 @@ int main(int argc, char **argv)
 #endif /* CONFIG_TASN1 */
 #endif /* CONFIG_GNUTLS */
 
-/* qtest_add_func("/migration/ignore_shared", test_ignore_shared); */
+qtest_add_func("/migration/ignore_shared", test_ignore_shared);
 #ifndef _WIN32
 qtest_add_func("/migration/fd_proto", test_migrate_fd_proto);
 #endif
-- 
2.40.1




[PATCH 40/42] migration-test: Create migrate_incoming() function

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 1a03077166..d8479abb4a 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -684,6 +684,13 @@ static void migrate_set_capability(QTestState *who, const 
char *capability,
  capability, value);
 }
 
+static void migrate_incoming(GuestState *who, const char *uri)
+{
+qtest_qmp_assert_success(who->qs, "{ 'execute': 'migrate-incoming',"
+ "  'arguments': { 'uri': %s }}", uri);
+guest_set_uri(who, uri);
+}
+
 static void migrate_postcopy_start(GuestState *from, GuestState *to)
 {
 qtest_qmp_assert_success(from->qs,
@@ -1851,9 +1858,7 @@ static void *test_migrate_fd_start_hook(GuestState *from, 
GuestState *to)
 close(pair[0]);
 
 /* Start incoming migration from the 1st socket */
-qtest_qmp_assert_success(to->qs, "{ 'execute': 'migrate-incoming',"
- "  'arguments': { 'uri': 'fd:fd-mig' }}");
-guest_set_uri(to, "fd:fd-mig");
+migrate_incoming(to, "fd:fd-mig");
 
 /* Send the 2nd socket to the target */
 qtest_qmp_fds_assert_success(from->qs, &pair[1], 1,
@@ -2077,9 +2082,7 @@ test_migrate_precopy_tcp_multifd_start_common(GuestState 
*from, GuestState *to,
 migrate_set_capability(to->qs, "multifd", true);
 
 /* Start incoming migration from the 1st socket */
-qtest_qmp_assert_success(to->qs, "{ 'execute': 'migrate-incoming',"
- "  'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
-guest_set_uri(to, "tcp:127.0.0.1:0");
+migrate_incoming(to, "tcp:127.0.0.1:0");
 
 return NULL;
 }
@@ -2334,9 +2337,7 @@ static void test_multifd_tcp_cancel(void)
 migrate_set_capability(to->qs, "multifd", true);
 
 /* Start incoming migration from the 1st socket */
-qtest_qmp_assert_success(to->qs, "{ 'execute': 'migrate-incoming',"
- "  'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
-guest_set_uri(to, "tcp:127.0.0.1:0");
+migrate_incoming(to, "tcp:127.0.0.1:0");
 
 /* Wait for the first serial output from the source */
 wait_for_serial(from);
@@ -2360,9 +2361,7 @@ static void test_multifd_tcp_cancel(void)
 migrate_set_capability(to2->qs, "multifd", true);
 
 /* Start incoming migration from the 1st socket */
-qtest_qmp_assert_success(to2->qs, "{ 'execute': 'migrate-incoming',"
- "  'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
-guest_set_uri(to2, "tcp:127.0.0.1:0");
+migrate_incoming(to2, "tcp:127.0.0.1:0");
 
 wait_for_migration_status(from->qs, "cancelled", NULL);
 
-- 
2.40.1




[PATCH 39/42] migration-test: Unfold test_migrate_end() into three functions

2023-06-08 Thread Juan Quintela
guest_destroy(from)
test_migrate_check(from, to): depending of test value
guest_destroy(to);

This mimics previous change that split test_migrate_start()

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 63 
 1 file changed, 35 insertions(+), 28 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 29147b2be3..1a03077166 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -777,33 +777,26 @@ typedef struct {
 bool postcopy_preempt;
 } MigrateCommon;
 
-static void test_migrate_end(GuestState *from, GuestState *to, bool test_dest)
+static void test_migrate_check(GuestState *from, GuestState *to)
 {
 unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
 
-guest_destroy(from);
+qtest_memread(to->qs, to->start_address, &dest_byte_a, 1);
 
-if (test_dest) {
-qtest_memread(to->qs, to->start_address, &dest_byte_a, 1);
+/* Destination still running, wait for a byte to change */
+do {
+qtest_memread(to->qs, to->start_address, &dest_byte_b, 1);
+usleep(1000 * 10);
+} while (dest_byte_a == dest_byte_b);
 
-/* Destination still running, wait for a byte to change */
-do {
-qtest_memread(to->qs, to->start_address, &dest_byte_b, 1);
-usleep(1000 * 10);
-} while (dest_byte_a == dest_byte_b);
+qtest_qmp_assert_success(to->qs, "{ 'execute' : 'stop'}");
 
-qtest_qmp_assert_success(to->qs, "{ 'execute' : 'stop'}");
-
-/* With it stopped, check nothing changes */
-qtest_memread(to->qs, to->start_address, &dest_byte_c, 1);
-usleep(1000 * 200);
-qtest_memread(to->qs, to->start_address, &dest_byte_d, 1);
-g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
-
-check_guests_ram(to);
-}
-
-guest_destroy(to);
+/* With it stopped, check nothing changes */
+qtest_memread(to->qs, to->start_address, &dest_byte_c, 1);
+usleep(1000 * 200);
+qtest_memread(to->qs, to->start_address, &dest_byte_d, 1);
+g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
+check_guests_ram(to);
 }
 
 #ifdef CONFIG_GNUTLS
@@ -1203,7 +1196,9 @@ static void migrate_postcopy_complete(GuestState *from, 
GuestState *to,
 args->postcopy_data = NULL;
 }
 
-test_migrate_end(from, to, true);
+guest_destroy(from);
+test_migrate_check(from, to);
+guest_destroy(to);
 }
 
 static void test_postcopy_common(GuestState *from, GuestState *to,
@@ -1399,7 +1394,8 @@ static void test_baddest(void)
  */
 migrate_qmp(from->qs, "tcp:127.0.0.1:0", "{}");
 wait_for_migration_fail(from->qs, false);
-test_migrate_end(from, to, false);
+guest_destroy(from);
+guest_destroy(to);
 }
 
 static void test_precopy_common(GuestState *from, GuestState *to,
@@ -1497,7 +1493,11 @@ static void test_precopy_common(GuestState *from, 
GuestState *to,
 args->finish_hook(from, to, data_hook);
 }
 
-test_migrate_end(from, to, args->result == MIG_TEST_SUCCEED);
+guest_destroy(from);
+if (args->result == MIG_TEST_SUCCEED) {
+test_migrate_check(from, to);
+}
+guest_destroy(to);
 }
 
 static void test_precopy_unix_plain(void)
@@ -1615,7 +1615,9 @@ static void test_ignore_shared(void)
 g_assert_cmpint(
 read_ram_property_int(from->qs, "transferred"), <, 1024 * 1024);
 
-test_migrate_end(from, to, true);
+guest_destroy(from);
+test_migrate_check(from, to);
+guest_destroy(to);
 }
 
 static void *
@@ -1925,7 +1927,8 @@ static void do_test_validate_uuid(GuestState *from, 
GuestState *to,
 wait_for_migration_complete(from->qs);
 }
 
-test_migrate_end(from, to, false);
+guest_destroy(from);
+guest_destroy(to);
 }
 
 static void test_validate_uuid(void)
@@ -2055,7 +2058,9 @@ static void test_migrate_auto_converge(void)
 wait_for_serial(to);
 wait_for_migration_complete(from->qs);
 
-test_migrate_end(from, to, true);
+guest_destroy(from);
+test_migrate_check(from, to);
+guest_destroy(to);
 }
 
 static void *
@@ -2374,7 +2379,9 @@ static void test_multifd_tcp_cancel(void)
 
 wait_for_serial(to2);
 wait_for_migration_complete(from->qs);
-test_migrate_end(from, to2, true);
+guest_destroy(from);
+test_migrate_check(from, to2);
+guest_destroy(to2);
 }
 
 static void calc_dirty_rate(QTestState *who, uint64_t calc_time)
-- 
2.40.1




[PATCH 22/42] migration-test: Create guest_use_dirty_log()

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 27 +++
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 9671c4c6e5..69a3728e4b 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -156,6 +156,7 @@ typedef struct {
 gchar *arch_opts;
 gchar *arch_source;
 gchar *arch_target;
+gchar *kvm_opts;
 const gchar *memory_size;
 const gchar *name;
 unsigned start_address;
@@ -208,9 +209,16 @@ static void guest_destroy(GuestState *vm)
 g_free(vm->arch_opts);
 g_free(vm->arch_source);
 g_free(vm->arch_target);
+g_free(vm->kvm_opts);
 g_free(vm);
 }
 
+static void guest_use_dirty_ring(GuestState *vm)
+{
+g_assert(vm->kvm_opts == NULL);
+vm->kvm_opts = g_strdup(",dirty-ring-size=4096");
+}
+
 /*
  * Wait for some output in the serial output file,
  * we get an 'A' followed by an endless string of 'B's
@@ -608,8 +616,6 @@ typedef struct {
 bool use_shmem;
 /* only launch the target process */
 bool only_target;
-/* Use dirty ring if true; dirty logging otherwise */
-bool use_dirty_ring;
 const char *opts_source;
 const char *opts_target;
 } MigrateStart;
@@ -708,7 +714,6 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
 const gchar *ignore_stderr = NULL;
 g_autofree char *shmem_opts = NULL;
 g_autofree char *shmem_path = NULL;
-const char *kvm_opts = NULL;
 
 got_src_stop = false;
 got_dst_resume = false;
@@ -733,16 +738,12 @@ static void test_migrate_start(GuestState *from, 
GuestState *to,
 from->memory_size, shmem_path);
 }
 
-if (args->use_dirty_ring) {
-kvm_opts = ",dirty-ring-size=4096";
-}
-
 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name %s,debug-threads=on "
  "-m %s "
  "-serial file:%s/src_serial "
  "%s %s %s %s %s",
- kvm_opts ? kvm_opts : "",
+ from->kvm_opts ? from->kvm_opts : "",
  from->name,
  from->memory_size, tmpfs,
  from->arch_opts ? from->arch_opts : "",
@@ -764,7 +765,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
  "-serial file:%s/dest_serial "
  "-incoming %s "
  "%s %s %s %s %s",
- kvm_opts ? kvm_opts : "",
+ to->kvm_opts ? to->kvm_opts : "",
  to->name,
  to->memory_size, tmpfs, uri,
  to->arch_opts ? to->arch_opts : "",
@@ -1555,9 +1556,6 @@ static void test_precopy_unix_dirty_ring(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.start = {
-.use_dirty_ring = true,
-},
 .listen_uri = uri,
 .connect_uri = uri,
 /*
@@ -1567,6 +1565,8 @@ static void test_precopy_unix_dirty_ring(void)
 .live = true,
 };
 
+guest_use_dirty_ring(from);
+guest_use_dirty_ring(to);
 test_precopy_common(from, to, &args);
 }
 
@@ -2588,6 +2588,9 @@ static int64_t get_limit_rate(QTestState *who)
 static GuestState *dirtylimit_start_vm(void)
 {
 GuestState *vm = guest_create("dirtylimit-test");
+
+guest_use_dirty_ring(vm);
+
 g_autofree gchar *
 cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 "
   "-name dirtylimit-test,debug-threads=on "
-- 
2.40.1




[PATCH 07/42] migration-test: Create kvm_opts

2023-06-08 Thread Juan Quintela
So arch_dirty_ring option becomes one option like the others.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index cd49c249d3..1fa815fa66 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -608,6 +608,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 g_autofree char *bootpath = NULL;
 g_autofree char *shmem_opts = NULL;
 g_autofree char *shmem_path = NULL;
+const char *kvm_opts = NULL;
 const char *arch = qtest_get_arch();
 const char *memory_size;
 
@@ -677,13 +678,16 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 memory_size, shmem_path);
 }
 
+if (args->use_dirty_ring) {
+kvm_opts = ",dirty-ring-size=4096";
+}
+
 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name source,debug-threads=on "
  "-m %s "
  "-serial file:%s/src_serial "
  "%s %s %s %s %s",
- args->use_dirty_ring ?
- ",dirty-ring-size=4096" : "",
+ kvm_opts ? kvm_opts : "",
  memory_size, tmpfs,
  arch_opts ? arch_opts : "",
  arch_source ? arch_source : "",
@@ -704,8 +708,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  "-serial file:%s/dest_serial "
  "-incoming %s "
  "%s %s %s %s %s",
- args->use_dirty_ring ?
- ",dirty-ring-size=4096" : "",
+ kvm_opts ? kvm_opts : "",
  memory_size, tmpfs, uri,
  arch_opts ? arch_opts : "",
  arch_target ? arch_target : "",
-- 
2.40.1




[PATCH 28/42] migration-test: Create guest_hide_stderr()

2023-06-08 Thread Juan Quintela
So we can handle in a single place all the error output handling.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 115 ---
 1 file changed, 54 insertions(+), 61 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b9b11ebb0f..c70b08e7db 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -157,6 +157,7 @@ typedef struct {
 gchar *arch_source;
 gchar *arch_target;
 const gchar *extra_opts;
+const gchar *hide_stderr;
 gchar *kvm_opts;
 const gchar *memory_size;
 /*
@@ -244,6 +245,23 @@ static void guest_use_shmem(GuestState *vm)
 vm->memory_size, vm->shmem_path);
 }
 
+static void guest_hide_stderr(GuestState *vm)
+{
+g_assert(vm->hide_stderr == NULL);
+
+ if (!getenv("QTEST_LOG")) {
+#ifndef _WIN32
+vm->hide_stderr = "2>/dev/null";
+#else
+/*
+ * On Windows the QEMU executable is created via CreateProcess() and
+ * IO redirection does not work, so don't bother adding IO redirection
+ * to the command line.
+ */
+#endif
+}
+}
+
 static void guest_extra_opts(GuestState *vm, const gchar *opts)
 {
 g_assert(vm->extra_opts == NULL);
@@ -640,11 +658,6 @@ static void do_migrate(GuestState *from, GuestState *to, 
const gchar *uri)
 }
 
 typedef struct {
-/*
- * QTEST_LOG=1 may override this.  When QTEST_LOG=1, we always dump errors
- * unconditionally, because it means the user would like to be verbose.
- */
-bool hide_stderr;
 /* only launch the target process */
 bool only_target;
 } MigrateStart;
@@ -740,23 +753,10 @@ static void test_migrate_start(GuestState *from, 
GuestState *to,
 {
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
-const gchar *ignore_stderr = NULL;
 
 got_src_stop = false;
 got_dst_resume = false;
 
-if (!getenv("QTEST_LOG") && args->hide_stderr) {
-#ifndef _WIN32
-ignore_stderr = "2>/dev/null";
-#else
-/*
- * On Windows the QEMU executable is created via CreateProcess() and
- * IO redirection does not work, so don't bother adding IO redirection
- * to the command line.
- */
-#endif
-}
-
 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name %s,debug-threads=on "
  "-m %s "
@@ -770,7 +770,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
  from->arch_source ? from->arch_source : "",
  from->shmem_opts ? from->shmem_opts : "",
  from->extra_opts ? from->extra_opts : "",
- ignore_stderr ? ignore_stderr : "");
+ from->hide_stderr ? from->hide_stderr : "");
 
 if (!args->only_target) {
 from->qs = qtest_init(cmd_source);
@@ -794,7 +794,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
  to->arch_target ? to->arch_target : "",
  to->shmem_opts ? to->shmem_opts : "",
  to->extra_opts ? to->extra_opts : "",
- ignore_stderr ? ignore_stderr : "");
+ to->hide_stderr ? to->hide_stderr : "");
 to->qs = qtest_init(cmd_target);
 qtest_qmp_set_event_callback(to->qs,
  migrate_watch_for_resume,
@@ -1323,8 +1323,8 @@ static void test_postcopy_recovery_common(MigrateCommon 
*args)
 g_autofree char *uri = NULL;
 
 /* Always hide errors for postcopy recover tests since they're expected */
-args->start.hide_stderr = true;
-
+guest_hide_stderr(from);
+guest_hide_stderr(to);
 migrate_postcopy_prepare(from, to, args);
 
 /* Turn postcopy speed down, 4K/s is slow enough on any machines */
@@ -1431,12 +1431,12 @@ static void test_postcopy_preempt_all(void)
 
 static void test_baddest(void)
 {
-MigrateStart args = {
-.hide_stderr = true
-};
+MigrateStart args = { };
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 
+guest_hide_stderr(from);
+guest_hide_stderr(to);
 test_migrate_start(from, to, "tcp:127.0.0.1:0", &args);
 /*
  * Don't change to do_migrate(). We are using a wrong uri on purpose.
@@ -1605,9 +1605,6 @@ static void test_precopy_unix_tls_x509_default_host(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.start = {
-.hide_stderr = true,
-},
 .connect_uri = uri,
 .listen_uri = uri,
 .start_hook = test_migrate_tls_x509_start_default_host,
@@ -1615,6 +1612,8 @@ static void test_precopy_unix_tls_x509_default_host(void)
 .result = MIG_TEST

[PATCH 11/42] migration-test: Update test_ignore_shared to use args

2023-06-08 Thread Juan Quintela
It missed this treatment:

commit 11f1a4ce14803f15d59cff42a4cfb7ac50d36bd0
Author: Juan Quintela 
Date:   Mon Nov 29 18:57:51 2021 +0100

migration-test: Check for shared memory like for everything else

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 743aa873e6..7178c8e679 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1597,8 +1597,11 @@ static void test_ignore_shared(void)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 QTestState *from, *to;
+MigrateStart args = {
+.use_shmem = true
+};
 
-if (test_migrate_start(&from, &to, uri, false, true, NULL, NULL)) {
+if (test_migrate_start(&from, &to, uri, &args)) {
 return;
 }
 
-- 
2.40.1




[PATCH 16/42] migration-test: Create do_migrate()

2023-06-08 Thread Juan Quintela
We called migrate_qmp() in lot of places.  And there are tricks like
changing tcp address with the right port.

Only two callers remaining:
- postcopy resume: It needs to play with the qmp.
- baddest: We want to do a unvalid URI. For that we need to do it by
  hand.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 41 ++--
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index e623c43957..96b495f255 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -528,6 +528,17 @@ static void migrate_postcopy_start(QTestState *from, 
QTestState *to)
 qtest_qmp_eventwait(to, "RESUME");
 }
 
+static void do_migrate(QTestState *from, QTestState *to, const gchar *uri)
+{
+if (!uri) {
+g_autofree char *tcp_uri =
+migrate_get_socket_address(to, "socket-address");
+migrate_qmp(from, tcp_uri, "{}");
+} else {
+migrate_qmp(from, uri, "{}");
+}
+}
+
 typedef struct {
 /*
  * QTEST_LOG=1 may override this.  When QTEST_LOG=1, we always dump errors
@@ -1173,7 +1184,7 @@ static void migrate_postcopy_prepare(QTestState 
**from_ptr,
 /* Wait for the first serial output from the source */
 wait_for_serial("src_serial");
 
-migrate_qmp(from, uri, "{}");
+do_migrate(from, to, uri);
 
 wait_for_migration_pass(from);
 
@@ -1378,6 +1389,9 @@ static void test_baddest(void)
 QTestState *from, *to;
 
 test_migrate_start(&from, &to, "tcp:127.0.0.1:0", &args);
+/*
+ * Don't change to do_migrate(). We are using a wrong uri on purpose.
+ */
 migrate_qmp(from, "tcp:127.0.0.1:0", "{}");
 wait_for_migration_fail(from, false);
 test_migrate_end(from, to, false);
@@ -1424,14 +1438,7 @@ static void test_precopy_common(MigrateCommon *args)
 }
 }
 
-if (!args->connect_uri) {
-g_autofree char *local_connect_uri =
-migrate_get_socket_address(to, "socket-address");
-migrate_qmp(from, local_connect_uri, "{}");
-} else {
-migrate_qmp(from, args->connect_uri, "{}");
-}
-
+do_migrate(from, to, args->connect_uri);
 
 if (args->result != MIG_TEST_SUCCEED) {
 bool allow_active = args->result == MIG_TEST_FAIL;
@@ -1586,7 +1593,7 @@ static void test_ignore_shared(void)
 /* Wait for the first serial output from the source */
 wait_for_serial("src_serial");
 
-migrate_qmp(from, uri, "{}");
+do_migrate(from, to, uri);
 
 wait_for_migration_pass(from);
 
@@ -1890,7 +1897,7 @@ static void do_test_validate_uuid(MigrateStart *args, 
bool should_fail)
 /* Wait for the first serial output from the source */
 wait_for_serial("src_serial");
 
-migrate_qmp(from, uri, "{}");
+do_migrate(from, to, uri);
 
 if (should_fail) {
 qtest_set_expected_status(to, EXIT_FAILURE);
@@ -1991,7 +1998,7 @@ static void test_migrate_auto_converge(void)
 /* Wait for the first serial output from the source */
 wait_for_serial("src_serial");
 
-migrate_qmp(from, uri, "{}");
+do_migrate(from, to, uri);
 
 /* Wait for throttling begins */
 percentage = 0;
@@ -2280,7 +2287,6 @@ static void test_multifd_tcp_cancel(void)
 .hide_stderr = true,
 };
 QTestState *from, *to, *to2;
-g_autofree char *uri = NULL;
 
 test_migrate_start(&from, &to, "defer", &args);
 
@@ -2299,9 +2305,7 @@ static void test_multifd_tcp_cancel(void)
 /* Wait for the first serial output from the source */
 wait_for_serial("src_serial");
 
-uri = migrate_get_socket_address(to, "socket-address");
-
-migrate_qmp(from, uri, "{}");
+do_migrate(from, to, "127.0.0.1:0");
 
 wait_for_migration_pass(from);
 
@@ -2325,14 +2329,11 @@ static void test_multifd_tcp_cancel(void)
 qtest_qmp_assert_success(to2, "{ 'execute': 'migrate-incoming',"
  "  'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
 
-g_free(uri);
-uri = migrate_get_socket_address(to2, "socket-address");
-
 wait_for_migration_status(from, "cancelled", NULL);
 
 migrate_ensure_converge(from);
 
-migrate_qmp(from, uri, "{}");
+do_migrate(from, to2, "127.0.0.1:0");
 
 wait_for_migration_pass(from);
 
-- 
2.40.1




[PATCH 15/42] migration-test: migrate_postcopy_prepare() always return 0

2023-06-08 Thread Juan Quintela
So make it return void.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 16 +---
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b57811da75..e623c43957 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1146,9 +1146,9 @@ test_migrate_compress_nowait_start(QTestState *from,
 return NULL;
 }
 
-static int migrate_postcopy_prepare(QTestState **from_ptr,
-QTestState **to_ptr,
-MigrateCommon *args)
+static void migrate_postcopy_prepare(QTestState **from_ptr,
+ QTestState **to_ptr,
+ MigrateCommon *args)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 QTestState *from, *to;
@@ -1179,8 +1179,6 @@ static int migrate_postcopy_prepare(QTestState **from_ptr,
 
 *from_ptr = from;
 *to_ptr = to;
-
-return 0;
 }
 
 static void migrate_postcopy_complete(QTestState *from, QTestState *to,
@@ -1207,9 +1205,7 @@ static void test_postcopy_common(MigrateCommon *args)
 {
 QTestState *from, *to;
 
-if (migrate_postcopy_prepare(&from, &to, args)) {
-return;
-}
+migrate_postcopy_prepare(&from, &to, args);
 migrate_postcopy_start(from, to);
 migrate_postcopy_complete(from, to, args);
 }
@@ -1270,9 +1266,7 @@ static void test_postcopy_recovery_common(MigrateCommon 
*args)
 /* Always hide errors for postcopy recover tests since they're expected */
 args->start.hide_stderr = true;
 
-if (migrate_postcopy_prepare(&from, &to, args)) {
-return;
-}
+migrate_postcopy_prepare(&from, &to, args);
 
 /* Turn postcopy speed down, 4K/s is slow enough on any machines */
 migrate_set_parameter_int(from, "max-postcopy-bandwidth", 4096);
-- 
2.40.1




[PATCH 30/42] migration-test: Hooks also need GuestState

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 198 +++
 1 file changed, 86 insertions(+), 112 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index a0ed8eb05a..6438379dcf 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -653,15 +653,16 @@ static void migrate_set_capability(QTestState *who, const 
char *capability,
  capability, value);
 }
 
-static void migrate_postcopy_start(QTestState *from, QTestState *to)
+static void migrate_postcopy_start(GuestState *from, GuestState *to)
 {
-qtest_qmp_assert_success(from, "{ 'execute': 'migrate-start-postcopy' }");
+qtest_qmp_assert_success(from->qs,
+ "{ 'execute': 'migrate-start-postcopy' }");
 
 if (!got_src_stop) {
-qtest_qmp_eventwait(from, "STOP");
+qtest_qmp_eventwait(from->qs, "STOP");
 }
 
-qtest_qmp_eventwait(to, "RESUME");
+qtest_qmp_eventwait(to->qs, "RESUME");
 }
 
 static void do_migrate(GuestState *from, GuestState *to, const gchar *uri)
@@ -688,8 +689,7 @@ typedef struct {
  * Returns: NULL, or a pointer to opaque state to be
  *  later passed to the TestMigrateFinishHook
  */
-typedef void * (*TestMigrateStartHook)(QTestState *from,
-   QTestState *to);
+typedef void * (*TestMigrateStartHook)(GuestState *from, GuestState *to);
 
 /*
  * A hook that runs after the migration has finished,
@@ -700,8 +700,7 @@ typedef void * (*TestMigrateStartHook)(QTestState *from,
  * @opaque is a pointer to state previously returned
  * by the TestMigrateStartHook if any, or NULL.
  */
-typedef void (*TestMigrateFinishHook)(QTestState *from,
-  QTestState *to,
+typedef void (*TestMigrateFinishHook)(GuestState *from, GuestState *to,
   void *opaque);
 
 typedef struct {
@@ -859,8 +858,7 @@ struct TestMigrateTLSPSKData {
 };
 
 static void *
-test_migrate_tls_psk_start_common(QTestState *from,
-  QTestState *to,
+test_migrate_tls_psk_start_common(GuestState *from, GuestState *to,
   bool mismatch)
 {
 struct TestMigrateTLSPSKData *data =
@@ -880,7 +878,7 @@ test_migrate_tls_psk_start_common(QTestState *from,
 test_tls_psk_init_alt(data->pskfilealt);
 }
 
-qtest_qmp_assert_success(from,
+qtest_qmp_assert_success(from->qs,
  "{ 'execute': 'object-add',"
  "  'arguments': { 'qom-type': 'tls-creds-psk',"
  " 'id': 'tlscredspsk0',"
@@ -889,7 +887,7 @@ test_migrate_tls_psk_start_common(QTestState *from,
  " 'username': 'qemu'} }",
  data->workdir);
 
-qtest_qmp_assert_success(to,
+qtest_qmp_assert_success(to->qs,
  "{ 'execute': 'object-add',"
  "  'arguments': { 'qom-type': 'tls-creds-psk',"
  " 'id': 'tlscredspsk0',"
@@ -897,30 +895,26 @@ test_migrate_tls_psk_start_common(QTestState *from,
  " 'dir': %s } }",
  mismatch ? data->workdiralt : data->workdir);
 
-migrate_set_parameter_str(from, "tls-creds", "tlscredspsk0");
-migrate_set_parameter_str(to, "tls-creds", "tlscredspsk0");
+migrate_set_parameter_str(from->qs, "tls-creds", "tlscredspsk0");
+migrate_set_parameter_str(to->qs, "tls-creds", "tlscredspsk0");
 
 return data;
 }
 
 static void *
-test_migrate_tls_psk_start_match(QTestState *from,
- QTestState *to)
+test_migrate_tls_psk_start_match(GuestState *from, GuestState *to)
 {
 return test_migrate_tls_psk_start_common(from, to, false);
 }
 
 static void *
-test_migrate_tls_psk_start_mismatch(QTestState *from,
-QTestState *to)
+test_migrate_tls_psk_start_mismatch(GuestState *from, GuestState *to)
 {
 return test_migrate_tls_psk_start_common(from, to, true);
 }
 
 static void
-test_migrate_tls_psk_finish(QTestState *from,
-QTestState *to,
-void *opaque)
+test_migrate_tls_psk_finish(GuestState *from, GuestState *to, void *opaque)
 {
 struct TestMigrateTLSPSKData *data = opaque;
 
@@ -961,8 +955,7 @@ typedef struct {
 } TestMigrateTLSX509;
 
 static void *
-test_migrate_tls_x509_start_common(QTestState *from,
-   QTestState *to,
+test_migrate_tls_x509_start_common(GuestState *from, GuestState *to,
TestMigrateTLSX509 *args)
 {
 TestMigrateTLSX509Data *data = g_new0(TestMigrateTLSX509Data, 1);
@@ -1008,7 +1001,7 @@ test_migrate_tls_x509_start_common(QTestState *from,

[PATCH 10/42] migration-test: dirtylimit checks for x86_64 arch before

2023-06-08 Thread Juan Quintela
So no need to assert we are in x86_64.
Once there, refactor the function to remove useless variables.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 613fda79bb..743aa873e6 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -2510,10 +2510,7 @@ static int64_t get_limit_rate(QTestState *who)
 static QTestState *dirtylimit_start_vm(void)
 {
 QTestState *vm = NULL;
-g_autofree gchar *cmd = NULL;
-const char *arch = qtest_get_arch();
-
-assert((strcmp(arch, "x86_64") == 0));
+g_autofree gchar *
 cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 "
   "-name dirtylimit-test,debug-threads=on "
   "-m 150M -smp 1 "
-- 
2.40.1




[PATCH 29/42] migration-test: Create the migration unix socket by guest

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 50 +++-
 1 file changed, 32 insertions(+), 18 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index c70b08e7db..a0ed8eb05a 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -168,6 +168,8 @@ typedef struct {
 gchar *serial_path;
 gchar *shmem_opts;
 gchar *shmem_path;
+gchar *unix_socket;
+gchar *uri;
 unsigned start_address;
 unsigned end_address;
 } GuestState;
@@ -224,6 +226,11 @@ static void guest_destroy(GuestState *vm)
 g_free(vm->shmem_opts);
 unlink(vm->shmem_path);
 g_free(vm->shmem_path);
+if (vm->unix_socket) {
+unlink(vm->unix_socket);
+g_free(vm->unix_socket);
+}
+g_free(vm->uri);
 g_free(vm);
 }
 
@@ -268,6 +275,17 @@ static void guest_extra_opts(GuestState *vm, const gchar 
*opts)
 vm->extra_opts = opts;
 }
 
+static void guest_listen_unix_socket(GuestState *vm)
+{
+if (vm->unix_socket) {
+unlink(vm->unix_socket);
+g_free(vm->unix_socket);
+}
+g_free(vm->uri);
+vm->unix_socket = g_strdup_printf("%s/migsocket", tmpfs);
+vm->uri = g_strdup_printf("unix:%s", vm->unix_socket);
+}
+
 /*
  * Wait for some output in the serial output file,
  * we get an 'A' followed by an endless string of 'B's
@@ -789,7 +807,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
  to->name,
  to->memory_size,
  to->serial_path,
- uri,
+ to->uri ? to->uri : uri,
  to->arch_opts ? to->arch_opts : "",
  to->arch_target ? to->arch_target : "",
  to->shmem_opts ? to->shmem_opts : "",
@@ -1202,9 +1220,8 @@ static void migrate_postcopy_prepare(GuestState *from,
  GuestState *to,
  MigrateCommon *args)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
-
-test_migrate_start(from, to, uri, &args->start);
+guest_listen_unix_socket(to);
+test_migrate_start(from, to, NULL, &args->start);
 
 if (args->start_hook) {
 args->postcopy_data = args->start_hook(from->qs, to->qs);
@@ -1224,7 +1241,7 @@ static void migrate_postcopy_prepare(GuestState *from,
 /* Wait for the first serial output from the source */
 wait_for_serial(from);
 
-do_migrate(from, to, uri);
+do_migrate(from, to, to->uri);
 
 wait_for_migration_pass(from->qs);
 }
@@ -1320,8 +1337,6 @@ static void test_postcopy_recovery_common(MigrateCommon 
*args)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 
-g_autofree char *uri = NULL;
-
 /* Always hide errors for postcopy recover tests since they're expected */
 guest_hide_stderr(from);
 guest_hide_stderr(to);
@@ -1359,8 +1374,8 @@ static void test_postcopy_recovery_common(MigrateCommon 
*args)
  * from the broken migration channel; tell the destination to
  * listen to the new port
  */
-uri = g_strdup_printf("unix:%s/migsocket-recover", tmpfs);
-migrate_recover(to->qs, uri);
+guest_listen_unix_socket(to);
+migrate_recover(to->qs, to->uri);
 
 /*
  * Try to rebuild the migration channel using the resume flag and
@@ -1369,7 +1384,7 @@ static void test_postcopy_recovery_common(MigrateCommon 
*args)
 wait_for_migration_status(from->qs, "postcopy-paused",
   (const char * []) { "failed", "active",
   "completed", NULL });
-migrate_qmp(from->qs, uri, "{'resume': true}");
+migrate_qmp(from->qs, to->uri, "{'resume': true}");
 
 /* Restore the postcopy bandwidth to unlimited */
 migrate_set_parameter_int(from->qs, "max-postcopy-bandwidth", 0);
@@ -1651,7 +1666,7 @@ static void test_ignore_shared(void)
 /* Wait for the first serial output from the source */
 wait_for_serial(from);
 
-do_migrate(from, to, uri);
+do_migrate(from, to, to->uri);
 
 wait_for_migration_pass(from->qs);
 
@@ -1965,9 +1980,8 @@ static void test_migrate_fd_proto(void)
 static void do_test_validate_uuid(GuestState *from, GuestState *to,
   MigrateStart *args, bool should_fail)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
-
-test_migrate_start(from, to, uri, args);
+guest_listen_unix_socket(to);
+test_migrate_start(from, to, NULL, args);
 
 /*
  * UUID validation is at the begin of migration. So, the main process of
@@ -1980,7 +1994,7 @@ static void do_test_validate_uuid(GuestState *from, 
GuestState *to,
 /* Wait for the first serial output from the source */
 wait_for_serial(fro

[PATCH 09/42] migration-test: Add bootfile_create/delete() functions

2023-06-08 Thread Juan Quintela
The bootsector code is read only from the guest (otherwise we are
going to have problems with it being read from both source and
destination).

Create a single copy for all the tests.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 50 ++--
 1 file changed, 36 insertions(+), 14 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 6453216e4e..613fda79bb 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -111,14 +111,47 @@ static char *bootpath;
 #include "tests/migration/aarch64/a-b-kernel.h"
 #include "tests/migration/s390x/a-b-bios.h"
 
-static void init_bootfile(void *content, size_t len)
+static void bootfile_create(char *dir)
 {
+const char *arch = qtest_get_arch();
+unsigned char *content;
+size_t len;
+
+bootpath = g_strdup_printf("%s/bootsect", dir);
+if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+/* the assembled x86 boot sector should be exactly one sector large */
+g_assert(sizeof(x86_bootsect) == 512);
+content = x86_bootsect;
+len = sizeof(x86_bootsect);
+} else if (g_str_equal(arch, "s390x")) {
+content = s390x_elf;
+len = sizeof(s390x_elf);
+} else if (strcmp(arch, "ppc64") == 0) {
+/*
+ * sane architectures can be programmed at the boot prompt
+ */
+return;
+} else if (strcmp(arch, "aarch64") == 0) {
+content = aarch64_kernel;
+len = sizeof(aarch64_kernel);
+g_assert(sizeof(aarch64_kernel) <= ARM_TEST_MAX_KERNEL_SIZE);
+} else {
+g_assert_not_reached();
+}
+
 FILE *bootfile = fopen(bootpath, "wb");
 
 g_assert_cmpint(fwrite(content, len, 1, bootfile), ==, 1);
 fclose(bootfile);
 }
 
+static void bootfile_delete(void)
+{
+unlink(bootpath);
+g_free(bootpath);
+bootpath = NULL;
+}
+
 /*
  * Wait for some output in the serial output file,
  * we get an 'A' followed by an endless string of 'B's
@@ -622,15 +655,11 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 got_src_stop = false;
 got_dst_resume = false;
 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
-/* the assembled x86 boot sector should be exactly one sector large */
-assert(sizeof(x86_bootsect) == 512);
-init_bootfile(x86_bootsect, sizeof(x86_bootsect));
 memory_size = "150M";
 arch_opts = g_strdup_printf("-drive file=%s,format=raw", bootpath);
 start_address = X86_TEST_MEM_START;
 end_address = X86_TEST_MEM_END;
 } else if (g_str_equal(arch, "s390x")) {
-init_bootfile(s390x_elf, sizeof(s390x_elf));
 memory_size = "128M";
 arch_opts = g_strdup_printf("-bios %s", bootpath);
 start_address = S390_TEST_MEM_START;
@@ -645,14 +674,11 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
   "until'", end_address, start_address);
 arch_opts = g_strdup("-nodefaults -machine vsmt=8");
 } else if (strcmp(arch, "aarch64") == 0) {
-init_bootfile(aarch64_kernel, sizeof(aarch64_kernel));
 memory_size = "150M";
 arch_opts = g_strdup_printf("-machine virt,gic-version=max -cpu max "
 "-kernel %s", bootpath);
 start_address = ARM_TEST_MEM_START;
 end_address = ARM_TEST_MEM_END;
-
-g_assert(sizeof(aarch64_kernel) <= ARM_TEST_MAX_KERNEL_SIZE);
 } else {
 g_assert_not_reached();
 }
@@ -2488,9 +2514,6 @@ static QTestState *dirtylimit_start_vm(void)
 const char *arch = qtest_get_arch();
 
 assert((strcmp(arch, "x86_64") == 0));
-assert(sizeof(x86_bootsect) == 512);
-init_bootfile(x86_bootsect, sizeof(x86_bootsect));
-
 cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 "
   "-name dirtylimit-test,debug-threads=on "
   "-m 150M -smp 1 "
@@ -2666,7 +2689,7 @@ int main(int argc, char **argv)
g_get_tmp_dir(), err->message);
 }
 g_assert(tmpfs);
-bootpath = g_strdup_printf("%s/bootsect", tmpfs);
+bootfile_create(tmpfs);
 
 module_call_init(MODULE_INIT_QOM);
 
@@ -2810,8 +2833,7 @@ int main(int argc, char **argv)
 
 g_assert_cmpint(ret, ==, 0);
 
-cleanup("bootsect");
-g_free(bootpath);
+bootfile_delete();
 ret = rmdir(tmpfs);
 if (ret != 0) {
 g_test_message("unable to rmdir: path (%s): %s",
-- 
2.40.1




[PATCH 08/42] migration-test: bootpath is the same for all tests and for all archs

2023-06-08 Thread Juan Quintela
So just make it a global variable.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 1fa815fa66..6453216e4e 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -102,6 +102,7 @@ static bool ufd_version_check(void)
 #endif
 
 static char *tmpfs;
+static char *bootpath;
 
 /* The boot file modifies memory area in [start_address, end_address)
  * repeatedly. It outputs a 'B' at a fixed rate while it's still running.
@@ -110,7 +111,7 @@ static char *tmpfs;
 #include "tests/migration/aarch64/a-b-kernel.h"
 #include "tests/migration/s390x/a-b-bios.h"
 
-static void init_bootfile(const char *bootpath, void *content, size_t len)
+static void init_bootfile(void *content, size_t len)
 {
 FILE *bootfile = fopen(bootpath, "wb");
 
@@ -605,7 +606,6 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
 const gchar *ignore_stderr = NULL;
-g_autofree char *bootpath = NULL;
 g_autofree char *shmem_opts = NULL;
 g_autofree char *shmem_path = NULL;
 const char *kvm_opts = NULL;
@@ -621,17 +621,16 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 
 got_src_stop = false;
 got_dst_resume = false;
-bootpath = g_strdup_printf("%s/bootsect", tmpfs);
 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
 /* the assembled x86 boot sector should be exactly one sector large */
 assert(sizeof(x86_bootsect) == 512);
-init_bootfile(bootpath, x86_bootsect, sizeof(x86_bootsect));
+init_bootfile(x86_bootsect, sizeof(x86_bootsect));
 memory_size = "150M";
 arch_opts = g_strdup_printf("-drive file=%s,format=raw", bootpath);
 start_address = X86_TEST_MEM_START;
 end_address = X86_TEST_MEM_END;
 } else if (g_str_equal(arch, "s390x")) {
-init_bootfile(bootpath, s390x_elf, sizeof(s390x_elf));
+init_bootfile(s390x_elf, sizeof(s390x_elf));
 memory_size = "128M";
 arch_opts = g_strdup_printf("-bios %s", bootpath);
 start_address = S390_TEST_MEM_START;
@@ -646,7 +645,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
   "until'", end_address, start_address);
 arch_opts = g_strdup("-nodefaults -machine vsmt=8");
 } else if (strcmp(arch, "aarch64") == 0) {
-init_bootfile(bootpath, aarch64_kernel, sizeof(aarch64_kernel));
+init_bootfile(aarch64_kernel, sizeof(aarch64_kernel));
 memory_size = "150M";
 arch_opts = g_strdup_printf("-machine virt,gic-version=max -cpu max "
 "-kernel %s", bootpath);
@@ -759,7 +758,6 @@ static void test_migrate_end(QTestState *from, QTestState 
*to, bool test_dest)
 
 qtest_quit(to);
 
-cleanup("bootsect");
 cleanup("migsocket");
 cleanup("src_serial");
 cleanup("dest_serial");
@@ -2488,12 +2486,10 @@ static QTestState *dirtylimit_start_vm(void)
 QTestState *vm = NULL;
 g_autofree gchar *cmd = NULL;
 const char *arch = qtest_get_arch();
-g_autofree char *bootpath = NULL;
 
 assert((strcmp(arch, "x86_64") == 0));
-bootpath = g_strdup_printf("%s/bootsect", tmpfs);
 assert(sizeof(x86_bootsect) == 512);
-init_bootfile(bootpath, x86_bootsect, sizeof(x86_bootsect));
+init_bootfile(x86_bootsect, sizeof(x86_bootsect));
 
 cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 "
   "-name dirtylimit-test,debug-threads=on "
@@ -2509,7 +2505,6 @@ static QTestState *dirtylimit_start_vm(void)
 static void dirtylimit_stop_vm(QTestState *vm)
 {
 qtest_quit(vm);
-cleanup("bootsect");
 cleanup("vm_serial");
 }
 
@@ -2671,6 +2666,7 @@ int main(int argc, char **argv)
g_get_tmp_dir(), err->message);
 }
 g_assert(tmpfs);
+bootpath = g_strdup_printf("%s/bootsect", tmpfs);
 
 module_call_init(MODULE_INIT_QOM);
 
@@ -2814,6 +2810,8 @@ int main(int argc, char **argv)
 
 g_assert_cmpint(ret, ==, 0);
 
+cleanup("bootsect");
+g_free(bootpath);
 ret = rmdir(tmpfs);
 if (ret != 0) {
 g_test_message("unable to rmdir: path (%s): %s",
-- 
2.40.1




[PATCH 35/42] migration-test: Set uri for tcp tests with guest_set_uri()

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 76a5f8d353..8d497d0940 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1423,7 +1423,8 @@ static void test_baddest(void)
 
 guest_hide_stderr(from);
 guest_hide_stderr(to);
-test_migrate_start(from, to, "tcp:127.0.0.1:0", &args);
+guest_set_uri(to, "tcp:127.0.0.1:0");
+test_migrate_start(from, to, NULL, &args);
 /*
  * Don't change to do_migrate(). We are using a wrong uri on purpose.
  */
@@ -1722,10 +1723,9 @@ static void test_precopy_tcp_plain(void)
 {
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
-MigrateCommon args = {
-.listen_uri = "tcp:127.0.0.1:0",
-};
+MigrateCommon args = { };
 
+guest_set_uri(to, "tcp:127.0.0.1:0");
 test_precopy_common(from, to, &args);
 }
 
@@ -1735,11 +1735,11 @@ static void test_precopy_tcp_tls_psk_match(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "tcp:127.0.0.1:0",
 .start_hook = test_migrate_tls_psk_start_match,
 .finish_hook = test_migrate_tls_psk_finish,
 };
 
+guest_set_uri(to, "tcp:127.0.0.1:0");
 test_precopy_common(from, to, &args);
 }
 
@@ -1748,7 +1748,6 @@ static void test_precopy_tcp_tls_psk_mismatch(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "tcp:127.0.0.1:0",
 .start_hook = test_migrate_tls_psk_start_mismatch,
 .finish_hook = test_migrate_tls_psk_finish,
 .result = MIG_TEST_FAIL,
@@ -1756,6 +1755,7 @@ static void test_precopy_tcp_tls_psk_mismatch(void)
 
 guest_hide_stderr(from);
 guest_hide_stderr(to);
+guest_set_uri(to, "tcp:127.0.0.1:0");
 test_precopy_common(from, to, &args);
 }
 
@@ -1765,11 +1765,11 @@ static void test_precopy_tcp_tls_x509_default_host(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "tcp:127.0.0.1:0",
 .start_hook = test_migrate_tls_x509_start_default_host,
 .finish_hook = test_migrate_tls_x509_finish,
 };
 
+guest_set_uri(to, "tcp:127.0.0.1:0");
 test_precopy_common(from, to, &args);
 }
 
@@ -1778,11 +1778,11 @@ static void 
test_precopy_tcp_tls_x509_override_host(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "tcp:127.0.0.1:0",
 .start_hook = test_migrate_tls_x509_start_override_host,
 .finish_hook = test_migrate_tls_x509_finish,
 };
 
+guest_set_uri(to, "tcp:127.0.0.1:0");
 test_precopy_common(from, to, &args);
 }
 
@@ -1791,7 +1791,6 @@ static void test_precopy_tcp_tls_x509_mismatch_host(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "tcp:127.0.0.1:0",
 .start_hook = test_migrate_tls_x509_start_mismatch_host,
 .finish_hook = test_migrate_tls_x509_finish,
 .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
@@ -1799,6 +1798,7 @@ static void test_precopy_tcp_tls_x509_mismatch_host(void)
 
 guest_hide_stderr(from);
 guest_hide_stderr(to);
+guest_set_uri(to, "tcp:127.0.0.1:0");
 test_precopy_common(from, to, &args);
 }
 
@@ -1807,11 +1807,11 @@ static void 
test_precopy_tcp_tls_x509_friendly_client(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "tcp:127.0.0.1:0",
 .start_hook = test_migrate_tls_x509_start_friendly_client,
 .finish_hook = test_migrate_tls_x509_finish,
 };
 
+guest_set_uri(to, "tcp:127.0.0.1:0");
 test_precopy_common(from, to, &args);
 }
 
@@ -1820,7 +1820,6 @@ static void test_precopy_tcp_tls_x509_hostile_client(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = "tcp:127.0.0.1:0",
 .start_hook = test_migrate_tls_x509_start_hostile_client,
 .finish_hook = test_migrate_tls_x509_finish,
 .result = MIG_TEST_FAIL,
@@ -1828,6 +1827,7 @@ static void test_precopy_tcp_tls_x509_hostile_client(void)
 
 guest_hide_stderr(from);
 guest_hide_stderr(to);
+guest_set_uri(to, "tcp:127.0.0.1:0");
 test_precopy_common(from, to, &args);
 }
 
@@ -1836,11 +1836,11 @@ static void 
test_precopy_tcp_tls_x509_allow_anon_client(void)
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-

[PATCH 37/42] migration-test: Create get_event GuestState variable

2023-06-08 Thread Juan Quintela
So we don't use a global variable for events.  We use one by guest.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 48 +---
 1 file changed, 22 insertions(+), 26 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 95b7c9ed73..a96eb3eec7 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -41,8 +41,6 @@
 #endif
 
 static bool uffd_feature_thread_id;
-static bool got_src_stop;
-static bool got_dst_resume;
 
 /*
  * Dirtylimit stop working if dirty page rate error
@@ -172,6 +170,7 @@ typedef struct {
 gchar *uri;
 unsigned start_address;
 unsigned end_address;
+bool got_event;
 } GuestState;
 
 static GuestState *guest_create(const char *name)
@@ -396,21 +395,21 @@ static void read_blocktime(QTestState *who)
 qobject_unref(rsp_return);
 }
 
-static void wait_for_migration_pass(QTestState *who)
+static void wait_for_migration_pass(GuestState *who)
 {
-uint64_t initial_pass = get_migration_pass(who);
+uint64_t initial_pass = get_migration_pass(who->qs);
 uint64_t pass;
 
 /* Wait for the 1st sync */
-while (!got_src_stop && !initial_pass) {
+while (!who->got_event && !initial_pass) {
 usleep(1000);
-initial_pass = get_migration_pass(who);
+initial_pass = get_migration_pass(who->qs);
 }
 
 do {
 usleep(1000);
-pass = get_migration_pass(who);
-} while (pass == initial_pass && !got_src_stop);
+pass = get_migration_pass(who->qs);
+} while (pass == initial_pass && !who->got_event);
 }
 
 static void check_guests_ram(GuestState *who)
@@ -657,7 +656,7 @@ static void migrate_postcopy_start(GuestState *from, 
GuestState *to)
 qtest_qmp_assert_success(from->qs,
  "{ 'execute': 'migrate-start-postcopy' }");
 
-if (!got_src_stop) {
+if (!from->got_event) {
 qtest_qmp_eventwait(from->qs, "STOP");
 }
 
@@ -759,9 +758,6 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
 
-got_src_stop = false;
-got_dst_resume = false;
-
 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name %s,debug-threads=on "
  "-m %s "
@@ -781,7 +777,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
 from->qs = qtest_init(cmd_source);
 qtest_qmp_set_event_callback(from->qs,
  migrate_watch_for_stop,
- &got_src_stop);
+ &from->got_event);
 }
 
 cmd_target = g_strdup_printf("-accel kvm%s -accel tcg "
@@ -803,7 +799,7 @@ static void test_migrate_start(GuestState *from, GuestState 
*to,
 to->qs = qtest_init(cmd_target);
 qtest_qmp_set_event_callback(to->qs,
  migrate_watch_for_resume,
- &got_dst_resume);
+ &to->got_event);
 }
 
 static void test_migrate_end(GuestState *from, GuestState *to, bool test_dest)
@@ -1211,7 +1207,7 @@ static void migrate_postcopy_prepare(GuestState *from,
 
 do_migrate(from, to);
 
-wait_for_migration_pass(from->qs);
+wait_for_migration_pass(from);
 }
 
 static void migrate_postcopy_complete(GuestState *from, GuestState *to,
@@ -1464,7 +1460,7 @@ static void test_precopy_common(GuestState *from, 
GuestState *to,
  */
 if (args->result == MIG_TEST_SUCCEED) {
 qtest_qmp_assert_success(from->qs, "{ 'execute' : 'stop'}");
-if (!got_src_stop) {
+if (!from->got_event) {
 qtest_qmp_eventwait(from->qs, "STOP");
 }
 migrate_ensure_converge(from->qs);
@@ -1484,10 +1480,10 @@ static void test_precopy_common(GuestState *from, 
GuestState *to,
 if (args->live) {
 if (args->iterations) {
 while (args->iterations--) {
-wait_for_migration_pass(from->qs);
+wait_for_migration_pass(from);
 }
 } else {
-wait_for_migration_pass(from->qs);
+wait_for_migration_pass(from);
 }
 
 migrate_ensure_converge(from->qs);
@@ -1498,7 +1494,7 @@ static void test_precopy_common(GuestState *from, 
GuestState *to,
  */
 wait_for_migration_complete(from->qs);
 
-if (!got_src_stop) {
+if (!from->got_event) {
 qtest_qmp_eventwait(from->qs, "STOP");
 }
 } else {
@@ -1513,7 +1509,7 @@ static void test_precopy_common(GuestState *from, 
GuestState *to,
 qtest_qmp_assert_success(to->qs, "{ 'execute' : 'cont'}");
 }
 
-if (!got_dst_resume) {
+if (!to->got_event) {
 qtest_qmp_ev

[PATCH 23/42] migration-test: Move serial to GuestState

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 65 
 1 file changed, 37 insertions(+), 28 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 69a3728e4b..01ab51a391 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -158,7 +158,12 @@ typedef struct {
 gchar *arch_target;
 gchar *kvm_opts;
 const gchar *memory_size;
+/*
+ * name must *not* contain "target" if it is the target of a
+ * migration.
+ */
 const gchar *name;
+gchar *serial_path;
 unsigned start_address;
 unsigned end_address;
 } GuestState;
@@ -199,7 +204,7 @@ static GuestState *guest_create(const char *name)
 }
 
 vm->name = name;
-
+vm->serial_path = g_strdup_printf("%s/%s", tmpfs, vm->name);
 return vm;
 }
 
@@ -210,6 +215,8 @@ static void guest_destroy(GuestState *vm)
 g_free(vm->arch_source);
 g_free(vm->arch_target);
 g_free(vm->kvm_opts);
+unlink(vm->serial_path);
+g_free(vm->serial_path);
 g_free(vm);
 }
 
@@ -224,12 +231,12 @@ static void guest_use_dirty_ring(GuestState *vm)
  * we get an 'A' followed by an endless string of 'B's
  * but on the destination we won't have the A.
  */
-static void wait_for_serial(const char *side)
+static void wait_for_serial(GuestState *vm)
 {
-g_autofree char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
-FILE *serialfile = fopen(serialpath, "r");
+FILE *serialfile = fopen(vm->serial_path, "r");
 const char *arch = qtest_get_arch();
-int started = (strcmp(side, "src_serial") == 0 &&
+/* see serial_path comment on GuestState definition */
+int started = (strstr(vm->serial_path, "target") == NULL &&
strcmp(arch, "ppc64") == 0) ? 0 : 1;
 
 do {
@@ -262,14 +269,15 @@ static void wait_for_serial(const char *side)
 return;
 
 case EOF:
-started = (strcmp(side, "src_serial") == 0 &&
+started = (strstr(vm->serial_path, "target") == NULL &&
strcmp(arch, "ppc64") == 0) ? 0 : 1;
 fseek(serialfile, 0, SEEK_SET);
 usleep(1000);
 break;
 
 default:
-fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
+fprintf(stderr, "Unexpected %d on %s serial\n", readvalue,
+vm->serial_path);
 g_assert_not_reached();
 }
 } while (true);
@@ -741,11 +749,12 @@ static void test_migrate_start(GuestState *from, 
GuestState *to,
 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name %s,debug-threads=on "
  "-m %s "
- "-serial file:%s/src_serial "
+ "-serial file:%s "
  "%s %s %s %s %s",
  from->kvm_opts ? from->kvm_opts : "",
  from->name,
- from->memory_size, tmpfs,
+ from->memory_size,
+ from->serial_path,
  from->arch_opts ? from->arch_opts : "",
  from->arch_source ? from->arch_source : "",
  shmem_opts ? shmem_opts : "",
@@ -762,12 +771,14 @@ static void test_migrate_start(GuestState *from, 
GuestState *to,
 cmd_target = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name %s,debug-threads=on "
  "-m %s "
- "-serial file:%s/dest_serial "
+ "-serial file:%s "
  "-incoming %s "
  "%s %s %s %s %s",
  to->kvm_opts ? to->kvm_opts : "",
  to->name,
- to->memory_size, tmpfs, uri,
+ to->memory_size,
+ to->serial_path,
+ uri,
  to->arch_opts ? to->arch_opts : "",
  to->arch_target ? to->arch_target : "",
  shmem_opts ? shmem_opts : "",
@@ -816,8 +827,6 @@ static void test_migrate_end(GuestState *from, GuestState 
*to, bool test_dest)
 guest_destroy(to);
 
 cleanup("migsocket");
-cleanup("src_serial");
-cleanup("dest_serial");
 }
 
 #ifdef CONFIG_GNUTLS
@@ -1210,7 +1219,7 @@ static void migrate_postcopy_prepare(GuestState *from,
 migrate_ensure_non_converge(from->qs);
 
 /* Wait for the first serial output from the source */
-wait_for_serial("src_serial");
+wait_for_serial(from);
 
 do_migrate(from, to, uri);
 
@@ -1223,7 +1232,7 @@ static void migrate_postcop

[PATCH 34/42] migration-test: Use new schema for all tests that use unix sockets

2023-06-08 Thread Juan Quintela
Once there we can remove the now unused cleanup() function.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 39 ++--
 1 file changed, 11 insertions(+), 28 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 3b1b76fe6f..76a5f8d353 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -462,13 +462,6 @@ static void check_guests_ram(GuestState *who)
 g_assert(bad == 0);
 }
 
-static void cleanup(const char *filename)
-{
-g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, filename);
-
-unlink(path);
-}
-
 static char *SocketAddress_to_str(SocketAddress *addr)
 {
 switch (addr->type) {
@@ -843,8 +836,6 @@ static void test_migrate_end(GuestState *from, GuestState 
*to, bool test_dest)
 }
 
 guest_destroy(to);
-
-cleanup("migsocket");
 }
 
 #ifdef CONFIG_GNUTLS
@@ -1540,11 +1531,9 @@ static void test_precopy_common(GuestState *from, 
GuestState *to,
 
 static void test_precopy_unix_plain(void)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = uri,
 /*
  * The simplest use case of precopy, covering smoke tests of
  * get-dirty-log dirty tracking.
@@ -1552,17 +1541,16 @@ static void test_precopy_unix_plain(void)
 .live = true,
 };
 
+guest_listen_unix_socket(to);
 test_precopy_common(from, to, &args);
 }
 
 
 static void test_precopy_unix_dirty_ring(void)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = uri,
 /*
  * Besides the precopy/unix basic test, cover dirty ring interface
  * rather than get-dirty-log.
@@ -1572,32 +1560,30 @@ static void test_precopy_unix_dirty_ring(void)
 
 guest_use_dirty_ring(from);
 guest_use_dirty_ring(to);
+guest_listen_unix_socket(to);
 test_precopy_common(from, to, &args);
 }
 
 #ifdef CONFIG_GNUTLS
 static void test_precopy_unix_tls_psk(void)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = uri,
 .start_hook = test_migrate_tls_psk_start_match,
 .finish_hook = test_migrate_tls_psk_finish,
 };
 
+guest_listen_unix_socket(to);
 test_precopy_common(from, to, &args);
 }
 
 #ifdef CONFIG_TASN1
 static void test_precopy_unix_tls_x509_default_host(void)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = uri,
 .start_hook = test_migrate_tls_x509_start_default_host,
 .finish_hook = test_migrate_tls_x509_finish,
 .result = MIG_TEST_FAIL_DEST_QUIT_ERR,
@@ -1605,20 +1591,20 @@ static void 
test_precopy_unix_tls_x509_default_host(void)
 
 guest_hide_stderr(from);
 guest_hide_stderr(to);
+guest_listen_unix_socket(to);
 test_precopy_common(from, to, &args);
 }
 
 static void test_precopy_unix_tls_x509_override_host(void)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = uri,
 .start_hook = test_migrate_tls_x509_start_override_host,
 .finish_hook = test_migrate_tls_x509_finish,
 };
 
+guest_listen_unix_socket(to);
 test_precopy_common(from, to, &args);
 }
 #endif /* CONFIG_TASN1 */
@@ -1626,14 +1612,14 @@ static void 
test_precopy_unix_tls_x509_override_host(void)
 
 static void test_ignore_shared(void)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateStart args = { };
 
 guest_use_shmem(from);
 guest_use_shmem(to);
-test_migrate_start(from, to, uri, &args);
+guest_listen_unix_socket(to);
+test_migrate_start(from, to, NULL, &args);
 
 migrate_set_capability(from->qs, "x-ignore-shared", true);
 migrate_set_capability(to->qs, "x-ignore-shared", true);
@@ -1674,11 +1660,9 @@ test_migrate_xbzrle_start(GuestState *from, GuestState 
*to)
 
 static void test_precopy_unix_xbzrle(void)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 GuestState *from = guest_create("source");
 GuestState *to = guest_create("target");
 MigrateCommon args = {
-.listen_uri = uri,
 .start_hook = test_migrate_xbzrle_start,
 .iterations = 2,
  

[PATCH 24/42] migration-test: Re-enable multifd_cancel test

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 01ab51a391..9f86d9bc80 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -2886,14 +2886,8 @@ int main(int argc, char **argv)
 }
 qtest_add_func("/migration/multifd/tcp/plain/none",
test_multifd_tcp_none);
-/*
- * This test is flaky and sometimes fails in CI and otherwise:
- * don't run unless user opts in via environment variable.
- */
-if (getenv("QEMU_TEST_FLAKY_TESTS")) {
-qtest_add_func("/migration/multifd/tcp/plain/cancel",
-   test_multifd_tcp_cancel);
-}
+qtest_add_func("/migration/multifd/tcp/plain/cancel",
+   test_multifd_tcp_cancel);
 qtest_add_func("/migration/multifd/tcp/plain/zlib",
test_multifd_tcp_zlib);
 #ifdef CONFIG_ZSTD
-- 
2.40.1




[PATCH 32/42] migration-test: Create guest_set_uri()

2023-06-08 Thread Juan Quintela
We need this for migration-incoming cases.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 0afe871cfb..f029258f67 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -286,6 +286,12 @@ static void guest_listen_unix_socket(GuestState *vm)
 vm->uri = g_strdup_printf("unix:%s", vm->unix_socket);
 }
 
+static void guest_set_uri(GuestState *vm, const gchar *uri)
+{
+g_free(vm->uri);
+vm->uri = g_strdup(uri);
+}
+
 /*
  * Wait for some output in the serial output file,
  * we get an 'A' followed by an endless string of 'B's
@@ -1918,6 +1924,7 @@ static void *test_migrate_fd_start_hook(GuestState *from, 
GuestState *to)
 /* Start incoming migration from the 1st socket */
 qtest_qmp_assert_success(to->qs, "{ 'execute': 'migrate-incoming',"
  "  'arguments': { 'uri': 'fd:fd-mig' }}");
+guest_set_uri(to, "fd:fd-mig");
 
 /* Send the 2nd socket to the target */
 qtest_qmp_fds_assert_success(from->qs, &pair[1], 1,
@@ -1958,7 +1965,6 @@ static void test_migrate_fd_proto(void)
 GuestState *to = guest_create("target");
 MigrateCommon args = {
 .listen_uri = "defer",
-.connect_uri = "fd:fd-mig",
 .start_hook = test_migrate_fd_start_hook,
 .finish_hook = test_migrate_fd_finish_hook
 };
@@ -2145,6 +2151,7 @@ test_migrate_precopy_tcp_multifd_start_common(GuestState 
*from, GuestState *to,
 /* Start incoming migration from the 1st socket */
 qtest_qmp_assert_success(to->qs, "{ 'execute': 'migrate-incoming',"
  "  'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
+guest_set_uri(to, "tcp:127.0.0.1:0");
 
 return NULL;
 }
@@ -2411,6 +2418,7 @@ static void test_multifd_tcp_cancel(void)
 /* Start incoming migration from the 1st socket */
 qtest_qmp_assert_success(to->qs, "{ 'execute': 'migrate-incoming',"
  "  'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
+guest_set_uri(to, "tcp:127.0.0.1:0");
 
 /* Wait for the first serial output from the source */
 wait_for_serial(from);
@@ -2440,6 +2448,7 @@ static void test_multifd_tcp_cancel(void)
 /* Start incoming migration from the 1st socket */
 qtest_qmp_assert_success(to2->qs, "{ 'execute': 'migrate-incoming',"
  "  'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
+guest_set_uri(to2, "tcp:127.0.0.1:0");
 
 wait_for_migration_status(from->qs, "cancelled", NULL);
 
-- 
2.40.1




[PATCH 17/42] migration-test: Introduce GuestState

2023-06-08 Thread Juan Quintela
It will contain all the information that we need for a guest.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 330 +++
 1 file changed, 180 insertions(+), 150 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 96b495f255..5cfc7a6ebc 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -152,6 +152,26 @@ static void bootfile_delete(void)
 bootpath = NULL;
 }
 
+typedef struct {
+QTestState *qs;
+const gchar *name;
+} GuestState;
+
+static GuestState *guest_create(const char *name)
+{
+GuestState *vm = g_new0(GuestState, 1);
+
+vm->name = name;
+
+return vm;
+}
+
+static void guest_destroy(GuestState *vm)
+{
+qtest_quit(vm->qs);
+g_free(vm);
+}
+
 /*
  * Wait for some output in the serial output file,
  * we get an 'A' followed by an endless string of 'B's
@@ -272,7 +292,7 @@ static void wait_for_migration_pass(QTestState *who)
 } while (pass == initial_pass && !got_src_stop);
 }
 
-static void check_guests_ram(QTestState *who)
+static void check_guests_ram(GuestState *who)
 {
 /* Our ASM test will have been incrementing one byte from each page from
  * start_address to < end_address in order. This gives us a constraint
@@ -287,14 +307,14 @@ static void check_guests_ram(QTestState *who)
 bool hit_edge = false;
 int bad = 0;
 
-qtest_memread(who, start_address, &first_byte, 1);
+qtest_memread(who->qs, start_address, &first_byte, 1);
 last_byte = first_byte;
 
 for (address = start_address + TEST_MEM_PAGE_SIZE; address < end_address;
  address += TEST_MEM_PAGE_SIZE)
 {
 uint8_t b;
-qtest_memread(who, address, &b, 1);
+qtest_memread(who->qs, address, &b, 1);
 if (b != last_byte) {
 if (((b + 1) % 256) == last_byte && !hit_edge) {
 /* This is OK, the guest stopped at the point of
@@ -528,14 +548,14 @@ static void migrate_postcopy_start(QTestState *from, 
QTestState *to)
 qtest_qmp_eventwait(to, "RESUME");
 }
 
-static void do_migrate(QTestState *from, QTestState *to, const gchar *uri)
+static void do_migrate(GuestState *from, GuestState *to, const gchar *uri)
 {
 if (!uri) {
 g_autofree char *tcp_uri =
-migrate_get_socket_address(to, "socket-address");
-migrate_qmp(from, tcp_uri, "{}");
+migrate_get_socket_address(to->qs, "socket-address");
+migrate_qmp(from->qs, tcp_uri, "{}");
 } else {
-migrate_qmp(from, uri, "{}");
+migrate_qmp(from->qs, uri, "{}");
 }
 }
 
@@ -640,7 +660,7 @@ typedef struct {
 bool postcopy_preempt;
 } MigrateCommon;
 
-static void test_migrate_start(QTestState **from, QTestState **to,
+static void test_migrate_start(GuestState *from, GuestState *to,
const char *uri, MigrateStart *args)
 {
 g_autofree gchar *arch_source = NULL;
@@ -712,11 +732,12 @@ static void test_migrate_start(QTestState **from, 
QTestState **to,
 }
 
 cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
- "-name source,debug-threads=on "
+ "-name %s,debug-threads=on "
  "-m %s "
  "-serial file:%s/src_serial "
  "%s %s %s %s %s",
  kvm_opts ? kvm_opts : "",
+ from->name,
  memory_size, tmpfs,
  arch_opts ? arch_opts : "",
  arch_source ? arch_source : "",
@@ -725,27 +746,28 @@ static void test_migrate_start(QTestState **from, 
QTestState **to,
  ignore_stderr ? ignore_stderr : "");
 
 if (!args->only_target) {
-*from = qtest_init(cmd_source);
-qtest_qmp_set_event_callback(*from,
+from->qs = qtest_init(cmd_source);
+qtest_qmp_set_event_callback(from->qs,
  migrate_watch_for_stop,
  &got_src_stop);
 }
 
 cmd_target = g_strdup_printf("-accel kvm%s -accel tcg "
- "-name target,debug-threads=on "
+ "-name %s,debug-threads=on "
  "-m %s "
  "-serial file:%s/dest_serial "
  "-incoming %s "
  "%s %s %s %s %s",
  kvm_opts ? kvm_opts : "",
+ to->name,
  memory_size, tmpfs, uri,
  arch_opts ? arch_opts : "",
  arch_target ? arch_target : "",
  shmem_opts ? shmem_opts : "",
  args->o

[PATCH 38/42] migration-test: Create guest_realize()

2023-06-08 Thread Juan Quintela
So we can get rid of the duplication in test_migrate_start().
- unfold test_migrate_start() because it is just two calls to
  guest_realize().
- make dirty_limit test use guest_realize()
- get rid of MigrateStart as now it is empty.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 147 +--
 1 file changed, 54 insertions(+), 93 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index a96eb3eec7..29147b2be3 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -233,6 +233,39 @@ static void guest_destroy(GuestState *vm)
 g_free(vm);
 }
 
+static void guest_realize(GuestState *who)
+{
+bool target = false;
+if (strncmp(who->name, "target", strlen("target")) == 0) {
+target = true;
+}
+gchar *
+cmd = g_strdup_printf("-accel kvm%s -accel tcg "
+  "-name %s,debug-threads=on "
+  "-m %s "
+  "-serial file:%s "
+  "%s %s "
+  "%s %s %s %s %s",
+  who->kvm_opts ? who->kvm_opts : "",
+  who->name,
+  who->memory_size,
+  who->serial_path,
+  target ? "-incoming" : "",
+  target ? who->uri ? who->uri : "defer"
+ : "",
+  who->arch_opts ? who->arch_opts : "",
+  target ? who->arch_target ? who->arch_target : ""
+ : who->arch_source ? who->arch_source : "",
+  who->shmem_opts ? who->shmem_opts : "",
+  who->extra_opts ? who->extra_opts : "",
+  who->hide_stderr ? who->hide_stderr : "");
+who->qs = qtest_init(cmd);
+qtest_qmp_set_event_callback(who->qs,
+ target ? migrate_watch_for_resume
+: migrate_watch_for_stop,
+ &who->got_event);
+}
+
 static void guest_use_dirty_ring(GuestState *vm)
 {
 g_assert(vm->kvm_opts == NULL);
@@ -674,11 +707,6 @@ static void do_migrate(GuestState *from, GuestState *to)
 }
 }
 
-typedef struct {
-/* only launch the target process */
-bool only_target;
-} MigrateStart;
-
 /*
  * A hook that runs after the src and dst QEMUs have been
  * created, but before the migration is started. This can
@@ -702,9 +730,6 @@ typedef void (*TestMigrateFinishHook)(GuestState *from, 
GuestState *to,
   void *opaque);
 
 typedef struct {
-/* Optional: fine tune start parameters */
-MigrateStart start;
-
 /* Optional: callback to run at start to set migration parameters */
 TestMigrateStartHook start_hook;
 /* Optional: callback to run at finish to cleanup */
@@ -752,56 +777,6 @@ typedef struct {
 bool postcopy_preempt;
 } MigrateCommon;
 
-static void test_migrate_start(GuestState *from, GuestState *to,
-   MigrateStart *args)
-{
-g_autofree gchar *cmd_source = NULL;
-g_autofree gchar *cmd_target = NULL;
-
-cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
- "-name %s,debug-threads=on "
- "-m %s "
- "-serial file:%s "
- "%s %s %s %s %s",
- from->kvm_opts ? from->kvm_opts : "",
- from->name,
- from->memory_size,
- from->serial_path,
- from->arch_opts ? from->arch_opts : "",
- from->arch_source ? from->arch_source : "",
- from->shmem_opts ? from->shmem_opts : "",
- from->extra_opts ? from->extra_opts : "",
- from->hide_stderr ? from->hide_stderr : "");
-
-if (!args->only_target) {
-from->qs = qtest_init(cmd_source);
-qtest_qmp_set_event_callback(from->qs,
- migrate_watch_for_stop,
- &from->got_event);
-}
-
-cmd_target = g_strdup_printf("-accel kvm%s -accel tcg "
- "-name %s,debug-threads=on "
- "-m %s "
- "-serial file:%s "
- "-incoming %s "
- "%s %s %s %s %s",
- to->kvm_opts ? to->kvm_opts : "",
- to->name,
- to->memory_size,
- to->serial_path,
- to->uri ? to->uri : "defer",
-  

[PATCH 31/42] migration-test: Preffer to->uri to uri parameter for migration

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 6438379dcf..0afe871cfb 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -667,12 +667,22 @@ static void migrate_postcopy_start(GuestState *from, 
GuestState *to)
 
 static void do_migrate(GuestState *from, GuestState *to, const gchar *uri)
 {
-if (!uri) {
-g_autofree char *tcp_uri =
-migrate_get_socket_address(to->qs, "socket-address");
-migrate_qmp(from->qs, tcp_uri, "{}");
+if (to->uri) {
+if (strncmp(to->uri, "tcp:", strlen("tcp:")) == 0) {
+g_autofree char *tcp_uri =
+migrate_get_socket_address(to->qs, "socket-address");
+migrate_qmp(from->qs, tcp_uri, "{}");
+} else {
+migrate_qmp(from->qs, to->uri, "{}");
+}
 } else {
-migrate_qmp(from->qs, uri, "{}");
+if (!uri) {
+g_autofree char *tcp_uri =
+migrate_get_socket_address(to->qs, "socket-address");
+migrate_qmp(from->qs, tcp_uri, "{}");
+} else {
+migrate_qmp(from->qs, uri, "{}");
+}
 }
 }
 
-- 
2.40.1




[PATCH 42/42] migration-test: Split vcpu-dirty-limit-test

2023-06-08 Thread Juan Quintela
It is not really a migration test, it just happens that migration
infrastructure is useful to it.

Once there, put migration-helpers.* as maintained.

Signed-off-by: Juan Quintela 
---
 MAINTAINERS |   3 +-
 tests/qtest/migration-test.c| 246 --
 tests/qtest/vcpu-dirty-limit-test.c | 310 
 tests/qtest/meson.build |   5 +-
 4 files changed, 316 insertions(+), 248 deletions(-)
 create mode 100644 tests/qtest/vcpu-dirty-limit-test.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 436b3f0afe..20de5ae8b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3176,7 +3176,8 @@ F: include/qemu/userfaultfd.h
 F: migration/
 F: scripts/vmstate-static-checker.py
 F: tests/vmstate-static-checker-data/
-F: tests/qtest/migration-test.c
+F: tests/qtest/migration-*
+F: tests/qtest/vcpu-dirty-limit-test.c
 F: docs/devel/migration.rst
 F: qapi/migration.json
 F: tests/migration/
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 4d3321b7b3..58bb829dcf 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -14,17 +14,11 @@
 
 #include "libqtest.h"
 #include "qapi/error.h"
-#include "qapi/qmp/qdict.h"
-#include "qemu/module.h"
 #include "qemu/option.h"
-#include "qemu/range.h"
 #include "qemu/sockets.h"
-#include "chardev/char.h"
 #include "qapi/qapi-visit-sockets.h"
 #include "qapi/qobject-input-visitor.h"
-#include "qapi/qobject-output-visitor.h"
 #include "crypto/tlscredspsk.h"
-#include "qapi/qmp/qlist.h"
 
 #include "migration-helpers.h"
 #include "tests/migration/migration-test.h"
@@ -37,12 +31,6 @@
 
 static bool uffd_feature_thread_id;
 
-/*
- * Dirtylimit stop working if dirty page rate error
- * value less than DIRTYLIMIT_TOLERANCE_RANGE
- */
-#define DIRTYLIMIT_TOLERANCE_RANGE  25  /* MB/s */
-
 #if defined(__linux__)
 #include 
 #include 
@@ -2146,238 +2134,6 @@ static void test_multifd_tcp_cancel(void)
 guest_destroy(to2);
 }
 
-static void calc_dirty_rate(QTestState *who, uint64_t calc_time)
-{
-qtest_qmp_assert_success(who,
- "{ 'execute': 'calc-dirty-rate',"
- "'arguments': { "
- "'calc-time': %" PRIu64 ","
- "'mode': 'dirty-ring' }}",
- calc_time);
-}
-
-static QDict *query_dirty_rate(QTestState *who)
-{
-return qtest_qmp_assert_success_ref(who,
-"{ 'execute': 'query-dirty-rate' }");
-}
-
-static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate)
-{
-qtest_qmp_assert_success(who,
- "{ 'execute': 'set-vcpu-dirty-limit',"
- "'arguments': { "
- "'dirty-rate': %" PRIu64 " } }",
- dirtyrate);
-}
-
-static void cancel_vcpu_dirty_limit(QTestState *who)
-{
-qtest_qmp_assert_success(who,
- "{ 'execute': 'cancel-vcpu-dirty-limit' }");
-}
-
-static QDict *query_vcpu_dirty_limit(QTestState *who)
-{
-QDict *rsp;
-
-rsp = qtest_qmp(who, "{ 'execute': 'query-vcpu-dirty-limit' }");
-g_assert(!qdict_haskey(rsp, "error"));
-g_assert(qdict_haskey(rsp, "return"));
-
-return rsp;
-}
-
-static bool calc_dirtyrate_ready(QTestState *who)
-{
-QDict *rsp_return;
-gchar *status;
-
-rsp_return = query_dirty_rate(who);
-g_assert(rsp_return);
-
-status = g_strdup(qdict_get_str(rsp_return, "status"));
-g_assert(status);
-
-return g_strcmp0(status, "measuring");
-}
-
-static void wait_for_calc_dirtyrate_complete(QTestState *who,
- int64_t time_s)
-{
-int max_try_count = 1;
-usleep(time_s * 100);
-
-while (!calc_dirtyrate_ready(who) && max_try_count--) {
-usleep(1000);
-}
-
-/*
- * Set the timeout with 10 s(max_try_count * 1000us),
- * if dirtyrate measurement not complete, fail test.
- */
-g_assert_cmpint(max_try_count, !=, 0);
-}
-
-static int64_t get_dirty_rate(QTestState *who)
-{
-QDict *rsp_return;
-gchar *status;
-QList *rates;
-const QListEntry *entry;
-QDict *rate;
-int64_t dirtyrate;
-
-rsp_return = query_dirty_rate(who);
-g_assert(rsp_return);
-
-status = g_strdup(qdict_get_str(rsp_return, "status"));
-g_assert(status);
-g_assert_cmpstr(status, ==, "measured");
-
-rates = qdict_get_qlist(rsp_return, "vcpu-dirty-rate");
-g_assert(rates && !qlist_empty(rates));
-
-entry = qlist_first(rates);
-g_assert(entry);
-
-rate = qobject_to(QDict, qlist_entry_obj(entry));
-g_assert(rate);
-
-dirtyrate = qdict_get_try_int(rate, "dirty-rate", -1);
-
-qobject_unref(rsp_return);
-return dirtyrate;
-}
-
-static int64_t get_limit_rate(QTestState *who)
-{
-QDict *rsp_return;
-QList *rates;
-const QListEntry *entry;
-QDict *rate;
-int64_

[PATCH 14/42] migration-test: test_migrate_start() always return 0

2023-06-08 Thread Juan Quintela
So make it return void instead and adjust all callers.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 38 ++--
 1 file changed, 10 insertions(+), 28 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 5837060138..b57811da75 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -629,8 +629,8 @@ typedef struct {
 bool postcopy_preempt;
 } MigrateCommon;
 
-static int test_migrate_start(QTestState **from, QTestState **to,
-  const char *uri, MigrateStart *args)
+static void test_migrate_start(QTestState **from, QTestState **to,
+   const char *uri, MigrateStart *args)
 {
 g_autofree gchar *arch_source = NULL;
 g_autofree gchar *arch_target = NULL;
@@ -745,8 +745,6 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 if (args->use_shmem) {
 unlink(shmem_path);
 }
-
-return 0;
 }
 
 static void test_migrate_end(QTestState *from, QTestState *to, bool test_dest)
@@ -1155,9 +1153,7 @@ static int migrate_postcopy_prepare(QTestState **from_ptr,
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 QTestState *from, *to;
 
-if (test_migrate_start(&from, &to, uri, &args->start)) {
-return -1;
-}
+test_migrate_start(&from, &to, uri, &args->start);
 
 if (args->start_hook) {
 args->postcopy_data = args->start_hook(from, to);
@@ -1387,9 +1383,7 @@ static void test_baddest(void)
 };
 QTestState *from, *to;
 
-if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", &args)) {
-return;
-}
+test_migrate_start(&from, &to, "tcp:127.0.0.1:0", &args);
 migrate_qmp(from, "tcp:127.0.0.1:0", "{}");
 wait_for_migration_fail(from, false);
 test_migrate_end(from, to, false);
@@ -1400,9 +1394,7 @@ static void test_precopy_common(MigrateCommon *args)
 QTestState *from, *to;
 void *data_hook = NULL;
 
-if (test_migrate_start(&from, &to, args->listen_uri, &args->start)) {
-return;
-}
+test_migrate_start(&from, &to, args->listen_uri, &args->start);
 
 if (args->start_hook) {
 data_hook = args->start_hook(from, to);
@@ -1592,9 +1584,7 @@ static void test_ignore_shared(void)
 .use_shmem = true
 };
 
-if (test_migrate_start(&from, &to, uri, &args)) {
-return;
-}
+test_migrate_start(&from, &to, uri, &args);
 
 migrate_set_capability(from, "x-ignore-shared", true);
 migrate_set_capability(to, "x-ignore-shared", true);
@@ -1893,9 +1883,7 @@ static void do_test_validate_uuid(MigrateStart *args, 
bool should_fail)
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
 QTestState *from, *to;
 
-if (test_migrate_start(&from, &to, uri, args)) {
-return;
-}
+test_migrate_start(&from, &to, uri, args);
 
 /*
  * UUID validation is at the begin of migration. So, the main process of
@@ -1990,9 +1978,7 @@ static void test_migrate_auto_converge(void)
  */
 const int64_t init_pct = 5, inc_pct = 25, max_pct = 95;
 
-if (test_migrate_start(&from, &to, uri, &args)) {
-return;
-}
+test_migrate_start(&from, &to, uri, &args);
 
 migrate_set_capability(from, "auto-converge", true);
 migrate_set_parameter_int(from, "cpu-throttle-initial", init_pct);
@@ -2302,9 +2288,7 @@ static void test_multifd_tcp_cancel(void)
 QTestState *from, *to, *to2;
 g_autofree char *uri = NULL;
 
-if (test_migrate_start(&from, &to, "defer", &args)) {
-return;
-}
+test_migrate_start(&from, &to, "defer", &args);
 
 migrate_ensure_non_converge(from);
 
@@ -2337,9 +2321,7 @@ static void test_multifd_tcp_cancel(void)
 .only_target = true,
 };
 
-if (test_migrate_start(&from, &to2, "defer", &args)) {
-return;
-}
+test_migrate_start(&from, &to2, "defer", &args);
 
 migrate_set_parameter_int(to2, "multifd-channels", 16);
 
-- 
2.40.1




[PATCH 04/42] migration-test: Make machine_opts regular with other options

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 95ccc9bce7..2490035569 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -637,7 +637,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 start_address = S390_TEST_MEM_START;
 end_address = S390_TEST_MEM_END;
 } else if (strcmp(arch, "ppc64") == 0) {
-machine_opts = "vsmt=8";
+machine_opts = "-machine vsmt=8";
 memory_size = "256M";
 start_address = PPC_TEST_MEM_START;
 end_address = PPC_TEST_MEM_END;
@@ -649,7 +649,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 arch_target = g_strdup("-nodefaults");
 } else if (strcmp(arch, "aarch64") == 0) {
 init_bootfile(bootpath, aarch64_kernel, sizeof(aarch64_kernel));
-machine_opts = "virt,gic-version=max";
+machine_opts = "-machine virt,gic-version=max";
 memory_size = "150M";
 arch_source = g_strdup_printf("-cpu max "
   "-kernel %s",
@@ -683,14 +683,13 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 memory_size, shmem_path);
 }
 
-cmd_source = g_strdup_printf("-accel kvm%s -accel tcg%s%s "
+cmd_source = g_strdup_printf("-accel kvm%s -accel tcg %s "
  "-name source,debug-threads=on "
  "-m %s "
  "-serial file:%s/src_serial "
  "%s %s %s %s",
  args->use_dirty_ring ?
  ",dirty-ring-size=4096" : "",
- machine_opts ? " -machine " : "",
  machine_opts ? machine_opts : "",
  memory_size, tmpfs,
  arch_source,
@@ -705,7 +704,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  &got_src_stop);
 }
 
-cmd_target = g_strdup_printf("-accel kvm%s -accel tcg%s%s "
+cmd_target = g_strdup_printf("-accel kvm%s -accel tcg %s "
  "-name target,debug-threads=on "
  "-m %s "
  "-serial file:%s/dest_serial "
@@ -713,7 +712,6 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  "%s %s %s %s",
  args->use_dirty_ring ?
  ",dirty-ring-size=4096" : "",
- machine_opts ? " -machine " : "",
  machine_opts ? machine_opts : "",
  memory_size, tmpfs, uri,
  arch_target,
-- 
2.40.1




[PATCH 05/42] migration-test: Create arch_opts

2023-06-08 Thread Juan Quintela
This will contain the options needed for both source and target.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 28 +---
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 2490035569..6b4e3bf827 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -600,6 +600,8 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 {
 g_autofree gchar *arch_source = NULL;
 g_autofree gchar *arch_target = NULL;
+/* options for source and target */
+g_autofree gchar *arch_opts = NULL;
 g_autofree gchar *cmd_source = NULL;
 g_autofree gchar *cmd_target = NULL;
 const gchar *ignore_stderr = NULL;
@@ -625,15 +627,13 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 assert(sizeof(x86_bootsect) == 512);
 init_bootfile(bootpath, x86_bootsect, sizeof(x86_bootsect));
 memory_size = "150M";
-arch_source = g_strdup_printf("-drive file=%s,format=raw", bootpath);
-arch_target = g_strdup(arch_source);
+arch_opts = g_strdup_printf("-drive file=%s,format=raw", bootpath);
 start_address = X86_TEST_MEM_START;
 end_address = X86_TEST_MEM_END;
 } else if (g_str_equal(arch, "s390x")) {
 init_bootfile(bootpath, s390x_elf, sizeof(s390x_elf));
 memory_size = "128M";
-arch_source = g_strdup_printf("-bios %s", bootpath);
-arch_target = g_strdup(arch_source);
+arch_opts = g_strdup_printf("-bios %s", bootpath);
 start_address = S390_TEST_MEM_START;
 end_address = S390_TEST_MEM_END;
 } else if (strcmp(arch, "ppc64") == 0) {
@@ -641,20 +641,16 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 memory_size = "256M";
 start_address = PPC_TEST_MEM_START;
 end_address = PPC_TEST_MEM_END;
-arch_source = g_strdup_printf("-nodefaults "
-  "-prom-env 'use-nvramrc?=true' -prom-env 
"
+arch_source = g_strdup_printf("-prom-env 'use-nvramrc?=true' -prom-env 
"
   "'nvramrc=hex .\" _\" begin %x %x "
   "do i c@ 1 + i c! 1000 +loop .\" B\" 0 "
   "until'", end_address, start_address);
-arch_target = g_strdup("-nodefaults");
+arch_opts = g_strdup("-nodefaults");
 } else if (strcmp(arch, "aarch64") == 0) {
 init_bootfile(bootpath, aarch64_kernel, sizeof(aarch64_kernel));
 machine_opts = "-machine virt,gic-version=max";
 memory_size = "150M";
-arch_source = g_strdup_printf("-cpu max "
-  "-kernel %s",
-  bootpath);
-arch_target = g_strdup(arch_source);
+arch_opts = g_strdup_printf("-cpu max -kernel %s", bootpath);
 start_address = ARM_TEST_MEM_START;
 end_address = ARM_TEST_MEM_END;
 
@@ -687,12 +683,13 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
  "-name source,debug-threads=on "
  "-m %s "
  "-serial file:%s/src_serial "
- "%s %s %s %s",
+ "%s %s %s %s %s",
  args->use_dirty_ring ?
  ",dirty-ring-size=4096" : "",
  machine_opts ? machine_opts : "",
  memory_size, tmpfs,
- arch_source,
+ arch_opts ? arch_opts : "",
+ arch_source ? arch_source : "",
  shmem_opts ? shmem_opts : "",
  args->opts_source ? args->opts_source : "",
  ignore_stderr ? ignore_stderr : "");
@@ -709,12 +706,13 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
  "-m %s "
  "-serial file:%s/dest_serial "
  "-incoming %s "
- "%s %s %s %s",
+ "%s %s %s %s %s",
  args->use_dirty_ring ?
  ",dirty-ring-size=4096" : "",
  machine_opts ? machine_opts : "",
  memory_size, tmpfs, uri,
- arch_target,
+ arch_opts ? arch_opts : "",
+ arch_target ? arch_target : "",
  shmem_opts ? shmem_opts : "",
  args->opts_target ? args->opts_target : "",
 

[PATCH 20/42] migration-test: Create guest before calling test_postcopy_common()

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 528dc571ef..a18b3ce1e2 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1230,11 +1230,9 @@ static void migrate_postcopy_complete(GuestState *from, 
GuestState *to,
 test_migrate_end(from, to, true);
 }
 
-static void test_postcopy_common(MigrateCommon *args)
+static void test_postcopy_common(GuestState *from, GuestState *to,
+ MigrateCommon *args)
 {
-GuestState *from = guest_create("source");
-GuestState *to = guest_create("target");
-
 migrate_postcopy_prepare(from, to, args);
 migrate_postcopy_start(from->qs, to->qs);
 migrate_postcopy_complete(from, to, args);
@@ -1242,49 +1240,59 @@ static void test_postcopy_common(MigrateCommon *args)
 
 static void test_postcopy(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = { };
 
-test_postcopy_common(&args);
+test_postcopy_common(from, to, &args);
 }
 
 static void test_postcopy_compress(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .start_hook = test_migrate_compress_start
 };
 
-test_postcopy_common(&args);
+test_postcopy_common(from, to, &args);
 }
 
 static void test_postcopy_preempt(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .postcopy_preempt = true,
 };
 
-test_postcopy_common(&args);
+test_postcopy_common(from, to, &args);
 }
 
 #ifdef CONFIG_GNUTLS
 static void test_postcopy_tls_psk(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .start_hook = test_migrate_tls_psk_start_match,
 .finish_hook = test_migrate_tls_psk_finish,
 };
 
-test_postcopy_common(&args);
+test_postcopy_common(from, to, &args);
 }
 
 static void test_postcopy_preempt_tls_psk(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateCommon args = {
 .postcopy_preempt = true,
 .start_hook = test_migrate_tls_psk_start_match,
 .finish_hook = test_migrate_tls_psk_finish,
 };
 
-test_postcopy_common(&args);
+test_postcopy_common(from, to, &args);
 }
 #endif
 
-- 
2.40.1




[PATCH 18/42] migration-test: Create guest before calling do_test_validate_uuid()

2023-06-08 Thread Juan Quintela
Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 21 ++---
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 5cfc7a6ebc..14f4fd579b 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1905,11 +1905,10 @@ static void test_migrate_fd_proto(void)
 }
 #endif /* _WIN32 */
 
-static void do_test_validate_uuid(MigrateStart *args, bool should_fail)
+static void do_test_validate_uuid(GuestState *from, GuestState *to,
+  MigrateStart *args, bool should_fail)
 {
 g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
-GuestState *from = guest_create("source");
-GuestState *to = guest_create("target");
 
 test_migrate_start(from, to, uri, args);
 
@@ -1938,43 +1937,51 @@ static void do_test_validate_uuid(MigrateStart *args, 
bool should_fail)
 
 static void test_validate_uuid(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateStart args = {
 .opts_source = "-uuid ----",
 .opts_target = "-uuid ----",
 };
 
-do_test_validate_uuid(&args, false);
+do_test_validate_uuid(from, to, &args, false);
 }
 
 static void test_validate_uuid_error(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateStart args = {
 .opts_source = "-uuid ----",
 .opts_target = "-uuid ----",
 .hide_stderr = true,
 };
 
-do_test_validate_uuid(&args, true);
+do_test_validate_uuid(from, to, &args, true);
 }
 
 static void test_validate_uuid_src_not_set(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateStart args = {
 .opts_target = "-uuid ----",
 .hide_stderr = true,
 };
 
-do_test_validate_uuid(&args, false);
+do_test_validate_uuid(from, to, &args, false);
 }
 
 static void test_validate_uuid_dst_not_set(void)
 {
+GuestState *from = guest_create("source");
+GuestState *to = guest_create("target");
 MigrateStart args = {
 .opts_source = "-uuid ----",
 .hide_stderr = true,
 };
 
-do_test_validate_uuid(&args, false);
+do_test_validate_uuid(from, to, &args, false);
 }
 
 /*
-- 
2.40.1




[PATCH 00/42] Migration test refactoring

2023-06-08 Thread Juan Quintela
Hi

This series do a lot of much neededs cleanups and fixes to migration-test:

- We make source and target machines coherent/constent
- We make all command line options consistent
- We split test_migrate_start() and test_migrate_end() into:

  * guest_start() from from and to.  It is the same function, just
defines the basic options.  I am open to renaming it to
guest_define() or anything else that people can came with.

  * guest_destroy(), you have guessed it, right?

  * guest_realize() after guest_start() and adding any options we
need, we just create the guest.  We use the same function from
source and target, making inconsistencies disapear.

- uri: right now it is a mess, we can have:
  * uri created with migration_start()
  * or listen_uri
  * or connect_uri
  * or by hand
  now we just setup to->uri, and we get the migrate uri automatically from 
there.

- we were creating bootfile for each migration test.  Change the code
  so we only create it once for the whole migration test.

- Introduce GuestState.  Using QTestState directly means that we can
  add state by guest, making it abuse local variables.  Now we move
  all guest state into GuestState.

- Apart from test found by Fabiano, we had another problems with
  multifd + cancel:

  * We didn't wait for "to" guest to finish before we launch second
target guest "to2".  We fixed it by destroying "to" before
launching "to2".

  * We reused "dest_serial" filename from "to" and "to2", so in a very
loaded host, it could be that we contact with the wrong vm, and we
never end.

  * I change the code so the serial filename is dependent on guest
name, that made changing the interface:
wait_for_serial("dest_serial") to
wait_for_relial(to) (or to2 or ...) so we can't fail.

- we move the global event variables to GuestState, so no more
  got_src_stop or got_dst_resume, we just check
who->got_event

- create a function from migrate-incoming, so now we do:
  migrate_incoming(uri) and it does what we want/expect.

- vcpu_dirty_limit is not related to migration at all, just is easier
  to write with migration infrastructure.  Move all useful functions
  to migration-helpers.[ch] and split the test into
  vcpu-dirty-limit-test.c.  I think that we can declare that test slow.

- Now that guest_create/destry exist, we can "reuse" them in
  vcpu_dirty_limit test.

- The removal of files, like "migsocket" was flaky at least, i.e. not
  always removed.  "migsocket-recover" was not even tried to remove.
  New code just remove them by default.

- MigrationStart is gone, instead of creating that flags, I just call
  functions that do that function.

- if no uri is given for a target guest, it launches with -incoming
  defer, that should be the default.

ToDo:

- Tests shouldn't really use QMP, if we need QMP, we should hide it
  behind a c function.  Almost everything is there now, except things
  like "reuse".

- I think we should split auto-converge test:
  * we are not testing migration there, we are testing vcpu slowdown
  * the test is really slow, see documentation why we can't make it much faster.

- I still need to make test faster with stoping switchover.

Please, review.

Juan Quintela (42):
  migration-test: Be consistent for ppc
  migration-test: Make ignore_stderr regular with other options
  migration-test: simplify shmem_opts handling
  migration-test: Make machine_opts regular with other options
  migration-test: Create arch_opts
  migration-test: machine_opts is really arch specific
  migration-test: Create kvm_opts
  migration-test: bootpath is the same for all tests and for all archs
  migration-test: Add bootfile_create/delete() functions
  migration-test: dirtylimit checks for x86_64 arch before
  migration-test: Update test_ignore_shared to use args
  migration-test: Enable back ignore-shared test
  migration-test: Check for shared memory like for everything else
  migration-test: test_migrate_start() always return 0
  migration-test: migrate_postcopy_prepare() always return 0
  migration-test: Create do_migrate()
  migration-test: Introduce GuestState
  migration-test: Create guest before calling do_test_validate_uuid()
  migration-test: Create guest before calling test_precopy_common()
  migration-test: Create guest before calling test_postcopy_common()
  migration-test: Move common guest code to guest_create()
  migration-test: Create guest_use_dirty_log()
  migration-test: Move serial to GuestState
  migration-test: Re-enable multifd_cancel test
  migration-test: We were not waiting for "target" to finish
  migration-test: create guest_use_shmem()
  migration-test: Create guest_extra_opts()
  migration-test: Create guest_hide_stderr()
  migration-test: Create the migration unix socket by guest
  migration-test: Hooks also need GuestState
  migration-test: Preffer to->uri to uri parameter for migration
  migration-test: Create guest_set_uri()
  migration-test: Remove connect_uri
  migration-test:

[PATCH 06/42] migration-test: machine_opts is really arch specific

2023-06-08 Thread Juan Quintela
And it needs to be in both source and target, so put it on arch_opts.

Signed-off-by: Juan Quintela 
---
 tests/qtest/migration-test.c | 14 +-
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 6b4e3bf827..cd49c249d3 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -609,7 +609,6 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 g_autofree char *shmem_opts = NULL;
 g_autofree char *shmem_path = NULL;
 const char *arch = qtest_get_arch();
-const char *machine_opts = NULL;
 const char *memory_size;
 
 if (args->use_shmem) {
@@ -637,7 +636,6 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
 start_address = S390_TEST_MEM_START;
 end_address = S390_TEST_MEM_END;
 } else if (strcmp(arch, "ppc64") == 0) {
-machine_opts = "-machine vsmt=8";
 memory_size = "256M";
 start_address = PPC_TEST_MEM_START;
 end_address = PPC_TEST_MEM_END;
@@ -645,12 +643,12 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
   "'nvramrc=hex .\" _\" begin %x %x "
   "do i c@ 1 + i c! 1000 +loop .\" B\" 0 "
   "until'", end_address, start_address);
-arch_opts = g_strdup("-nodefaults");
+arch_opts = g_strdup("-nodefaults -machine vsmt=8");
 } else if (strcmp(arch, "aarch64") == 0) {
 init_bootfile(bootpath, aarch64_kernel, sizeof(aarch64_kernel));
-machine_opts = "-machine virt,gic-version=max";
 memory_size = "150M";
-arch_opts = g_strdup_printf("-cpu max -kernel %s", bootpath);
+arch_opts = g_strdup_printf("-machine virt,gic-version=max -cpu max "
+"-kernel %s", bootpath);
 start_address = ARM_TEST_MEM_START;
 end_address = ARM_TEST_MEM_END;
 
@@ -679,14 +677,13 @@ static int test_migrate_start(QTestState **from, 
QTestState **to,
 memory_size, shmem_path);
 }
 
-cmd_source = g_strdup_printf("-accel kvm%s -accel tcg %s "
+cmd_source = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name source,debug-threads=on "
  "-m %s "
  "-serial file:%s/src_serial "
  "%s %s %s %s %s",
  args->use_dirty_ring ?
  ",dirty-ring-size=4096" : "",
- machine_opts ? machine_opts : "",
  memory_size, tmpfs,
  arch_opts ? arch_opts : "",
  arch_source ? arch_source : "",
@@ -701,7 +698,7 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  &got_src_stop);
 }
 
-cmd_target = g_strdup_printf("-accel kvm%s -accel tcg %s "
+cmd_target = g_strdup_printf("-accel kvm%s -accel tcg "
  "-name target,debug-threads=on "
  "-m %s "
  "-serial file:%s/dest_serial "
@@ -709,7 +706,6 @@ static int test_migrate_start(QTestState **from, QTestState 
**to,
  "%s %s %s %s %s",
  args->use_dirty_ring ?
  ",dirty-ring-size=4096" : "",
- machine_opts ? machine_opts : "",
  memory_size, tmpfs, uri,
  arch_opts ? arch_opts : "",
  arch_target ? arch_target : "",
-- 
2.40.1




  1   2   3   4   >