[PATCH] hw/i386/acpi-build: Get NUMA information from struct NumaState

2021-08-02 Thread Jingqi Liu
The NUMA information in PCMachineState is copied from MachineState.
We get this information uniformly from struct NumaState in MachineState.

Signed-off-by: Jingqi Liu 
---
 hw/i386/acpi-build.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 17836149fe..e3c9ad011e 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1902,6 +1902,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 X86MachineState *x86ms = X86_MACHINE(machine);
 const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
 PCMachineState *pcms = PC_MACHINE(machine);
+int nb_numa_nodes = machine->numa_state->num_nodes;
+NodeInfo *numa_info = machine->numa_state->nodes;
 ram_addr_t hotplugabble_address_space_size =
 object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZE,
 NULL);
@@ -1945,9 +1947,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 next_base = 0;
 numa_start = table_data->len;
 
-for (i = 1; i < pcms->numa_nodes + 1; ++i) {
+for (i = 1; i < nb_numa_nodes + 1; ++i) {
 mem_base = next_base;
-mem_len = pcms->node_mem[i - 1];
+mem_len = numa_info[i - 1].node_mem;
 next_base = mem_base + mem_len;
 
 /* Cut out the 640K hole */
@@ -1995,7 +1997,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 }
 
 slots = (table_data->len - numa_start) / sizeof *numamem;
-for (; slots < pcms->numa_nodes + 2; slots++) {
+for (; slots < nb_numa_nodes + 2; slots++) {
 numamem = acpi_data_push(table_data, sizeof *numamem);
 build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
 }
@@ -2011,7 +2013,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 if (hotplugabble_address_space_size) {
 numamem = acpi_data_push(table_data, sizeof *numamem);
 build_srat_memory(numamem, machine->device_memory->base,
-  hotplugabble_address_space_size, pcms->numa_nodes - 
1,
+  hotplugabble_address_space_size, nb_numa_nodes - 1,
   MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
 }
 
@@ -2513,7 +2515,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 }
 }
 #endif
-if (pcms->numa_nodes) {
+if (machine->numa_state->num_nodes) {
 acpi_add_table(table_offsets, tables_blob);
 build_srat(tables_blob, tables->linker, machine);
 if (machine->numa_state->have_numa_distance) {
-- 
2.21.3




Re: [PATCH 1/1] migration: Terminate multifd threads on yank

2021-08-02 Thread Lukas Straub
On Fri, 30 Jul 2021 04:40:45 -0300
Leonardo Bras  wrote:

> From source host viewpoint, losing a connection during migration will
> cause the sockets to get stuck in sendmsg() syscall, waiting for
> the receiving side to reply.
> 
> In migration, yank works by shutting-down the migration QIOChannel fd.
> This causes a failure in the next sendmsg() for that fd, and the whole
> migration gets cancelled.
> 
> In multifd, due to having multiple sockets in multiple threads,
> on a connection loss there will be extra sockets stuck in sendmsg(),
> and because they will be holding their own mutex, there is good chance
> the main migration thread can get stuck in multifd_send_pages()
> waiting for one of those mutexes.
> 
> While it's waiting, the main migration thread can't run sendmsg() on
> it's fd, and therefore can't cause the migration to be cancelled, thus
> causing yank not to work.
> 
> Fixes this by shutting down all migration fds (including multifd ones),
> so no thread get's stuck in sendmsg() while holding a lock, and thus
> allowing the main migration thread to properly cancel migration when
> yank is used.
> 
> There is no need to do the same procedure to yank to work in the
> receiving host since ops->recv_pages() is kept outside the mutex protected
> code in multifd_recv_thread().
> 
> Buglink:https://bugzilla.redhat.com/show_bug.cgi?id=1970337
> Reported-by: Li Xiaohui 
> Signed-off-by: Leonardo Bras 
> ---

Hi,
There is an easier explanation: I forgot the send side of multifd
altogether (I thought it was covered by migration_channel_connect()).
So yank won't actually shutdown() the multifd sockets on the send side.

In the bugreport you wrote
> (As a test, I called qio_channel_shutdown() in every multifd iochannel and 
> yank worked just fine, but I could not retry migration, because it was still 
> 'ongoing')
That sounds like a bug in the error handling for multifd. But quickly
looking at the code, it should properly fail the migration.

BTW: You can shutdown outgoing sockets from outside of qemu with the
'ss' utility, like this: 'sudo ss -K dst  dport = '

Regards,
Lukas Straub


pgpUAwiOJ57ws.pgp
Description: OpenPGP digital signature


Re: [PATCH 0/6] Updates for Coverity modeling file

2021-08-02 Thread Markus Armbruster
Paolo Bonzini  writes:

[...]

> This series is a sort of FYI; since the only way to debug the model file
> is to upload it to scan.coverity.com, these changes are all already live.

When I mess with Coverity, I test with my locally installed version
first.  Version skew and lack of the web interface can make that less
than useful sometimes.

This is not criticism of your work flow.

> The last will be as of the next build, but was effective last Thursday
> and worked (I tried disabling it on Friday in something like a bisection,
> but it failed and I have now reverted to Thursday's model).




Re: [PATCH 10/16] migration: Handle migration_incoming_setup() errors consistently

2021-08-02 Thread Markus Armbruster
"Dr. David Alan Gilbert"  writes:

> * Markus Armbruster (arm...@redhat.com) wrote:
>> Commit b673eab4e2 "multifd: Make multifd_load_setup() get an Error
>> parameter" changed migration_incoming_setup() to take an Error **
>> argument, and adjusted the callers accordingly.  It neglected to
>> change adjust multifd_load_setup(): it still exit()s on error.  Clean
>> that up.
>> 
>> The error now gets propagated up two call chains: via
>> migration_fd_process_incoming() to rdma_accept_incoming_migration(),
>> and via migration_ioc_process_incoming() to
>> migration_channel_process_incoming().  Both chain ends report the
>> error with error_report_err(), but otherwise ignore it.  Behavioral
>> change: we no longer exit() on this error.
>> 
>> This is consistent with how we handle other errors here, e.g. from
>> multifd_recv_new_channel() via migration_ioc_process_incoming() to
>> migration_channel_process_incoming().  Wether it's consistently right
>> or consistently wrong I can't tell.
>> 
>> Also clean up the return value from the unusual 0 on success, 1 on
>> error to the more common true on success, false on error.
>> 
>> Cc: Juan Quintela 
>> Cc: Dr. David Alan Gilbert 
>> Signed-off-by: Markus Armbruster 
>> ---
>>  migration/migration.c | 27 +--
>>  1 file changed, 9 insertions(+), 18 deletions(-)
>> 
>> diff --git a/migration/migration.c b/migration/migration.c
>> index 231dc24414..c1c0a48647 100644
>> --- a/migration/migration.c
>> +++ b/migration/migration.c
>> @@ -609,30 +609,25 @@ fail:
>>  }
>>  
>>  /**
>> - * @migration_incoming_setup: Setup incoming migration
>> - *
>> - * Returns 0 for no error or 1 for error
>> - *
>> + * migration_incoming_setup: Setup incoming migration
>>   * @f: file for main migration channel
>>   * @errp: where to put errors
>> + *
>> + * Returns: %true on success, %false on error.
>>   */
>> -static int migration_incoming_setup(QEMUFile *f, Error **errp)
>> +static bool migration_incoming_setup(QEMUFile *f, Error **errp)
>>  {
>>  MigrationIncomingState *mis = migration_incoming_get_current();
>> -Error *local_err = NULL;
>>  
>> -if (multifd_load_setup(&local_err) != 0) {
>> -/* We haven't been able to create multifd threads
>> -   nothing better to do */
>> -error_report_err(local_err);
>> -exit(EXIT_FAILURE);
>> +if (multifd_load_setup(errp) != 0) {
>> +return false;
>>  }
>
> What I don't know is how well that will survive; for example in
> multifd_load_setup it creates multiple threads and calls the recv_setup
> member on each thread; now if one of those fails what happens - if we
> don't exit, is it cleaned up enough so you can try another
> migrate_incoming or is it just going to fall over?

I don't know, either.

The inconsistent error handling we have is not good.  More consistent
error handling that unmasks bad error handling could be worse, unless we
fix the unmasked badness.

How can we move forward with this patch?

One way *I* could move forward is to tack a FIXME comment to the
problematic exit(1) instead of removing it.

[...]




Re: [PATCH v2 1/1] nvdimm: add 'target-node' option

2021-08-02 Thread Liu, Jingqi

Hi Igor,

On 7/29/2021 8:44 PM, Igor Mammedov wrote:

On Mon, 19 Jul 2021 10:01:53 +0800
Jingqi Liu  wrote:


Linux kernel version 5.1 brings in support for the volatile-use of
persistent memory as a hotplugged memory region (KMEM DAX).
When this feature is enabled, persistent memory can be seen as a
separate memory-only NUMA node(s). This newly-added memory can be
selected by its unique NUMA node.

Add 'target-node' option for 'nvdimm' device to indicate this NUMA
node. It can be extended to a new node after all existing NUMA nodes.

The 'node' option of 'pc-dimm' device is to add the DIMM to an
existing NUMA node. The 'node' should be in the available NUMA nodes.
For KMEM DAX mode, persistent memory can be in a new separate
memory-only NUMA node. The new node is created dynamically.
So users use 'target-node' to control whether persistent memory
is added to an existing NUMA node or a new NUMA node.

An example of configuration is as follows.

Using the following QEMU command:
  -object 
memory-backend-file,id=nvmem1,share=on,mem-path=/dev/dax0.0,size=3G,align=2M
  -device nvdimm,id=nvdimm1,memdev=mem1,label-size=128K,targe-node=2

To list DAX devices:
  # daxctl list -u
  {
"chardev":"dax0.0",
"size":"3.00 GiB (3.22 GB)",
"target_node":2,
"mode":"devdax"
  }

To create a namespace in Device-DAX mode as a standard memory:
  $ ndctl create-namespace --mode=devdax --map=mem
To reconfigure DAX device from devdax mode to a system-ram mode:
  $ daxctl reconfigure-device dax0.0 --mode=system-ram

There are two existing NUMA nodes in Guest. After these operations,
persistent memory is configured as a separate Node 2 and
can be used as a volatile memory. This NUMA node is dynamically
created according to 'target-node'.



Well, I've looked at spec and series pointed at v1 thread,
and I don't really see a good reason to add duplicate 'target-node'
property to NVDIMM that for all practical purposes serves the same
purpose as already existing 'node' property.
The only thing that it does on top of existing 'node' property is
facilitate implicit creation of numa nodes on top of user configured
ones.

But what I really dislike, is adding implicit path to create
numa nodes from random place.

It just creates mess and and doesn't really work well because you
will have to plumb into other code to account for implicit nodes
for it to work properly. (1st thing that comes to mind is HMAT
configuration won't accept this implicit nodes, there might be
other places that will not work as expected).
So I suggest to abandon this approach and use already existing
numa CLI options to do what you need.

What you are trying to achieve can be done without this series
as QEMU allows to create memory only nodes and even empty ones
(for future hotplug) just fine.
The only thing is that one shall specify complete planned
numa topology on command line.

Here is an example that works for me:
-machine q35,nvdimm=on \
-m 4G,slots=4,maxmem=12G \
-smp 4,cores=2 \
-object memory-backend-ram,size=4G,policy=bind,host-nodes=0,id=ram-node0 \
-numa node,nodeid=0,memdev=ram-node0
# explicitly assign all CPUs
-numa cpu,node-id=0,socket-id=0 -numa cpu,node-id=0,socket-id=1
# and create a cpu-less node for you nvdimm
-numa node,nodeid=1

with that you can hotplug nvdimm to with 'node=1' property set
or provide that at startup, like this:
-object 
memory-backend-file,id=mem1,share=on,mem-path=nvdimmfile,size=3G,align=2M \
-device nvdimm,id=nvdimm1,memdev=mem1,label-size=128K,node=1

after boot numactl -H will show:

available: 1 nodes (0)
node 0 cpus: 0 1 2 3
node 0 size: 3924 MB
node 0 free: 3657 MB
node distances:
node   0
   0:  10

and after initializing nvdimm as a dax device and
reconfiguring that to system memory it will show
as 'new' 'memory only' node

available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3
node 0 size: 3924 MB
node 0 free: 3641 MB
node 1 cpus:
node 1 size: 896 MB
node 1 free: 896 MB
node distances:
node   0   1
   0:  10  20
   1:  20  10


Signed-off-by: Jingqi Liu 

[...]



Thanks for your comments and detailed example.
I agree with you.
I've tried these commands and it works.

Actually, I've provided similar commands to the customer before.
They just had some concerns on the need to create complete numa 
topology. But seems it's the only way to create memory-only nodes for 
future hotplugging.


I'll try to convince the customer to use it.

Thanks,
Jingqi





Re: [PATCH 12/16] vhost: Clean up how VhostOpts method vhost_get_config() fails

2021-08-02 Thread Markus Armbruster
Philippe Mathieu-Daudé  writes:

> On 7/20/21 2:54 PM, Markus Armbruster wrote:
>> vhost_user_get_config() can fail without setting an error.  Unclean.
>> Its caller vhost_dev_get_config() compensates by substituting a
>> generic error then.  Goes back to commit 50de51387f "vhost:
>> Distinguish errors in vhost_dev_get_config()".
>> 
>> Clean up by moving the generic error from vhost_dev_get_config() to
>> all the failure paths that neglect to set an error.
>> 
>> Cc: Kevin Wolf 
>> Cc: Michael S. Tsirkin 
>> Signed-off-by: Markus Armbruster 
>> ---
>>  hw/virtio/vhost-user.c |  2 ++
>>  hw/virtio/vhost.c  | 10 ++
>>  2 files changed, 4 insertions(+), 8 deletions(-)
>> 
>> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
>> index 29ea2b4fce..dbbd6fbc25 100644
>> --- a/hw/virtio/vhost-user.c
>> +++ b/hw/virtio/vhost-user.c
>> @@ -2139,10 +2139,12 @@ static int vhost_user_get_config(struct vhost_dev 
>> *dev, uint8_t *config,
>>  msg.payload.config.offset = 0;
>>  msg.payload.config.size = config_len;
>>  if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
>> +error_setg_errno(errp, -EPROTO, "vhost_get_config failed");
>>  return -EPROTO;
>>  }
>>  
>>  if (vhost_user_read(dev, &msg) < 0) {
>> +error_setg_errno(errp, -EPROTO, "vhost_get_config failed");
>>  return -EPROTO;
>>  }
>
> Oops, should be error_setg_errno(EPROTO)!

D'oh!  Thanks!




Re: [PATCH 01/16] error: Use error_fatal to simplify obvious fatal errors (again)

2021-08-02 Thread Markus Armbruster
Philippe Mathieu-Daudé  writes:

> On 7/20/21 2:53 PM, Markus Armbruster wrote:
>> We did this with scripts/coccinelle/use-error_fatal.cocci before, in
>> commit 50beeb68094 and 007b06578ab.  This commit cleans up rarer
>> variations that don't seem worth matching with Coccinelle.
>> 
>> Cc: Thomas Huth 
>> Cc: Cornelia Huck 
>> Cc: Peter Xu 
>> Cc: Juan Quintela 
>> Cc: Stefan Hajnoczi 
>> Cc: Paolo Bonzini 
>> Cc: Marc-André Lureau 
>> Cc: Gerd Hoffmann 
>> Cc: Daniel P. Berrangé 
>> Signed-off-by: Markus Armbruster 
>> ---
>>  hw/s390x/ipl.c|  6 +-
>>  migration/migration.c |  7 +--
>>  qemu-img.c|  6 +-
>>  qemu-io.c |  6 +-
>>  qemu-nbd.c|  5 +
>>  scsi/qemu-pr-helper.c | 11 +++
>>  softmmu/vl.c  |  7 +--
>>  target/i386/sev.c |  8 +---
>>  ui/console.c  |  6 ++
>>  ui/spice-core.c   |  7 +--
>>  10 files changed, 13 insertions(+), 56 deletions(-)
>
>> diff --git a/softmmu/vl.c b/softmmu/vl.c
>> index 4df1496101..0d2db1abc3 100644
>> --- a/softmmu/vl.c
>> +++ b/softmmu/vl.c
>> @@ -2673,12 +2673,7 @@ void qmp_x_exit_preconfig(Error **errp)
>>  qemu_machine_creation_done();
>>  
>>  if (loadvm) {
>> -Error *local_err = NULL;
>> -if (!load_snapshot(loadvm, NULL, false, NULL, &local_err)) {
>> -error_report_err(local_err);
>> -autostart = 0;
>
> Uh, odd assignment...

Yup.

Commit 05f2401eb2 "make load_vmstate() return errors" added the
assignment:

@@ -6030,8 +6030,11 @@ int main(int argc, char **argv, char **envp)
 exit(1);
 }

-if (loadvm)
-load_vmstate(cur_mon, loadvm);
+if (loadvm) {
+if (load_vmstate(cur_mon, loadvm) < 0) {
+autostart = 0;
+}
+}

 if (incoming) {
 qemu_start_incoming_migration(incoming);


827beacb47 "Add a hint message to loadvm and exits on failure" added the
exit(1) without deleting the now useless assignment:

@@ -4530,6 +4530,7 @@ int main(int argc, char **argv, char **envp)
 if (load_snapshot(loadvm, &local_err) < 0) {
 error_report_err(local_err);
 autostart = 0;
+exit(1);
 }
 }

>> -exit(1);
>> -}
>> +load_snapshot(loadvm, NULL, false, NULL, &error_fatal);
>>  }
>>  if (replay_mode != REPLAY_MODE_NONE) {
>>  replay_vmstate_init();
>
> Reviewed-by: Philippe Mathieu-Daudé 

Thanks!




Re: [PATCH] vhost: use large iotlb entry if no IOMMU translation is needed

2021-08-02 Thread Chao Gao
On Tue, Aug 03, 2021 at 12:43:58PM +0800, Jason Wang wrote:
>
>在 2021/8/3 下午12:29, Chao Gao 写道:
>> Ping. Could someone help to review this patch?
>> 
>> Thanks
>> Chao
>> 
>> On Wed, Jul 21, 2021 at 03:54:02PM +0800, Chao Gao wrote:
>> > If guest enables IOMMU_PLATFORM for virtio-net, severe network
>> > performance drop is observed even if there is no IOMMU.
>
>
>We see such reports internally and we're testing a patch series to disable
>vhost IOTLB in this case.
>
>Will post a patch soon.

OK. put me in the CC list. I would like to test with TDX to ensure your patch
fix the performance issue I am facing.

>
>
>
>> >   And disabling
>> > vhost can mitigate the perf issue. Finally, we found the culprit is
>> > frequent iotlb misses: kernel vhost-net has 2048 entries and each
>> > entry is 4K (qemu uses 4K for i386 if no IOMMU); vhost-net can cache
>> > translations for up to 8M (i.e. 4K*2048) IOVAs. If guest uses >8M
>> > memory for DMA, there are some iotlb misses.
>> > 
>> > If there is no IOMMU or IOMMU is disabled or IOMMU works in pass-thru
>> > mode, we can optimistically use large, unaligned iotlb entries instead
>> > of 4K-aligned entries to reduce iotlb pressure.
>
>
>Instead of introducing new general facilities like unaligned IOTLB entry. I
>wonder if we optimize the vtd_iommu_translate() to use e.g 1G instead?

using 1G iotlb entry looks feasible.

>
>    } else {
>    /* DMAR disabled, passthrough, use 4k-page*/
>    iotlb.iova = addr & VTD_PAGE_MASK_4K;
>    iotlb.translated_addr = addr & VTD_PAGE_MASK_4K;
>    iotlb.addr_mask = ~VTD_PAGE_MASK_4K;
>    iotlb.perm = IOMMU_RW;
>    success = true;
>    }
>
>
>> >   Actually, vhost-net
>> > in kernel supports unaligned iotlb entry. The alignment requirement is
>> > imposed by address_space_get_iotlb_entry() and flatview_do_translate().
>
>
>For the passthrough case, is there anyway to detect them and then disable
>device IOTLB in those case?

yes. I guess so; qemu knows the presence and status of iommu. Currently,
in flatview_do_translate(), memory_region_get_iommu() tells whether a memory
region is behind an iommu.

Thanks
Chao



Re: [PATCH v2 19/55] target/xtensa: Implement do_unaligned_access for user-only

2021-08-02 Thread Max Filippov
On Mon, Aug 2, 2021 at 9:15 PM Richard Henderson
 wrote:
>
> Cc: Max Filippov 
> Signed-off-by: Richard Henderson 
> ---
>  target/xtensa/cpu.c|  2 +-
>  target/xtensa/helper.c | 30 +++---
>  2 files changed, 16 insertions(+), 16 deletions(-)

Acked-by: Max Filippov 
-- 
Thanks.
-- Max



[PATCH for-6.1] qga-win/msi: fix missing libstdc++-6 DLL in MSI installer

2021-08-02 Thread Michael Roth
libstdc++ is required for the qga-vss.dll that provides fsfreeze
functionality. Currently it is not provided by the MSI installer,
resulting in fsfreeze being disabled in guest environments where it has
not been installed by other means.

In the future this would be better handled via gcc-cpp ComponentGroup
provided by msitools, but that would be better handled with a general
rework of DLL dependency handling in the installer build. Keep it
simple for now to fix this regression.

Tested with Fedora 34 mingw build environment.

Cc: Gerd Hoffmann 
Cc: Kostiantyn Kostiuk 
Cc: Marc-André Lureau 
Cc: Philippe Mathieu-Daudé 
Signed-off-by: Michael Roth 
---
 qga/installer/qemu-ga.wxs | 4 
 1 file changed, 4 insertions(+)

diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs
index ce7b25b5e1..0950e8c6be 100644
--- a/qga/installer/qemu-ga.wxs
+++ b/qga/installer/qemu-ga.wxs
@@ -84,6 +84,9 @@
 
   
   
+  
+
+  
   
 
   
@@ -164,6 +167,7 @@
 
   
   
+  
   
   
   
-- 
2.25.1




[PATCH v2 55/55] target/sh4: Implement prctl_unalign_sigbus

2021-08-02 Thread Richard Henderson
Leave TARGET_ALIGNED_ONLY set, but use the new CPUState
flag to set MO_UNALN for the instructions that the kernel
handles in the unaligned trap.

The Linux kernel does not handle all memory operations: no
floating-point and no MAC.

Signed-off-by: Richard Henderson 
---
 target/sh4/cpu.h   |  4 
 hw/core/cpu-user.c |  2 +-
 linux-user/syscall.c   |  2 +-
 target/sh4/translate.c | 50 --
 4 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index a9191951f8..5f2dc551e3 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -83,6 +83,7 @@
 #define DELAY_SLOT_RTE (1 << 2)
 
 #define TB_FLAG_PENDING_MOVCA  (1 << 3)
+#define TB_FLAG_UNALIGN(1 << 4)
 
 #define GUSA_SHIFT 4
 #ifdef CONFIG_USER_ONLY
@@ -376,6 +377,9 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, 
target_ulong *pc,
 | (env->sr & ((1u << SR_MD) | (1u << SR_RB)))  /* Bits 29-30 */
 | (env->sr & (1u << SR_FD))/* Bit 15 */
 | (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 3 */
+#ifdef CONFIG_USER_ONLY
+*flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
+#endif
 }
 
 #endif /* SH4_CPU_H */
diff --git a/hw/core/cpu-user.c b/hw/core/cpu-user.c
index 6a5edcfb77..0ad009f186 100644
--- a/hw/core/cpu-user.c
+++ b/hw/core/cpu-user.c
@@ -24,7 +24,7 @@ static Property cpu_useronly_props[] = {
  * up its memory. The default if no link is set up is to use the
  * system address space.
  */
-#if defined(TARGET_ALPHA) || defined(TARGET_HPPA)
+#if defined(TARGET_ALPHA) || defined(TARGET_HPPA) || defined(TARGET_SH4)
 DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState,
  prctl_unalign_sigbus, false),
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 836a7eaee2..784ced821d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6644,7 +6644,7 @@ static abi_long do_prctl(CPUArchState *env, abi_long 
option, abi_long arg2,
  * We only implement PR_UNALIGN_SIGBUS, and only for those targets
  * who have had their translator updated to insert MO_ALIGN.
  */
-#if defined(TARGET_ALPHA) || defined(TARGET_HPPA)
+#if defined(TARGET_ALPHA) || defined(TARGET_HPPA) || defined(TARGET_SH4)
 case PR_GET_UNALIGN:
 {
 CPUState *cs = env_cpu(env);
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
index 8704fea1ca..58ec6e8ac9 100644
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -50,8 +50,10 @@ typedef struct DisasContext {
 
 #if defined(CONFIG_USER_ONLY)
 #define IS_USER(ctx) 1
+#define UNALIGN(C)   (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : 0)
 #else
 #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
+#define UNALIGN(C)   0
 #endif
 
 /* Target-specific values for ctx->base.is_jmp.  */
@@ -499,7 +501,8 @@ static void _decode_opc(DisasContext * ctx)
{
TCGv addr = tcg_temp_new();
tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
-tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
+tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
+MO_TEUL | UNALIGN(ctx));
tcg_temp_free(addr);
}
return;
@@ -507,7 +510,8 @@ static void _decode_opc(DisasContext * ctx)
{
TCGv addr = tcg_temp_new();
tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
-tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
+tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
+MO_TESL | UNALIGN(ctx));
tcg_temp_free(addr);
}
return;
@@ -562,19 +566,23 @@ static void _decode_opc(DisasContext * ctx)
 tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
return;
 case 0x2001:   /* mov.w Rm,@Rn */
-tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW);
+tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx,
+MO_TEUW | UNALIGN(ctx));
return;
 case 0x2002:   /* mov.l Rm,@Rn */
-tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
+tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx,
+MO_TEUL | UNALIGN(ctx));
return;
 case 0x6000:   /* mov.b @Rm,Rn */
 tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
return;
 case 0x6001:   /* mov.w @Rm,Rn */
-tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
+tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
+MO_TESW | UNALIGN(ctx));
return;
 case 0x6002:   /* mov.l @Rm,Rn */
-tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
+tcg_gen_qemu_ld_

[PATCH v2 50/55] hw/core/cpu: Add prctl-unalign-sigbus property for user-only

2021-08-02 Thread Richard Henderson
Actually disabled for now.  Will enable for each cpu that
supports the feature.

Signed-off-by: Richard Henderson 
---
 hw/core/cpu-user.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/hw/core/cpu-user.c b/hw/core/cpu-user.c
index 62037e8669..23786865cb 100644
--- a/hw/core/cpu-user.c
+++ b/hw/core/cpu-user.c
@@ -11,12 +11,27 @@
 
 #include "qemu/osdep.h"
 #include "hw/core/cpu.h"
+#include "hw/qdev-properties.h"
 #include "cpu-common.h"
 
 /*
  * This can't go in hw/core/cpu-common.c because that file is compiled only
  * once for both user-mode and system builds.
  */
+static Property cpu_useronly_props[] = {
+/*
+ * Create a memory property for softmmu CPU object, so users can wire
+ * up its memory. The default if no link is set up is to use the
+ * system address space.
+ */
+#if 0
+DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState,
+ prctl_unalign_sigbus, false),
+#endif
+DEFINE_PROP_END_OF_LIST(),
+};
+
 void cpu_class_init_props(DeviceClass *dc)
 {
+device_class_set_props(dc, cpu_useronly_props);
 }
-- 
2.25.1




Re: [PATCH] vhost: use large iotlb entry if no IOMMU translation is needed

2021-08-02 Thread Jason Wang



在 2021/8/3 下午12:29, Chao Gao 写道:

Ping. Could someone help to review this patch?

Thanks
Chao

On Wed, Jul 21, 2021 at 03:54:02PM +0800, Chao Gao wrote:

If guest enables IOMMU_PLATFORM for virtio-net, severe network
performance drop is observed even if there is no IOMMU.



We see such reports internally and we're testing a patch series to 
disable vhost IOTLB in this case.


Will post a patch soon.




  And disabling
vhost can mitigate the perf issue. Finally, we found the culprit is
frequent iotlb misses: kernel vhost-net has 2048 entries and each
entry is 4K (qemu uses 4K for i386 if no IOMMU); vhost-net can cache
translations for up to 8M (i.e. 4K*2048) IOVAs. If guest uses >8M
memory for DMA, there are some iotlb misses.

If there is no IOMMU or IOMMU is disabled or IOMMU works in pass-thru
mode, we can optimistically use large, unaligned iotlb entries instead
of 4K-aligned entries to reduce iotlb pressure.



Instead of introducing new general facilities like unaligned IOTLB 
entry. I wonder if we optimize the vtd_iommu_translate() to use e.g 1G 
instead?


    } else {
    /* DMAR disabled, passthrough, use 4k-page*/
    iotlb.iova = addr & VTD_PAGE_MASK_4K;
    iotlb.translated_addr = addr & VTD_PAGE_MASK_4K;
    iotlb.addr_mask = ~VTD_PAGE_MASK_4K;
    iotlb.perm = IOMMU_RW;
    success = true;
    }



  Actually, vhost-net
in kernel supports unaligned iotlb entry. The alignment requirement is
imposed by address_space_get_iotlb_entry() and flatview_do_translate().



For the passthrough case, is there anyway to detect them and then 
disable device IOTLB in those case?


Thanks




Introduce IOMMUTLBEntryUnaligned which has a @len field to specify the
iotlb size to abstract a generic iotlb entry: aligned (original
IOMMUTLBEntry) and unaligned entry. flatview_do_translate() now
returns a magic value in @page_mask_out if no IOMMU translation is
needed. Then, address_space_get_iotbl_entry() can accordingly return a
page-aligned iotlb entry or the whole memory region section where the
iova resides as a large iotlb entry.

Signed-off-by: Chao Gao 
---
hw/virtio/vhost.c |  6 +++---
include/exec/memory.h | 16 ++--
softmmu/physmem.c | 37 +
3 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index e8f85a5d2d..6745caa129 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1010,7 +1010,7 @@ static int vhost_memory_region_lookup(struct vhost_dev 
*hdev,

int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
{
-IOMMUTLBEntry iotlb;
+IOMMUTLBEntryUnaligned iotlb;
 uint64_t uaddr, len;
 int ret = -EFAULT;

@@ -1031,8 +1031,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, 
uint64_t iova, int write)
 goto out;
 }

-len = MIN(iotlb.addr_mask + 1, len);
-iova = iova & ~iotlb.addr_mask;
+len = MIN(iotlb.len, len);
+iova = iotlb.iova;

 ret = vhost_backend_update_device_iotlb(dev, iova, uaddr,
 len, iotlb.perm);
diff --git a/include/exec/memory.h b/include/exec/memory.h
index c3d417d317..3f04e8fe88 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -94,6 +94,7 @@ struct MemoryRegionSection {
};

typedef struct IOMMUTLBEntry IOMMUTLBEntry;
+typedef struct IOMMUTLBEntryUnaligned IOMMUTLBEntryUnaligned;

/* See address_space_translate: bit 0 is read, bit 1 is write.  */
typedef enum {
@@ -113,6 +114,15 @@ struct IOMMUTLBEntry {
 IOMMUAccessFlags perm;
};

+/* IOMMUTLBEntryUnaligned may be not page-aligned */
+struct IOMMUTLBEntryUnaligned {
+AddressSpace*target_as;
+hwaddr   iova;
+hwaddr   translated_addr;
+hwaddr   len;
+IOMMUAccessFlags perm;
+};
+
/*
  * Bitmap for different IOMMUNotifier capabilities. Each notifier can
  * register with one or multiple IOMMU Notifier capability bit(s).
@@ -2653,8 +2663,10 @@ void address_space_cache_destroy(MemoryRegionCache 
*cache);
/* address_space_get_iotlb_entry: translate an address into an IOTLB
  * entry. Should be called from an RCU critical section.
  */
-IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
-bool is_write, MemTxAttrs attrs);
+IOMMUTLBEntryUnaligned address_space_get_iotlb_entry(AddressSpace *as,
+ hwaddr addr,
+ bool is_write,
+ MemTxAttrs attrs);

/* address_space_translate: translate an address range into an address space
  * into a MemoryRegion and an address range into that section.  Should be
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index 3c1912a1a0..469963f754 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -143,6 +143,8 @@ typedef struct subpage_t {

#def

[PATCH v2 48/55] linux-user: Add code for PR_GET/SET_UNALIGN

2021-08-02 Thread Richard Henderson
This requires extra work for each target, but adds the
common syscall code, and the necessary flag in CPUState.

Signed-off-by: Richard Henderson 
---
 include/hw/core/cpu.h |  3 +++
 linux-user/syscall.c  | 21 +++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index b7d5bc1200..088b2d1adf 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -412,6 +412,9 @@ struct CPUState {
 
 bool ignore_memory_transaction_failures;
 
+/* Used for user-only emulation of prctl(PR_SET_UNALIGN). */
+bool prctl_unalign_sigbus;
+
 struct hax_vcpu_state *hax_vcpu;
 
 struct hvf_vcpu_state *hvf;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e303a9da7f..b2e3c28b41 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6640,6 +6640,25 @@ static abi_long do_prctl(CPUArchState *env, abi_long 
option, abi_long arg2,
 }
 return do_prctl_get_tagged_addr_ctrl(env);
 
+/*
+ * We only implement PR_UNALIGN_SIGBUS, and only for those targets
+ * who have had their translator updated to insert MO_ALIGN.
+ */
+#if 0
+case PR_GET_UNALIGN:
+{
+CPUState *cs = env_cpu(env);
+uint32_t res = PR_UNALIGN_NOPRINT;
+if (cs->prctl_unalign_sigbus) {
+res |= PR_UNALIGN_SIGBUS;
+}
+return put_user_u32(res, arg2);
+}
+case PR_SET_UNALIGN:
+env_cpu(env)->prctl_unalign_sigbus = arg2 & PR_UNALIGN_SIGBUS;
+return 0;
+#endif
+
 case PR_GET_DUMPABLE:
 case PR_SET_DUMPABLE:
 case PR_GET_KEEPCAPS:
@@ -6682,8 +6701,6 @@ static abi_long do_prctl(CPUArchState *env, abi_long 
option, abi_long arg2,
 case PR_SET_THP_DISABLE:
 case PR_GET_TSC:
 case PR_SET_TSC:
-case PR_GET_UNALIGN:
-case PR_SET_UNALIGN:
 default:
 /* Disable to prevent the target disabling stuff we need. */
 return -TARGET_EINVAL;
-- 
2.25.1




[PATCH v2 45/55] linux-user: Split out do_prctl and subroutines

2021-08-02 Thread Richard Henderson
Since the prctl constants are supposed to be generic, supply
any that are not provided by the host.

Split out subroutines for PR_GET_FP_MODE, PR_SET_FP_MODE,
PR_GET_VL, PR_SET_VL, PR_RESET_KEYS, PR_SET_TAGGED_ADDR_CTRL,
PR_GET_TAGGED_ADDR_CTRL.  Return EINVAL for guests that do
not support these options rather than pass them on to the host.

Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/target_syscall.h |  23 -
 linux-user/mips/target_syscall.h|   6 -
 linux-user/mips64/target_syscall.h  |   6 -
 linux-user/syscall.c| 644 
 4 files changed, 359 insertions(+), 320 deletions(-)

diff --git a/linux-user/aarch64/target_syscall.h 
b/linux-user/aarch64/target_syscall.h
index 76f6c3391d..819f112ab0 100644
--- a/linux-user/aarch64/target_syscall.h
+++ b/linux-user/aarch64/target_syscall.h
@@ -20,27 +20,4 @@ struct target_pt_regs {
 #define TARGET_MCL_FUTURE  2
 #define TARGET_MCL_ONFAULT 4
 
-#define TARGET_PR_SVE_SET_VL  50
-#define TARGET_PR_SVE_GET_VL  51
-
-#define TARGET_PR_PAC_RESET_KEYS 54
-# define TARGET_PR_PAC_APIAKEY   (1 << 0)
-# define TARGET_PR_PAC_APIBKEY   (1 << 1)
-# define TARGET_PR_PAC_APDAKEY   (1 << 2)
-# define TARGET_PR_PAC_APDBKEY   (1 << 3)
-# define TARGET_PR_PAC_APGAKEY   (1 << 4)
-
-#define TARGET_PR_SET_TAGGED_ADDR_CTRL 55
-#define TARGET_PR_GET_TAGGED_ADDR_CTRL 56
-# define TARGET_PR_TAGGED_ADDR_ENABLE  (1UL << 0)
-/* MTE tag check fault modes */
-# define TARGET_PR_MTE_TCF_SHIFT   1
-# define TARGET_PR_MTE_TCF_NONE(0UL << TARGET_PR_MTE_TCF_SHIFT)
-# define TARGET_PR_MTE_TCF_SYNC(1UL << TARGET_PR_MTE_TCF_SHIFT)
-# define TARGET_PR_MTE_TCF_ASYNC   (2UL << TARGET_PR_MTE_TCF_SHIFT)
-# define TARGET_PR_MTE_TCF_MASK(3UL << TARGET_PR_MTE_TCF_SHIFT)
-/* MTE tag inclusion mask */
-# define TARGET_PR_MTE_TAG_SHIFT   3
-# define TARGET_PR_MTE_TAG_MASK(0xUL << TARGET_PR_MTE_TAG_SHIFT)
-
 #endif /* AARCH64_TARGET_SYSCALL_H */
diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h
index f59057493a..1ce0a5bbf4 100644
--- a/linux-user/mips/target_syscall.h
+++ b/linux-user/mips/target_syscall.h
@@ -36,10 +36,4 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
 return 0x4;
 }
 
-/* MIPS-specific prctl() options */
-#define TARGET_PR_SET_FP_MODE  45
-#define TARGET_PR_GET_FP_MODE  46
-#define TARGET_PR_FP_MODE_FR   (1 << 0)
-#define TARGET_PR_FP_MODE_FRE  (1 << 1)
-
 #endif /* MIPS_TARGET_SYSCALL_H */
diff --git a/linux-user/mips64/target_syscall.h 
b/linux-user/mips64/target_syscall.h
index cd1e1b4969..74f12365bc 100644
--- a/linux-user/mips64/target_syscall.h
+++ b/linux-user/mips64/target_syscall.h
@@ -33,10 +33,4 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
 return 0x4;
 }
 
-/* MIPS-specific prctl() options */
-#define TARGET_PR_SET_FP_MODE  45
-#define TARGET_PR_GET_FP_MODE  46
-#define TARGET_PR_FP_MODE_FR   (1 << 0)
-#define TARGET_PR_FP_MODE_FRE  (1 << 1)
-
 #endif /* MIPS64_TARGET_SYSCALL_H */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ccd3892b2d..6e630745fa 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6282,9 +6282,366 @@ abi_long do_arch_prctl(CPUX86State *env, int code, 
abi_ulong addr)
 return ret;
 }
 #endif /* defined(TARGET_ABI32 */
-
 #endif /* defined(TARGET_I386) */
 
+/*
+ * These constants are generic.  Supply any that are missing from the host.
+ */
+#ifndef PR_SET_NAME
+# define PR_SET_NAME15
+# define PR_GET_NAME16
+#endif
+#ifndef PR_SET_FP_MODE
+# define PR_SET_FP_MODE 45
+# define PR_GET_FP_MODE 46
+# define PR_FP_MODE_FR   (1 << 0)
+# define PR_FP_MODE_FRE  (1 << 1)
+#endif
+#ifndef PR_SVE_SET_VL
+# define PR_SVE_SET_VL  50
+# define PR_SVE_GET_VL  51
+# define PR_SVE_VL_LEN_MASK  0x
+# define PR_SVE_VL_INHERIT   (1 << 17)
+#endif
+#ifndef PR_PAC_RESET_KEYS
+# define PR_PAC_RESET_KEYS  54
+# define PR_PAC_APIAKEY   (1 << 0)
+# define PR_PAC_APIBKEY   (1 << 1)
+# define PR_PAC_APDAKEY   (1 << 2)
+# define PR_PAC_APDBKEY   (1 << 3)
+# define PR_PAC_APGAKEY   (1 << 4)
+#endif
+#ifndef PR_SET_TAGGED_ADDR_CTRL
+# define PR_SET_TAGGED_ADDR_CTRL 55
+# define PR_GET_TAGGED_ADDR_CTRL 56
+# define PR_TAGGED_ADDR_ENABLE  (1UL << 0)
+#endif
+#ifndef PR_MTE_TCF_SHIFT
+# define PR_MTE_TCF_SHIFT   1
+# define PR_MTE_TCF_NONE(0UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_SYNC(1UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_ASYNC   (2UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TCF_MASK(3UL << PR_MTE_TCF_SHIFT)
+# define PR_MTE_TAG_SHIFT   3
+# define PR_MTE_TAG_MASK(0xUL << PR_MTE_TAG_SHIFT)
+#endif
+
+static abi_long do_prctl_get_fp_mode(CPUArchState *env)
+{
+#ifdef TARGET_MIPS
+abi_long ret = 0;
+
+if (env->CP0_Status & (1 << CP0St_FR)) {
+ret |= PR_FP_MODE_FR;
+}
+if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
+ret |= PR_FP_MODE_FRE;
+}
+return ret;
+#else
+return -TARGET_EINVA

[PATCH v2 54/55] target/hppa: Implement prctl_unalign_sigbus

2021-08-02 Thread Richard Henderson
Leave TARGET_ALIGNED_ONLY set, but use the new CPUState
flag to set MO_UNALN for the instructions that the kernel
handles in the unaligned trap.

Signed-off-by: Richard Henderson 
---
 target/hppa/cpu.h   |  5 -
 hw/core/cpu-user.c  |  2 +-
 linux-user/syscall.c|  2 +-
 target/hppa/translate.c | 19 +++
 4 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 748270bfa3..332ca5de62 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -259,12 +259,14 @@ static inline target_ulong hppa_form_gva(CPUHPPAState 
*env, uint64_t spc,
 return hppa_form_gva_psw(env->psw, spc, off);
 }
 
-/* Since PSW_{I,CB} will never need to be in tb->flags, reuse them.
+/*
+ * Since PSW_{I,CB} will never need to be in tb->flags, reuse them.
  * TB_FLAG_SR_SAME indicates that SR4 through SR7 all contain the
  * same value.
  */
 #define TB_FLAG_SR_SAME PSW_I
 #define TB_FLAG_PRIV_SHIFT  8
+#define TB_FLAG_UNALIGN 0x400
 
 static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc,
 target_ulong *cs_base,
@@ -279,6 +281,7 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, 
target_ulong *pc,
 #ifdef CONFIG_USER_ONLY
 *pc = env->iaoq_f & -4;
 *cs_base = env->iaoq_b & -4;
+flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
 #else
 /* ??? E, T, H, L, B, P bits need to be here, when implemented.  */
 flags |= env->psw & (PSW_W | PSW_C | PSW_D);
diff --git a/hw/core/cpu-user.c b/hw/core/cpu-user.c
index daf8ff59b5..6a5edcfb77 100644
--- a/hw/core/cpu-user.c
+++ b/hw/core/cpu-user.c
@@ -24,7 +24,7 @@ static Property cpu_useronly_props[] = {
  * up its memory. The default if no link is set up is to use the
  * system address space.
  */
-#if defined(TARGET_ALPHA)
+#if defined(TARGET_ALPHA) || defined(TARGET_HPPA)
 DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState,
  prctl_unalign_sigbus, false),
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 15080d0539..836a7eaee2 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6644,7 +6644,7 @@ static abi_long do_prctl(CPUArchState *env, abi_long 
option, abi_long arg2,
  * We only implement PR_UNALIGN_SIGBUS, and only for those targets
  * who have had their translator updated to insert MO_ALIGN.
  */
-#if defined(TARGET_ALPHA)
+#if defined(TARGET_ALPHA) || defined(TARGET_HPPA)
 case PR_GET_UNALIGN:
 {
 CPUState *cs = env_cpu(env);
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index b18150ef8d..1cfa801533 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -275,8 +275,18 @@ typedef struct DisasContext {
 int mmu_idx;
 int privilege;
 bool psw_n_nonzero;
+
+#ifdef CONFIG_USER_ONLY
+MemOp unalign;
+#endif
 } DisasContext;
 
+#ifdef CONFIG_USER_ONLY
+#define UNALIGN(C)  (C)->unalign
+#else
+#define UNALIGN(C)  0
+#endif
+
 /* Note that ssm/rsm instructions number PSW_W and PSW_E differently.  */
 static int expand_sm_imm(DisasContext *ctx, int val)
 {
@@ -1480,7 +1490,7 @@ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, 
unsigned rb,
 
 form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
  ctx->mmu_idx == MMU_PHYS_IDX);
-tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop);
+tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
 if (modify) {
 save_gpr(ctx, rb, ofs);
 }
@@ -1498,7 +1508,7 @@ static void do_load_64(DisasContext *ctx, TCGv_i64 dest, 
unsigned rb,
 
 form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
  ctx->mmu_idx == MMU_PHYS_IDX);
-tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop);
+tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
 if (modify) {
 save_gpr(ctx, rb, ofs);
 }
@@ -1516,7 +1526,7 @@ static void do_store_32(DisasContext *ctx, TCGv_i32 src, 
unsigned rb,
 
 form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
  ctx->mmu_idx == MMU_PHYS_IDX);
-tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop);
+tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
 if (modify) {
 save_gpr(ctx, rb, ofs);
 }
@@ -1534,7 +1544,7 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, 
unsigned rb,
 
 form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
  ctx->mmu_idx == MMU_PHYS_IDX);
-tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop);
+tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
 if (modify) {
 save_gpr(ctx, rb, ofs);
 }
@@ -4113,6 +4123,7 @@ static void hppa_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->mmu_idx = MMU_USER_IDX;
 ctx->iaoq_f = ctx->base.pc_first | MMU_USER_IDX;
 ctx->iaoq_b = ctx->base.tb->cs_base | MMU_USER_IDX;
+ctx->unalign =

Re: [PATCH] vhost: use large iotlb entry if no IOMMU translation is needed

2021-08-02 Thread Chao Gao
Ping. Could someone help to review this patch?

Thanks
Chao

On Wed, Jul 21, 2021 at 03:54:02PM +0800, Chao Gao wrote:
>If guest enables IOMMU_PLATFORM for virtio-net, severe network
>performance drop is observed even if there is no IOMMU. And disabling
>vhost can mitigate the perf issue. Finally, we found the culprit is
>frequent iotlb misses: kernel vhost-net has 2048 entries and each
>entry is 4K (qemu uses 4K for i386 if no IOMMU); vhost-net can cache
>translations for up to 8M (i.e. 4K*2048) IOVAs. If guest uses >8M
>memory for DMA, there are some iotlb misses.
>
>If there is no IOMMU or IOMMU is disabled or IOMMU works in pass-thru
>mode, we can optimistically use large, unaligned iotlb entries instead
>of 4K-aligned entries to reduce iotlb pressure. Actually, vhost-net
>in kernel supports unaligned iotlb entry. The alignment requirement is
>imposed by address_space_get_iotlb_entry() and flatview_do_translate().
>
>Introduce IOMMUTLBEntryUnaligned which has a @len field to specify the
>iotlb size to abstract a generic iotlb entry: aligned (original
>IOMMUTLBEntry) and unaligned entry. flatview_do_translate() now
>returns a magic value in @page_mask_out if no IOMMU translation is
>needed. Then, address_space_get_iotbl_entry() can accordingly return a
>page-aligned iotlb entry or the whole memory region section where the
>iova resides as a large iotlb entry.
>
>Signed-off-by: Chao Gao 
>---
> hw/virtio/vhost.c |  6 +++---
> include/exec/memory.h | 16 ++--
> softmmu/physmem.c | 37 +
> 3 files changed, 46 insertions(+), 13 deletions(-)
>
>diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
>index e8f85a5d2d..6745caa129 100644
>--- a/hw/virtio/vhost.c
>+++ b/hw/virtio/vhost.c
>@@ -1010,7 +1010,7 @@ static int vhost_memory_region_lookup(struct vhost_dev 
>*hdev,
> 
> int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
> {
>-IOMMUTLBEntry iotlb;
>+IOMMUTLBEntryUnaligned iotlb;
> uint64_t uaddr, len;
> int ret = -EFAULT;
> 
>@@ -1031,8 +1031,8 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, 
>uint64_t iova, int write)
> goto out;
> }
> 
>-len = MIN(iotlb.addr_mask + 1, len);
>-iova = iova & ~iotlb.addr_mask;
>+len = MIN(iotlb.len, len);
>+iova = iotlb.iova;
> 
> ret = vhost_backend_update_device_iotlb(dev, iova, uaddr,
> len, iotlb.perm);
>diff --git a/include/exec/memory.h b/include/exec/memory.h
>index c3d417d317..3f04e8fe88 100644
>--- a/include/exec/memory.h
>+++ b/include/exec/memory.h
>@@ -94,6 +94,7 @@ struct MemoryRegionSection {
> };
> 
> typedef struct IOMMUTLBEntry IOMMUTLBEntry;
>+typedef struct IOMMUTLBEntryUnaligned IOMMUTLBEntryUnaligned;
> 
> /* See address_space_translate: bit 0 is read, bit 1 is write.  */
> typedef enum {
>@@ -113,6 +114,15 @@ struct IOMMUTLBEntry {
> IOMMUAccessFlags perm;
> };
> 
>+/* IOMMUTLBEntryUnaligned may be not page-aligned */
>+struct IOMMUTLBEntryUnaligned {
>+AddressSpace*target_as;
>+hwaddr   iova;
>+hwaddr   translated_addr;
>+hwaddr   len;
>+IOMMUAccessFlags perm;
>+};
>+
> /*
>  * Bitmap for different IOMMUNotifier capabilities. Each notifier can
>  * register with one or multiple IOMMU Notifier capability bit(s).
>@@ -2653,8 +2663,10 @@ void address_space_cache_destroy(MemoryRegionCache 
>*cache);
> /* address_space_get_iotlb_entry: translate an address into an IOTLB
>  * entry. Should be called from an RCU critical section.
>  */
>-IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
>-bool is_write, MemTxAttrs attrs);
>+IOMMUTLBEntryUnaligned address_space_get_iotlb_entry(AddressSpace *as,
>+ hwaddr addr,
>+ bool is_write,
>+ MemTxAttrs attrs);
> 
> /* address_space_translate: translate an address range into an address space
>  * into a MemoryRegion and an address range into that section.  Should be
>diff --git a/softmmu/physmem.c b/softmmu/physmem.c
>index 3c1912a1a0..469963f754 100644
>--- a/softmmu/physmem.c
>+++ b/softmmu/physmem.c
>@@ -143,6 +143,8 @@ typedef struct subpage_t {
> 
> #define PHYS_SECTION_UNASSIGNED 0
> 
>+#define PAGE_MASK_NOT_BEHIND_IOMMU ((hwaddr)-1)
>+
> static void io_mem_init(void);
> static void memory_map_init(void);
> static void tcg_log_global_after_sync(MemoryListener *listener);
>@@ -470,7 +472,9 @@ unassigned:
>  * @page_mask_out: page mask for the translated address. This
>  *should only be meaningful for IOMMU translated
>  *addresses, since there may be huge pages that this bit
>- *would tell. It can be @NULL if we don't care about it.
>+ *would tell. If the returned memory region section isn't
>+

[Bug 1878054] Re: Hang with high CPU usage in sdhci_data_transfer

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

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

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

Title:
  Hang with high CPU usage in sdhci_data_transfer

Status in QEMU:
  Expired

Bug description:
  Hello,
  While fuzzing, I found an input that causes QEMU to hang with 100% CPU usage.
  I have waited several minutes, and QEMU is still unresponsive. Using gdb, It
  appears that it is stuck in an sdhci_data_transfer:

  #0   memory_region_access_valid (mr=, addr=0x10284920, 
size=, is_write=0xff, attrs=...) at 
/home/alxndr/Development/qemu/memory.c:1378
  #1   memory_region_dispatch_write (mr=, addr=, 
data=, op=MO_32, attrs=...) at 
/home/alxndr/Development/qemu/memory.c:1463
  #2   flatview_write_continue (fv=, addr=0x10284920, attrs=..., 
ptr=, len=0xb7, addr1=0x582798e0, l=, 
mr=0x582798e0 ) at 
/home/alxndr/Development/qemu/exec.c:3137
  #3   flatview_write (fv=0x60645da0, addr=, attrs=..., 
buf=, len=) at 
/home/alxndr/Development/qemu/exec.c:3177
  #4   address_space_write (as=, addr=, 
attrs=..., buf=0xb04f325, len=0x4) at 
/home/alxndr/Development/qemu/exec.c:3268
  #5   address_space_rw (as=0x572509ac , 
addr=0x582798e0, attrs=..., attrs@entry=..., buf=0xb04f325, len=0x4, 
is_write=0xb8, is_write@entry=0x1) at
  /home/alxndr/Development/qemu/exec.c:3278
  #6   dma_memory_rw_relaxed (as=0x572509ac , 
addr=0x582798e0, buf=0xb04f325, len=0x4, dir=DMA_DIRECTION_FROM_DEVICE) 
at /home/alxndr/Development/qemu/include/sysemu/dma.h:87
  #7   dma_memory_rw (as=0x572509ac , 
addr=0x582798e0, buf=0xb04f325, len=0x4, dir=DMA_DIRECTION_FROM_DEVICE) 
at /home/alxndr/Development/qemu/include/sysemu/dma.h:110
  #8   dma_memory_write (as=0x572509ac , 
addr=0x582798e0, buf=0xb04f325, len=0x4) at 
/home/alxndr/Development/qemu/include/sysemu/dma.h:122
  #9   sdhci_sdma_transfer_multi_blocks (s=) at 
/home/alxndr/Development/qemu/hw/sd/sdhci.c:618
  #10  sdhci_data_transfer (opaque=0x61e21080) at 
/home/alxndr/Development/qemu/hw/sd/sdhci.c:891
  #11  sdhci_send_command (s=0x61e21080) at 
/home/alxndr/Development/qemu/hw/sd/sdhci.c:364
  #12  sdhci_write (opaque=, offset=0xc, val=, 
size=) at /home/alxndr/Development/qemu/hw/sd/sdhci.c:1158
  #13  memory_region_write_accessor (mr=, addr=, 
value=, size=, shift=, 
mask=, attrs=...) at
  /home/alxndr/Development/qemu/memory.c:483
  #14  access_with_adjusted_size (addr=, value=, 
size=, access_size_min=, 
access_size_max=, access_fn=, mr=0x61e219f0, 
attrs=...) at /home/alxndr/Development/qemu/memory.c:544
  #15  memory_region_dispatch_write (mr=, addr=, 
data=0x1ffe0ff, op=, attrs=...) at 
/home/alxndr/Development/qemu/memory.c:1476
  #16  flatview_write_continue (fv=, addr=0xe106800c, attrs=..., 
ptr=, len=0xff3, addr1=0x582798e0, l=, 
mr=0x61e219f0) at /home/alxndr/Development/qemu/exec.c:3137
  #17  flatview_write (fv=0x60645da0, addr=, attrs=..., 
buf=, len=) at 
/home/alxndr/Development/qemu/exec.c:3177
  #18  address_space_write (as=, addr=, 
attrs=..., attrs@entry=..., buf=0xb04f325, buf@entry=0x6218ad00, 
len=0x4) at /home/alxndr/Development/qemu/exec.c:3268
  #19  qtest_process_command (chr=, chr@entry=0x5827c040 
, words=) at /home/alxndr/Development/qemu/qtest.c:567
  #20  qtest_process_inbuf (chr=0x5827c040 , 
inbuf=0x6190f640) at /home/alxndr/Development/qemu/qtest.c:710

  
  I am attaching the qtest commands for reproducing it.
  I can reproduce it in a qemu 5.0 build using:

  qemu-system-i386 -M pc-q35-5.0 -qtest stdio -device sdhci-pci,sd-spec-
  version=3 -device sd-card,drive=mydrive -drive
  if=sd,index=0,file=null-co://,format=raw,id=mydrive -nographic
  -nographic -serial none -monitor none < attachment

  Please let me know if I can provide any further info.
  -Alex

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




[PATCH v2 40/55] target/arm: Use cpu_*_mmu instead of helper_*_mmu

2021-08-02 Thread Richard Henderson
The helper_*_mmu functions were the only thing available
when this code was written.  This could have been adjusted
when we added cpu_*_mmuidx_ra, but now we can most easily
use the newest set of interfaces.

Cc: qemu-...@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/arm/helper-a64.c | 52 +++--
 target/arm/m_helper.c   |  6 ++---
 2 files changed, 11 insertions(+), 47 deletions(-)

diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index f1a4089a4f..17c0ebebb2 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -512,37 +512,19 @@ uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, 
uint64_t addr,
 uintptr_t ra = GETPC();
 uint64_t o0, o1;
 bool success;
-
-#ifdef CONFIG_USER_ONLY
-/* ??? Enforce alignment.  */
-uint64_t *haddr = g2h(env_cpu(env), addr);
-
-set_helper_retaddr(ra);
-o0 = ldq_le_p(haddr + 0);
-o1 = ldq_le_p(haddr + 1);
-oldv = int128_make128(o0, o1);
-
-success = int128_eq(oldv, cmpv);
-if (success) {
-stq_le_p(haddr + 0, int128_getlo(newv));
-stq_le_p(haddr + 1, int128_gethi(newv));
-}
-clear_helper_retaddr();
-#else
 int mem_idx = cpu_mmu_index(env, false);
 MemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
 MemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx);
 
-o0 = helper_le_ldq_mmu(env, addr + 0, oi0, ra);
-o1 = helper_le_ldq_mmu(env, addr + 8, oi1, ra);
+o0 = cpu_ldq_le_mmu(env, addr + 0, oi0, ra);
+o1 = cpu_ldq_le_mmu(env, addr + 8, oi1, ra);
 oldv = int128_make128(o0, o1);
 
 success = int128_eq(oldv, cmpv);
 if (success) {
-helper_le_stq_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
-helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
+cpu_stq_le_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
+cpu_stq_le_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
 }
-#endif
 
 return !success;
 }
@@ -582,37 +564,19 @@ uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, 
uint64_t addr,
 uintptr_t ra = GETPC();
 uint64_t o0, o1;
 bool success;
-
-#ifdef CONFIG_USER_ONLY
-/* ??? Enforce alignment.  */
-uint64_t *haddr = g2h(env_cpu(env), addr);
-
-set_helper_retaddr(ra);
-o1 = ldq_be_p(haddr + 0);
-o0 = ldq_be_p(haddr + 1);
-oldv = int128_make128(o0, o1);
-
-success = int128_eq(oldv, cmpv);
-if (success) {
-stq_be_p(haddr + 0, int128_gethi(newv));
-stq_be_p(haddr + 1, int128_getlo(newv));
-}
-clear_helper_retaddr();
-#else
 int mem_idx = cpu_mmu_index(env, false);
 MemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
 MemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx);
 
-o1 = helper_be_ldq_mmu(env, addr + 0, oi0, ra);
-o0 = helper_be_ldq_mmu(env, addr + 8, oi1, ra);
+o1 = cpu_ldq_be_mmu(env, addr + 0, oi0, ra);
+o0 = cpu_ldq_be_mmu(env, addr + 8, oi1, ra);
 oldv = int128_make128(o0, o1);
 
 success = int128_eq(oldv, cmpv);
 if (success) {
-helper_be_stq_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
-helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
+cpu_stq_be_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
+cpu_stq_be_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
 }
-#endif
 
 return !success;
 }
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index efb522dc44..b6019595f5 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -1947,9 +1947,9 @@ static bool do_v7m_function_return(ARMCPU *cpu)
  * do them as secure, so work out what MMU index that is.
  */
 mmu_idx = arm_v7m_mmu_idx_for_secstate(env, true);
-oi = make_memop_idx(MO_LE, arm_to_core_mmu_idx(mmu_idx));
-newpc = helper_le_ldul_mmu(env, frameptr, oi, 0);
-newpsr = helper_le_ldul_mmu(env, frameptr + 4, oi, 0);
+oi = make_memop_idx(MO_LEUL, arm_to_core_mmu_idx(mmu_idx));
+newpc = cpu_ldl_le_mmu(env, frameptr, oi, 0);
+newpsr = cpu_ldl_le_mmu(env, frameptr + 4, oi, 0);
 
 /* Consistency checks on new IPSR */
 newpsr_exc = newpsr & XPSR_EXCP;
-- 
2.25.1




[PATCH v2 51/55] target/alpha: Reorg fp memory operations

2021-08-02 Thread Richard Henderson
Pass in the context to each mini-helper, instead of an
incorrectly named "flags".  Separate gen_load_fp and
gen_store_fp, away from the integer helpers.

Signed-off-by: Richard Henderson 
---
 target/alpha/translate.c | 83 +++-
 1 file changed, 57 insertions(+), 26 deletions(-)

diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index de6c0a8439..607b6c3da7 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -267,30 +267,47 @@ static inline DisasJumpType gen_invalid(DisasContext *ctx)
 return gen_excp(ctx, EXCP_OPCDEC, 0);
 }
 
-static inline void gen_qemu_ldf(TCGv t0, TCGv t1, int flags)
+static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
 {
 TCGv_i32 tmp32 = tcg_temp_new_i32();
-tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
-gen_helper_memory_to_f(t0, tmp32);
+tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
+gen_helper_memory_to_f(dest, tmp32);
 tcg_temp_free_i32(tmp32);
 }
 
-static inline void gen_qemu_ldg(TCGv t0, TCGv t1, int flags)
+static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
 {
 TCGv tmp = tcg_temp_new();
-tcg_gen_qemu_ld_i64(tmp, t1, flags, MO_LEQ);
-gen_helper_memory_to_g(t0, tmp);
+tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ);
+gen_helper_memory_to_g(dest, tmp);
 tcg_temp_free(tmp);
 }
 
-static inline void gen_qemu_lds(TCGv t0, TCGv t1, int flags)
+static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
 {
 TCGv_i32 tmp32 = tcg_temp_new_i32();
-tcg_gen_qemu_ld_i32(tmp32, t1, flags, MO_LEUL);
-gen_helper_memory_to_s(t0, tmp32);
+tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
+gen_helper_memory_to_s(dest, tmp32);
 tcg_temp_free_i32(tmp32);
 }
 
+static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
+{
+tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ);
+}
+
+static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
+void (*func)(DisasContext *, TCGv, TCGv))
+{
+/* Loads to $f31 are prefetches, which we can treat as nops. */
+if (likely(ra != 31)) {
+TCGv addr = tcg_temp_new();
+tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
+func(ctx, cpu_fir[ra], addr);
+tcg_temp_free(addr);
+}
+}
+
 static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
 {
 tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
@@ -338,30 +355,44 @@ static inline void gen_load_mem(DisasContext *ctx,
 tcg_temp_free(tmp);
 }
 
-static inline void gen_qemu_stf(TCGv t0, TCGv t1, int flags)
+static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
 {
 TCGv_i32 tmp32 = tcg_temp_new_i32();
-gen_helper_f_to_memory(tmp32, t0);
-tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
+gen_helper_f_to_memory(tmp32, addr);
+tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
 tcg_temp_free_i32(tmp32);
 }
 
-static inline void gen_qemu_stg(TCGv t0, TCGv t1, int flags)
+static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr)
 {
 TCGv tmp = tcg_temp_new();
-gen_helper_g_to_memory(tmp, t0);
-tcg_gen_qemu_st_i64(tmp, t1, flags, MO_LEQ);
+gen_helper_g_to_memory(tmp, src);
+tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEQ);
 tcg_temp_free(tmp);
 }
 
-static inline void gen_qemu_sts(TCGv t0, TCGv t1, int flags)
+static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr)
 {
 TCGv_i32 tmp32 = tcg_temp_new_i32();
-gen_helper_s_to_memory(tmp32, t0);
-tcg_gen_qemu_st_i32(tmp32, t1, flags, MO_LEUL);
+gen_helper_s_to_memory(tmp32, src);
+tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
 tcg_temp_free_i32(tmp32);
 }
 
+static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
+{
+tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEQ);
+}
+
+static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
+ void (*func)(DisasContext *, TCGv, TCGv))
+{
+TCGv addr = tcg_temp_new();
+tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
+func(ctx, load_fpr(ctx, ra), addr);
+tcg_temp_free(addr);
+}
+
 static inline void gen_store_mem(DisasContext *ctx,
  void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
 int flags),
@@ -2776,42 +2807,42 @@ static DisasJumpType translate_one(DisasContext *ctx, 
uint32_t insn)
 case 0x20:
 /* LDF */
 REQUIRE_FEN;
-gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
+gen_load_fp(ctx, ra, rb, disp16, gen_ldf);
 break;
 case 0x21:
 /* LDG */
 REQUIRE_FEN;
-gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
+gen_load_fp(ctx, ra, rb, disp16, gen_ldg);
 break;
 case 0x22:
 /* LDS */
 REQUIRE_FEN;
-gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
+gen_load_fp(ctx, 

[PATCH v2 49/55] hw/core/cpu: Move cpu properties to cpu-sysemu.c

2021-08-02 Thread Richard Henderson
The comment in cpu-common.c is absolutely correct, we can't
rely on the ifdef in a file built once.  This was only "working"
because we used ifndef.

Signed-off-by: Richard Henderson 
---
 hw/core/cpu-common.h | 17 +
 hw/core/cpu-common.c | 18 ++
 hw/core/cpu-sysemu.c | 24 
 hw/core/cpu-user.c   | 22 ++
 hw/core/meson.build  |  4 
 5 files changed, 69 insertions(+), 16 deletions(-)
 create mode 100644 hw/core/cpu-common.h
 create mode 100644 hw/core/cpu-user.c

diff --git a/hw/core/cpu-common.h b/hw/core/cpu-common.h
new file mode 100644
index 00..9049f74e67
--- /dev/null
+++ b/hw/core/cpu-common.h
@@ -0,0 +1,17 @@
+/*
+ * QEMU CPU model
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef HW_CORE_CPU_COMMON_H
+#define HW_CORE_CPU_COMMON_H
+
+void cpu_class_init_props(DeviceClass *dc);
+
+#endif
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index e2f5a64604..6406ea79f0 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -34,6 +34,7 @@
 #include "hw/qdev-properties.h"
 #include "trace/trace-root.h"
 #include "qemu/plugin.h"
+#include "cpu-common.h"
 
 CPUState *cpu_by_arch_id(int64_t id)
 {
@@ -257,21 +258,6 @@ static int64_t cpu_common_get_arch_id(CPUState *cpu)
 return cpu->cpu_index;
 }
 
-static Property cpu_common_props[] = {
-#ifndef CONFIG_USER_ONLY
-/* Create a memory property for softmmu CPU object,
- * so users can wire up its memory. (This can't go in hw/core/cpu.c
- * because that file is compiled only once for both user-mode
- * and system builds.) The default if no link is set up is to use
- * the system address space.
- */
-DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
- MemoryRegion *),
-#endif
-DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, false),
-DEFINE_PROP_END_OF_LIST(),
-};
-
 static void cpu_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -286,7 +272,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
 dc->realize = cpu_common_realizefn;
 dc->unrealize = cpu_common_unrealizefn;
 dc->reset = cpu_common_reset;
-device_class_set_props(dc, cpu_common_props);
+cpu_class_init_props(dc);
 /*
  * Reason: CPUs still need special care by board code: wiring up
  * IRQs, adding reset handlers, halting non-first CPUs, ...
diff --git a/hw/core/cpu-sysemu.c b/hw/core/cpu-sysemu.c
index 00253f8929..5a62960f3c 100644
--- a/hw/core/cpu-sysemu.c
+++ b/hw/core/cpu-sysemu.c
@@ -20,8 +20,11 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "exec/memory.h"
 #include "hw/core/cpu.h"
 #include "hw/core/sysemu-cpu-ops.h"
+#include "hw/qdev-properties.h"
+#include "cpu-common.h"
 
 bool cpu_paging_enabled(const CPUState *cpu)
 {
@@ -143,3 +146,24 @@ GuestPanicInformation *cpu_get_crash_info(CPUState *cpu)
 }
 return res;
 }
+
+/*
+ * This can't go in hw/core/cpu-common.c because that file is compiled only
+ * once for both user-mode and system builds.
+ */
+static Property cpu_sysemu_props[] = {
+/*
+ * Create a memory property for softmmu CPU object, so users can wire
+ * up its memory. The default if no link is set up is to use the
+ * system address space.
+ */
+DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
+ MemoryRegion *),
+DEFINE_PROP_BOOL("start-powered-off", CPUState, start_powered_off, false),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+void cpu_class_init_props(DeviceClass *dc)
+{
+device_class_set_props(dc, cpu_sysemu_props);
+}
diff --git a/hw/core/cpu-user.c b/hw/core/cpu-user.c
new file mode 100644
index 00..62037e8669
--- /dev/null
+++ b/hw/core/cpu-user.c
@@ -0,0 +1,22 @@
+/*
+ * QEMU CPU model (user-only emulation specific)
+ *
+ * Copyright (c) 2021 Linaro, Ltd.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/core/cpu.h"
+#include "cpu-common.h"
+
+/*
+ * This can't go in hw/core/cpu-common.c because that file is compiled only
+ * once for both user-mode and system builds.
+ */
+void cpu_class_init_props(DeviceClass *dc)
+{
+}
diff --git a/hw/core/meson.build b/hw/core/meson.build
index 18f44fb7c2..4b3de4e247 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -43,3 +43,7 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files(
   'machine-qmp-cmds.c',
   'numa.c',
 ))
+
+specific_ss.add(when: 'CONFIG_USER_ONLY', if_true: files(
+  'cpu-user.c'
+))
-- 
2.25.1




[PATCH v2 53/55] target/alpha: Implement prctl_unalign_sigbus

2021-08-02 Thread Richard Henderson
Leave TARGET_ALIGNED_ONLY set, but use the new CPUState
flag to set MO_UNALN for the instructions that the kernel
handles in the unaligned trap.

Signed-off-by: Richard Henderson 
---
 target/alpha/cpu.h   |  5 +
 hw/core/cpu-user.c   |  2 +-
 linux-user/syscall.c |  2 +-
 target/alpha/translate.c | 31 ++-
 4 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 6eb3fcc63e..d9099ea188 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -387,6 +387,8 @@ enum {
 #define ENV_FLAG_TB_MASK \
 (ENV_FLAG_PAL_MODE | ENV_FLAG_PS_USER | ENV_FLAG_FEN)
 
+#define TB_FLAG_UNALIGN   (1u << 1)
+
 static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
 {
 int ret = env->flags & ENV_FLAG_PS_USER ? MMU_USER_IDX : MMU_KERNEL_IDX;
@@ -469,6 +471,9 @@ static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, 
target_ulong *pc,
 *pc = env->pc;
 *cs_base = 0;
 *pflags = env->flags & ENV_FLAG_TB_MASK;
+#ifdef CONFIG_USER_ONLY
+*pflags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
+#endif
 }
 
 #ifdef CONFIG_USER_ONLY
diff --git a/hw/core/cpu-user.c b/hw/core/cpu-user.c
index 23786865cb..daf8ff59b5 100644
--- a/hw/core/cpu-user.c
+++ b/hw/core/cpu-user.c
@@ -24,7 +24,7 @@ static Property cpu_useronly_props[] = {
  * up its memory. The default if no link is set up is to use the
  * system address space.
  */
-#if 0
+#if defined(TARGET_ALPHA)
 DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState,
  prctl_unalign_sigbus, false),
 #endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b2e3c28b41..15080d0539 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6644,7 +6644,7 @@ static abi_long do_prctl(CPUArchState *env, abi_long 
option, abi_long arg2,
  * We only implement PR_UNALIGN_SIGBUS, and only for those targets
  * who have had their translator updated to insert MO_ALIGN.
  */
-#if 0
+#if defined(TARGET_ALPHA)
 case PR_GET_UNALIGN:
 {
 CPUState *cs = env_cpu(env);
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index c14c1156a0..f6ba6a1a59 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -45,7 +45,9 @@ typedef struct DisasContext DisasContext;
 struct DisasContext {
 DisasContextBase base;
 
-#ifndef CONFIG_USER_ONLY
+#ifdef CONFIG_USER_ONLY
+MemOp unalign;
+#else
 uint64_t palbr;
 #endif
 uint32_t tbflags;
@@ -68,6 +70,12 @@ struct DisasContext {
 TCGv sink;
 };
 
+#ifdef CONFIG_USER_ONLY
+#define UNALIGN(C)  (C)->unalign
+#else
+#define UNALIGN(C)  0
+#endif
+
 /* Target-specific return values from translate_one, indicating the
state of the TB.  Note that DISAS_NEXT indicates that we are not
exiting the TB.  */
@@ -270,7 +278,7 @@ static inline DisasJumpType gen_invalid(DisasContext *ctx)
 static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
 {
 TCGv_i32 tmp32 = tcg_temp_new_i32();
-tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
+tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
 gen_helper_memory_to_f(dest, tmp32);
 tcg_temp_free_i32(tmp32);
 }
@@ -278,7 +286,7 @@ static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
 static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
 {
 TCGv tmp = tcg_temp_new();
-tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ);
+tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
 gen_helper_memory_to_g(dest, tmp);
 tcg_temp_free(tmp);
 }
@@ -286,14 +294,14 @@ static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv 
addr)
 static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
 {
 TCGv_i32 tmp32 = tcg_temp_new_i32();
-tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
+tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
 gen_helper_memory_to_s(dest, tmp32);
 tcg_temp_free_i32(tmp32);
 }
 
 static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
 {
-tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ);
+tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
 }
 
 static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
@@ -324,6 +332,8 @@ static void gen_load_int(DisasContext *ctx, int ra, int rb, 
int32_t disp16,
 tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
 if (clear) {
 tcg_gen_andi_i64(addr, addr, ~0x7);
+} else if (!locked) {
+op |= UNALIGN(ctx);
 }
 
 dest = ctx->ir[ra];
@@ -340,7 +350,7 @@ static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
 {
 TCGv_i32 tmp32 = tcg_temp_new_i32();
 gen_helper_f_to_memory(tmp32, addr);
-tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
+tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
 tcg_temp_free_i32(tmp32);
 }
 
@@ -348,7 +358,7 @@ s

[PATCH v2 34/55] accel/tcg: Add cpu_{ld,st}*_mmu interfaces

2021-08-02 Thread Richard Henderson
These functions are much closer to the softmmu helper
functions, in that they take the complete MemOpIdx,
and from that they may enforce required alignment.

The previous cpu_ldst.h functions did not have alignment info,
and so did not enforce it.  Retain this by adding MO_UNALN to
the MemOp that we create in calling the new functions.

Signed-off-by: Richard Henderson 
---
 docs/devel/loads-stores.rst |  52 -
 include/exec/cpu_ldst.h | 245 --
 accel/tcg/cputlb.c  | 392 
 accel/tcg/user-exec.c   | 390 +++
 accel/tcg/ldst_common.c.inc | 307 
 5 files changed, 722 insertions(+), 664 deletions(-)
 create mode 100644 accel/tcg/ldst_common.c.inc

diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
index 568274baec..8f0035c821 100644
--- a/docs/devel/loads-stores.rst
+++ b/docs/devel/loads-stores.rst
@@ -68,15 +68,19 @@ Regexes for git grep
  - ``\``
  - ``\``
 
-``cpu_{ld,st}*_mmuidx_ra``
-~~
+``cpu_{ld,st}*_mmu``
+
 
-These functions operate on a guest virtual address plus a context,
-known as a "mmu index" or ``mmuidx``, which controls how that virtual
-address is translated.  The meaning of the indexes are target specific,
-but specifying a particular index might be necessary if, for instance,
-the helper requires an "always as non-privileged" access rather that
-the default access for the current state of the guest CPU.
+These functions operate on a guest virtual address, plus a context
+known as a "mmu index" which controls how that virtual address is
+translated, plus a ``MemOp`` which contains alignment requirements
+among other things.  The ``MemOp`` and mmu index are combined into
+a single argument of type ``MemOpIdx``.
+
+The meaning of the indexes are target specific, but specifying a
+particular index might be necessary if, for instance, the helper
+requires a "always as non-privileged" access rather than the
+default access for the current state of the guest CPU.
 
 These functions may cause a guest CPU exception to be taken
 (e.g. for an alignment fault or MMU fault) which will result in
@@ -99,6 +103,35 @@ function, which is a return address into the generated code 
[#gpc]_.
 
 Function names follow the pattern:
 
+load: ``cpu_ld{size}{end}_mmu(env, ptr, oi, retaddr)``
+
+store: ``cpu_st{size}{end}_mmu(env, ptr, val, oi, retaddr)``
+
+``size``
+ - ``b`` : 8 bits
+ - ``w`` : 16 bits
+ - ``l`` : 32 bits
+ - ``q`` : 64 bits
+
+``end``
+ - (empty) : for target endian, or 8 bit sizes
+ - ``_be`` : big endian
+ - ``_le`` : little endian
+
+Regexes for git grep:
+ - ``\``
+ - ``\``
+
+
+``cpu_{ld,st}*_mmuidx_ra``
+~~
+
+These functions work like the ``cpu_{ld,st}_mmu`` functions except
+that the ``mmuidx`` parameter is not combined with a ``MemOp``,
+and therefore there is no required alignment supplied or enforced.
+
+Function names follow the pattern:
+
 load: ``cpu_ld{sign}{size}{end}_mmuidx_ra(env, ptr, mmuidx, retaddr)``
 
 store: ``cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmuidx, retaddr)``
@@ -132,7 +165,8 @@ of the guest CPU, as determined by ``cpu_mmu_index(env, 
false)``.
 
 These are generally the preferred way to do accesses by guest
 virtual address from helper functions, unless the access should
-be performed with a context other than the default.
+be performed with a context other than the default, or alignment
+should be enforced for the access.
 
 Function names follow the pattern:
 
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index ce6ce82618..a4dad0772f 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -28,10 +28,12 @@
  * load:  cpu_ld{sign}{size}{end}_{mmusuffix}(env, ptr)
  *cpu_ld{sign}{size}{end}_{mmusuffix}_ra(env, ptr, retaddr)
  *cpu_ld{sign}{size}{end}_mmuidx_ra(env, ptr, mmu_idx, retaddr)
+ *cpu_ld{sign}{size}{end}_mmu(env, ptr, oi, retaddr)
  *
  * store: cpu_st{size}{end}_{mmusuffix}(env, ptr, val)
  *cpu_st{size}{end}_{mmusuffix}_ra(env, ptr, val, retaddr)
  *cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmu_idx, retaddr)
+ *cpu_st{size}{end}_mmu(env, ptr, val, oi, retaddr)
  *
  * sign is:
  * (empty): for 32 and 64 bit sizes
@@ -53,10 +55,15 @@
  * The "mmuidx" suffix carries an extra mmu_idx argument that specifies
  * the index to use; the "data" and "code" suffixes take the index from
  * cpu_mmu_index().
+ *
+ * The "mmu" suffix carries the full MemOpIdx, with both mmu_idx and the
+ * MemOp including alignment requirements.  The alignment will be enforced.
  */
 #ifndef CPU_LDST_H
 #define CPU_LDST_H
 
+#include "exec/memopidx.h"
+
 #if defined(CONFIG_USER_ONLY)
 /* sparc32plus has 64bit long but 32bit space address
  * this can make bad result with g2h() and h2g()
@@ -118,12 +125,10 @@ typedef target_ulong abi_ptr;
 
 uint32_t cpu_ldub_data(CPUArchState *env, a

[PATCH v2 43/55] tcg/i386: Support raising sigbus for user-only

2021-08-02 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 tcg/i386/tcg-target.h |   2 -
 tcg/i386/tcg-target.c.inc | 114 --
 2 files changed, 110 insertions(+), 6 deletions(-)

diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index b00a6da293..3b2c9437a0 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -232,9 +232,7 @@ static inline void tb_target_set_jmp_target(uintptr_t 
tc_ptr, uintptr_t jmp_rx,
 
 #define TCG_TARGET_HAS_MEMORY_BSWAP  have_movbe
 
-#ifdef CONFIG_SOFTMMU
 #define TCG_TARGET_NEED_LDST_LABELS
-#endif
 #define TCG_TARGET_NEED_POOL_LABELS
 
 #endif
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
index 1e42a877fb..31dc3fafe9 100644
--- a/tcg/i386/tcg-target.c.inc
+++ b/tcg/i386/tcg-target.c.inc
@@ -420,8 +420,9 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct)
 #define OPC_VZEROUPPER  (0x77 | P_EXT)
 #define OPC_XCHG_ax_r32(0x90)
 
-#define OPC_GRP3_Ev(0xf7)
-#define OPC_GRP5   (0xff)
+#define OPC_GRP3_Eb (0xf6)
+#define OPC_GRP3_Ev (0xf7)
+#define OPC_GRP5(0xff)
 #define OPC_GRP14   (0x73 | P_EXT | P_DATA16)
 
 /* Group 1 opcode extensions for 0x80-0x83.
@@ -443,6 +444,7 @@ static bool tcg_target_const_match(int64_t val, TCGType 
type, int ct)
 #define SHIFT_SAR 7
 
 /* Group 3 opcode extensions for 0xf6, 0xf7.  To be used with OPC_GRP3.  */
+#define EXT3_TESTi 0
 #define EXT3_NOT   2
 #define EXT3_NEG   3
 #define EXT3_MUL   4
@@ -1604,9 +1606,9 @@ static void tcg_out_nopn(TCGContext *s, int n)
 tcg_out8(s, 0x90);
 }
 
-#if defined(CONFIG_SOFTMMU)
 #include "../tcg-ldst.c.inc"
 
+#if defined(CONFIG_SOFTMMU)
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  * int mmu_idx, uintptr_t ra)
  */
@@ -1915,7 +1917,96 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
 tcg_out_jmp(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
 return true;
 }
-#elif TCG_TARGET_REG_BITS == 32
+#else
+
+static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addrlo,
+   TCGReg addrhi, unsigned a_bits)
+{
+unsigned a_mask = (1 << a_bits) - 1;
+TCGLabelQemuLdst *label;
+
+/*
+ * We are expecting a_bits to max out at 7, so we can usually use testb.
+ * For i686, we have to use testl for %esi/%edi.
+ */
+if (a_mask <= 0xff && (TCG_TARGET_REG_BITS == 64 || addrlo < 4)) {
+tcg_out_modrm(s, OPC_GRP3_Eb | P_REXB_RM, EXT3_TESTi, addrlo);
+tcg_out8(s, a_mask);
+} else {
+tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_TESTi, addrlo);
+tcg_out32(s, a_mask);
+}
+
+/* jne slow_path */
+tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0);
+
+label = new_ldst_label(s);
+label->is_ld = is_ld;
+label->addrlo_reg = addrlo;
+label->addrhi_reg = addrhi;
+label->raddr = tcg_splitwx_to_rx(s->code_ptr + 4);
+label->label_ptr[0] = s->code_ptr;
+
+s->code_ptr += 4;
+}
+
+static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l)
+{
+MMUAccessType type = l->is_ld ? MMU_DATA_LOAD : MMU_DATA_STORE;
+TCGReg retaddr;
+
+/* resolve label address */
+tcg_patch32(l->label_ptr[0], s->code_ptr - l->label_ptr[0] - 4);
+
+if (TCG_TARGET_REG_BITS == 32) {
+int ofs = 0;
+
+tcg_out_st(s, TCG_TYPE_PTR, TCG_AREG0, TCG_REG_ESP, ofs);
+ofs += 4;
+
+tcg_out_st(s, TCG_TYPE_I32, l->addrlo_reg, TCG_REG_ESP, ofs);
+ofs += 4;
+if (TARGET_LONG_BITS == 64) {
+tcg_out_st(s, TCG_TYPE_I32, l->addrhi_reg, TCG_REG_ESP, ofs);
+ofs += 4;
+}
+
+tcg_out_sti(s, TCG_TYPE_I32, type, TCG_REG_ESP, ofs);
+
+retaddr = TCG_REG_EAX;
+tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
+tcg_out_st(s, TCG_TYPE_PTR, retaddr, TCG_REG_ESP, ofs);
+} else {
+tcg_out_mov(s, TCG_TYPE_TL, tcg_target_call_iarg_regs[1],
+l->addrlo_reg);
+tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
+tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[2], type);
+
+retaddr = tcg_target_call_iarg_regs[3];
+tcg_out_movi(s, TCG_TYPE_PTR, retaddr, (uintptr_t)l->raddr);
+}
+
+/*
+ * "Tail call" to the helper, with the return address back inline,
+ * just for the clarity of the debugging traceback -- the helper
+ * cannot return.
+ */
+tcg_out_push(s, retaddr);
+tcg_out_jmp(s, (const void *)helper_unaligned_mmu);
+return true;
+}
+
+static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+{
+return tcg_out_fail_alignment(s, l);
+}
+
+static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
+{
+return tcg_out_fail_alignment(s, l);
+}
+
+#if TCG_TARGET_REG_BITS == 32
 # define x86_guest_base_seg 0
 # define x86_guest_base_index   -1
 # define x

[PATCH v2 47/55] hw/core/cpu: Re-sort the non-pointers to the end of CPUClass

2021-08-02 Thread Richard Henderson
Despite the comment, the members were not kept at the end.

Signed-off-by: Richard Henderson 
---
 include/hw/core/cpu.h | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index bc864564ce..b7d5bc1200 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -131,7 +131,6 @@ struct CPUClass {
 ObjectClass *(*class_by_name)(const char *cpu_model);
 void (*parse_features)(const char *typename, char *str, Error **errp);
 
-int reset_dump_flags;
 bool (*has_work)(CPUState *cpu);
 int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
uint8_t *buf, int len, bool is_write);
@@ -149,9 +148,6 @@ struct CPUClass {
 void (*disas_set_info)(CPUState *cpu, disassemble_info *info);
 
 const char *deprecation_note;
-/* Keep non-pointer data at the end to minimize holes.  */
-int gdb_num_core_regs;
-bool gdb_stop_before_watchpoint;
 struct AccelCPUClass *accel_cpu;
 
 /* when system emulation is not available, this pointer is NULL */
@@ -165,6 +161,13 @@ struct CPUClass {
  * class data that depends on the accelerator, see accel/accel-common.c.
  */
 void (*init_accel_cpu)(struct AccelCPUClass *accel_cpu, CPUClass *cc);
+
+/*
+ * Keep non-pointer data at the end to minimize holes.
+ */
+int reset_dump_flags;
+int gdb_num_core_regs;
+bool gdb_stop_before_watchpoint;
 };
 
 /*
-- 
2.25.1




[PATCH v2 52/55] target/alpha: Reorg integer memory operations

2021-08-02 Thread Richard Henderson
Pass in the MemOp instead of a callback.
Drop the fp argument; add a locked argument.

Signed-off-by: Richard Henderson 
---
 target/alpha/translate.c | 104 +++
 1 file changed, 40 insertions(+), 64 deletions(-)

diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 607b6c3da7..c14c1156a0 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -308,27 +308,10 @@ static void gen_load_fp(DisasContext *ctx, int ra, int 
rb, int32_t disp16,
 }
 }
 
-static inline void gen_qemu_ldl_l(TCGv t0, TCGv t1, int flags)
+static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
+ MemOp op, bool clear, bool locked)
 {
-tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LESL);
-tcg_gen_mov_i64(cpu_lock_addr, t1);
-tcg_gen_mov_i64(cpu_lock_value, t0);
-}
-
-static inline void gen_qemu_ldq_l(TCGv t0, TCGv t1, int flags)
-{
-tcg_gen_qemu_ld_i64(t0, t1, flags, MO_LEQ);
-tcg_gen_mov_i64(cpu_lock_addr, t1);
-tcg_gen_mov_i64(cpu_lock_value, t0);
-}
-
-static inline void gen_load_mem(DisasContext *ctx,
-void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1,
-  int flags),
-int ra, int rb, int32_t disp16, bool fp,
-bool clear)
-{
-TCGv tmp, addr, va;
+TCGv addr, dest;
 
 /* LDQ_U with ra $31 is UNOP.  Other various loads are forms of
prefetches, which we can treat as nops.  No worries about
@@ -337,22 +320,20 @@ static inline void gen_load_mem(DisasContext *ctx,
 return;
 }
 
-tmp = tcg_temp_new();
-addr = load_gpr(ctx, rb);
-
-if (disp16) {
-tcg_gen_addi_i64(tmp, addr, disp16);
-addr = tmp;
-}
+addr = tcg_temp_new();
+tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
 if (clear) {
-tcg_gen_andi_i64(tmp, addr, ~0x7);
-addr = tmp;
+tcg_gen_andi_i64(addr, addr, ~0x7);
 }
 
-va = (fp ? cpu_fir[ra] : ctx->ir[ra]);
-tcg_gen_qemu_load(va, addr, ctx->mem_idx);
+dest = ctx->ir[ra];
+tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, op);
 
-tcg_temp_free(tmp);
+if (locked) {
+tcg_gen_mov_i64(cpu_lock_addr, addr);
+tcg_gen_mov_i64(cpu_lock_value, dest);
+}
+tcg_temp_free(addr);
 }
 
 static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
@@ -393,30 +374,21 @@ static void gen_store_fp(DisasContext *ctx, int ra, int 
rb, int32_t disp16,
 tcg_temp_free(addr);
 }
 
-static inline void gen_store_mem(DisasContext *ctx,
- void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1,
-int flags),
- int ra, int rb, int32_t disp16, bool fp,
- bool clear)
+static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
+  MemOp op, bool clear)
 {
-TCGv tmp, addr, va;
+TCGv addr, src;
 
-tmp = tcg_temp_new();
-addr = load_gpr(ctx, rb);
-
-if (disp16) {
-tcg_gen_addi_i64(tmp, addr, disp16);
-addr = tmp;
-}
+addr = tcg_temp_new();
+tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
 if (clear) {
-tcg_gen_andi_i64(tmp, addr, ~0x7);
-addr = tmp;
+tcg_gen_andi_i64(addr, addr, ~0x7);
 }
 
-va = (fp ? load_fpr(ctx, ra) : load_gpr(ctx, ra));
-tcg_gen_qemu_store(va, addr, ctx->mem_idx);
+src = load_gpr(ctx, ra);
+tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, op);
 
-tcg_temp_free(tmp);
+tcg_temp_free(addr);
 }
 
 static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb,
@@ -1511,30 +1483,30 @@ static DisasJumpType translate_one(DisasContext *ctx, 
uint32_t insn)
 case 0x0A:
 /* LDBU */
 REQUIRE_AMASK(BWX);
-gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
+gen_load_int(ctx, ra, rb, disp16, MO_UB, 0, 0);
 break;
 case 0x0B:
 /* LDQ_U */
-gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
+gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 1, 0);
 break;
 case 0x0C:
 /* LDWU */
 REQUIRE_AMASK(BWX);
-gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
+gen_load_int(ctx, ra, rb, disp16, MO_LEUW, 0, 0);
 break;
 case 0x0D:
 /* STW */
 REQUIRE_AMASK(BWX);
-gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
+gen_store_int(ctx, ra, rb, disp16, MO_LEUW, 0);
 break;
 case 0x0E:
 /* STB */
 REQUIRE_AMASK(BWX);
-gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
+gen_store_int(ctx, ra, rb, disp16, MO_UB, 0);
 break;
 case 0x0F:
 /* STQ_U */
-gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, dis

[PATCH v2 30/55] target/i386: Use MO_128 for 16 byte atomics

2021-08-02 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/i386/tcg/mem_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/i386/tcg/mem_helper.c b/target/i386/tcg/mem_helper.c
index 0fd696f9c1..a207e624cb 100644
--- a/target/i386/tcg/mem_helper.c
+++ b/target/i386/tcg/mem_helper.c
@@ -136,7 +136,7 @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
 Int128 newv = int128_make128(env->regs[R_EBX], env->regs[R_ECX]);
 
 int mem_idx = cpu_mmu_index(env, false);
-MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
+MemOpIdx oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
 Int128 oldv = cpu_atomic_cmpxchgo_le_mmu(env, a0, cmpv, newv, oi, ra);
 
 if (int128_eq(oldv, cmpv)) {
-- 
2.25.1




[PATCH v2 42/55] tcg: Add helper_unaligned_mmu for user-only sigbus

2021-08-02 Thread Richard Henderson
To be called from tcg generated code on hosts that support
unaligned accesses natively, in response to an access that
is supposed to be aligned.

Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-ldst.h | 5 +
 accel/tcg/user-exec.c  | 7 +++
 2 files changed, 12 insertions(+)

diff --git a/include/tcg/tcg-ldst.h b/include/tcg/tcg-ldst.h
index 8c86365611..a934bed042 100644
--- a/include/tcg/tcg-ldst.h
+++ b/include/tcg/tcg-ldst.h
@@ -70,5 +70,10 @@ void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, 
uint32_t val,
 void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
MemOpIdx oi, uintptr_t retaddr);
 
+#else
+
+void QEMU_NORETURN helper_unaligned_mmu(CPUArchState *env, target_ulong addr,
+uint32_t type, uintptr_t ra);
+
 #endif /* CONFIG_SOFTMMU */
 #endif /* TCG_LDST_H */
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 46b74b5f70..2da11aeca0 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -27,6 +27,7 @@
 #include "exec/helper-proto.h"
 #include "qemu/atomic128.h"
 #include "trace/trace-root.h"
+#include "tcg/tcg-ldst.h"
 #include "internal.h"
 
 #undef EAX
@@ -867,6 +868,12 @@ static void validate_memop(MemOpIdx oi, MemOp expected)
 #endif
 }
 
+void helper_unaligned_mmu(CPUArchState *env, target_ulong addr,
+  uint32_t access_type, uintptr_t ra)
+{
+cpu_unaligned_access(env_cpu(env), addr, access_type, MMU_USER_IDX, ra);
+}
+
 static void *cpu_mmu_lookup(CPUArchState *env, target_ulong addr,
 MemOpIdx oi, uintptr_t ra, MMUAccessType type)
 {
-- 
2.25.1




[PATCH v2 46/55] linux-user: Disable more prctl subcodes

2021-08-02 Thread Richard Henderson
Create a list of subcodes that we want to pass on, a list of
subcodes that should not be passed on because they would affect
the running qemu itself, and a list that probably could be
implemented but require extra work. Do not pass on unknown subcodes.

Signed-off-by: Richard Henderson 
---
 linux-user/syscall.c | 56 
 1 file changed, 52 insertions(+), 4 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6e630745fa..e303a9da7f 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6325,6 +6325,13 @@ abi_long do_arch_prctl(CPUX86State *env, int code, 
abi_ulong addr)
 # define PR_MTE_TAG_SHIFT   3
 # define PR_MTE_TAG_MASK(0xUL << PR_MTE_TAG_SHIFT)
 #endif
+#ifndef PR_SET_IO_FLUSHER
+# define PR_SET_IO_FLUSHER 57
+# define PR_GET_IO_FLUSHER 58
+#endif
+#ifndef PR_SET_SYSCALL_USER_DISPATCH
+# define PR_SET_SYSCALL_USER_DISPATCH 59
+#endif
 
 static abi_long do_prctl_get_fp_mode(CPUArchState *env)
 {
@@ -6632,13 +6639,54 @@ static abi_long do_prctl(CPUArchState *env, abi_long 
option, abi_long arg2,
 return -TARGET_EINVAL;
 }
 return do_prctl_get_tagged_addr_ctrl(env);
+
+case PR_GET_DUMPABLE:
+case PR_SET_DUMPABLE:
+case PR_GET_KEEPCAPS:
+case PR_SET_KEEPCAPS:
+case PR_GET_TIMING:
+case PR_SET_TIMING:
+case PR_GET_TIMERSLACK:
+case PR_SET_TIMERSLACK:
+case PR_MCE_KILL:
+case PR_MCE_KILL_GET:
+case PR_GET_NO_NEW_PRIVS:
+case PR_SET_NO_NEW_PRIVS:
+case PR_GET_IO_FLUSHER:
+case PR_SET_IO_FLUSHER:
+/* Some prctl options have no pointer arguments and we can pass on. */
+return get_errno(prctl(option, arg2, arg3, arg4, arg5));
+
+case PR_GET_CHILD_SUBREAPER:
+case PR_SET_CHILD_SUBREAPER:
+case PR_GET_SPECULATION_CTRL:
+case PR_SET_SPECULATION_CTRL:
+case PR_GET_TID_ADDRESS:
+/* TODO */
+return -TARGET_EINVAL;
+
+case PR_GET_FPEXC:
+case PR_SET_FPEXC:
+/* Was used for SPE on PowerPC. */
+return -TARGET_EINVAL;
+
+case PR_GET_ENDIAN:
+case PR_SET_ENDIAN:
+case PR_GET_FPEMU:
+case PR_SET_FPEMU:
+case PR_SET_MM:
 case PR_GET_SECCOMP:
 case PR_SET_SECCOMP:
-/* Disable seccomp to prevent the target disabling syscalls we need. */
-return -TARGET_EINVAL;
+case PR_SET_SYSCALL_USER_DISPATCH:
+case PR_GET_THP_DISABLE:
+case PR_SET_THP_DISABLE:
+case PR_GET_TSC:
+case PR_SET_TSC:
+case PR_GET_UNALIGN:
+case PR_SET_UNALIGN:
 default:
-/* Most prctl options have no pointer arguments */
-return get_errno(prctl(option, arg2, arg3, arg4, arg5));
+/* Disable to prevent the target disabling stuff we need. */
+return -TARGET_EINVAL;
 }
 }
 
-- 
2.25.1




[PATCH v2 44/55] tests/tcg/multiarch: Add sigbus.c

2021-08-02 Thread Richard Henderson
A mostly generic test for unaligned access raising SIGBUS.

Signed-off-by: Richard Henderson 
---
 tests/tcg/multiarch/sigbus.c | 68 
 1 file changed, 68 insertions(+)
 create mode 100644 tests/tcg/multiarch/sigbus.c

diff --git a/tests/tcg/multiarch/sigbus.c b/tests/tcg/multiarch/sigbus.c
new file mode 100644
index 00..8134c5fd56
--- /dev/null
+++ b/tests/tcg/multiarch/sigbus.c
@@ -0,0 +1,68 @@
+#define _GNU_SOURCE 1
+
+#include 
+#include 
+#include 
+#include 
+
+
+unsigned long long x = 0x8877665544332211ull;
+void * volatile p = (void *)&x + 1;
+
+void sigbus(int sig, siginfo_t *info, void *uc)
+{
+assert(sig == SIGBUS);
+assert(info->si_signo == SIGBUS);
+#ifdef BUS_ADRALN
+assert(info->si_code == BUS_ADRALN);
+#endif
+assert(info->si_addr == p);
+exit(EXIT_SUCCESS);
+}
+
+int main()
+{
+struct sigaction sa = {
+.sa_sigaction = sigbus,
+.sa_flags = SA_SIGINFO
+};
+int allow_fail = 0;
+int tmp;
+
+tmp = sigaction(SIGBUS, &sa, NULL);
+assert(tmp == 0);
+
+/*
+ * Select an operation that's likely to enforce alignment.
+ * On many guests that support unaligned accesses by default,
+ * this is often an atomic operation.
+ */
+#if defined(__aarch64__)
+asm volatile("ldxr %w0,[%1]" : "=r"(tmp) : "r"(p) : "memory");
+#elif defined(__alpha__)
+asm volatile("ldl_l %0,0(%1)" : "=r"(tmp) : "r"(p) : "memory");
+#elif defined(__arm__)
+asm volatile("ldrex %0,[%1]" : "=r"(tmp) : "r"(p) : "memory");
+#elif defined(__powerpc__)
+asm volatile("lwarx %0,0,%1" : "=r"(tmp) : "r"(p) : "memory");
+#elif defined(__riscv_atomic)
+asm volatile("lr.w %0,(%1)" : "=r"(tmp) : "r"(p) : "memory");
+#else
+/* No insn known to fault unaligned -- try for a straight load. */
+allow_fail = 1;
+tmp = *(volatile int *)p;
+#endif
+
+assert(allow_fail);
+
+/*
+ * We didn't see a signal.
+ * We might as well validate the unaligned load worked.
+ */
+if (BYTE_ORDER == LITTLE_ENDIAN) {
+assert(tmp == 0x55443322);
+} else {
+assert(tmp == 0x77665544);
+}
+return EXIT_SUCCESS;
+}
-- 
2.25.1




[PATCH v2 28/55] trace: Split guest_mem_before

2021-08-02 Thread Richard Henderson
There is no point in encoding load/store within a bit of
the memory trace info operand.  Represent atomic operations
as a single read-modify-write tracepoint.  Use MemOpIdx
instead of inventing a form specifically for traces.

Signed-off-by: Richard Henderson 
---
 accel/tcg/atomic_template.h   |  1 -
 trace/mem.h   | 51 ---
 accel/tcg/cputlb.c|  7 ++---
 accel/tcg/user-exec.c | 43 ++---
 tcg/tcg-op.c  | 17 +++-
 accel/tcg/atomic_common.c.inc | 12 +++--
 trace-events  | 18 +++--
 7 files changed, 27 insertions(+), 122 deletions(-)
 delete mode 100644 trace/mem.h

diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
index c08d859a8a..2d917b6b1f 100644
--- a/accel/tcg/atomic_template.h
+++ b/accel/tcg/atomic_template.h
@@ -19,7 +19,6 @@
  */
 
 #include "qemu/plugin.h"
-#include "trace/mem.h"
 
 #if DATA_SIZE == 16
 # define SUFFIX o
diff --git a/trace/mem.h b/trace/mem.h
deleted file mode 100644
index 699566c661..00
--- a/trace/mem.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Helper functions for guest memory tracing
- *
- * Copyright (C) 2016 Lluís Vilanova 
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef TRACE__MEM_H
-#define TRACE__MEM_H
-
-#include "exec/memopidx.h"
-
-#define TRACE_MEM_SZ_SHIFT_MASK 0xf /* size shift mask */
-#define TRACE_MEM_SE (1ULL << 4)/* sign extended (y/n) */
-#define TRACE_MEM_BE (1ULL << 5)/* big endian (y/n) */
-#define TRACE_MEM_ST (1ULL << 6)/* store (y/n) */
-#define TRACE_MEM_MMU_SHIFT 8   /* mmu idx */
-
-/**
- * trace_mem_get_info:
- *
- * Return a value for the 'info' argument in guest memory access traces.
- */
-static inline uint16_t trace_mem_get_info(MemOpIdx oi, bool store)
-{
-MemOp op = get_memop(oi);
-uint32_t size_shift = op & MO_SIZE;
-bool sign_extend = op & MO_SIGN;
-bool big_endian = (op & MO_BSWAP) == MO_BE;
-uint16_t res;
-
-res = size_shift & TRACE_MEM_SZ_SHIFT_MASK;
-if (sign_extend) {
-res |= TRACE_MEM_SE;
-}
-if (big_endian) {
-res |= TRACE_MEM_BE;
-}
-if (store) {
-res |= TRACE_MEM_ST;
-}
-#ifdef CONFIG_SOFTMMU
-res |= get_mmuidx(oi) << TRACE_MEM_MMU_SHIFT;
-#endif
-
-return res;
-}
-
-#endif /* TRACE__MEM_H */
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 04436f98c8..3d8471810c 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -34,7 +34,6 @@
 #include "qemu/atomic128.h"
 #include "exec/translate-all.h"
 #include "trace/trace-root.h"
-#include "trace/mem.h"
 #include "tb-hash.h"
 #include "internal.h"
 #ifdef CONFIG_PLUGIN
@@ -2104,10 +2103,9 @@ static inline uint64_t cpu_load_helper(CPUArchState 
*env, abi_ptr addr,
MemOp op, FullLoadHelper *full_load)
 {
 MemOpIdx oi = make_memop_idx(op, mmu_idx);
-uint16_t meminfo = trace_mem_get_info(oi, false);
 uint64_t ret;
 
-trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
+trace_guest_ld_before_exec(env_cpu(env), addr, oi);
 
 ret = full_load(env, addr, oi, retaddr);
 
@@ -2541,9 +2539,8 @@ cpu_store_helper(CPUArchState *env, target_ulong addr, 
uint64_t val,
  int mmu_idx, uintptr_t retaddr, MemOp op)
 {
 MemOpIdx oi = make_memop_idx(op, mmu_idx);
-uint16_t meminfo = trace_mem_get_info(oi, true);
 
-trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
+trace_guest_st_before_exec(env_cpu(env), addr, oi);
 
 store_helper(env, addr, val, oi, retaddr, op);
 
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index d96d60a804..246be4502d 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -27,7 +27,6 @@
 #include "exec/helper-proto.h"
 #include "qemu/atomic128.h"
 #include "trace/trace-root.h"
-#include "trace/mem.h"
 #include "internal.h"
 
 #undef EAX
@@ -856,10 +855,9 @@ int cpu_signal_handler(int host_signum, void *pinfo,
 uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr)
 {
 MemOpIdx oi = make_memop_idx(MO_UB, MMU_USER_IDX);
-uint16_t meminfo = trace_mem_get_info(oi, false);
 uint32_t ret;
 
-trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
+trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
 ret = ldub_p(g2h(env_cpu(env), ptr));
 qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
 return ret;
@@ -873,10 +871,9 @@ int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr)
 uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
 {
 MemOpIdx oi = make_memop_idx(MO_BEUW, MMU_USER_IDX);
-uint16_t meminfo = trace_mem_get_info(oi, false);
 uint32_t ret;
 
-trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
+trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
 ret = lduw_be_p(g2h(env_cpu(env), ptr));
 qemu_p

[PATCH v2 38/55] target/s390x: Use cpu_*_mmu instead of helper_*_mmu

2021-08-02 Thread Richard Henderson
The helper_*_mmu functions were the only thing available
when this code was written.  This could have been adjusted
when we added cpu_*_mmuidx_ra, but now we can most easily
use the newest set of interfaces.

Cc: qemu-s3...@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/s390x/tcg/mem_helper.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index b20a82a914..4115cadbd7 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -248,13 +248,13 @@ static void do_access_memset(CPUS390XState *env, vaddr 
vaddr, char *haddr,
  * page. This is especially relevant to speed up TLB_NOTDIRTY.
  */
 g_assert(size > 0);
-helper_ret_stb_mmu(env, vaddr, byte, oi, ra);
+cpu_stb_mmu(env, vaddr, byte, oi, ra);
 haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx);
 if (likely(haddr)) {
 memset(haddr + 1, byte, size - 1);
 } else {
 for (i = 1; i < size; i++) {
-helper_ret_stb_mmu(env, vaddr + i, byte, oi, ra);
+cpu_stb_mmu(env, vaddr + i, byte, oi, ra);
 }
 }
 }
@@ -290,7 +290,7 @@ static uint8_t do_access_get_byte(CPUS390XState *env, vaddr 
vaddr, char **haddr,
  * Do a single access and test if we can then get access to the
  * page. This is especially relevant to speed up TLB_NOTDIRTY.
  */
-byte = helper_ret_ldub_mmu(env, vaddr + offset, oi, ra);
+byte = cpu_ldb_mmu(env, vaddr + offset, oi, ra);
 *haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_LOAD, mmu_idx);
 return byte;
 #endif
@@ -324,7 +324,7 @@ static void do_access_set_byte(CPUS390XState *env, vaddr 
vaddr, char **haddr,
  * Do a single access and test if we can then get access to the
  * page. This is especially relevant to speed up TLB_NOTDIRTY.
  */
-helper_ret_stb_mmu(env, vaddr + offset, byte, oi, ra);
+cpu_stb_mmu(env, vaddr + offset, byte, oi, ra);
 *haddr = tlb_vaddr_to_host(env, vaddr, MMU_DATA_STORE, mmu_idx);
 #endif
 }
-- 
2.25.1




[PATCH v2 36/55] target/mips: Use cpu_*_data_ra for msa load/store

2021-08-02 Thread Richard Henderson
We should not have been using the helper_ret_* set of
functions, as they are supposed to be private to tcg.
Nor should we have been using the plain cpu_*_data set
of functions, as they do not handle unwinding properly.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/mips/tcg/msa_helper.c | 420 +++
 1 file changed, 135 insertions(+), 285 deletions(-)

diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
index 167d9a591c..a8880ce81c 100644
--- a/target/mips/tcg/msa_helper.c
+++ b/target/mips/tcg/msa_helper.c
@@ -8222,79 +8222,42 @@ void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
  target_ulong addr)
 {
 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
-MEMOP_IDX(DF_BYTE)
-#if !defined(CONFIG_USER_ONLY)
+uintptr_t ra = GETPC();
+
 #if !defined(HOST_WORDS_BIGENDIAN)
-pwd->b[0]  = helper_ret_ldub_mmu(env, addr + (0  << DF_BYTE), oi, GETPC());
-pwd->b[1]  = helper_ret_ldub_mmu(env, addr + (1  << DF_BYTE), oi, GETPC());
-pwd->b[2]  = helper_ret_ldub_mmu(env, addr + (2  << DF_BYTE), oi, GETPC());
-pwd->b[3]  = helper_ret_ldub_mmu(env, addr + (3  << DF_BYTE), oi, GETPC());
-pwd->b[4]  = helper_ret_ldub_mmu(env, addr + (4  << DF_BYTE), oi, GETPC());
-pwd->b[5]  = helper_ret_ldub_mmu(env, addr + (5  << DF_BYTE), oi, GETPC());
-pwd->b[6]  = helper_ret_ldub_mmu(env, addr + (6  << DF_BYTE), oi, GETPC());
-pwd->b[7]  = helper_ret_ldub_mmu(env, addr + (7  << DF_BYTE), oi, GETPC());
-pwd->b[8]  = helper_ret_ldub_mmu(env, addr + (8  << DF_BYTE), oi, GETPC());
-pwd->b[9]  = helper_ret_ldub_mmu(env, addr + (9  << DF_BYTE), oi, GETPC());
-pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
-pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
-pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
-pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
-pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
-pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
+pwd->b[0]  = cpu_ldub_data_ra(env, addr + (0  << DF_BYTE), ra);
+pwd->b[1]  = cpu_ldub_data_ra(env, addr + (1  << DF_BYTE), ra);
+pwd->b[2]  = cpu_ldub_data_ra(env, addr + (2  << DF_BYTE), ra);
+pwd->b[3]  = cpu_ldub_data_ra(env, addr + (3  << DF_BYTE), ra);
+pwd->b[4]  = cpu_ldub_data_ra(env, addr + (4  << DF_BYTE), ra);
+pwd->b[5]  = cpu_ldub_data_ra(env, addr + (5  << DF_BYTE), ra);
+pwd->b[6]  = cpu_ldub_data_ra(env, addr + (6  << DF_BYTE), ra);
+pwd->b[7]  = cpu_ldub_data_ra(env, addr + (7  << DF_BYTE), ra);
+pwd->b[8]  = cpu_ldub_data_ra(env, addr + (8  << DF_BYTE), ra);
+pwd->b[9]  = cpu_ldub_data_ra(env, addr + (9  << DF_BYTE), ra);
+pwd->b[10] = cpu_ldub_data_ra(env, addr + (10 << DF_BYTE), ra);
+pwd->b[11] = cpu_ldub_data_ra(env, addr + (11 << DF_BYTE), ra);
+pwd->b[12] = cpu_ldub_data_ra(env, addr + (12 << DF_BYTE), ra);
+pwd->b[13] = cpu_ldub_data_ra(env, addr + (13 << DF_BYTE), ra);
+pwd->b[14] = cpu_ldub_data_ra(env, addr + (14 << DF_BYTE), ra);
+pwd->b[15] = cpu_ldub_data_ra(env, addr + (15 << DF_BYTE), ra);
 #else
-pwd->b[0]  = helper_ret_ldub_mmu(env, addr + (7  << DF_BYTE), oi, GETPC());
-pwd->b[1]  = helper_ret_ldub_mmu(env, addr + (6  << DF_BYTE), oi, GETPC());
-pwd->b[2]  = helper_ret_ldub_mmu(env, addr + (5  << DF_BYTE), oi, GETPC());
-pwd->b[3]  = helper_ret_ldub_mmu(env, addr + (4  << DF_BYTE), oi, GETPC());
-pwd->b[4]  = helper_ret_ldub_mmu(env, addr + (3  << DF_BYTE), oi, GETPC());
-pwd->b[5]  = helper_ret_ldub_mmu(env, addr + (2  << DF_BYTE), oi, GETPC());
-pwd->b[6]  = helper_ret_ldub_mmu(env, addr + (1  << DF_BYTE), oi, GETPC());
-pwd->b[7]  = helper_ret_ldub_mmu(env, addr + (0  << DF_BYTE), oi, GETPC());
-pwd->b[8]  = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC());
-pwd->b[9]  = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC());
-pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC());
-pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC());
-pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC());
-pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC());
-pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9  << DF_BYTE), oi, GETPC());
-pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8  << DF_BYTE), oi, GETPC());
-#endif
-#else
-#if !defined(HOST_WORDS_BIGENDIAN)
-pwd->b[0]  = cpu_ldub_data(env, addr + (0  << DF_BYTE));
-pwd->b[1]  = cpu_ldub_data(env, addr + (1  << DF_BYTE));
-pwd->b[2]  = cpu_ldub_data(env, addr + (2  << DF_BYTE));
-pwd->b[3]  = cpu_ldub_data(env, addr + (3  << DF_BYTE));
-pwd->b[4]  = cpu_ldub_data(env, addr + (4  << DF_BYTE));
-pwd->b[5]  = cpu_ldub_data(env, addr +

[PATCH v2 41/55] tcg: Move helper_*_mmu decls to tcg/tcg-ldst.h

2021-08-02 Thread Richard Henderson
These functions have been replaced by cpu_*_mmu as the
most proper interface to use from target code.

Hide these declarations from code that should not use them.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/tcg/tcg-ldst.h | 74 ++
 include/tcg/tcg.h  | 71 
 accel/tcg/cputlb.c |  1 +
 tcg/tcg.c  |  1 +
 tcg/tci.c  |  1 +
 5 files changed, 77 insertions(+), 71 deletions(-)
 create mode 100644 include/tcg/tcg-ldst.h

diff --git a/include/tcg/tcg-ldst.h b/include/tcg/tcg-ldst.h
new file mode 100644
index 00..8c86365611
--- /dev/null
+++ b/include/tcg/tcg-ldst.h
@@ -0,0 +1,74 @@
+/*
+ * Memory helpers that will be used by TCG generated code.
+ *
+ * Copyright (c) 2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef TCG_LDST_H
+#define TCG_LDST_H 1
+
+#ifdef CONFIG_SOFTMMU
+
+/* Value zero-extended to tcg register size.  */
+tcg_target_ulong helper_ret_ldub_mmu(CPUArchState *env, target_ulong addr,
+ MemOpIdx oi, uintptr_t retaddr);
+tcg_target_ulong helper_le_lduw_mmu(CPUArchState *env, target_ulong addr,
+MemOpIdx oi, uintptr_t retaddr);
+tcg_target_ulong helper_le_ldul_mmu(CPUArchState *env, target_ulong addr,
+MemOpIdx oi, uintptr_t retaddr);
+uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr,
+   MemOpIdx oi, uintptr_t retaddr);
+tcg_target_ulong helper_be_lduw_mmu(CPUArchState *env, target_ulong addr,
+MemOpIdx oi, uintptr_t retaddr);
+tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr,
+MemOpIdx oi, uintptr_t retaddr);
+uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr,
+   MemOpIdx oi, uintptr_t retaddr);
+
+/* Value sign-extended to tcg register size.  */
+tcg_target_ulong helper_ret_ldsb_mmu(CPUArchState *env, target_ulong addr,
+ MemOpIdx oi, uintptr_t retaddr);
+tcg_target_ulong helper_le_ldsw_mmu(CPUArchState *env, target_ulong addr,
+MemOpIdx oi, uintptr_t retaddr);
+tcg_target_ulong helper_le_ldsl_mmu(CPUArchState *env, target_ulong addr,
+MemOpIdx oi, uintptr_t retaddr);
+tcg_target_ulong helper_be_ldsw_mmu(CPUArchState *env, target_ulong addr,
+MemOpIdx oi, uintptr_t retaddr);
+tcg_target_ulong helper_be_ldsl_mmu(CPUArchState *env, target_ulong addr,
+MemOpIdx oi, uintptr_t retaddr);
+
+void helper_ret_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val,
+MemOpIdx oi, uintptr_t retaddr);
+void helper_le_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+   MemOpIdx oi, uintptr_t retaddr);
+void helper_le_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+   MemOpIdx oi, uintptr_t retaddr);
+void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+   MemOpIdx oi, uintptr_t retaddr);
+void helper_be_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val,
+   MemOpIdx oi, uintptr_t retaddr);
+void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val,
+   MemOpIdx oi, uintptr_t retaddr);
+void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val,
+   MemOpIdx oi, uintptr_t retaddr);
+
+#endif /* CONFIG_SOFTMMU */
+#endif /* TCG_LDST_H */
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 114ad66b25..82b4abfa31 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -1234,77 +1234,6 @@ uint64_t dup_const(uns

[PATCH v2 25/55] trace/mem: Pass MemOpIdx to trace_mem_get_info

2021-08-02 Thread Richard Henderson
We (will) often have the complete MemOpIdx handy, so use that.

Signed-off-by: Richard Henderson 
---
 trace/mem.h   | 32 +-
 accel/tcg/cputlb.c| 12 --
 accel/tcg/user-exec.c | 42 +++
 tcg/tcg-op.c  |  8 +++
 accel/tcg/atomic_common.c.inc |  6 ++---
 5 files changed, 49 insertions(+), 51 deletions(-)

diff --git a/trace/mem.h b/trace/mem.h
index 2f27e7bdf0..699566c661 100644
--- a/trace/mem.h
+++ b/trace/mem.h
@@ -10,7 +10,7 @@
 #ifndef TRACE__MEM_H
 #define TRACE__MEM_H
 
-#include "tcg/tcg.h"
+#include "exec/memopidx.h"
 
 #define TRACE_MEM_SZ_SHIFT_MASK 0xf /* size shift mask */
 #define TRACE_MEM_SE (1ULL << 4)/* sign extended (y/n) */
@@ -19,45 +19,33 @@
 #define TRACE_MEM_MMU_SHIFT 8   /* mmu idx */
 
 /**
- * trace_mem_build_info:
+ * trace_mem_get_info:
  *
  * Return a value for the 'info' argument in guest memory access traces.
  */
-static inline uint16_t trace_mem_build_info(int size_shift, bool sign_extend,
-MemOp endianness, bool store,
-unsigned int mmu_idx)
+static inline uint16_t trace_mem_get_info(MemOpIdx oi, bool store)
 {
+MemOp op = get_memop(oi);
+uint32_t size_shift = op & MO_SIZE;
+bool sign_extend = op & MO_SIGN;
+bool big_endian = (op & MO_BSWAP) == MO_BE;
 uint16_t res;
 
 res = size_shift & TRACE_MEM_SZ_SHIFT_MASK;
 if (sign_extend) {
 res |= TRACE_MEM_SE;
 }
-if (endianness == MO_BE) {
+if (big_endian) {
 res |= TRACE_MEM_BE;
 }
 if (store) {
 res |= TRACE_MEM_ST;
 }
 #ifdef CONFIG_SOFTMMU
-res |= mmu_idx << TRACE_MEM_MMU_SHIFT;
+res |= get_mmuidx(oi) << TRACE_MEM_MMU_SHIFT;
 #endif
+
 return res;
 }
 
-
-/**
- * trace_mem_get_info:
- *
- * Return a value for the 'info' argument in guest memory access traces.
- */
-static inline uint16_t trace_mem_get_info(MemOp op,
-  unsigned int mmu_idx,
-  bool store)
-{
-return trace_mem_build_info(op & MO_SIZE, !!(op & MO_SIGN),
-op & MO_BSWAP, store,
-mmu_idx);
-}
-
 #endif /* TRACE__MEM_H */
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 2dfbc29a0c..c27658b8a2 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -2103,14 +2103,12 @@ static inline uint64_t cpu_load_helper(CPUArchState 
*env, abi_ptr addr,
int mmu_idx, uintptr_t retaddr,
MemOp op, FullLoadHelper *full_load)
 {
-uint16_t meminfo;
-MemOpIdx oi;
+MemOpIdx oi = make_memop_idx(op, mmu_idx);
+uint16_t meminfo = trace_mem_get_info(oi, false);
 uint64_t ret;
 
-meminfo = trace_mem_get_info(op, mmu_idx, false);
 trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
 
-oi = make_memop_idx(op, mmu_idx);
 ret = full_load(env, addr, oi, retaddr);
 
 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, meminfo);
@@ -2542,13 +2540,11 @@ static inline void QEMU_ALWAYS_INLINE
 cpu_store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
  int mmu_idx, uintptr_t retaddr, MemOp op)
 {
-MemOpIdx oi;
-uint16_t meminfo;
+MemOpIdx oi = make_memop_idx(op, mmu_idx);
+uint16_t meminfo = trace_mem_get_info(oi, true);
 
-meminfo = trace_mem_get_info(op, mmu_idx, true);
 trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
 
-oi = make_memop_idx(op, mmu_idx);
 store_helper(env, addr, val, oi, retaddr, op);
 
 qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, meminfo);
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index eab2b9804d..68d9c1b33d 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -855,8 +855,9 @@ int cpu_signal_handler(int host_signum, void *pinfo,
 
 uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr)
 {
+MemOpIdx oi = make_memop_idx(MO_UB, MMU_USER_IDX);
+uint16_t meminfo = trace_mem_get_info(oi, false);
 uint32_t ret;
-uint16_t meminfo = trace_mem_get_info(MO_UB, MMU_USER_IDX, false);
 
 trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
 ret = ldub_p(g2h(env_cpu(env), ptr));
@@ -871,8 +872,9 @@ int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr)
 
 uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
 {
+MemOpIdx oi = make_memop_idx(MO_BEUW, MMU_USER_IDX);
+uint16_t meminfo = trace_mem_get_info(oi, false);
 uint32_t ret;
-uint16_t meminfo = trace_mem_get_info(MO_BEUW, MMU_USER_IDX, false);
 
 trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
 ret = lduw_be_p(g2h(env_cpu(env), ptr));
@@ -887,8 +889,9 @@ int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr)
 
 uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr)
 {
+MemOpIdx oi = make_memop_idx(MO_BEUL,

[PATCH v2 37/55] target/mips: Use 8-byte memory ops for msa load/store

2021-08-02 Thread Richard Henderson
Rather than use 4-16 separate operations, use 2 operations
plus some byte reordering as necessary.

Cc: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/mips/tcg/msa_helper.c | 201 +--
 1 file changed, 71 insertions(+), 130 deletions(-)

diff --git a/target/mips/tcg/msa_helper.c b/target/mips/tcg/msa_helper.c
index a8880ce81c..e40c1b7057 100644
--- a/target/mips/tcg/msa_helper.c
+++ b/target/mips/tcg/msa_helper.c
@@ -8218,47 +8218,31 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t 
df, uint32_t wd,
 #define MEMOP_IDX(DF)
 #endif
 
+#ifdef TARGET_WORDS_BIGENDIAN
+static inline uint64_t bswap16x4(uint64_t x)
+{
+uint64_t m = 0x00ff00ff00ff00ffull;
+return ((x & m) << 8) | ((x >> 8) & m);
+}
+
+static inline uint64_t bswap32x2(uint64_t x)
+{
+return ror64(bswap64(x), 32);
+}
+#endif
+
 void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd,
  target_ulong addr)
 {
 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 uintptr_t ra = GETPC();
+uint64_t d0, d1;
 
-#if !defined(HOST_WORDS_BIGENDIAN)
-pwd->b[0]  = cpu_ldub_data_ra(env, addr + (0  << DF_BYTE), ra);
-pwd->b[1]  = cpu_ldub_data_ra(env, addr + (1  << DF_BYTE), ra);
-pwd->b[2]  = cpu_ldub_data_ra(env, addr + (2  << DF_BYTE), ra);
-pwd->b[3]  = cpu_ldub_data_ra(env, addr + (3  << DF_BYTE), ra);
-pwd->b[4]  = cpu_ldub_data_ra(env, addr + (4  << DF_BYTE), ra);
-pwd->b[5]  = cpu_ldub_data_ra(env, addr + (5  << DF_BYTE), ra);
-pwd->b[6]  = cpu_ldub_data_ra(env, addr + (6  << DF_BYTE), ra);
-pwd->b[7]  = cpu_ldub_data_ra(env, addr + (7  << DF_BYTE), ra);
-pwd->b[8]  = cpu_ldub_data_ra(env, addr + (8  << DF_BYTE), ra);
-pwd->b[9]  = cpu_ldub_data_ra(env, addr + (9  << DF_BYTE), ra);
-pwd->b[10] = cpu_ldub_data_ra(env, addr + (10 << DF_BYTE), ra);
-pwd->b[11] = cpu_ldub_data_ra(env, addr + (11 << DF_BYTE), ra);
-pwd->b[12] = cpu_ldub_data_ra(env, addr + (12 << DF_BYTE), ra);
-pwd->b[13] = cpu_ldub_data_ra(env, addr + (13 << DF_BYTE), ra);
-pwd->b[14] = cpu_ldub_data_ra(env, addr + (14 << DF_BYTE), ra);
-pwd->b[15] = cpu_ldub_data_ra(env, addr + (15 << DF_BYTE), ra);
-#else
-pwd->b[0]  = cpu_ldub_data_ra(env, addr + (7  << DF_BYTE), ra);
-pwd->b[1]  = cpu_ldub_data_ra(env, addr + (6  << DF_BYTE), ra);
-pwd->b[2]  = cpu_ldub_data_ra(env, addr + (5  << DF_BYTE), ra);
-pwd->b[3]  = cpu_ldub_data_ra(env, addr + (4  << DF_BYTE), ra);
-pwd->b[4]  = cpu_ldub_data_ra(env, addr + (3  << DF_BYTE), ra);
-pwd->b[5]  = cpu_ldub_data_ra(env, addr + (2  << DF_BYTE), ra);
-pwd->b[6]  = cpu_ldub_data_ra(env, addr + (1  << DF_BYTE), ra);
-pwd->b[7]  = cpu_ldub_data_ra(env, addr + (0  << DF_BYTE), ra);
-pwd->b[8]  = cpu_ldub_data_ra(env, addr + (15 << DF_BYTE), ra);
-pwd->b[9]  = cpu_ldub_data_ra(env, addr + (14 << DF_BYTE), ra);
-pwd->b[10] = cpu_ldub_data_ra(env, addr + (13 << DF_BYTE), ra);
-pwd->b[11] = cpu_ldub_data_ra(env, addr + (12 << DF_BYTE), ra);
-pwd->b[12] = cpu_ldub_data_ra(env, addr + (11 << DF_BYTE), ra);
-pwd->b[13] = cpu_ldub_data_ra(env, addr + (10 << DF_BYTE), ra);
-pwd->b[14] = cpu_ldub_data_ra(env, addr + (9 << DF_BYTE), ra);
-pwd->b[15] = cpu_ldub_data_ra(env, addr + (8 << DF_BYTE), ra);
-#endif
+/* Load 8 bytes at a time.  Vector element ordering makes this LE.  */
+d0 = cpu_ldq_le_data_ra(env, addr + 0, ra);
+d1 = cpu_ldq_le_data_ra(env, addr + 8, ra);
+pwd->d[0] = d0;
+pwd->d[1] = d1;
 }
 
 void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
@@ -8266,26 +8250,20 @@ void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd,
 {
 wr_t *pwd = &(env->active_fpu.fpr[wd].wr);
 uintptr_t ra = GETPC();
+uint64_t d0, d1;
 
-#if !defined(HOST_WORDS_BIGENDIAN)
-pwd->h[0] = cpu_lduw_data_ra(env, addr + (0 << DF_HALF), ra);
-pwd->h[1] = cpu_lduw_data_ra(env, addr + (1 << DF_HALF), ra);
-pwd->h[2] = cpu_lduw_data_ra(env, addr + (2 << DF_HALF), ra);
-pwd->h[3] = cpu_lduw_data_ra(env, addr + (3 << DF_HALF), ra);
-pwd->h[4] = cpu_lduw_data_ra(env, addr + (4 << DF_HALF), ra);
-pwd->h[5] = cpu_lduw_data_ra(env, addr + (5 << DF_HALF), ra);
-pwd->h[6] = cpu_lduw_data_ra(env, addr + (6 << DF_HALF), ra);
-pwd->h[7] = cpu_lduw_data_ra(env, addr + (7 << DF_HALF), ra);
-#else
-pwd->h[0] = cpu_lduw_data_ra(env, addr + (3 << DF_HALF), ra);
-pwd->h[1] = cpu_lduw_data_ra(env, addr + (2 << DF_HALF), ra);
-pwd->h[2] = cpu_lduw_data_ra(env, addr + (1 << DF_HALF), ra);
-pwd->h[3] = cpu_lduw_data_ra(env, addr + (0 << DF_HALF), ra);
-pwd->h[4] = cpu_lduw_data_ra(env, addr + (7 << DF_HALF), ra);
-pwd->h[5] = cpu_lduw_data_ra(env, addr + (6 << DF_HALF), ra);
-pwd->h[6] = cpu_lduw_data_ra(env, addr + (5 << DF_HALF), ra);
-pwd->h[7] = cpu_lduw_data_ra(env, addr + (4 << DF_HALF), ra);
+/*
+ * Load 8 bytes at a time.  Use little-endian load, then for
+ * big-endian target, we 

[PATCH v2 39/55] target/sparc: Use cpu_*_mmu instead of helper_*_mmu

2021-08-02 Thread Richard Henderson
The helper_*_mmu functions were the only thing available
when this code was written.  This could have been adjusted
when we added cpu_*_mmuidx_ra, but now we can most easily
use the newest set of interfaces.

Cc: Mark Cave-Ayland 
Signed-off-by: Richard Henderson 
---
 target/sparc/ldst_helper.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
index 299fc386ea..a3e1cf9b6e 100644
--- a/target/sparc/ldst_helper.c
+++ b/target/sparc/ldst_helper.c
@@ -1328,27 +1328,27 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong 
addr,
 oi = make_memop_idx(memop, idx);
 switch (size) {
 case 1:
-ret = helper_ret_ldub_mmu(env, addr, oi, GETPC());
+ret = cpu_ldb_mmu(env, addr, oi, GETPC());
 break;
 case 2:
 if (asi & 8) {
-ret = helper_le_lduw_mmu(env, addr, oi, GETPC());
+ret = cpu_ldw_le_mmu(env, addr, oi, GETPC());
 } else {
-ret = helper_be_lduw_mmu(env, addr, oi, GETPC());
+ret = cpu_ldw_be_mmu(env, addr, oi, GETPC());
 }
 break;
 case 4:
 if (asi & 8) {
-ret = helper_le_ldul_mmu(env, addr, oi, GETPC());
+ret = cpu_ldl_le_mmu(env, addr, oi, GETPC());
 } else {
-ret = helper_be_ldul_mmu(env, addr, oi, GETPC());
+ret = cpu_ldl_be_mmu(env, addr, oi, GETPC());
 }
 break;
 case 8:
 if (asi & 8) {
-ret = helper_le_ldq_mmu(env, addr, oi, GETPC());
+ret = cpu_ldq_le_mmu(env, addr, oi, GETPC());
 } else {
-ret = helper_be_ldq_mmu(env, addr, oi, GETPC());
+ret = cpu_ldq_be_mmu(env, addr, oi, GETPC());
 }
 break;
 default:
-- 
2.25.1




[PATCH v2 31/55] target/ppc: Use MO_128 for 16 byte atomics

2021-08-02 Thread Richard Henderson
Cc: qemu-...@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/ppc/translate.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 171b216e17..540efa858f 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -3461,10 +3461,12 @@ static void gen_std(DisasContext *ctx)
 if (HAVE_ATOMIC128) {
 TCGv_i32 oi = tcg_temp_new_i32();
 if (ctx->le_mode) {
-tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
+tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128,
+ctx->mem_idx));
 gen_helper_stq_le_parallel(cpu_env, EA, lo, hi, oi);
 } else {
-tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
+tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128,
+ctx->mem_idx));
 gen_helper_stq_be_parallel(cpu_env, EA, lo, hi, oi);
 }
 tcg_temp_free_i32(oi);
@@ -4066,11 +4068,11 @@ static void gen_lqarx(DisasContext *ctx)
 if (HAVE_ATOMIC128) {
 TCGv_i32 oi = tcg_temp_new_i32();
 if (ctx->le_mode) {
-tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ | MO_ALIGN_16,
+tcg_gen_movi_i32(oi, make_memop_idx(MO_LE | MO_128 | MO_ALIGN,
 ctx->mem_idx));
 gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
 } else {
-tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ | MO_ALIGN_16,
+tcg_gen_movi_i32(oi, make_memop_idx(MO_BE | MO_128 | MO_ALIGN,
 ctx->mem_idx));
 gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
 }
@@ -4121,7 +4123,7 @@ static void gen_stqcx_(DisasContext *ctx)
 
 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
 if (HAVE_CMPXCHG128) {
-TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_Q) | MO_ALIGN_16);
+TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_128) | MO_ALIGN);
 if (ctx->le_mode) {
 gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env,
  EA, lo, hi, oi);
-- 
2.25.1




[PATCH v2 26/55] accel/tcg: Pass MemOpIdx to atomic_trace_*_post

2021-08-02 Thread Richard Henderson
We will shortly use the MemOpIdx directly, but in the meantime
re-compute the trace meminfo.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 accel/tcg/atomic_template.h   | 48 +--
 accel/tcg/atomic_common.c.inc | 30 +++---
 2 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
index 4230ff2957..c08d859a8a 100644
--- a/accel/tcg/atomic_template.h
+++ b/accel/tcg/atomic_template.h
@@ -77,15 +77,15 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, 
target_ulong addr,
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_READ | PAGE_WRITE, retaddr);
 DATA_TYPE ret;
-uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
 
+atomic_trace_rmw_pre(env, addr, oi);
 #if DATA_SIZE == 16
 ret = atomic16_cmpxchg(haddr, cmpv, newv);
 #else
 ret = qatomic_cmpxchg__nocheck(haddr, cmpv, newv);
 #endif
 ATOMIC_MMU_CLEANUP;
-atomic_trace_rmw_post(env, addr, info);
+atomic_trace_rmw_post(env, addr, oi);
 return ret;
 }
 
@@ -97,11 +97,11 @@ ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong 
addr,
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_READ, retaddr);
 DATA_TYPE val;
-uint16_t info = atomic_trace_ld_pre(env, addr, oi);
 
+atomic_trace_ld_pre(env, addr, oi);
 val = atomic16_read(haddr);
 ATOMIC_MMU_CLEANUP;
-atomic_trace_ld_post(env, addr, info);
+atomic_trace_ld_post(env, addr, oi);
 return val;
 }
 
@@ -110,11 +110,11 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong 
addr, ABI_TYPE val,
 {
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_WRITE, retaddr);
-uint16_t info = atomic_trace_st_pre(env, addr, oi);
 
+atomic_trace_st_pre(env, addr, oi);
 atomic16_set(haddr, val);
 ATOMIC_MMU_CLEANUP;
-atomic_trace_st_post(env, addr, info);
+atomic_trace_st_post(env, addr, oi);
 }
 #endif
 #else
@@ -124,11 +124,11 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, 
target_ulong addr, ABI_TYPE val,
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_READ | PAGE_WRITE, retaddr);
 DATA_TYPE ret;
-uint16_t info = atomic_trace_rmw_pre(env, addr, oi);
 
+atomic_trace_rmw_pre(env, addr, oi);
 ret = qatomic_xchg__nocheck(haddr, val);
 ATOMIC_MMU_CLEANUP;
-atomic_trace_rmw_post(env, addr, info);
+atomic_trace_rmw_post(env, addr, oi);
 return ret;
 }
 
@@ -139,10 +139,10 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong 
addr,   \
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,  \
  PAGE_READ | PAGE_WRITE, retaddr); \
 DATA_TYPE ret;  \
-uint16_t info = atomic_trace_rmw_pre(env, addr, oi);\
+atomic_trace_rmw_pre(env, addr, oi);\
 ret = qatomic_##X(haddr, val);  \
 ATOMIC_MMU_CLEANUP; \
-atomic_trace_rmw_post(env, addr, info); \
+atomic_trace_rmw_post(env, addr, oi);   \
 return ret; \
 }
 
@@ -172,7 +172,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong 
addr,   \
 XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
   PAGE_READ | PAGE_WRITE, retaddr); \
 XDATA_TYPE cmp, old, new, val = xval;   \
-uint16_t info = atomic_trace_rmw_pre(env, addr, oi);\
+atomic_trace_rmw_pre(env, addr, oi);\
 smp_mb();   \
 cmp = qatomic_read__nocheck(haddr); \
 do {\
@@ -180,7 +180,7 @@ ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong 
addr,   \
 cmp = qatomic_cmpxchg__nocheck(haddr, old, new);\
 } while (cmp != old);   \
 ATOMIC_MMU_CLEANUP; \
-atomic_trace_rmw_post(env, addr, info); \
+atomic_trace_rmw_post(env, addr, oi);   \
 return RET; \
 }
 
@@ -216,15 +216,15 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, 
target_ulong addr,
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_READ | PAGE_WRITE, retaddr);
 DATA_TYPE ret;
-uint16_t info = atomic_trace_rmw_pre

[PATCH v2 32/55] target/s390x: Use MO_128 for 16 byte atomics

2021-08-02 Thread Richard Henderson
Reviewed-by: David Hildenbrand 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/s390x/tcg/mem_helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c
index ec88f5dbb0..3782c1c098 100644
--- a/target/s390x/tcg/mem_helper.c
+++ b/target/s390x/tcg/mem_helper.c
@@ -1810,7 +1810,7 @@ void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t 
addr,
 assert(HAVE_CMPXCHG128);
 
 mem_idx = cpu_mmu_index(env, false);
-oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
+oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, mem_idx);
 oldv = cpu_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
 fail = !int128_eq(oldv, cmpv);
 
@@ -1939,7 +1939,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, 
uint64_t a1,
 cpu_stq_data_ra(env, a1 + 0, int128_gethi(nv), ra);
 cpu_stq_data_ra(env, a1 + 8, int128_getlo(nv), ra);
 } else if (HAVE_CMPXCHG128) {
-MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
+MemOpIdx oi = make_memop_idx(MO_TE | MO_128 | MO_ALIGN, 
mem_idx);
 ov = cpu_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
 cc = !int128_eq(ov, cv);
 } else {
-- 
2.25.1




[PATCH v2 35/55] accel/tcg: Move cpu_atomic decls to exec/cpu_ldst.h

2021-08-02 Thread Richard Henderson
The previous placement in tcg/tcg.h was not logical.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/exec/cpu_ldst.h   | 87 +++
 include/tcg/tcg.h | 87 ---
 target/arm/helper-a64.c   |  1 -
 target/m68k/op_helper.c   |  1 -
 target/ppc/mem_helper.c   |  1 -
 target/s390x/tcg/mem_helper.c |  1 -
 6 files changed, 87 insertions(+), 91 deletions(-)

diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index a4dad0772f..a878fd0105 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -63,6 +63,7 @@
 #define CPU_LDST_H
 
 #include "exec/memopidx.h"
+#include "qemu/int128.h"
 
 #if defined(CONFIG_USER_ONLY)
 /* sparc32plus has 64bit long but 32bit space address
@@ -233,6 +234,92 @@ void cpu_stl_le_mmu(CPUArchState *env, abi_ptr ptr, 
uint32_t val,
 void cpu_stq_le_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
 MemOpIdx oi, uintptr_t ra);
 
+uint32_t cpu_atomic_cmpxchgb_mmu(CPUArchState *env, target_ulong addr,
+ uint32_t cmpv, uint32_t newv,
+ MemOpIdx oi, uintptr_t retaddr);
+uint32_t cpu_atomic_cmpxchgw_le_mmu(CPUArchState *env, target_ulong addr,
+uint32_t cmpv, uint32_t newv,
+MemOpIdx oi, uintptr_t retaddr);
+uint32_t cpu_atomic_cmpxchgl_le_mmu(CPUArchState *env, target_ulong addr,
+uint32_t cmpv, uint32_t newv,
+MemOpIdx oi, uintptr_t retaddr);
+uint64_t cpu_atomic_cmpxchgq_le_mmu(CPUArchState *env, target_ulong addr,
+uint64_t cmpv, uint64_t newv,
+MemOpIdx oi, uintptr_t retaddr);
+uint32_t cpu_atomic_cmpxchgw_be_mmu(CPUArchState *env, target_ulong addr,
+uint32_t cmpv, uint32_t newv,
+MemOpIdx oi, uintptr_t retaddr);
+uint32_t cpu_atomic_cmpxchgl_be_mmu(CPUArchState *env, target_ulong addr,
+uint32_t cmpv, uint32_t newv,
+MemOpIdx oi, uintptr_t retaddr);
+uint64_t cpu_atomic_cmpxchgq_be_mmu(CPUArchState *env, target_ulong addr,
+uint64_t cmpv, uint64_t newv,
+MemOpIdx oi, uintptr_t retaddr);
+
+#define GEN_ATOMIC_HELPER(NAME, TYPE, SUFFIX) \
+TYPE cpu_atomic_ ## NAME ## SUFFIX ## _mmu\
+(CPUArchState *env, target_ulong addr, TYPE val,  \
+ MemOpIdx oi, uintptr_t retaddr);
+
+#ifdef CONFIG_ATOMIC64
+#define GEN_ATOMIC_HELPER_ALL(NAME)  \
+GEN_ATOMIC_HELPER(NAME, uint32_t, b) \
+GEN_ATOMIC_HELPER(NAME, uint32_t, w_le)  \
+GEN_ATOMIC_HELPER(NAME, uint32_t, w_be)  \
+GEN_ATOMIC_HELPER(NAME, uint32_t, l_le)  \
+GEN_ATOMIC_HELPER(NAME, uint32_t, l_be)  \
+GEN_ATOMIC_HELPER(NAME, uint64_t, q_le)  \
+GEN_ATOMIC_HELPER(NAME, uint64_t, q_be)
+#else
+#define GEN_ATOMIC_HELPER_ALL(NAME)  \
+GEN_ATOMIC_HELPER(NAME, uint32_t, b) \
+GEN_ATOMIC_HELPER(NAME, uint32_t, w_le)  \
+GEN_ATOMIC_HELPER(NAME, uint32_t, w_be)  \
+GEN_ATOMIC_HELPER(NAME, uint32_t, l_le)  \
+GEN_ATOMIC_HELPER(NAME, uint32_t, l_be)
+#endif
+
+GEN_ATOMIC_HELPER_ALL(fetch_add)
+GEN_ATOMIC_HELPER_ALL(fetch_sub)
+GEN_ATOMIC_HELPER_ALL(fetch_and)
+GEN_ATOMIC_HELPER_ALL(fetch_or)
+GEN_ATOMIC_HELPER_ALL(fetch_xor)
+GEN_ATOMIC_HELPER_ALL(fetch_smin)
+GEN_ATOMIC_HELPER_ALL(fetch_umin)
+GEN_ATOMIC_HELPER_ALL(fetch_smax)
+GEN_ATOMIC_HELPER_ALL(fetch_umax)
+
+GEN_ATOMIC_HELPER_ALL(add_fetch)
+GEN_ATOMIC_HELPER_ALL(sub_fetch)
+GEN_ATOMIC_HELPER_ALL(and_fetch)
+GEN_ATOMIC_HELPER_ALL(or_fetch)
+GEN_ATOMIC_HELPER_ALL(xor_fetch)
+GEN_ATOMIC_HELPER_ALL(smin_fetch)
+GEN_ATOMIC_HELPER_ALL(umin_fetch)
+GEN_ATOMIC_HELPER_ALL(smax_fetch)
+GEN_ATOMIC_HELPER_ALL(umax_fetch)
+
+GEN_ATOMIC_HELPER_ALL(xchg)
+
+#undef GEN_ATOMIC_HELPER_ALL
+#undef GEN_ATOMIC_HELPER
+
+Int128 cpu_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr,
+  Int128 cmpv, Int128 newv,
+  MemOpIdx oi, uintptr_t retaddr);
+Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr,
+  Int128 cmpv, Int128 newv,
+  MemOpIdx oi, uintptr_t retaddr);
+
+Int128 cpu_atomic_ldo_le_mmu(CPUArchState *env, target_ulong addr,
+ MemOpIdx oi, uintptr_t retaddr);
+Int128 cpu_atomic_ldo_be_mmu(CPUArchState *env, target_ulong addr,
+ MemOpIdx oi, uintptr_t retaddr);
+void cpu_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
+   MemOpIdx oi, uintptr_t retaddr);
+void cpu_atomic_sto_be_mmu(CPUArchState *env, target_ulong 

[PATCH v2 23/55] tcg: Rename TCGMemOpIdx to MemOpIdx

2021-08-02 Thread Richard Henderson
We're about to move this out of tcg.h, so rename it
as we did when moving MemOp.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 accel/tcg/atomic_template.h   | 24 +--
 include/tcg/tcg.h | 74 -
 accel/tcg/cputlb.c| 78 +--
 accel/tcg/user-exec.c |  2 +-
 target/arm/helper-a64.c   | 16 +++
 target/arm/m_helper.c |  2 +-
 target/i386/tcg/mem_helper.c  |  4 +-
 target/m68k/op_helper.c   |  2 +-
 target/mips/tcg/msa_helper.c  |  6 +--
 target/s390x/tcg/mem_helper.c | 20 -
 target/sparc/ldst_helper.c|  2 +-
 tcg/optimize.c|  2 +-
 tcg/tcg-op.c  | 12 +++---
 tcg/tcg.c |  2 +-
 tcg/tci.c | 14 +++
 accel/tcg/atomic_common.c.inc |  6 +--
 tcg/aarch64/tcg-target.c.inc  | 14 +++
 tcg/arm/tcg-target.c.inc  | 10 ++---
 tcg/i386/tcg-target.c.inc | 10 ++---
 tcg/mips/tcg-target.c.inc | 12 +++---
 tcg/ppc/tcg-target.c.inc  | 10 ++---
 tcg/riscv/tcg-target.c.inc| 16 +++
 tcg/s390/tcg-target.c.inc | 10 ++---
 tcg/sparc/tcg-target.c.inc|  4 +-
 tcg/tcg-ldst.c.inc|  2 +-
 25 files changed, 177 insertions(+), 177 deletions(-)

diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
index 8098a1be31..4230ff2957 100644
--- a/accel/tcg/atomic_template.h
+++ b/accel/tcg/atomic_template.h
@@ -72,7 +72,7 @@
 
 ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
   ABI_TYPE cmpv, ABI_TYPE newv,
-  TCGMemOpIdx oi, uintptr_t retaddr)
+  MemOpIdx oi, uintptr_t retaddr)
 {
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_READ | PAGE_WRITE, retaddr);
@@ -92,7 +92,7 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong 
addr,
 #if DATA_SIZE >= 16
 #if HAVE_ATOMIC128
 ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr,
- TCGMemOpIdx oi, uintptr_t retaddr)
+ MemOpIdx oi, uintptr_t retaddr)
 {
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_READ, retaddr);
@@ -106,7 +106,7 @@ ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong 
addr,
 }
 
 void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
- TCGMemOpIdx oi, uintptr_t retaddr)
+ MemOpIdx oi, uintptr_t retaddr)
 {
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_WRITE, retaddr);
@@ -119,7 +119,7 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr, 
ABI_TYPE val,
 #endif
 #else
 ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr, ABI_TYPE val,
-   TCGMemOpIdx oi, uintptr_t retaddr)
+   MemOpIdx oi, uintptr_t retaddr)
 {
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_READ | PAGE_WRITE, retaddr);
@@ -134,7 +134,7 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong 
addr, ABI_TYPE val,
 
 #define GEN_ATOMIC_HELPER(X)\
 ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr,   \
-ABI_TYPE val, TCGMemOpIdx oi, uintptr_t retaddr) \
+ABI_TYPE val, MemOpIdx oi, uintptr_t retaddr) \
 {   \
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,  \
  PAGE_READ | PAGE_WRITE, retaddr); \
@@ -167,7 +167,7 @@ GEN_ATOMIC_HELPER(xor_fetch)
  */
 #define GEN_ATOMIC_HELPER_FN(X, FN, XDATA_TYPE, RET)\
 ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr,   \
-ABI_TYPE xval, TCGMemOpIdx oi, uintptr_t retaddr) \
+ABI_TYPE xval, MemOpIdx oi, uintptr_t retaddr) \
 {   \
 XDATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE, \
   PAGE_READ | PAGE_WRITE, retaddr); \
@@ -211,7 +211,7 @@ GEN_ATOMIC_HELPER_FN(umax_fetch, MAX,  DATA_TYPE, new)
 
 ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
   ABI_TYPE cmpv, ABI_TYPE newv,
-  TCGMemOpIdx oi, uintptr_t retaddr)
+  MemOpIdx oi, uintptr_t retaddr)
 {
 DATA_TYPE *haddr = atomic_mmu_lookup(env, addr, oi, DATA_SIZE,
  PAGE_READ | PAGE_WRITE, retaddr);
@@ -231,7 +231,7 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, 
target_ulong addr,
 #if DATA_SIZE >= 16
 

[PATCH v2 29/55] target/arm: Use MO_128 for 16 byte atomics

2021-08-02 Thread Richard Henderson
Cc: qemu-...@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/arm/helper-a64.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 13d1e3f808..f06399f351 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -560,7 +560,7 @@ uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState 
*env, uint64_t addr,
 assert(HAVE_CMPXCHG128);
 
 mem_idx = cpu_mmu_index(env, false);
-oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
+oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
 
 cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
 newv = int128_make128(new_lo, new_hi);
@@ -630,7 +630,7 @@ uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState 
*env, uint64_t addr,
 assert(HAVE_CMPXCHG128);
 
 mem_idx = cpu_mmu_index(env, false);
-oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
+oi = make_memop_idx(MO_BE | MO_128 | MO_ALIGN, mem_idx);
 
 /*
  * High and low need to be switched here because this is not actually a
@@ -656,7 +656,7 @@ void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t 
rs, uint64_t addr,
 assert(HAVE_CMPXCHG128);
 
 mem_idx = cpu_mmu_index(env, false);
-oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
+oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
 
 cmpv = int128_make128(env->xregs[rs], env->xregs[rs + 1]);
 newv = int128_make128(new_lo, new_hi);
@@ -677,7 +677,7 @@ void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t 
rs, uint64_t addr,
 assert(HAVE_CMPXCHG128);
 
 mem_idx = cpu_mmu_index(env, false);
-oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
+oi = make_memop_idx(MO_LE | MO_128 | MO_ALIGN, mem_idx);
 
 cmpv = int128_make128(env->xregs[rs + 1], env->xregs[rs]);
 newv = int128_make128(new_lo, new_hi);
-- 
2.25.1




[PATCH v2 27/55] plugins: Reorg arguments to qemu_plugin_vcpu_mem_cb

2021-08-02 Thread Richard Henderson
Use the MemOpIdx directly, rather than the rearrangement
of the same bits currently done by the trace infrastructure.
Pass in enum qemu_plugin_mem_rw so that we are able to treat
read-modify-write operations as a single operation.

Signed-off-by: Richard Henderson 
---
 include/qemu/plugin.h | 26 --
 accel/tcg/cputlb.c|  4 ++--
 accel/tcg/plugin-gen.c|  5 ++---
 accel/tcg/user-exec.c | 28 ++--
 plugins/api.c | 19 +++
 plugins/core.c| 10 +-
 tcg/tcg-op.c  | 30 +-
 accel/tcg/atomic_common.c.inc | 13 +++--
 8 files changed, 82 insertions(+), 53 deletions(-)

diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index 9a8438f683..b3172b147f 100644
--- a/include/qemu/plugin.h
+++ b/include/qemu/plugin.h
@@ -12,6 +12,7 @@
 #include "qemu/error-report.h"
 #include "qemu/queue.h"
 #include "qemu/option.h"
+#include "exec/memopidx.h"
 
 /*
  * Events that plugins can subscribe to.
@@ -36,6 +37,25 @@ enum qemu_plugin_event {
 struct qemu_plugin_desc;
 typedef QTAILQ_HEAD(, qemu_plugin_desc) QemuPluginList;
 
+/*
+ * Construct a qemu_plugin_meminfo_t.
+ */
+static inline qemu_plugin_meminfo_t
+make_plugin_meminfo(MemOpIdx oi, enum qemu_plugin_mem_rw rw)
+{
+return oi | (rw << 16);
+}
+
+/*
+ * Extract the memory operation direction from a qemu_plugin_meminfo_t.
+ * Other portions may be extracted via get_memop and get_mmuidx.
+ */
+static inline enum qemu_plugin_mem_rw
+get_plugin_meminfo_rw(qemu_plugin_meminfo_t i)
+{
+return i >> 16;
+}
+
 #ifdef CONFIG_PLUGIN
 extern QemuOptsList qemu_plugin_opts;
 
@@ -180,7 +200,8 @@ qemu_plugin_vcpu_syscall(CPUState *cpu, int64_t num, 
uint64_t a1,
  uint64_t a6, uint64_t a7, uint64_t a8);
 void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t num, int64_t ret);
 
-void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr, uint32_t meminfo);
+void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
+ MemOpIdx oi, enum qemu_plugin_mem_rw rw);
 
 void qemu_plugin_flush_cb(void);
 
@@ -244,7 +265,8 @@ void qemu_plugin_vcpu_syscall_ret(CPUState *cpu, int64_t 
num, int64_t ret)
 { }
 
 static inline void qemu_plugin_vcpu_mem_cb(CPUState *cpu, uint64_t vaddr,
-   uint32_t meminfo)
+   MemOpIdx oi,
+   enum qemu_plugin_mem_rw rw)
 { }
 
 static inline void qemu_plugin_flush_cb(void)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index c27658b8a2..04436f98c8 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -2111,7 +2111,7 @@ static inline uint64_t cpu_load_helper(CPUArchState *env, 
abi_ptr addr,
 
 ret = full_load(env, addr, oi, retaddr);
 
-qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, meminfo);
+qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
 
 return ret;
 }
@@ -2547,7 +2547,7 @@ cpu_store_helper(CPUArchState *env, target_ulong addr, 
uint64_t val,
 
 store_helper(env, addr, val, oi, retaddr, op);
 
-qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, meminfo);
+qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
 }
 
 void cpu_stb_mmuidx_ra(CPUArchState *env, target_ulong addr, uint32_t val,
diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c
index 88e25c6df9..f5fd5f279c 100644
--- a/accel/tcg/plugin-gen.c
+++ b/accel/tcg/plugin-gen.c
@@ -45,7 +45,6 @@
 #include "qemu/osdep.h"
 #include "tcg/tcg.h"
 #include "tcg/tcg-op.h"
-#include "trace/mem.h"
 #include "exec/exec-all.h"
 #include "exec/plugin-gen.h"
 #include "exec/translator.h"
@@ -211,9 +210,9 @@ static void gen_mem_wrapped(enum plugin_gen_cb type,
 const union mem_gen_fn *f, TCGv addr,
 uint32_t info, bool is_mem)
 {
-int wr = !!(info & TRACE_MEM_ST);
+enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info);
 
-gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, type, wr);
+gen_plugin_cb_start(PLUGIN_GEN_FROM_MEM, type, rw);
 if (is_mem) {
 f->mem_fn(addr, info);
 } else {
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 68d9c1b33d..d96d60a804 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -861,7 +861,7 @@ uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr)
 
 trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
 ret = ldub_p(g2h(env_cpu(env), ptr));
-qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
+qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
 return ret;
 }
 
@@ -878,7 +878,7 @@ uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
 
 trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
 ret = lduw_be_p(g2h(env_cpu(env), ptr));
-qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
+

[PATCH v2 33/55] target/hexagon: Implement cpu_mmu_index

2021-08-02 Thread Richard Henderson
The function is trivial for user-only, but still must be present.

Reviewed-by: Taylor Simpson 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/hexagon/cpu.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 2855dd3881..bde538fd5c 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -144,6 +144,15 @@ static inline void cpu_get_tb_cpu_state(CPUHexagonState 
*env, target_ulong *pc,
 #endif
 }
 
+static inline int cpu_mmu_index(CPUHexagonState *env, bool ifetch)
+{
+#ifdef CONFIG_USER_ONLY
+return MMU_USER_IDX;
+#else
+#error System mode not supported on Hexagon yet
+#endif
+}
+
 typedef struct CPUHexagonState CPUArchState;
 typedef HexagonCPU ArchCPU;
 
-- 
2.25.1




[PATCH v2 18/55] target/sparc: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Cc: Mark Cave-Ayland 
Signed-off-by: Richard Henderson 
---
 linux-user/sparc/cpu_loop.c | 11 +++
 target/sparc/cpu.c  |  2 +-
 target/sparc/mmu_helper.c   |  4 +++-
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c
index 02532f198d..612e77807e 100644
--- a/linux-user/sparc/cpu_loop.c
+++ b/linux-user/sparc/cpu_loop.c
@@ -272,6 +272,17 @@ void cpu_loop (CPUSPARCState *env)
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
 }
 break;
+case TT_UNALIGNED:
+info.si_signo = TARGET_SIGBUS;
+info.si_errno = 0;
+info.si_code = TARGET_BUS_ADRALN;
+#ifdef TARGET_SPARC64
+info._sifields._sigfault._addr = env->dmmu.sfar;
+#else
+info._sifields._sigfault._addr = env->mmuregs[4];
+#endif
+queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+break;
 case EXCP_DEBUG:
 info.si_signo = TARGET_SIGTRAP;
 info.si_errno = 0;
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index da6b30ec74..d33d41e837 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -865,11 +865,11 @@ static const struct TCGCPUOps sparc_tcg_ops = {
 .synchronize_from_tb = sparc_cpu_synchronize_from_tb,
 .cpu_exec_interrupt = sparc_cpu_exec_interrupt,
 .tlb_fill = sparc_cpu_tlb_fill,
+.do_unaligned_access = sparc_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
 .do_interrupt = sparc_cpu_do_interrupt,
 .do_transaction_failed = sparc_cpu_do_transaction_failed,
-.do_unaligned_access = sparc_cpu_do_unaligned_access,
 #endif /* !CONFIG_USER_ONLY */
 };
 #endif /* CONFIG_TCG */
diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c
index 2f260b0085..6b4aa32181 100644
--- a/target/sparc/mmu_helper.c
+++ b/target/sparc/mmu_helper.c
@@ -946,6 +946,7 @@ hwaddr sparc_cpu_get_phys_page_debug(CPUState *cs, vaddr 
addr)
 }
 return phys_addr;
 }
+#endif /* CONFIG_USER_ONLY */
 
 void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
  MMUAccessType access_type,
@@ -956,7 +957,9 @@ void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState 
*cs, vaddr addr,
 CPUSPARCState *env = &cpu->env;
 
 #ifdef TARGET_SPARC64
+#ifndef CONFIG_USER_ONLY
 env->dmmu.sfsr = build_sfsr(env, mmu_idx, access_type);
+#endif
 env->dmmu.sfar = addr;
 #else
 env->mmuregs[4] = addr;
@@ -964,4 +967,3 @@ void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState 
*cs, vaddr addr,
 
 cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr);
 }
-#endif /* CONFIG_USER_ONLY */
-- 
2.25.1




[PATCH v2 22/55] tcg: Expand MO_SIZE to 3 bits

2021-08-02 Thread Richard Henderson
We have lacked expressive support for memory sizes larger
than 64-bits for a while.  Fixing that requires adjustment
to several points where we used this for array indexing,
and two places that develop -Wswitch warnings after the change.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/exec/memop.h| 14 +-
 target/arm/translate-a64.c  |  2 +-
 tcg/tcg-op.c| 13 -
 target/s390x/tcg/translate_vx.c.inc |  2 +-
 tcg/aarch64/tcg-target.c.inc|  4 ++--
 tcg/arm/tcg-target.c.inc|  4 ++--
 tcg/i386/tcg-target.c.inc   |  4 ++--
 tcg/mips/tcg-target.c.inc   |  4 ++--
 tcg/ppc/tcg-target.c.inc|  8 
 tcg/riscv/tcg-target.c.inc  |  4 ++--
 tcg/s390/tcg-target.c.inc   |  4 ++--
 tcg/sparc/tcg-target.c.inc  | 16 
 12 files changed, 43 insertions(+), 36 deletions(-)

diff --git a/include/exec/memop.h b/include/exec/memop.h
index 529d07b02d..04264ffd6b 100644
--- a/include/exec/memop.h
+++ b/include/exec/memop.h
@@ -19,11 +19,15 @@ typedef enum MemOp {
 MO_16= 1,
 MO_32= 2,
 MO_64= 3,
-MO_SIZE  = 3,   /* Mask for the above.  */
+MO_128   = 4,
+MO_256   = 5,
+MO_512   = 6,
+MO_1024  = 7,
+MO_SIZE  = 0x07,   /* Mask for the above.  */
 
-MO_SIGN  = 4,   /* Sign-extended, otherwise zero-extended.  */
+MO_SIGN  = 0x08,   /* Sign-extended, otherwise zero-extended.  */
 
-MO_BSWAP = 8,   /* Host reverse endian.  */
+MO_BSWAP = 0x10,   /* Host reverse endian.  */
 #ifdef HOST_WORDS_BIGENDIAN
 MO_LE= MO_BSWAP,
 MO_BE= 0,
@@ -59,8 +63,8 @@ typedef enum MemOp {
  * - an alignment to a specified size, which may be more or less than
  *   the access size (MO_ALIGN_x where 'x' is a size in bytes);
  */
-MO_ASHIFT = 4,
-MO_AMASK = 7 << MO_ASHIFT,
+MO_ASHIFT = 5,
+MO_AMASK = 0x7 << MO_ASHIFT,
 #ifdef NEED_CPU_H
 #ifdef TARGET_ALIGNED_ONLY
 MO_ALIGN = 0,
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 422e2ac0c9..247c9672be 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1045,7 +1045,7 @@ static void read_vec_element(DisasContext *s, TCGv_i64 
tcg_dest, int srcidx,
  int element, MemOp memop)
 {
 int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
-switch (memop) {
+switch ((unsigned)memop) {
 case MO_8:
 tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
 break;
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index c754396575..e01f68f44d 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -2780,10 +2780,13 @@ static inline MemOp tcg_canonicalize_memop(MemOp op, 
bool is64, bool st)
 }
 break;
 case MO_64:
-if (!is64) {
-tcg_abort();
+if (is64) {
+op &= ~MO_SIGN;
+break;
 }
-break;
+/* fall through */
+default:
+g_assert_not_reached();
 }
 if (st) {
 op &= ~MO_SIGN;
@@ -3095,7 +3098,7 @@ typedef void (*gen_atomic_op_i64)(TCGv_i64, TCGv_env, 
TCGv,
 # define WITH_ATOMIC64(X)
 #endif
 
-static void * const table_cmpxchg[16] = {
+static void * const table_cmpxchg[(MO_SIZE | MO_BSWAP) + 1] = {
 [MO_8] = gen_helper_atomic_cmpxchgb,
 [MO_16 | MO_LE] = gen_helper_atomic_cmpxchgw_le,
 [MO_16 | MO_BE] = gen_helper_atomic_cmpxchgw_be,
@@ -3297,7 +3300,7 @@ static void do_atomic_op_i64(TCGv_i64 ret, TCGv addr, 
TCGv_i64 val,
 }
 
 #define GEN_ATOMIC_HELPER(NAME, OP, NEW)\
-static void * const table_##NAME[16] = {\
+static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = {  \
 [MO_8] = gen_helper_atomic_##NAME##b,   \
 [MO_16 | MO_LE] = gen_helper_atomic_##NAME##w_le,   \
 [MO_16 | MO_BE] = gen_helper_atomic_##NAME##w_be,   \
diff --git a/target/s390x/tcg/translate_vx.c.inc 
b/target/s390x/tcg/translate_vx.c.inc
index 0afa46e463..28bf5a23b6 100644
--- a/target/s390x/tcg/translate_vx.c.inc
+++ b/target/s390x/tcg/translate_vx.c.inc
@@ -67,7 +67,7 @@ static void read_vec_element_i64(TCGv_i64 dst, uint8_t reg, 
uint8_t enr,
 {
 const int offs = vec_reg_offset(reg, enr, memop & MO_SIZE);
 
-switch (memop) {
+switch ((unsigned)memop) {
 case ES_8:
 tcg_gen_ld8u_i64(dst, cpu_env, offs);
 break;
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 5924977b42..6f43c048a5 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -1547,7 +1547,7 @@ static void tcg_out_cltz(TCGContext *s, TCGType ext, 
TCGReg d,
 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
  * TCGMemOpIdx oi, uintptr_t ra)
  */
-static void * const qem

[PATCH v2 19/55] target/xtensa: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Cc: Max Filippov 
Signed-off-by: Richard Henderson 
---
 target/xtensa/cpu.c|  2 +-
 target/xtensa/helper.c | 30 +++---
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index 58ec3a0862..41816d91f6 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -195,11 +195,11 @@ static const struct TCGCPUOps xtensa_tcg_ops = {
 .cpu_exec_interrupt = xtensa_cpu_exec_interrupt,
 .tlb_fill = xtensa_cpu_tlb_fill,
 .debug_excp_handler = xtensa_breakpoint_handler,
+.do_unaligned_access = xtensa_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
 .do_interrupt = xtensa_cpu_do_interrupt,
 .do_transaction_failed = xtensa_cpu_do_transaction_failed,
-.do_unaligned_access = xtensa_cpu_do_unaligned_access,
 #endif /* !CONFIG_USER_ONLY */
 };
 
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index f18ab383fd..a5296399c5 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -242,6 +242,21 @@ void xtensa_cpu_list(void)
 }
 }
 
+void xtensa_cpu_do_unaligned_access(CPUState *cs,
+vaddr addr, MMUAccessType access_type,
+int mmu_idx, uintptr_t retaddr)
+{
+XtensaCPU *cpu = XTENSA_CPU(cs);
+CPUXtensaState *env = &cpu->env;
+
+assert(xtensa_option_enabled(env->config,
+ XTENSA_OPTION_UNALIGNED_EXCEPTION));
+cpu_restore_state(CPU(cpu), retaddr, true);
+HELPER(exception_cause_vaddr)(env,
+  env->pc, LOAD_STORE_ALIGNMENT_CAUSE,
+  addr);
+}
+
 #ifdef CONFIG_USER_ONLY
 
 bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
@@ -263,21 +278,6 @@ bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 
 #else /* !CONFIG_USER_ONLY */
 
-void xtensa_cpu_do_unaligned_access(CPUState *cs,
-vaddr addr, MMUAccessType access_type,
-int mmu_idx, uintptr_t retaddr)
-{
-XtensaCPU *cpu = XTENSA_CPU(cs);
-CPUXtensaState *env = &cpu->env;
-
-assert(xtensa_option_enabled(env->config,
- XTENSA_OPTION_UNALIGNED_EXCEPTION));
-cpu_restore_state(CPU(cpu), retaddr, true);
-HELPER(exception_cause_vaddr)(env,
-  env->pc, LOAD_STORE_ALIGNMENT_CAUSE,
-  addr);
-}
-
 bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
  MMUAccessType access_type, int mmu_idx,
  bool probe, uintptr_t retaddr)
-- 
2.25.1




[PATCH v2 24/55] tcg: Split out MemOpIdx to exec/memopidx.h

2021-08-02 Thread Richard Henderson
Move this code from tcg/tcg.h to its own header.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 include/exec/memopidx.h | 55 +
 include/tcg/tcg.h   | 39 +
 2 files changed, 56 insertions(+), 38 deletions(-)
 create mode 100644 include/exec/memopidx.h

diff --git a/include/exec/memopidx.h b/include/exec/memopidx.h
new file mode 100644
index 00..83bce97874
--- /dev/null
+++ b/include/exec/memopidx.h
@@ -0,0 +1,55 @@
+/*
+ * Combine the MemOp and mmu_idx parameters into a single value.
+ *
+ * Authors:
+ *  Richard Henderson 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef EXEC_MEMOPIDX_H
+#define EXEC_MEMOPIDX_H 1
+
+#include "exec/memop.h"
+
+typedef uint32_t MemOpIdx;
+
+/**
+ * make_memop_idx
+ * @op: memory operation
+ * @idx: mmu index
+ *
+ * Encode these values into a single parameter.
+ */
+static inline MemOpIdx make_memop_idx(MemOp op, unsigned idx)
+{
+#ifdef CONFIG_DEBUG_TCG
+assert(idx <= 15);
+#endif
+return (op << 4) | idx;
+}
+
+/**
+ * get_memop
+ * @oi: combined op/idx parameter
+ *
+ * Extract the memory operation from the combined value.
+ */
+static inline MemOp get_memop(MemOpIdx oi)
+{
+return oi >> 4;
+}
+
+/**
+ * get_mmuidx
+ * @oi: combined op/idx parameter
+ *
+ * Extract the mmu index from the combined value.
+ */
+static inline unsigned get_mmuidx(MemOpIdx oi)
+{
+return oi & 15;
+}
+
+#endif
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index f91ebd0743..e67ef34694 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -27,6 +27,7 @@
 
 #include "cpu.h"
 #include "exec/memop.h"
+#include "exec/memopidx.h"
 #include "qemu/bitops.h"
 #include "qemu/plugin.h"
 #include "qemu/queue.h"
@@ -1147,44 +1148,6 @@ static inline size_t tcg_current_code_size(TCGContext *s)
 return tcg_ptr_byte_diff(s->code_ptr, s->code_buf);
 }
 
-/* Combine the MemOp and mmu_idx parameters into a single value.  */
-typedef uint32_t MemOpIdx;
-
-/**
- * make_memop_idx
- * @op: memory operation
- * @idx: mmu index
- *
- * Encode these values into a single parameter.
- */
-static inline MemOpIdx make_memop_idx(MemOp op, unsigned idx)
-{
-tcg_debug_assert(idx <= 15);
-return (op << 4) | idx;
-}
-
-/**
- * get_memop
- * @oi: combined op/idx parameter
- *
- * Extract the memory operation from the combined value.
- */
-static inline MemOp get_memop(MemOpIdx oi)
-{
-return oi >> 4;
-}
-
-/**
- * get_mmuidx
- * @oi: combined op/idx parameter
- *
- * Extract the mmu index from the combined value.
- */
-static inline unsigned get_mmuidx(MemOpIdx oi)
-{
-return oi & 15;
-}
-
 /**
  * tcg_qemu_tb_exec:
  * @env: pointer to CPUArchState for the CPU
-- 
2.25.1




[PATCH v2 17/55] target/sparc: Set fault address in sparc_cpu_do_unaligned_access

2021-08-02 Thread Richard Henderson
We ought to have been recording the virtual address for reporting
to the guest trap handler.  Move the function to mmu_helper.c, so
that we can re-use code shared with get_physical_address_data.

Cc: Mark Cave-Ayland 
Signed-off-by: Richard Henderson 
---
 target/sparc/ldst_helper.c | 13 -
 target/sparc/mmu_helper.c  | 18 ++
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
index 974afea041..ea163200a4 100644
--- a/target/sparc/ldst_helper.c
+++ b/target/sparc/ldst_helper.c
@@ -1953,16 +1953,3 @@ void sparc_cpu_do_transaction_failed(CPUState *cs, 
hwaddr physaddr,
   is_asi, size, retaddr);
 }
 #endif
-
-#if !defined(CONFIG_USER_ONLY)
-void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
- MMUAccessType access_type,
- int mmu_idx,
- uintptr_t retaddr)
-{
-SPARCCPU *cpu = SPARC_CPU(cs);
-CPUSPARCState *env = &cpu->env;
-
-cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr);
-}
-#endif
diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c
index 5b2fda534a..2f260b0085 100644
--- a/target/sparc/mmu_helper.c
+++ b/target/sparc/mmu_helper.c
@@ -946,4 +946,22 @@ hwaddr sparc_cpu_get_phys_page_debug(CPUState *cs, vaddr 
addr)
 }
 return phys_addr;
 }
+
+void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+ MMUAccessType access_type,
+ int mmu_idx,
+ uintptr_t retaddr)
+{
+SPARCCPU *cpu = SPARC_CPU(cs);
+CPUSPARCState *env = &cpu->env;
+
+#ifdef TARGET_SPARC64
+env->dmmu.sfsr = build_sfsr(env, mmu_idx, access_type);
+env->dmmu.sfar = addr;
+#else
+env->mmuregs[4] = addr;
 #endif
+
+cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr);
+}
+#endif /* CONFIG_USER_ONLY */
-- 
2.25.1




[PATCH v2 20/55] accel/tcg: Report unaligned atomics for user-only

2021-08-02 Thread Richard Henderson
Use the newly exposed cpu_unaligned_access for atomic_mmu_lookup,
which has access to complete alignment info from the TCGMemOpIdx arg.

Signed-off-by: Richard Henderson 
---
 accel/tcg/user-exec.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 90d1a2d327..5ad808a25a 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -28,6 +28,7 @@
 #include "qemu/atomic128.h"
 #include "trace/trace-root.h"
 #include "trace/mem.h"
+#include "internal.h"
 
 #undef EAX
 #undef ECX
@@ -1230,11 +1231,22 @@ static void *atomic_mmu_lookup(CPUArchState *env, 
target_ulong addr,
TCGMemOpIdx oi, int size, int prot,
uintptr_t retaddr)
 {
+MemOp mop = get_memop(oi);
+int a_bits = get_alignment_bits(mop);
+void *ret;
+
+/* Enforce guest required alignment.  */
+if (unlikely(addr & ((1 << a_bits) - 1))) {
+MMUAccessType t = prot == PAGE_READ ? MMU_DATA_LOAD : MMU_DATA_STORE;
+cpu_unaligned_access(env_cpu(env), addr, t, get_mmuidx(oi), retaddr);
+}
+
 /* Enforce qemu required alignment.  */
 if (unlikely(addr & (size - 1))) {
 cpu_loop_exit_atomic(env_cpu(env), retaddr);
 }
-void *ret = g2h(env_cpu(env), addr);
+
+ret = g2h(env_cpu(env), addr);
 set_helper_retaddr(retaddr);
 return ret;
 }
-- 
2.25.1




[PATCH v2 21/55] accel/tcg: Drop signness in tracing in cputlb.c

2021-08-02 Thread Richard Henderson
We are already inconsistent about whether or not
MO_SIGN is set in trace_mem_get_info.  Dropping it
entirely allows some simplification.

Signed-off-by: Richard Henderson 
---
 accel/tcg/cputlb.c| 10 +++---
 accel/tcg/user-exec.c | 45 ++-
 2 files changed, 9 insertions(+), 46 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 116b289907..acdd20b1bc 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -2110,7 +2110,6 @@ static inline uint64_t cpu_load_helper(CPUArchState *env, 
abi_ptr addr,
 meminfo = trace_mem_get_info(op, mmu_idx, false);
 trace_guest_mem_before_exec(env_cpu(env), addr, meminfo);
 
-op &= ~MO_SIGN;
 oi = make_memop_idx(op, mmu_idx);
 ret = full_load(env, addr, oi, retaddr);
 
@@ -2128,8 +2127,7 @@ uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr 
addr,
 int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
int mmu_idx, uintptr_t ra)
 {
-return (int8_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_SB,
-   full_ldub_mmu);
+return (int8_t)cpu_ldub_mmuidx_ra(env, addr, mmu_idx, ra);
 }
 
 uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
@@ -2141,8 +2139,7 @@ uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr 
addr,
 int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
   int mmu_idx, uintptr_t ra)
 {
-return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_BESW,
-full_be_lduw_mmu);
+return (int16_t)cpu_lduw_be_mmuidx_ra(env, addr, mmu_idx, ra);
 }
 
 uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
@@ -2166,8 +2163,7 @@ uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr 
addr,
 int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
   int mmu_idx, uintptr_t ra)
 {
-return (int16_t)cpu_load_helper(env, addr, mmu_idx, ra, MO_LESW,
-full_le_lduw_mmu);
+return (int16_t)cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, ra);
 }
 
 uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 5ad808a25a..e687b9652e 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -866,13 +866,7 @@ uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr)
 
 int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr)
 {
-int ret;
-uint16_t meminfo = trace_mem_get_info(MO_SB, MMU_USER_IDX, false);
-
-trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
-ret = ldsb_p(g2h(env_cpu(env), ptr));
-qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
-return ret;
+return (int8_t)cpu_ldub_data(env, ptr);
 }
 
 uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
@@ -888,13 +882,7 @@ uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
 
 int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr)
 {
-int ret;
-uint16_t meminfo = trace_mem_get_info(MO_BESW, MMU_USER_IDX, false);
-
-trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
-ret = ldsw_be_p(g2h(env_cpu(env), ptr));
-qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
-return ret;
+return (int16_t)cpu_lduw_be_data(env, ptr);
 }
 
 uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr)
@@ -932,13 +920,7 @@ uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr)
 
 int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr)
 {
-int ret;
-uint16_t meminfo = trace_mem_get_info(MO_LESW, MMU_USER_IDX, false);
-
-trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
-ret = ldsw_le_p(g2h(env_cpu(env), ptr));
-qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
-return ret;
+return (int16_t)cpu_lduw_le_data(env, ptr);
 }
 
 uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr)
@@ -975,12 +957,7 @@ uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, 
uintptr_t retaddr)
 
 int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
 {
-int ret;
-
-set_helper_retaddr(retaddr);
-ret = cpu_ldsb_data(env, ptr);
-clear_helper_retaddr();
-return ret;
+return (int8_t)cpu_ldub_data_ra(env, ptr, retaddr);
 }
 
 uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
@@ -995,12 +972,7 @@ uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr 
ptr, uintptr_t retaddr)
 
 int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
 {
-int ret;
-
-set_helper_retaddr(retaddr);
-ret = cpu_ldsw_be_data(env, ptr);
-clear_helper_retaddr();
-return ret;
+return (int16_t)cpu_lduw_be_data_ra(env, ptr, retaddr);
 }
 
 uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
@@ -1035,12 +1007,7 @@ uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr 
ptr, uintptr_t retaddr)
 
 int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
 {
-int 

[PATCH v2 12/55] target/s390x: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Reviewed-by: David Hildenbrand 
Signed-off-by: Richard Henderson 
---
 target/s390x/cpu.c |  2 +-
 target/s390x/tcg/excp_helper.c | 28 +++-
 2 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 7b7b05f1d3..9d8cfb37cd 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -267,12 +267,12 @@ static void s390_cpu_reset_full(DeviceState *dev)
 static const struct TCGCPUOps s390_tcg_ops = {
 .initialize = s390x_translate_init,
 .tlb_fill = s390_cpu_tlb_fill,
+.do_unaligned_access = s390x_cpu_do_unaligned_access,
 
 #if !defined(CONFIG_USER_ONLY)
 .cpu_exec_interrupt = s390_cpu_exec_interrupt,
 .do_interrupt = s390_cpu_do_interrupt,
 .debug_excp_handler = s390x_cpu_debug_excp_handler,
-.do_unaligned_access = s390x_cpu_do_unaligned_access,
 #endif /* !CONFIG_USER_ONLY */
 };
 #endif /* CONFIG_TCG */
diff --git a/target/s390x/tcg/excp_helper.c b/target/s390x/tcg/excp_helper.c
index a61917d04f..9cbe160f66 100644
--- a/target/s390x/tcg/excp_helper.c
+++ b/target/s390x/tcg/excp_helper.c
@@ -82,6 +82,21 @@ void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc)
 tcg_s390_data_exception(env, dxc, GETPC());
 }
 
+/*
+ * Unaligned accesses are only diagnosed with MO_ALIGN.  At the moment,
+ * this is only for the atomic operations, for which we want to raise a
+ * specification exception.
+ */
+void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+   MMUAccessType access_type,
+   int mmu_idx, uintptr_t retaddr)
+{
+S390CPU *cpu = S390_CPU(cs);
+CPUS390XState *env = &cpu->env;
+
+tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr);
+}
+
 #if defined(CONFIG_USER_ONLY)
 
 void s390_cpu_do_interrupt(CPUState *cs)
@@ -602,19 +617,6 @@ void s390x_cpu_debug_excp_handler(CPUState *cs)
 }
 }
 
-/* Unaligned accesses are only diagnosed with MO_ALIGN.  At the moment,
-   this is only for the atomic operations, for which we want to raise a
-   specification exception.  */
-void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
-   MMUAccessType access_type,
-   int mmu_idx, uintptr_t retaddr)
-{
-S390CPU *cpu = S390_CPU(cs);
-CPUS390XState *env = &cpu->env;
-
-tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr);
-}
-
 static void QEMU_NORETURN monitor_event(CPUS390XState *env,
 uint64_t monitor_code,
 uint8_t monitor_class, uintptr_t ra)
-- 
2.25.1




[PATCH v2 15/55] target/sparc: Remove DEBUG_UNALIGNED

2021-08-02 Thread Richard Henderson
The printf should have been qemu_log_mask, the parameters
themselves no longer compile, and because this is placed
before unwinding the PC is actively wrong.

We get better (and correct) logging on the other side of
raising the exception, in sparc_cpu_do_interrupt.

Cc: Mark Cave-Ayland 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/sparc/ldst_helper.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/target/sparc/ldst_helper.c b/target/sparc/ldst_helper.c
index 22327d7d72..974afea041 100644
--- a/target/sparc/ldst_helper.c
+++ b/target/sparc/ldst_helper.c
@@ -27,7 +27,6 @@
 
 //#define DEBUG_MMU
 //#define DEBUG_MXCC
-//#define DEBUG_UNALIGNED
 //#define DEBUG_UNASSIGNED
 //#define DEBUG_ASI
 //#define DEBUG_CACHE_CONTROL
@@ -364,10 +363,6 @@ static void do_check_align(CPUSPARCState *env, 
target_ulong addr,
uint32_t align, uintptr_t ra)
 {
 if (addr & align) {
-#ifdef DEBUG_UNALIGNED
-printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
-   "\n", addr, env->pc);
-#endif
 cpu_raise_exception_ra(env, TT_UNALIGNED, ra);
 }
 }
@@ -1968,10 +1963,6 @@ void QEMU_NORETURN 
sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 SPARCCPU *cpu = SPARC_CPU(cs);
 CPUSPARCState *env = &cpu->env;
 
-#ifdef DEBUG_UNALIGNED
-printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
-   "\n", addr, env->pc);
-#endif
 cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr);
 }
 #endif
-- 
2.25.1




[PATCH v2 11/55] target/riscv: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Reviewed-by: Alistair Francis 
Signed-off-by: Richard Henderson 
---
 linux-user/riscv/cpu_loop.c | 7 +++
 target/riscv/cpu.c  | 2 +-
 target/riscv/cpu_helper.c   | 8 +++-
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c
index 74a9628dc9..0428140d86 100644
--- a/linux-user/riscv/cpu_loop.c
+++ b/linux-user/riscv/cpu_loop.c
@@ -92,6 +92,13 @@ void cpu_loop(CPURISCVState *env)
 sigcode = TARGET_SEGV_MAPERR;
 sigaddr = env->badaddr;
 break;
+case RISCV_EXCP_INST_ADDR_MIS:
+case RISCV_EXCP_LOAD_ADDR_MIS:
+case RISCV_EXCP_STORE_AMO_ADDR_MIS:
+signum = TARGET_SIGBUS;
+sigcode = TARGET_BUS_ADRALN;
+sigaddr = env->badaddr;
+break;
 case RISCV_EXCP_SEMIHOST:
 env->gpr[xA0] = do_common_semihosting(cs);
 env->pc += 4;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 991a6bb760..591d17e62d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -644,11 +644,11 @@ static const struct TCGCPUOps riscv_tcg_ops = {
 .synchronize_from_tb = riscv_cpu_synchronize_from_tb,
 .cpu_exec_interrupt = riscv_cpu_exec_interrupt,
 .tlb_fill = riscv_cpu_tlb_fill,
+.do_unaligned_access = riscv_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
 .do_interrupt = riscv_cpu_do_interrupt,
 .do_transaction_failed = riscv_cpu_do_transaction_failed,
-.do_unaligned_access = riscv_cpu_do_unaligned_access,
 #endif /* !CONFIG_USER_ONLY */
 };
 
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 968cb8046f..a440b2834f 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -727,6 +727,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr,
 riscv_cpu_two_stage_lookup(mmu_idx);
 riscv_raise_exception(&cpu->env, cs->exception_index, retaddr);
 }
+#endif /* !CONFIG_USER_ONLY */
 
 void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type, int mmu_idx,
@@ -734,6 +735,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = &cpu->env;
+
 switch (access_type) {
 case MMU_INST_FETCH:
 cs->exception_index = RISCV_EXCP_INST_ADDR_MIS;
@@ -748,11 +750,15 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 g_assert_not_reached();
 }
 env->badaddr = addr;
+
+#ifdef CONFIG_USER_ONLY
+cpu_loop_exit_restore(cs, retaddr);
+#else
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
 riscv_raise_exception(env, cs->exception_index, retaddr);
+#endif
 }
-#endif /* !CONFIG_USER_ONLY */
 
 bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 MMUAccessType access_type, int mmu_idx,
-- 
2.25.1




[PATCH v2 14/55] target/sh4: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Cc: Yoshinori Sato 
Signed-off-by: Richard Henderson 
---
 linux-user/sh4/cpu_loop.c | 8 
 target/sh4/cpu.c  | 2 +-
 target/sh4/op_helper.c| 3 ---
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/linux-user/sh4/cpu_loop.c b/linux-user/sh4/cpu_loop.c
index 222ed1c670..21d97250a8 100644
--- a/linux-user/sh4/cpu_loop.c
+++ b/linux-user/sh4/cpu_loop.c
@@ -71,6 +71,14 @@ void cpu_loop(CPUSH4State *env)
 info._sifields._sigfault._addr = env->tea;
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
 break;
+case 0xe0:
+case 0x100:
+info.si_signo = TARGET_SIGBUS;
+info.si_errno = 0;
+info.si_code = TARGET_BUS_ADRALN;
+info._sifields._sigfault._addr = env->tea;
+queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+break;
 case EXCP_ATOMIC:
 cpu_exec_step_atomic(cs);
 arch_interrupt = false;
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 8326922942..b60234cd31 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -238,10 +238,10 @@ static const struct TCGCPUOps superh_tcg_ops = {
 .synchronize_from_tb = superh_cpu_synchronize_from_tb,
 .cpu_exec_interrupt = superh_cpu_exec_interrupt,
 .tlb_fill = superh_cpu_tlb_fill,
+.do_unaligned_access = superh_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
 .do_interrupt = superh_cpu_do_interrupt,
-.do_unaligned_access = superh_cpu_do_unaligned_access,
 .io_recompile_replay_branch = superh_io_recompile_replay_branch,
 #endif /* !CONFIG_USER_ONLY */
 };
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index d6d70c339f..b46fc1bf11 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -23,7 +23,6 @@
 #include "exec/cpu_ldst.h"
 #include "fpu/softfloat.h"
 
-#ifndef CONFIG_USER_ONLY
 
 void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 MMUAccessType access_type,
@@ -46,8 +45,6 @@ void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 cpu_loop_exit_restore(cs, retaddr);
 }
 
-#endif
-
 void helper_ldtlb(CPUSH4State *env)
 {
 #ifdef CONFIG_USER_ONLY
-- 
2.25.1




[PATCH v2 16/55] target/sparc: Split out build_sfsr

2021-08-02 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 target/sparc/mmu_helper.c | 72 +--
 1 file changed, 46 insertions(+), 26 deletions(-)

diff --git a/target/sparc/mmu_helper.c b/target/sparc/mmu_helper.c
index a44473a1c7..5b2fda534a 100644
--- a/target/sparc/mmu_helper.c
+++ b/target/sparc/mmu_helper.c
@@ -526,16 +526,60 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
 return 0;
 }
 
+static uint64_t build_sfsr(CPUSPARCState *env, int mmu_idx, int rw)
+{
+uint64_t sfsr = SFSR_VALID_BIT;
+
+switch (mmu_idx) {
+case MMU_PHYS_IDX:
+sfsr |= SFSR_CT_NOTRANS;
+break;
+case MMU_USER_IDX:
+case MMU_KERNEL_IDX:
+sfsr |= SFSR_CT_PRIMARY;
+break;
+case MMU_USER_SECONDARY_IDX:
+case MMU_KERNEL_SECONDARY_IDX:
+sfsr |= SFSR_CT_SECONDARY;
+break;
+case MMU_NUCLEUS_IDX:
+sfsr |= SFSR_CT_NUCLEUS;
+break;
+default:
+g_assert_not_reached();
+}
+
+if (rw == 1) {
+sfsr |= SFSR_WRITE_BIT;
+} else if (rw == 4) {
+sfsr |= SFSR_NF_BIT;
+}
+
+if (env->pstate & PS_PRIV) {
+sfsr |= SFSR_PR_BIT;
+}
+
+if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
+sfsr |= SFSR_OW_BIT; /* overflow (not read before another fault) */
+}
+
+/* FIXME: ASI field in SFSR must be set */
+
+return sfsr;
+}
+
 static int get_physical_address_data(CPUSPARCState *env, hwaddr *physical,
  int *prot, MemTxAttrs *attrs,
  target_ulong address, int rw, int mmu_idx)
 {
 CPUState *cs = env_cpu(env);
 unsigned int i;
+uint64_t sfsr;
 uint64_t context;
-uint64_t sfsr = 0;
 bool is_user = false;
 
+sfsr = build_sfsr(env, mmu_idx, rw);
+
 switch (mmu_idx) {
 case MMU_PHYS_IDX:
 g_assert_not_reached();
@@ -544,29 +588,18 @@ static int get_physical_address_data(CPUSPARCState *env, 
hwaddr *physical,
 /* fallthru */
 case MMU_KERNEL_IDX:
 context = env->dmmu.mmu_primary_context & 0x1fff;
-sfsr |= SFSR_CT_PRIMARY;
 break;
 case MMU_USER_SECONDARY_IDX:
 is_user = true;
 /* fallthru */
 case MMU_KERNEL_SECONDARY_IDX:
 context = env->dmmu.mmu_secondary_context & 0x1fff;
-sfsr |= SFSR_CT_SECONDARY;
 break;
-case MMU_NUCLEUS_IDX:
-sfsr |= SFSR_CT_NUCLEUS;
-/* FALLTHRU */
 default:
 context = 0;
 break;
 }
 
-if (rw == 1) {
-sfsr |= SFSR_WRITE_BIT;
-} else if (rw == 4) {
-sfsr |= SFSR_NF_BIT;
-}
-
 for (i = 0; i < 64; i++) {
 /* ctx match, vaddr match, valid? */
 if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
@@ -616,22 +649,9 @@ static int get_physical_address_data(CPUSPARCState *env, 
hwaddr *physical,
 return 0;
 }
 
-if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
-sfsr |= SFSR_OW_BIT; /* overflow (not read before
-another fault) */
-}
-
-if (env->pstate & PS_PRIV) {
-sfsr |= SFSR_PR_BIT;
-}
-
-/* FIXME: ASI field in SFSR must be set */
-env->dmmu.sfsr = sfsr | SFSR_VALID_BIT;
-
+env->dmmu.sfsr = sfsr;
 env->dmmu.sfar = address; /* Fault address register */
-
 env->dmmu.tag_access = (address & ~0x1fffULL) | context;
-
 return 1;
 }
 }
-- 
2.25.1




[PATCH v2 13/55] target/sh4: Set fault address in superh_cpu_do_unaligned_access

2021-08-02 Thread Richard Henderson
We ought to have been recording the virtual address for reporting
to the guest trap handler.

Cc: Yoshinori Sato 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 target/sh4/op_helper.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index c0cbb95382..d6d70c339f 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -29,6 +29,9 @@ void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 MMUAccessType access_type,
 int mmu_idx, uintptr_t retaddr)
 {
+CPUSH4State *env = cs->env_ptr;
+
+env->tea = addr;
 switch (access_type) {
 case MMU_INST_FETCH:
 case MMU_DATA_LOAD:
@@ -37,6 +40,8 @@ void superh_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 case MMU_DATA_STORE:
 cs->exception_index = 0x100;
 break;
+default:
+g_assert_not_reached();
 }
 cpu_loop_exit_restore(cs, retaddr);
 }
-- 
2.25.1




[PATCH v2 05/55] target/hppa: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 linux-user/hppa/cpu_loop.c | 2 +-
 target/hppa/cpu.c  | 9 ++---
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c
index 82d8183821..5ce30fec8b 100644
--- a/linux-user/hppa/cpu_loop.c
+++ b/linux-user/hppa/cpu_loop.c
@@ -161,7 +161,7 @@ void cpu_loop(CPUHPPAState *env)
 case EXCP_UNALIGN:
 info.si_signo = TARGET_SIGBUS;
 info.si_errno = 0;
-info.si_code = 0;
+info.si_code = TARGET_BUS_ADRALN;
 info._sifields._sigfault._addr = env->cr[CR_IOR];
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
 break;
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index c2c56e7635..91f149ed77 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -71,7 +71,6 @@ static void hppa_cpu_disas_set_info(CPUState *cs, 
disassemble_info *info)
 info->print_insn = print_insn_hppa;
 }
 
-#ifndef CONFIG_USER_ONLY
 static void QEMU_NORETURN
 hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
  MMUAccessType access_type, int mmu_idx,
@@ -81,15 +80,19 @@ hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 CPUHPPAState *env = &cpu->env;
 
 cs->exception_index = EXCP_UNALIGN;
+#ifdef CONFIG_USER_ONLY
+/* Recall that user-only always uses address space 0. */
+env->cr[CR_IOR] = addr;
+#else
 if (env->psw & PSW_Q) {
 /* ??? Needs tweaking for hppa64.  */
 env->cr[CR_IOR] = addr;
 env->cr[CR_ISR] = addr >> 32;
 }
+#endif
 
 cpu_loop_exit_restore(cs, retaddr);
 }
-#endif /* CONFIG_USER_ONLY */
 
 static void hppa_cpu_realizefn(DeviceState *dev, Error **errp)
 {
@@ -147,10 +150,10 @@ static const struct TCGCPUOps hppa_tcg_ops = {
 .synchronize_from_tb = hppa_cpu_synchronize_from_tb,
 .cpu_exec_interrupt = hppa_cpu_exec_interrupt,
 .tlb_fill = hppa_cpu_tlb_fill,
+.do_unaligned_access = hppa_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
 .do_interrupt = hppa_cpu_do_interrupt,
-.do_unaligned_access = hppa_cpu_do_unaligned_access,
 #endif /* !CONFIG_USER_ONLY */
 };
 
-- 
2.25.1




[PATCH v2 10/55] target/ppc: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
For simplicity on the linux-user side, always use SPR_DAR.

Cc: qemu-...@nongnu.org
Signed-off-by: Richard Henderson 
---
 linux-user/ppc/cpu_loop.c | 2 +-
 target/ppc/cpu_init.c | 2 +-
 target/ppc/excp_helper.c  | 2 ++
 3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index fa91ea0eed..d72d30248b 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -165,7 +165,7 @@ void cpu_loop(CPUPPCState *env)
 info.si_signo = TARGET_SIGBUS;
 info.si_errno = 0;
 info.si_code = TARGET_BUS_ADRALN;
-info._sifields._sigfault._addr = env->nip;
+info._sifields._sigfault._addr = env->spr[SPR_DAR];
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
 break;
 case POWERPC_EXCP_PROGRAM:  /* Program exception */
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 505a0ed6ac..84fb6bbb83 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -9014,12 +9014,12 @@ static const struct TCGCPUOps ppc_tcg_ops = {
   .initialize = ppc_translate_init,
   .cpu_exec_interrupt = ppc_cpu_exec_interrupt,
   .tlb_fill = ppc_cpu_tlb_fill,
+  .do_unaligned_access = ppc_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
   .do_interrupt = ppc_cpu_do_interrupt,
   .cpu_exec_enter = ppc_cpu_exec_enter,
   .cpu_exec_exit = ppc_cpu_exec_exit,
-  .do_unaligned_access = ppc_cpu_do_unaligned_access,
 #endif /* !CONFIG_USER_ONLY */
 };
 #endif /* CONFIG_TCG */
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index d7743704ac..08cc474340 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1505,6 +1505,7 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr 
vaddr,
 CPUPPCState *env = cs->env_ptr;
 
 switch (env->mmu_model) {
+#ifndef CONFIG_USER_ONLY
 case POWERPC_MMU_SOFT_4xx:
 case POWERPC_MMU_SOFT_4xx_Z:
 env->spr[SPR_40x_DEAR] = vaddr;
@@ -1513,6 +1514,7 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr 
vaddr,
 case POWERPC_MMU_BOOKE206:
 env->spr[SPR_BOOKE_DEAR] = vaddr;
 break;
+#endif
 default:
 env->spr[SPR_DAR] = vaddr;
 break;
-- 
2.25.1




[PATCH v2 09/55] target/ppc: Set fault address in ppc_cpu_do_unaligned_access

2021-08-02 Thread Richard Henderson
We ought to have been recording the virtual address for reporting
to the guest trap handler.

Cc: qemu-...@nongnu.org
Signed-off-by: Richard Henderson 
---
 target/ppc/excp_helper.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 0df358f93f..d7743704ac 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -1504,6 +1504,20 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr 
vaddr,
 {
 CPUPPCState *env = cs->env_ptr;
 
+switch (env->mmu_model) {
+case POWERPC_MMU_SOFT_4xx:
+case POWERPC_MMU_SOFT_4xx_Z:
+env->spr[SPR_40x_DEAR] = vaddr;
+break;
+case POWERPC_MMU_BOOKE:
+case POWERPC_MMU_BOOKE206:
+env->spr[SPR_BOOKE_DEAR] = vaddr;
+break;
+default:
+env->spr[SPR_DAR] = vaddr;
+break;
+}
+
 cs->exception_index = POWERPC_EXCP_ALIGN;
 env->error_code = 0;
 cpu_loop_exit_restore(cs, retaddr);
-- 
2.25.1




[PATCH v2 03/55] target/alpha: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 target/alpha/cpu.c| 2 +-
 target/alpha/mem_helper.c | 8 +++-
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index 4871ad0c0a..cb7e5261bd 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -220,11 +220,11 @@ static const struct TCGCPUOps alpha_tcg_ops = {
 .initialize = alpha_translate_init,
 .cpu_exec_interrupt = alpha_cpu_exec_interrupt,
 .tlb_fill = alpha_cpu_tlb_fill,
+.do_unaligned_access = alpha_cpu_do_unaligned_access,
 
 #ifndef CONFIG_USER_ONLY
 .do_interrupt = alpha_cpu_do_interrupt,
 .do_transaction_failed = alpha_cpu_do_transaction_failed,
-.do_unaligned_access = alpha_cpu_do_unaligned_access,
 #endif /* !CONFIG_USER_ONLY */
 };
 
diff --git a/target/alpha/mem_helper.c b/target/alpha/mem_helper.c
index 75e72bc337..e3cf98b270 100644
--- a/target/alpha/mem_helper.c
+++ b/target/alpha/mem_helper.c
@@ -23,30 +23,28 @@
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
 
-/* Softmmu support */
-#ifndef CONFIG_USER_ONLY
 void alpha_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr)
 {
 AlphaCPU *cpu = ALPHA_CPU(cs);
 CPUAlphaState *env = &cpu->env;
-uint64_t pc;
 uint32_t insn;
 
 cpu_restore_state(cs, retaddr, true);
 
-pc = env->pc;
-insn = cpu_ldl_code(env, pc);
+insn = cpu_ldl_code(env, env->pc);
 
 env->trap_arg0 = addr;
 env->trap_arg1 = insn >> 26;/* opcode */
 env->trap_arg2 = (insn >> 21) & 31; /* dest regno */
+
 cs->exception_index = EXCP_UNALIGN;
 env->error_code = 0;
 cpu_loop_exit(cs);
 }
 
+#ifndef CONFIG_USER_ONLY
 void alpha_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
  vaddr addr, unsigned size,
  MMUAccessType access_type,
-- 
2.25.1




[PATCH v2 06/55] target/microblaze: Do not set MO_ALIGN for user-only

2021-08-02 Thread Richard Henderson
The kernel will fix up unaligned accesses, so emulate that
by allowing unaligned accesses to succeed.

Cc: Edgar E. Iglesias 
Signed-off-by: Richard Henderson 
---
 target/microblaze/translate.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index a14ffed784..ef44bca2fd 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -727,6 +727,7 @@ static TCGv compute_ldst_addr_ea(DisasContext *dc, int ra, 
int rb)
 }
 #endif
 
+#ifndef CONFIG_USER_ONLY
 static void record_unaligned_ess(DisasContext *dc, int rd,
  MemOp size, bool store)
 {
@@ -739,6 +740,7 @@ static void record_unaligned_ess(DisasContext *dc, int rd,
 
 tcg_set_insn_start_param(dc->insn_start, 1, iflags);
 }
+#endif
 
 static bool do_load(DisasContext *dc, int rd, TCGv addr, MemOp mop,
 int mem_index, bool rev)
@@ -760,12 +762,19 @@ static bool do_load(DisasContext *dc, int rd, TCGv addr, 
MemOp mop,
 }
 }
 
+/*
+ * For system mode, enforce alignment if the cpu configuration
+ * requires it.  For user-mode, the Linux kernel will have fixed up
+ * any unaligned access, so emulate that by *not* setting MO_ALIGN.
+ */
+#ifndef CONFIG_USER_ONLY
 if (size > MO_8 &&
 (dc->tb_flags & MSR_EE) &&
 dc->cfg->unaligned_exceptions) {
 record_unaligned_ess(dc, rd, size, false);
 mop |= MO_ALIGN;
 }
+#endif
 
 tcg_gen_qemu_ld_i32(reg_for_write(dc, rd), addr, mem_index, mop);
 
@@ -906,12 +915,19 @@ static bool do_store(DisasContext *dc, int rd, TCGv addr, 
MemOp mop,
 }
 }
 
+/*
+ * For system mode, enforce alignment if the cpu configuration
+ * requires it.  For user-mode, the Linux kernel will have fixed up
+ * any unaligned access, so emulate that by *not* setting MO_ALIGN.
+ */
+#ifndef CONFIG_USER_ONLY
 if (size > MO_8 &&
 (dc->tb_flags & MSR_EE) &&
 dc->cfg->unaligned_exceptions) {
 record_unaligned_ess(dc, rd, size, true);
 mop |= MO_ALIGN;
 }
+#endif
 
 tcg_gen_qemu_st_i32(reg_for_read(dc, rd), addr, mem_index, mop);
 
-- 
2.25.1




[PATCH v2 04/55] target/arm: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 linux-user/aarch64/cpu_loop.c |  4 
 linux-user/arm/cpu_loop.c | 43 +++
 target/arm/cpu.c  |  2 +-
 target/arm/cpu_tcg.c  |  2 +-
 4 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index ee72a1c20f..998831f87f 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -137,6 +137,10 @@ void cpu_loop(CPUARMState *env)
 case 0x11: /* Synchronous Tag Check Fault */
 info.si_code = TARGET_SEGV_MTESERR;
 break;
+case 0x21: /* Alignment fault */
+info.si_signo = TARGET_SIGBUS;
+info.si_code = TARGET_BUS_ADRALN;
+break;
 default:
 g_assert_not_reached();
 }
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 69632d15be..da7da6a0c1 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -23,6 +23,7 @@
 #include "elf.h"
 #include "cpu_loop-common.h"
 #include "semihosting/common-semi.h"
+#include "target/arm/syndrome.h"
 
 #define get_user_code_u32(x, gaddr, env)\
 ({ abi_long __r = get_user_u32((x), (gaddr));   \
@@ -286,9 +287,8 @@ void cpu_loop(CPUARMState *env)
 {
 CPUState *cs = env_cpu(env);
 int trapnr;
-unsigned int n, insn;
+unsigned int n, insn, ec, fsc;
 target_siginfo_t info;
-uint32_t addr;
 abi_ulong ret;
 
 for(;;) {
@@ -437,15 +437,40 @@ void cpu_loop(CPUARMState *env)
 break;
 case EXCP_PREFETCH_ABORT:
 case EXCP_DATA_ABORT:
-addr = env->exception.vaddress;
-{
-info.si_signo = TARGET_SIGSEGV;
-info.si_errno = 0;
-/* XXX: check env->error_code */
+info.si_signo = TARGET_SIGSEGV;
+info.si_errno = 0;
+info._sifields._sigfault._addr = env->exception.vaddress;
+/*
+ * We should only arrive here with EC in {DATAABORT, INSNABORT},
+ * and short-form FSC, which then tells us to look at the FSR.
+ * ??? arm_cpu_reset never sets TTBCR_EAE, so we always get
+ * short-form FSC.
+ */
+ec = syn_get_ec(env->exception.syndrome);
+assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
+fsc = extract32(env->exception.syndrome, 0, 6);
+assert(fsc == 0x3f);
+switch (env->exception.fsr & 0x1f) {
+case 0x1: /* Alignment */
+info.si_signo = TARGET_SIGBUS;
+info.si_code = TARGET_BUS_ADRALN;
+break;
+case 0x3: /* Access flag fault, level 1 */
+case 0x6: /* Access flag fault, level 2 */
+case 0x9: /* Domain fault, level 1 */
+case 0xb: /* Domain fault, level 2 */
+case 0xd: /* Permision fault, level 1 */
+case 0xf: /* Permision fault, level 2 */
+info.si_code = TARGET_SEGV_ACCERR;
+break;
+case 0x5: /* Translation fault, level 1 */
+case 0x7: /* Translation fault, level 2 */
 info.si_code = TARGET_SEGV_MAPERR;
-info._sifields._sigfault._addr = addr;
-queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+break;
+default:
+g_assert_not_reached();
 }
+queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
 break;
 case EXCP_DEBUG:
 case EXCP_BKPT:
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 2866dd7658..de0d968d76 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1987,11 +1987,11 @@ static const struct TCGCPUOps arm_tcg_ops = {
 .cpu_exec_interrupt = arm_cpu_exec_interrupt,
 .tlb_fill = arm_cpu_tlb_fill,
 .debug_excp_handler = arm_debug_excp_handler,
+.do_unaligned_access = arm_cpu_do_unaligned_access,
 
 #if !defined(CONFIG_USER_ONLY)
 .do_interrupt = arm_cpu_do_interrupt,
 .do_transaction_failed = arm_cpu_do_transaction_failed,
-.do_unaligned_access = arm_cpu_do_unaligned_access,
 .adjust_watchpoint_address = arm_adjust_watchpoint_address,
 .debug_check_watchpoint = arm_debug_check_watchpoint,
 .debug_check_breakpoint = arm_debug_check_breakpoint,
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
index ed444bf436..1b91fdc890 100644
--- a/target/arm/cpu_tcg.c
+++ b/target/arm/cpu_tcg.c
@@ -904,11 +904,11 @@ static const struct TCGCPUOps arm_v7m_tcg_ops = {
 .cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
 .tlb_fill = arm_cpu_tlb_fill,
 .debug_excp_handler = arm_debug_excp_handler,
+.do_unaligned_access = arm_cpu_do_unaligned_access,
 
 #if !defined(CONFIG_USER_ONLY)
 .do_interrupt = arm_v7m_cpu_do

[PATCH v2 07/55] target/mips: Implement do_unaligned_access for user-only

2021-08-02 Thread Richard Henderson
Cc: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/mips/cpu_loop.c| 20 
 target/mips/cpu.c |  2 +-
 target/mips/tcg/op_helper.c   |  3 +--
 target/mips/tcg/user/tlb_helper.c | 23 +++
 4 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c
index 9d813ece4e..51f4eb65a6 100644
--- a/linux-user/mips/cpu_loop.c
+++ b/linux-user/mips/cpu_loop.c
@@ -158,12 +158,24 @@ done_syscall:
 break;
 case EXCP_TLBL:
 case EXCP_TLBS:
-case EXCP_AdEL:
-case EXCP_AdES:
 info.si_signo = TARGET_SIGSEGV;
 info.si_errno = 0;
-/* XXX: check env->error_code */
-info.si_code = TARGET_SEGV_MAPERR;
+info.si_code = (env->error_code & EXCP_TLB_NOMATCH
+? TARGET_SEGV_MAPERR : TARGET_SEGV_ACCERR);
+info._sifields._sigfault._addr = env->CP0_BadVAddr;
+queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+break;
+case EXCP_AdEL:
+case EXCP_AdES:
+/*
+ * Note that on real hw AdE is also raised for access to a
+ * kernel address from user mode instead of a TLB error.
+ * For simplicity, we do not distinguish this in the user
+ * version of mips_cpu_tlb_fill so only unaligned comes here.
+ */
+info.si_signo = TARGET_SIGBUS;
+info.si_errno = 0;
+info.si_code = TARGET_BUS_ADRALN;
 info._sifields._sigfault._addr = env->CP0_BadVAddr;
 queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
 break;
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index d426918291..a1658af910 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -541,11 +541,11 @@ static const struct TCGCPUOps mips_tcg_ops = {
 .synchronize_from_tb = mips_cpu_synchronize_from_tb,
 .cpu_exec_interrupt = mips_cpu_exec_interrupt,
 .tlb_fill = mips_cpu_tlb_fill,
+.do_unaligned_access = mips_cpu_do_unaligned_access,
 
 #if !defined(CONFIG_USER_ONLY)
 .do_interrupt = mips_cpu_do_interrupt,
 .do_transaction_failed = mips_cpu_do_transaction_failed,
-.do_unaligned_access = mips_cpu_do_unaligned_access,
 .io_recompile_replay_branch = mips_io_recompile_replay_branch,
 #endif /* !CONFIG_USER_ONLY */
 };
diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c
index fafbf1faca..0b874823e4 100644
--- a/target/mips/tcg/op_helper.c
+++ b/target/mips/tcg/op_helper.c
@@ -375,8 +375,6 @@ void helper_pmon(CPUMIPSState *env, int function)
 }
 }
 
-#if !defined(CONFIG_USER_ONLY)
-
 void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
   MMUAccessType access_type,
   int mmu_idx, uintptr_t retaddr)
@@ -402,6 +400,7 @@ void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 do_raise_exception_err(env, excp, error_code, retaddr);
 }
 
+#if !defined(CONFIG_USER_ONLY)
 void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
 vaddr addr, unsigned size,
 MMUAccessType access_type,
diff --git a/target/mips/tcg/user/tlb_helper.c 
b/target/mips/tcg/user/tlb_helper.c
index b835144b82..61a99356e9 100644
--- a/target/mips/tcg/user/tlb_helper.c
+++ b/target/mips/tcg/user/tlb_helper.c
@@ -26,24 +26,23 @@ static void raise_mmu_exception(CPUMIPSState *env, 
target_ulong address,
 MMUAccessType access_type)
 {
 CPUState *cs = env_cpu(env);
+int error_code = 0;
+int flags;
 
-env->error_code = 0;
 if (access_type == MMU_INST_FETCH) {
-env->error_code |= EXCP_INST_NOTAVAIL;
+error_code |= EXCP_INST_NOTAVAIL;
 }
 
-/* Reference to kernel address from user mode or supervisor mode */
-/* Reference to supervisor address from user mode */
-if (access_type == MMU_DATA_STORE) {
-cs->exception_index = EXCP_AdES;
-} else {
-cs->exception_index = EXCP_AdEL;
+flags = page_get_flags(address);
+if (!(flags & PAGE_VALID)) {
+error_code |= EXCP_TLB_NOMATCH;
 }
 
-/* Raise exception */
-if (!(env->hflags & MIPS_HFLAG_DM)) {
-env->CP0_BadVAddr = address;
-}
+cs->exception_index = (access_type == MMU_DATA_STORE
+   ? EXCP_TLBS : EXCP_TLBL);
+
+env->error_code = error_code;
+env->CP0_BadVAddr = address;
 }
 
 bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
-- 
2.25.1




[PATCH v2 08/55] target/ppc: Move SPR_DSISR setting to powerpc_excp

2021-08-02 Thread Richard Henderson
By doing this while sending the exception, we will have already
done the unwinding, which makes the ppc_cpu_do_unaligned_access
code a bit cleaner.

Update the comment about the expected instruction format.

Signed-off-by: Richard Henderson 
---
 target/ppc/excp_helper.c | 21 +
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index a79a0ed465..0df358f93f 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -478,13 +478,15 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int 
excp_model, int excp)
 break;
 }
 case POWERPC_EXCP_ALIGN: /* Alignment exception  */
-/* Get rS/rD and rA from faulting opcode */
 /*
- * Note: the opcode fields will not be set properly for a
- * direct store load/store, but nobody cares as nobody
- * actually uses direct store segments.
+ * Get rS/rD and rA from faulting opcode.
+ * Note: We will only invoke ALIGN for atomic operations,
+ * so all instructions are X-form.
  */
-env->spr[SPR_DSISR] |= (env->error_code & 0x03FF) >> 16;
+{
+uint32_t insn = cpu_ldl_code(env, env->nip);
+env->spr[SPR_DSISR] |= (insn & 0x03FF) >> 16;
+}
 break;
 case POWERPC_EXCP_PROGRAM:   /* Program exception*/
 switch (env->error_code & ~0xF) {
@@ -1501,14 +1503,9 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr 
vaddr,
  int mmu_idx, uintptr_t retaddr)
 {
 CPUPPCState *env = cs->env_ptr;
-uint32_t insn;
-
-/* Restore state and reload the insn we executed, for filling in DSISR.  */
-cpu_restore_state(cs, retaddr, true);
-insn = cpu_ldl_code(env, env->nip);
 
 cs->exception_index = POWERPC_EXCP_ALIGN;
-env->error_code = insn & 0x03FF;
-cpu_loop_exit(cs);
+env->error_code = 0;
+cpu_loop_exit_restore(cs, retaddr);
 }
 #endif
-- 
2.25.1




[PATCH v2 02/55] hw/core: Make do_unaligned_access available to user-only

2021-08-02 Thread Richard Henderson
We shouldn't be ignoring SIGBUS for user-only.

Move our existing TCGCPUOps hook out from CONFIG_SOFTMMU.
Move the wrapper, cpu_unaligned_access, to cpu-exec-common.c.

Signed-off-by: Richard Henderson 
---
 accel/tcg/internal.h  |  4 
 include/hw/core/tcg-cpu-ops.h | 16 
 accel/tcg/cpu-exec-common.c   | 12 
 accel/tcg/cputlb.c|  9 -
 4 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h
index 881bc1ede0..a5e70cd91d 100644
--- a/accel/tcg/internal.h
+++ b/accel/tcg/internal.h
@@ -19,4 +19,8 @@ void QEMU_NORETURN cpu_io_recompile(CPUState *cpu, uintptr_t 
retaddr);
 void page_init(void);
 void tb_htable_init(void);
 
+void QEMU_NORETURN cpu_unaligned_access(CPUState *cpu, vaddr addr,
+MMUAccessType access_type,
+int mmu_idx, uintptr_t retaddr);
+
 #endif /* ACCEL_TCG_INTERNAL_H */
diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h
index ee0795def4..3753af03d8 100644
--- a/include/hw/core/tcg-cpu-ops.h
+++ b/include/hw/core/tcg-cpu-ops.h
@@ -60,6 +60,14 @@ struct TCGCPUOps {
 /** @debug_excp_handler: Callback for handling debug exceptions */
 void (*debug_excp_handler)(CPUState *cpu);
 
+/**
+ * @do_unaligned_access: Callback for unaligned access handling
+ * The callback must exit via raising an exception.
+ */
+void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
+MMUAccessType access_type,
+int mmu_idx, uintptr_t retaddr) QEMU_NORETURN;
+
 #ifdef NEED_CPU_H
 #ifdef CONFIG_SOFTMMU
 /**
@@ -70,14 +78,6 @@ struct TCGCPUOps {
   unsigned size, MMUAccessType access_type,
   int mmu_idx, MemTxAttrs attrs,
   MemTxResult response, uintptr_t retaddr);
-/**
- * @do_unaligned_access: Callback for unaligned access handling
- * The callback must exit via raising an exception.
- */
-void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
-MMUAccessType access_type,
-int mmu_idx, uintptr_t retaddr) QEMU_NORETURN;
-
 /**
  * @adjust_watchpoint_address: hack for cpu_check_watchpoint used by ARM
  */
diff --git a/accel/tcg/cpu-exec-common.c b/accel/tcg/cpu-exec-common.c
index be6fe45aa5..eeff20a347 100644
--- a/accel/tcg/cpu-exec-common.c
+++ b/accel/tcg/cpu-exec-common.c
@@ -21,6 +21,8 @@
 #include "sysemu/cpus.h"
 #include "sysemu/tcg.h"
 #include "exec/exec-all.h"
+#include "hw/core/tcg-cpu-ops.h"
+#include "internal.h"
 
 bool tcg_allowed;
 
@@ -81,3 +83,13 @@ void cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc)
 cpu->exception_index = EXCP_ATOMIC;
 cpu_loop_exit_restore(cpu, pc);
 }
+
+void cpu_unaligned_access(CPUState *cpu, vaddr addr,
+  MMUAccessType access_type,
+  int mmu_idx, uintptr_t retaddr)
+{
+CPUClass *cc = CPU_GET_CLASS(cpu);
+
+assert(cc->tcg_ops->do_unaligned_access != NULL);
+cc->tcg_ops->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
+}
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index b1e5471f94..116b289907 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1306,15 +1306,6 @@ static void tlb_fill(CPUState *cpu, target_ulong addr, 
int size,
 assert(ok);
 }
 
-static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
-MMUAccessType access_type,
-int mmu_idx, uintptr_t retaddr)
-{
-CPUClass *cc = CPU_GET_CLASS(cpu);
-
-cc->tcg_ops->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr);
-}
-
 static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
   vaddr addr, unsigned size,
   MMUAccessType access_type,
-- 
2.25.1




[PATCH v2 00/55] Unaligned access for user-only

2021-08-02 Thread Richard Henderson
This began with Peter wanting a cpu_ldst.h interface that can handle
alignment info for Arm M-profile system mode, which will also compile
for user-only without ifdefs.  This is patch 32.

Once I had that interface, I thought I might as well enforce the
requested alignment in user-only.  There are plenty of cases where
we ought to have been doing that for quite a while.  This took rather
more work than I imagined to start.

So far only x86 host has been fully converted to handle unaligned
operations in user-only mode.  I'll get to the others later.  But
the added testcase is fairly broad, and caught lots of bugs and/or
missing code between target/ and linux-user/.

Changes for v2:
  * Cleanup prctl(2), add support for prctl(PR_GET/SET_UNALIGN).
  * Adjustments for ppc and sparc reporting address during alignment fault.


r~


Richard Henderson (55):
  hw/core: Make do_unaligned_access noreturn
  hw/core: Make do_unaligned_access available to user-only
  target/alpha: Implement do_unaligned_access for user-only
  target/arm: Implement do_unaligned_access for user-only
  target/hppa: Implement do_unaligned_access for user-only
  target/microblaze: Do not set MO_ALIGN for user-only
  target/mips: Implement do_unaligned_access for user-only
  target/ppc: Move SPR_DSISR setting to powerpc_excp
  target/ppc: Set fault address in ppc_cpu_do_unaligned_access
  target/ppc: Implement do_unaligned_access for user-only
  target/riscv: Implement do_unaligned_access for user-only
  target/s390x: Implement do_unaligned_access for user-only
  target/sh4: Set fault address in superh_cpu_do_unaligned_access
  target/sh4: Implement do_unaligned_access for user-only
  target/sparc: Remove DEBUG_UNALIGNED
  target/sparc: Split out build_sfsr
  target/sparc: Set fault address in sparc_cpu_do_unaligned_access
  target/sparc: Implement do_unaligned_access for user-only
  target/xtensa: Implement do_unaligned_access for user-only
  accel/tcg: Report unaligned atomics for user-only
  accel/tcg: Drop signness in tracing in cputlb.c
  tcg: Expand MO_SIZE to 3 bits
  tcg: Rename TCGMemOpIdx to MemOpIdx
  tcg: Split out MemOpIdx to exec/memopidx.h
  trace/mem: Pass MemOpIdx to trace_mem_get_info
  accel/tcg: Pass MemOpIdx to atomic_trace_*_post
  plugins: Reorg arguments to qemu_plugin_vcpu_mem_cb
  trace: Split guest_mem_before
  target/arm: Use MO_128 for 16 byte atomics
  target/i386: Use MO_128 for 16 byte atomics
  target/ppc: Use MO_128 for 16 byte atomics
  target/s390x: Use MO_128 for 16 byte atomics
  target/hexagon: Implement cpu_mmu_index
  accel/tcg: Add cpu_{ld,st}*_mmu interfaces
  accel/tcg: Move cpu_atomic decls to exec/cpu_ldst.h
  target/mips: Use cpu_*_data_ra for msa load/store
  target/mips: Use 8-byte memory ops for msa load/store
  target/s390x: Use cpu_*_mmu instead of helper_*_mmu
  target/sparc: Use cpu_*_mmu instead of helper_*_mmu
  target/arm: Use cpu_*_mmu instead of helper_*_mmu
  tcg: Move helper_*_mmu decls to tcg/tcg-ldst.h
  tcg: Add helper_unaligned_mmu for user-only sigbus
  tcg/i386: Support raising sigbus for user-only
  tests/tcg/multiarch: Add sigbus.c
  linux-user: Split out do_prctl and subroutines
  linux-user: Disable more prctl subcodes
  hw/core/cpu: Re-sort the non-pointers to the end of CPUClass
  linux-user: Add code for PR_GET/SET_UNALIGN
  hw/core/cpu: Move cpu properties to cpu-sysemu.c
  hw/core/cpu: Add prctl-unalign-sigbus property for user-only
  target/alpha: Reorg fp memory operations
  target/alpha: Reorg integer memory operations
  target/alpha: Implement prctl_unalign_sigbus
  target/hppa: Implement prctl_unalign_sigbus
  target/sh4: Implement prctl_unalign_sigbus

 docs/devel/loads-stores.rst |  52 +-
 accel/tcg/atomic_template.h |  73 ++-
 accel/tcg/internal.h|   4 +
 hw/core/cpu-common.h|  17 +
 include/exec/cpu_ldst.h | 332 ++---
 include/exec/memop.h|  14 +-
 include/exec/memopidx.h |  55 +++
 include/hw/core/cpu.h   |  14 +-
 include/hw/core/tcg-cpu-ops.h   |  15 +-
 include/qemu/plugin.h   |  26 +-
 include/tcg/tcg-ldst.h  |  79 
 include/tcg/tcg.h   | 197 +---
 linux-user/aarch64/target_syscall.h |  23 -
 linux-user/mips/target_syscall.h|   6 -
 linux-user/mips64/target_syscall.h  |   6 -
 target/alpha/cpu.h  |   9 +-
 target/arm/internals.h  |   3 +-
 target/hexagon/cpu.h|   9 +
 target/hppa/cpu.h   |   5 +-
 target/microblaze/cpu.h |   2 +-
 target/mips/tcg/tcg-internal.h  |   4 +-
 target/nios2/cpu.h  |   4 +-
 target/ppc/internal.h   |   4 +-
 target/riscv/cpu.h  |   2 +-
 target/s390x/s390x-internal.h   |   4 +-
 target/sh4/cpu.h|   8 +-
 target/xtensa/cpu.h |   4 +-
 tcg/i386/tcg-target.h   |   2 -
 trace/mem.h 

[PATCH v2 01/55] hw/core: Make do_unaligned_access noreturn

2021-08-02 Thread Richard Henderson
While we may have had some thought of allowing system-mode
to return from this hook, we have no guests that require this.

Signed-off-by: Richard Henderson 
---
 include/hw/core/tcg-cpu-ops.h  | 3 ++-
 target/alpha/cpu.h | 4 ++--
 target/arm/internals.h | 3 ++-
 target/microblaze/cpu.h| 2 +-
 target/mips/tcg/tcg-internal.h | 4 ++--
 target/nios2/cpu.h | 4 ++--
 target/ppc/internal.h  | 4 ++--
 target/riscv/cpu.h | 2 +-
 target/s390x/s390x-internal.h  | 4 ++--
 target/sh4/cpu.h   | 4 ++--
 target/xtensa/cpu.h| 4 ++--
 target/hppa/cpu.c  | 7 ---
 12 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h
index eab27d0c03..ee0795def4 100644
--- a/include/hw/core/tcg-cpu-ops.h
+++ b/include/hw/core/tcg-cpu-ops.h
@@ -72,10 +72,11 @@ struct TCGCPUOps {
   MemTxResult response, uintptr_t retaddr);
 /**
  * @do_unaligned_access: Callback for unaligned access handling
+ * The callback must exit via raising an exception.
  */
 void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
 MMUAccessType access_type,
-int mmu_idx, uintptr_t retaddr);
+int mmu_idx, uintptr_t retaddr) QEMU_NORETURN;
 
 /**
  * @adjust_watchpoint_address: hack for cpu_check_watchpoint used by ARM
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index 82df108967..6eb3fcc63e 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -283,8 +283,8 @@ hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr 
addr);
 int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 void alpha_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
-   MMUAccessType access_type,
-   int mmu_idx, uintptr_t retaddr);
+   MMUAccessType access_type, int mmu_idx,
+   uintptr_t retaddr) QEMU_NORETURN;
 
 #define cpu_list alpha_cpu_list
 #define cpu_signal_handler cpu_alpha_signal_handler
diff --git a/target/arm/internals.h b/target/arm/internals.h
index cd2ea8a388..3da9b1c61e 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -594,7 +594,8 @@ bool arm_s1_regime_using_lpae_format(CPUARMState *env, 
ARMMMUIdx mmu_idx);
 /* Raise a data fault alignment exception for the specified virtual address */
 void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
  MMUAccessType access_type,
- int mmu_idx, uintptr_t retaddr);
+ int mmu_idx, uintptr_t retaddr)
+QEMU_NORETURN;
 
 /* arm_cpu_do_transaction_failed: handle a memory system error response
  * (eg "no device/memory present at address") by raising an external abort
diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index e4bba8a755..620c3742e1 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -359,7 +359,7 @@ void mb_cpu_do_interrupt(CPUState *cs);
 bool mb_cpu_exec_interrupt(CPUState *cs, int int_req);
 void mb_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
 MMUAccessType access_type,
-int mmu_idx, uintptr_t retaddr);
+int mmu_idx, uintptr_t retaddr) QEMU_NORETURN;
 void mb_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
 hwaddr mb_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
 MemTxAttrs *attrs);
diff --git a/target/mips/tcg/tcg-internal.h b/target/mips/tcg/tcg-internal.h
index 81b14eb219..7ac1e578d1 100644
--- a/target/mips/tcg/tcg-internal.h
+++ b/target/mips/tcg/tcg-internal.h
@@ -24,8 +24,8 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
 void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
-  MMUAccessType access_type,
-  int mmu_idx, uintptr_t retaddr);
+  MMUAccessType access_type, int mmu_idx,
+  uintptr_t retaddr) QEMU_NORETURN;
 
 const char *mips_exception_name(int32_t exception);
 
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 2ab82fdc71..27227b1e88 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -198,8 +198,8 @@ void dump_mmu(CPUNios2State *env);
 void nios2_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
 hwaddr nios2_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
-   MMUAcc

Re: [PATCH] nvdimm: release the correct device list

2021-08-02 Thread Li , Zhijian/李 智坚

ping

Any body could help to review/queue this patch ?



On 2021/6/29 22:05, Igor Mammedov wrote:

On Thu, 24 Jun 2021 19:04:15 +0800
Li Zhijian  wrote:


Signed-off-by: Li Zhijian 

Reviewed-by: Igor Mammedov 


---
  hw/acpi/nvdimm.c | 12 ++--
  1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index e3d5fe19392..ff317263e85 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -355,10 +355,10 @@ nvdimm_build_structure_caps(GArray *structures, uint32_t 
capabilities)
  
  static GArray *nvdimm_build_device_structure(NVDIMMState *state)

  {
-GSList *device_list = nvdimm_get_device_list();
+GSList *device_list, *list = nvdimm_get_device_list();
  GArray *structures = g_array_new(false, true /* clear */, 1);
  
-for (; device_list; device_list = device_list->next) {

+for (device_list = list; device_list; device_list = device_list->next) {
  DeviceState *dev = device_list->data;
  
  /* build System Physical Address Range Structure. */

@@ -373,7 +373,7 @@ static GArray *nvdimm_build_device_structure(NVDIMMState 
*state)
  /* build NVDIMM Control Region Structure. */
  nvdimm_build_structure_dcr(structures, dev);
  }
-g_slist_free(device_list);
+g_slist_free(list);
  
  if (state->persistence) {

  nvdimm_build_structure_caps(structures, state->persistence);
@@ -1339,9 +1339,9 @@ static void nvdimm_build_ssdt(GArray *table_offsets, 
GArray *table_data,
  
  void nvdimm_build_srat(GArray *table_data)

  {
-GSList *device_list = nvdimm_get_device_list();
+GSList *device_list, *list = nvdimm_get_device_list();
  
-for (; device_list; device_list = device_list->next) {

+for (device_list = list; device_list; device_list = device_list->next) {
  AcpiSratMemoryAffinity *numamem = NULL;
  DeviceState *dev = device_list->data;
  Object *obj = OBJECT(dev);
@@ -1356,7 +1356,7 @@ void nvdimm_build_srat(GArray *table_data)
  build_srat_memory(numamem, addr, size, node,
MEM_AFFINITY_ENABLED | MEM_AFFINITY_NON_VOLATILE);
  }
-g_slist_free(device_list);
+g_slist_free(list);
  }
  
  void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,









[RFC PATCH v2 1/2] Adding i2c interface for qemu

2021-08-02 Thread Padmakar
From: padmakar 

The changes here includes the interface for i2c/smbus 
for nvme-mi protocol. We have used an address of 0x15
using which the guest VM can send and recieve the nvme-mi
commands. Since the nvme-mi device uses the I2C_SLAVE as
parent, we have used the send and recieve callbacks by
which the nvme-mi device will get the required notification.
With the callback approach, we have eliminated the use of 
threads. 

Please provide us with your valuable feedback on this patch.

---
 hw/nvme/nvme-mi.c | 152 ++
 hw/nvme/nvme-mi.h |  23 ++---
 2 files changed, 79 insertions(+), 96 deletions(-)

diff --git a/hw/nvme/nvme-mi.c b/hw/nvme/nvme-mi.c
index 5e93417..a90ce90 100644
--- a/hw/nvme/nvme-mi.c
+++ b/hw/nvme/nvme-mi.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2021, Samsung Electronics co Ltd.
  *
  * Written by Padmakar Kalghatgi 
- *Arun Kumar Agasar 
+ *Arun Kumar Agasar 
  *Saurav Kumar 
  *
  * This code is licensed under the GNU GPL v2 or later.
@@ -19,10 +19,8 @@
  * The nvme-mi device has to be used along with nvme device only
  *
  * Add options:
- *-device  nvme-mi,bus=
- *-device  vhost-vsock-pci, guest-cid=
+ *-device  nvme-mi,nvme=,address=0x15",
  *
- * the cid is used to connect to the vsock
  */
 
 #include "qemu/osdep.h"
@@ -41,8 +39,8 @@ static void nvme_mi_send_resp(NvmeMiCtrl *ctrl_mi, uint8_t 
*resp, uint32_t size)
 {
 uint32_t crc_value = crc32c(0x, resp, size);
 size += 4;
-uint32_t retries = 5;
 uint32_t offset = 0;
+uint32_t ofst = 0;
 uint32_t som = 1;
 uint32_t eom = 0;
 uint32_t pktseq = 0;
@@ -51,24 +49,17 @@ static void nvme_mi_send_resp(NvmeMiCtrl *ctrl_mi, uint8_t 
*resp, uint32_t size)
 uint32_t sizesent = size > mtus ? mtus : size;
 size -= sizesent;
 eom = size > 0 ? 0 : 1;
-g_autofree uint8_t *buf = (uint8_t *)g_malloc(sizesent + 8);
+g_autofree uint8_t *buf = (uint8_t *)g_malloc0(sizesent + 8);
 buf[2] = sizesent + 5;
 buf[7] = (som << 7) | (eom << 6) | (pktseq << 5);
 som = 0;
 memcpy(buf + 8, resp + offset, sizesent);
 offset += sizesent;
 if (size <= 0) {
-memcpy(buf + 4 + offset , &crc_value, sizeof(crc_value));
-}
-retries = 5;
-while (retries > 0) {
-int32_t nsend = send(ctrl_mi->sock_desc, buf, sizesent + 8, 0);
-if (nsend < 0) {
-retries--;
-} else {
-break;
-}
+memcpy(buf + 8 + offset , &crc_value, sizeof(crc_value));
 }
+memcpy(ctrl_mi->misendrecv.sendrecvbuf + ofst, buf, sizesent + 8);
+ofst += sizesent + 8;
 }
 }
 
@@ -176,7 +167,6 @@ static void nvme_mi_controller_health_ds(NvmeMiCtrl 
*ctrl_mi,
  (dword1 & 0x2)) {
 nvme_mi_chds.cwarn.temp_above_or_under_thresh = 0x1;
 }
-printf("size = %lu\n", sizeof(resp) + sizeof(NvmeMiCtrlHealthDs));
 g_autofree uint8_t *resp_buf = (uint8_t *)g_malloc(sizeof(resp) +

sizeof(NvmeMiCtrlHealthDs));
 resp.mgmt_resp = 1 << 0x10;
@@ -283,9 +273,8 @@ static void nvme_mi_vpd_read(NvmeMiCtrl *ctrl_mi, 
NvmeMIRequest *req)
 nvme_mi_send_resp(ctrl_mi, resp_buf, dlen + sizeof(resp));
 }
 }
-
-static void nvme_mi_vpd_write(NvmeMiCtrl *ctrl_mi, NvmeMIRequest *req,
-  uint8_t *buf)
+static void nvme_mi_vpd_write(NvmeMiCtrl *ctrl_mi,
+  NvmeMIRequest *req, uint8_t *buf)
 {
 uint16_t dofst = (req->dword0 & 0x);
 uint16_t dlen = (req->dword1 & 0x);
@@ -308,7 +297,7 @@ static void 
nvme_mi_nvm_subsys_health_status_poll(NvmeMiCtrl *ctrl_mi,
 NvmeMiNvmSubsysHspds nshds;
 nvme_mi_resp_hdr_init(&resp, false);
 for (uint32_t cntlid = 1; cntlid < ARRAY_SIZE(ctrl_mi->n->subsys->ctrls);
- cntlid++) {
+  cntlid++) {
 
 NvmeCtrl *ctrl = nvme_subsys_ctrl(ctrl_mi->n->subsys, cntlid);
 if (!ctrl) {
@@ -335,7 +324,8 @@ static void 
nvme_mi_nvm_subsys_health_status_poll(NvmeMiCtrl *ctrl_mi,
 }
 
 
-g_autofree uint8_t *resp_buf = (uint8_t *)g_malloc(sizeof(resp) + 
sizeof(nshds));
+g_autofree uint8_t *resp_buf = (uint8_t *)g_malloc(sizeof(resp) +
+   sizeof(nshds));
 memcpy(resp_buf, &resp, sizeof(resp));
 memcpy(resp_buf + sizeof(resp), &nshds, sizeof(nshds));
 nvme_mi_send_resp(ctrl_mi, resp_buf, sizeof(resp_buf));
@@ -553,15 +543,12 @@ static void nvme_mi_admin_command(NvmeMiCtrl *ctrl_mi, 
void* req_arg)
 NvmeAdminMIRequest *req = (NvmeAdminMIRequest *) (msg);
 switch  (req->opc) {
 case NVME_ADM_MI_CMD_IDENTIFY:
-printf("identify\n");
 nvme_mi_admin_identify(ctrl_mi, req);
 break;
 case NVME_ADM_MI_CMD_GET_LOG_

Re: [Question] qemu-img convert block alignment

2021-08-02 Thread Zhenyu Ye
ping?

On 2021/4/2 11:52, Zhenyu Ye wrote:
> Hi all,
> 
> commit 8dcd3c9b91 ("qemu-img: align result of is_allocated_sectors")
> introduces block alignment when doing qemu-img convert. However, the
> alignment is:
> 
>   s.alignment = MAX(pow2floor(s.min_sparse),
>   DIV_ROUND_UP(out_bs->bl.request_alignment,
>BDRV_SECTOR_SIZE));
> 
> (where the default s.min_sparse is 8)
> When the target device's bl.request_alignment is smaller than 4K, this
> will cause additional write-zero overhead and makes the size of target
> file larger.
> 
> Is this as expected?  Should we change the MAX() to MIN()?
> 
> 
> Thanks,
> zhenyu
> 



Re: QEMU on x64

2021-08-02 Thread Christopher Caulfield
Thanks folks! I went ahead and made a feature/issue request based on
Paolo's suggestion:
QEMU registers support on x64 (#510) · Issues · QEMU / QEMU · GitLab


Please let me know if someone has the cycles to support this.

-Christopher

On Mon, Aug 2, 2021 at 10:37 AM Alex Bennée  wrote:

>
> Peter Maydell  writes:
>
> > On Fri, 30 Jul 2021 at 19:05, Christopher Caulfield
> >  wrote:
> >> This is Christopher from the debugging experiences team at Microsoft
> focused on kernel debugging. I am reaching out with a few questions about
> QEMU on x64.
> >>
> >> Is it possible for the QEMU-x86-64 GDB Server to send the full set
> >> of x64 system registers (whether they are included in a separated
> >> system xml file or as part of the core registers xml file)?
> >
> > Do you mean "is it possible for somebody to write code for
> > QEMU to make it do that", or "does QEMU do it today if you pass
> > it the right command line option" ? The answer to the former
> > is "yes", to the latter "no". (If you want the debugger to
> > be able to write to the system registers this might be a little
> > trickier, mostly in terms of "auditing the code to make sure this
> > can't confuse QEMU if you change some sysreg under its feet.".)
> >
> >> e.g. System registers missing from i386-64bit.xml file
> >
> >> DWORD64 IDTBase;
> >> DWORD64 IDTLimit;
> >> DWORD64 GDTBase;
> >> DWORD64 GDTLimit;
> >> DWORD SelLDT;
> >> SEG64_DESC_INFO SegLDT;
> >> DWORD SelTSS;
> >> SEG64_DESC_INFO SegTSS;
> >>
> >> How can I access x64 MSR registers by using the QEMU-x86-64 GDB server?
> >>
> >> #define MSR_EFER 0xc080 // extended function enable register
> >
> > EFER is in the xml ("x64_efer") so should be already accessible.
> > For anything else you're going to need to write some code to
> > make it happen.
> >
> >>is there any plan to support reading/writing to MSRs via QEMU-x86-64
> >GDB server?
>
> Not at the moment but I am keen to see any eventual solution try to be
> generic rather than hardwired for one architecture. The ARM code
> currently builds custom XML from it's register descriptors to expose
> it's MSR registers to the gdbstub. Ideally architecture front ends
> should register their registers with a new subsystem which can then do
> the glue between gdbstub as well as other systems that also care about
> register values (logging, HMP, TCG plugins).
>
> That said I'm not going to block any patches that just fix up the
> current XML and target/i386/gdbstub code. I'm not familiar enough with
> what the internal register representation state is for x86 w.r.t to TCG
> and hypervisor based running modes.
>
> > Not that I know of. We'd be happy to review patches if you want to
> > write them.
> >
> > thanks
> > -- PMM
>
>
> --
> Alex Bennée
>


Re: need help with my config

2021-08-02 Thread Lindsay Ryan
Hi Cedric,
Thanks for replying.
I think I want to go down the PowerNV Power 9
Which I will need the OpenPower firmware.
Looks like the webpage for downloading prebuild witherspoon and skiboot is 
down/dead. Hasn't been working for me for 24hours anyway
Is that the only place to download that firmware?

regards


Ryan Lindsay BEng, MSc.
Linux Storage Administrator
Research Computing Facility


From: Cédric Le Goater 
Sent: Saturday, 31 July 2021 2:50 AM
To: Philippe Mathieu-Daudé ; Lindsay Ryan 
; qemu-disc...@nongnu.org 
Cc: qemu-ppc ; qemu-devel 
Subject: Re: need help with my config

! EXTERNAL EMAIL: Think before you click. If suspicious send to 
cyberrep...@petermac.org

Hello,

On 7/30/21 3:25 PM, Philippe Mathieu-Daudé wrote:
> Cc'ing qemu-ppc@
>
> On 7/30/21 6:25 AM, Lindsay Ryan wrote:
>> Hi
>> I'm trying to emulate some physical IBM Power 9's that we have. There
>> seems to be plenty of examples of using x86_64 qemu, but slightly less
>> for Power.

For baremetal emulation, please use the PowerNV machine. See this page :

  https://qemu.readthedocs.io/en/latest/system/ppc/powernv.html

HW is not fully emulated but QEMU has enough support to start a multichip
system running any distro.

>> Unless it's specifically for installing AIX

AIX only runs under the pseries machine (virtualized) and not on baremetal.

>> Anyway, I'm trying to boot the VM as I guess a bare metal Power 9 box,
>> then install redhat from Iso on a disk and have it on the network.
>>
>> ./qemu-system-ppc64 -cpu POWER9 -smp cpus=4 -machine pseries -m 4096 -M
>> accel=tcg  -serial stdio -nodefaults -nographic -device
>> megasas,id=scsi0,bus=pci.0,addr=0x5 -drive
>> file=/home/hdisk1.qcow2,if=none,id=drive-scsi0-0-0-0,format=qcow2,cache=none
>> -device
>> scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,id=scsi0-0-0-0,bootindex=2
>> -cdrom /mnt/images/rhel-8.4-ppc64le-boot.iso -monitor
>> telnet:0.0.0.0:3344,server,nowait -netdev
>> bridge,id=net0,helper=qemu-bridge-helper,br=bridge0,id=hostnet0

This is a pseries machine (virtualized) and not baremetal.

Which machine do you want to run ? pseries is the VM platform as run by KVM,
It can run under TCG also. PowerNV is the baremetal platform on which KVM
runs using the OPAL firmware. QEMU only has a PowerNV emulator, so TCG.

These are two very different PPC machines.

>> So the megasas gets detected as a raid controller. Yay.
>> But my qcow2 disk image doesn't seem to be plugged into it correctly as
>> it's not detected.
>> It sees the cdrom image and I can boot from it.
>> The other thing I can't get working is the network card.

because you don't have any :) Add a device and link it to the netdev.


That's how I run a TCG pseries POWER9 machine on my x86 laptop:

qemu-system-ppc64 -M 
pseries,cap-cfpc=workaround,cap-sbbc=workaround,cap-ibs=workaround,cap-ccf-assist=on,ic-mode=dual
 -m 4G -accel tcg,thread=multi -cpu POWER9 -smp 4,cores=4,maxcpus=8,threads=1 
-device virtio-net-pci,netdev=net0,mac=C0:FF:EE:00:00:02,bus=pci.0,addr=0x2 
-netdev tap,id=net0,helper=/usr/libexec/qemu-bridge-helper,br=virbr0,vhost=on 
-device virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x1 -drive 
file=./ubuntu-ppc64le.qcow2,if=none,id=drive-scsi0-0-0-0,format=qcow2,cache=none
 -device 
scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,id=scsi0-0-0-0,bootindex=1
 -device qemu-xhci,id=usb,bus=pci.0,addr=0x4 -nographic -nodefaults -serial 
mon:stdio

and a PowerNV POWER9 machine :

qemu-system-ppc64 -m 4G -machine powernv9 -smp 2 -accel tcg,thread=multi 
-kernel ./open-power/images/witherspoon-latest/zImage.epapr -initrd 
./open-power/images/witherspoon-latest/rootfs.cpio.xz -bios 
./open-power/images/witherspoon-latest/skiboot.lid -device 
pcie-pci-bridge,id=bridge1,bus=pcie.1,addr=0x0 -device 
ich9-ahci,id=sata0,bus=pcie.0,addr=0x0 -drive 
file=./ubuntu-ppc64le-powernv.qcow2,if=none,id=drive0,format=qcow2,cache=none 
-device ide-hd,bus=sata0.0,unit=0,drive=drive0,id=ide,bootindex=1 -device 
e1000e,netdev=net0,mac=C0:FF:EE:00:01:03,bus=bridge1,addr=0x3 -netdev 
bridge,helper=/usr/libexec/qemu-bridge-helper,br=virbr0,id=net0 -device 
nec-usb-xhci,bus=bridge1,addr=0x2 -device usb-storage,drive=usbkey -drive 
file=./usb.img,if=none,id=usbkey,format=raw,cache=none -serial mon:stdio 
-nographic

You will need firmware images for the latter.


Cheers,
C.


Disclaimer: This email (including any attachments or links) may contain 
confidential and/or legally privileged information and is intended only to be 
read or used by the addressee. If you are not the intended addressee, any use, 
distribution, disclosure or copying of this email is strictly prohibited. 
Confidentiality and legal privilege attached to this email (including any 
attachments) are not waived or lost by reason of its mistaken delivery to you. 
If you have received this email in error, please delete it and notify us 
immediately by telephone or email. Peter MacCallum Cancer Cen

RE: [PATCH v2 0/3] Add support for Fujitsu A64FX processor

2021-08-02 Thread ishii.shuuic...@fujitsu.com
> I'm afraid this isn't the way a v2 patchseries should be structured.
> The idea is that a v2 series should be complete in itself, not based on 
> whatever v1
> was. So when you make the changes requested in review of v1, you update the
> commits in your local git branch, and then you send out the patches as the 
> v2. v2
> should apply cleanly on to master, and all the patches in it should be 
> logically
> separated out changes (with no "patch 1 makes a change and then patch 2
> changes the code that was added in patch 1" effects).

Thank you for comments.
We apologize for the inconvenience caused by our lack of understanding.
I understood your point.

Just to confirm, 
should I update to v3 and resubmit it as a patch series based on the points you 
mentioned?

Best regards.

> -Original Message-
> From: Peter Maydell 
> Sent: Friday, July 30, 2021 7:39 PM
> To: Ishii, Shuuichirou/石井 周一郎 
> Cc: qemu-arm ; QEMU Developers
> 
> Subject: Re: [PATCH v2 0/3] Add support for Fujitsu A64FX processor
> 
> On Fri, 30 Jul 2021 at 04:08, Shuuichirou Ishii 
> wrote:
> >
> > This is the v2 patch series.
> >
> > v2:
> > No features have been added or removed from the v1 patch series.
> > Removal of unused definitions that were added in excess, and
> > consolidation of patches for the purpose of functional consistency.
> >
> > For patch 1, ARM_FEATURE_A64FX is not used in the v1 patch series, so
> > it was deleted this time, and will be added again when it is used.
> >
> > For patch 2, since the a64fx_cp_reginfo structure is not used in the
> > v1 patch series, I deleted the empty definition and added the TODO in
> > the aarch64_a64fx_initfn function. Also fixed the appearance, and
> > cleaned up and removed some things for patch consistency.
> >
> > For patch 3, a64fx was added to docs/system/arm/virt.rst and
> > hw/arm/virt.c respectively, as a modification to the patch consistency
> > cleanup done in patch 2.
> 
> I'm afraid this isn't the way a v2 patchseries should be structured.
> The idea is that a v2 series should be complete in itself, not based on 
> whatever v1
> was. So when you make the changes requested in review of v1, you update the
> commits in your local git branch, and then you send out the patches as the 
> v2. v2
> should apply cleanly on to master, and all the patches in it should be 
> logically
> separated out changes (with no "patch 1 makes a change and then patch 2
> changes the code that was added in patch 1" effects).
> 
> thanks
> -- PMM


RE: [PATCH v2 1/3] target-arm: delete ARM_FEATURE_A64FX

2021-08-02 Thread ishii.shuuic...@fujitsu.com

> This is confusing because I can't see this feature flag in the mainline 
> branch. Have
> you inadvertently based this series from an internal branch?

I'm sorry for the confusion.

My lack of understanding of how to handle v2 patches has led me to create a v2 
patch series
based on patches that have not been merged into upstream.
I will repost this so that the implementation can be closed in one patch series.

Best regards.
> -Original Message-
> From: Alex Bennée 
> Sent: Friday, July 30, 2021 7:36 PM
> To: Ishii, Shuuichirou/石井 周一郎 
> Cc: peter.mayd...@linaro.org; qemu-devel@nongnu.org; qemu-...@nongnu.org
> Subject: Re: [PATCH v2 1/3] target-arm: delete ARM_FEATURE_A64FX
> 
> 
> Shuuichirou Ishii  writes:
> 
> > The ARM_FEATURE_A64FX property was added, but there is no function
> > that uses this property yet, so it will be removed until a function
> > that uses it is added.
> >
> > Signed-off-by: Shuuichirou Ishii 
> > ---
> >  target/arm/cpu.h   | 1 -
> >  target/arm/cpu64.c | 1 -
> >  2 files changed, 2 deletions(-)
> >
> > diff --git a/target/arm/cpu.h b/target/arm/cpu.h index
> > 1b0c7b91ec..9f0a5f84d5 100644
> > --- a/target/arm/cpu.h
> > +++ b/target/arm/cpu.h
> > @@ -2145,7 +2145,6 @@ enum arm_features {
> >  ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
> >  ARM_FEATURE_M_MAIN, /* M profile Main Extension */
> >  ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
> > -ARM_FEATURE_A64FX, /* Fujitsu A64FX processor HPC extensions
> > support */
> 
> This is confusing because I can't see this feature flag in the mainline 
> branch. Have
> you inadvertently based this series from an internal branch?
> 
> >  };
> >
> >  static inline int arm_feature(CPUARMState *env, int feature) diff
> > --git a/target/arm/cpu64.c b/target/arm/cpu64.c index
> > a15f9c0c55..dd72300e88 100644
> > --- a/target/arm/cpu64.c
> > +++ b/target/arm/cpu64.c
> > @@ -856,7 +856,6 @@ static void aarch64_a64fx_initfn(Object *obj)
> >  ARMCPU *cpu = ARM_CPU(obj);
> >
> >  cpu->dtb_compatible = "arm,a64fx";
> > -set_feature(&cpu->env, ARM_FEATURE_A64FX);
> >  set_feature(&cpu->env, ARM_FEATURE_V8);
> >  set_feature(&cpu->env, ARM_FEATURE_NEON);
> >  set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
> 
> 
> --
> Alex Bennée


RE: [PATCH v2 1/3] target-arm: delete ARM_FEATURE_A64FX

2021-08-02 Thread ishii.shuuic...@fujitsu.com

> This feature doesn't exist in upstream QEMU, so this won't apply.
> For a v2 of a patch, the patches should be based on upstream, not on top of 
> the v1
> series.

Thank you for your comment.
I understood your point.

Best regards.
> -Original Message-
> From: Peter Maydell 
> Sent: Friday, July 30, 2021 7:35 PM
> To: Ishii, Shuuichirou/石井 周一郎 
> Cc: qemu-arm ; QEMU Developers
> 
> Subject: Re: [PATCH v2 1/3] target-arm: delete ARM_FEATURE_A64FX
> 
> On Fri, 30 Jul 2021 at 04:08, Shuuichirou Ishii 
> wrote:
> >
> > The ARM_FEATURE_A64FX property was added, but there is no function
> > that uses this property yet, so it will be removed until a function
> > that uses it is added.
> >
> > Signed-off-by: Shuuichirou Ishii 
> > ---
> >  target/arm/cpu.h   | 1 -
> >  target/arm/cpu64.c | 1 -
> >  2 files changed, 2 deletions(-)
> >
> > diff --git a/target/arm/cpu.h b/target/arm/cpu.h index
> > 1b0c7b91ec..9f0a5f84d5 100644
> > --- a/target/arm/cpu.h
> > +++ b/target/arm/cpu.h
> > @@ -2145,7 +2145,6 @@ enum arm_features {
> >  ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
> >  ARM_FEATURE_M_MAIN, /* M profile Main Extension */
> >  ARM_FEATURE_V8_1M, /* M profile extras only in v8.1M and later */
> > -ARM_FEATURE_A64FX, /* Fujitsu A64FX processor HPC extensions
> support */
> >  };
> 
> This feature doesn't exist in upstream QEMU, so this won't apply.
> 
> For a v2 of a patch, the patches should be based on upstream, not on top of 
> the v1
> series.
> 
> thanks
> -- PMM


RE: [PATCH v2 3/3] target-arm: Add A64FX processor support to virt machine

2021-08-02 Thread ishii.shuuic...@fujitsu.com

> Commit messages should describe what the patch is doing and why, so the reader
> can understand it without having to cross-reference old mailing list threads.

Thank you for your comment.
I understood your point.

Best regards.
> -Original Message-
> From: Peter Maydell 
> Sent: Friday, July 30, 2021 7:36 PM
> To: Ishii, Shuuichirou 
> Cc: qemu-arm ; QEMU Developers
> 
> Subject: Re: [PATCH v2 3/3] target-arm: Add A64FX processor support to virt
> machine
> 
> On Fri, 30 Jul 2021 at 04:08, Shuuichirou Ishii 
> wrote:
> >
> > Fix for patch consistency.
> > https://lists.gnu.org/archive/html/qemu-devel/2021-07/msg06993.html
> 
> Commit messages should describe what the patch is doing and why, so the reader
> can understand it without having to cross-reference old mailing list threads.
> 
> > Signed-off-by: Shuuichirou Ishii 
> > ---
> >  docs/system/arm/virt.rst | 1 +
> >  hw/arm/virt.c| 1 +
> >  2 files changed, 2 insertions(+)
> >
> > diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index
> > 27652adfae..5329e952cf 100644
> > --- a/docs/system/arm/virt.rst
> > +++ b/docs/system/arm/virt.rst
> > @@ -55,6 +55,7 @@ Supported guest CPU types:
> >  - ``cortex-a53`` (64-bit)
> >  - ``cortex-a57`` (64-bit)
> >  - ``cortex-a72`` (64-bit)
> > +- ``a64fx`` (64-bit)
> >  - ``host`` (with KVM only)
> >  - ``max`` (same as ``host`` for KVM; best possible emulation with
> > TCG)
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c index
> > 81eda46b0b..10286d3fd6 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -200,6 +200,7 @@ static const char *valid_cpus[] = {
> >  ARM_CPU_TYPE_NAME("cortex-a53"),
> >  ARM_CPU_TYPE_NAME("cortex-a57"),
> >  ARM_CPU_TYPE_NAME("cortex-a72"),
> > +ARM_CPU_TYPE_NAME("a64fx"),
> >  ARM_CPU_TYPE_NAME("host"),
> >  ARM_CPU_TYPE_NAME("max"),
> >  };
> 
> thanks
> -- PMM


[PATCH-for-6.1 v2 2/2] hw/sd/sdcard: Fix assertion accessing out-of-range addresses with CMD30

2021-08-02 Thread Philippe Mathieu-Daudé
OSS-Fuzz found sending illegal addresses when querying the write
protection bits triggers the assertion added in commit 84816fb63e5
("hw/sd/sdcard: Assert if accessing an illegal group"):

  qemu-fuzz-i386-target-generic-fuzz-sdhci-v3: ../hw/sd/sd.c:824: uint32_t 
sd_wpbits(SDState *, uint64_t):
  Assertion `wpnum < sd->wpgrps_size' failed.
  #3 0x7f62a8b22c91 in __assert_fail
  #4 0x5569adcec405 in sd_wpbits hw/sd/sd.c:824:9
  #5 0x5569adce5f6d in sd_normal_command hw/sd/sd.c:1389:38
  #6 0x5569adce3870 in sd_do_command hw/sd/sd.c:1737:17
  #7 0x5569adcf1566 in sdbus_do_command hw/sd/core.c:100:16
  #8 0x5569adcfc192 in sdhci_send_command hw/sd/sdhci.c:337:12
  #9 0x5569adcfa3a3 in sdhci_write hw/sd/sdhci.c:1186:9
  #10 0x5569adfb3447 in memory_region_write_accessor softmmu/memory.c:492:5

It is legal for the CMD30 to query for out-of-range addresses.
Such invalid addresses are simply ignored in the response (write
protection bits set to 0).

In commit 84816fb63e5 ("hw/sd/sdcard: Assert if accessing an illegal
group") we misplaced the assertion *before* we test the address is
in range. Move it *after*.

Include the qtest reproducer provided by Alexander Bulekov:

  $ make check-qtest-i386
  ...
  Running test qtest-i386/fuzz-sdcard-test
  qemu-system-i386: ../hw/sd/sd.c:824: sd_wpbits: Assertion `wpnum < 
sd->wpgrps_size' failed.

Cc: qemu-sta...@nongnu.org
Reported-by: OSS-Fuzz (Issue 29225)
Suggested-by: Peter Maydell 
Fixes: 84816fb63e5 ("hw/sd/sdcard: Assert if accessing an illegal group")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/495
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c |  2 +-
 tests/qtest/fuzz-sdcard-test.c | 36 ++
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 707dcc12a14..bb5dbff68c0 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -821,7 +821,6 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
 wpnum = sd_addr_to_wpnum(addr);
 
 for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) {
-assert(wpnum < sd->wpgrps_size);
 if (addr >= sd->size) {
 /*
  * If the addresses of the last groups are outside the valid range,
@@ -829,6 +828,7 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
  */
 continue;
 }
+assert(wpnum < sd->wpgrps_size);
 if (test_bit(wpnum, sd->wp_groups)) {
 ret |= (1 << i);
 }
diff --git a/tests/qtest/fuzz-sdcard-test.c b/tests/qtest/fuzz-sdcard-test.c
index 96602eac7e5..ae14305344a 100644
--- a/tests/qtest/fuzz-sdcard-test.c
+++ b/tests/qtest/fuzz-sdcard-test.c
@@ -52,6 +52,41 @@ static void oss_fuzz_29225(void)
 qtest_quit(s);
 }
 
+/*
+ * https://gitlab.com/qemu-project/qemu/-/issues/495
+ * Used to trigger:
+ *  Assertion `wpnum < sd->wpgrps_size' failed.
+ */
+static void oss_fuzz_36217(void)
+{
+QTestState *s;
+
+s = qtest_init(" -display none -m 32 -nodefaults -nographic"
+   " -device sdhci-pci,sd-spec-version=3 "
+   "-device sd-card,drive=d0 "
+   "-drive if=none,index=0,file=null-co://,format=raw,id=d0");
+
+qtest_outl(s, 0xcf8, 0x80001010);
+qtest_outl(s, 0xcfc, 0xe000);
+qtest_outl(s, 0xcf8, 0x80001004);
+qtest_outw(s, 0xcfc, 0x02);
+qtest_bufwrite(s, 0xe02c, "\x05", 0x1);
+qtest_bufwrite(s, 0xe00f, "\x37", 0x1);
+qtest_bufwrite(s, 0xe00a, "\x01", 0x1);
+qtest_bufwrite(s, 0xe00f, "\x29", 0x1);
+qtest_bufwrite(s, 0xe00f, "\x02", 0x1);
+qtest_bufwrite(s, 0xe00f, "\x03", 0x1);
+qtest_bufwrite(s, 0xe005, "\x01", 0x1);
+qtest_bufwrite(s, 0xe00f, "\x06", 0x1);
+qtest_bufwrite(s, 0xe00c, "\x05", 0x1);
+qtest_bufwrite(s, 0xe00e, "\x20", 0x1);
+qtest_bufwrite(s, 0xe00f, "\x08", 0x1);
+qtest_bufwrite(s, 0xe00b, "\x3d", 0x1);
+qtest_bufwrite(s, 0xe00f, "\x1e", 0x1);
+
+qtest_quit(s);
+}
+
 int main(int argc, char **argv)
 {
 const char *arch = qtest_get_arch();
@@ -60,6 +95,7 @@ int main(int argc, char **argv)
 
if (strcmp(arch, "i386") == 0) {
 qtest_add_func("fuzz/sdcard/oss_fuzz_29225", oss_fuzz_29225);
+qtest_add_func("fuzz/sdcard/oss_fuzz_36217", oss_fuzz_36217);
}
 
return g_test_run();
-- 
2.31.1




[PATCH-for-6.1 v2 1/2] hw/sd/sdcard: Document out-of-range addresses for SEND_WRITE_PROT

2021-08-02 Thread Philippe Mathieu-Daudé
Per the 'Physical Layer Simplified Specification Version 3.01',
Table 4-22: 'Block Oriented Write Protection Commands'

  SEND_WRITE_PROT (CMD30)

  If the card provides write protection features, this command asks
  the card to send the status of the write protection bits [1].

  [1] 32 write protection bits (representing 32 write protect groups
  starting at the specified address) [...]
  The last (least significant) bit of the protection bits corresponds
  to the first addressed group. If the addresses of the last groups
  are outside the valid range, then the corresponding write protection
  bits shall be set to 0.

Split the if() statement (without changing the behaviour of the code)
to better position the description comment.

Reviewed-by: Alexander Bulekov 
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/sd.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1f964e022b1..707dcc12a14 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -822,7 +822,14 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
 
 for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) {
 assert(wpnum < sd->wpgrps_size);
-if (addr < sd->size && test_bit(wpnum, sd->wp_groups)) {
+if (addr >= sd->size) {
+/*
+ * If the addresses of the last groups are outside the valid range,
+ * then the corresponding write protection bits shall be set to 0.
+ */
+continue;
+}
+if (test_bit(wpnum, sd->wp_groups)) {
 ret |= (1 << i);
 }
 }
-- 
2.31.1




[PATCH-for-6.1 v2 0/2] hw/sd/sdcard: Fix assertion accessing out-of-range addresses with CMD30

2021-08-02 Thread Philippe Mathieu-Daudé
Fix an assertion reported by OSS-Fuzz, add corresponding qtest.

The change is (now) simple enough for the next rc.

Since v1:
- Simplified/corrected following Peter's suggestion

Philippe Mathieu-Daudé (2):
  hw/sd/sdcard: Document out-of-range addresses for SEND_WRITE_PROT
  hw/sd/sdcard: Fix assertion accessing out-of-range addresses with
CMD30

 hw/sd/sd.c |  9 -
 tests/qtest/fuzz-sdcard-test.c | 36 ++
 2 files changed, 44 insertions(+), 1 deletion(-)

-- 
2.31.1




Re: [PATCH-for-6.1 2/3] hw/sd/sdcard: Fix assertion accessing out-of-range addresses with CMD30

2021-08-02 Thread Philippe Mathieu-Daudé
On 8/2/21 2:03 PM, Peter Maydell wrote:
> On Wed, 28 Jul 2021 at 19:19, Philippe Mathieu-Daudé  wrote:
>>
>> OSS-Fuzz found sending illegal addresses when querying the write
>> protection bits triggers the assertion added in commit 84816fb63e5
>> ("hw/sd/sdcard: Assert if accessing an illegal group"):
>>
>>   qemu-fuzz-i386-target-generic-fuzz-sdhci-v3: ../hw/sd/sd.c:824: uint32_t 
>> sd_wpbits(SDState *, uint64_t):
>>   Assertion `wpnum < sd->wpgrps_size' failed.
>>   #3 0x7f62a8b22c91 in __assert_fail
>>   #4 0x5569adcec405 in sd_wpbits hw/sd/sd.c:824:9
>>   #5 0x5569adce5f6d in sd_normal_command hw/sd/sd.c:1389:38
>>   #6 0x5569adce3870 in sd_do_command hw/sd/sd.c:1737:17
>>   #7 0x5569adcf1566 in sdbus_do_command hw/sd/core.c:100:16
>>   #8 0x5569adcfc192 in sdhci_send_command hw/sd/sdhci.c:337:12
>>   #9 0x5569adcfa3a3 in sdhci_write hw/sd/sdhci.c:1186:9
>>   #10 0x5569adfb3447 in memory_region_write_accessor softmmu/memory.c:492:5
>>
>> It is legal for the CMD30 to query for out-of-range addresses.
>> Such invalid addresses are simply ignored in the response (write
>> protection bits set to 0).
>>
>> Note, we had an off-by-one in the wpgrps_size check since commit
>> a1bb27b1e98. Since we have a total of 'wpgrps_size' bits, the latest
>> valid group bit is 'wpgrps_size - 1'.
> 
> The commit message says "wpgrps_size - 1" is valid...
> 
>> @@ -820,8 +820,8 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
>>
>>  wpnum = sd_addr_to_wpnum(addr);
>>
>> -for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) {
>> -assert(wpnum < sd->wpgrps_size);
>> +for (i = 0; i < 32 && wpnum < sd->wpgrps_size - 1;
> 
> ...but the code change makes the loop terminate when
> wpnum == wpgrps_size - 1, so we don't execute the loop
> body for wpgrps_size -1.
> 
> Which is correct ?

The problem is in sd_reset(), this code is hard for me to follow
(and I plan to refactor it during next dev cycle):

blk_get_geometry(sd->blk, §);
size = sect << 9;
sect = sd_addr_to_wpnum(size) + 1;
sd->wpgrps_size = sect;
sd->wp_groups = bitmap_new(sd->wpgrps_size);

CID.WP_GRP_SIZE is defined as:

  The size of a write protected group. The content of this register
  is a 7-bit binary coded value, defining the number of erase sectors
  (see SECTOR_SIZE). The actual size is computed by increasing this
  number by one. A value of zero means one erase sector, 127 means
  128 erase sectors.

I think there is a confusion, wpgrps_size holds the real number of erase
sectors (used by the model, not returned in the CID.WP_GRP_SIZE
register). CID.WP_GRP_SIZE should be (wpgrps_size - 1).

Currently we iterate 1 sector number outside of the flash area.
To avoid that I used 'wpnum < sd->wpgrps_size - 1' instead of
'wpnum <= sd->wpgrps_size - 1'.

But with the fix you suggested responding to the cover, we don't hit
this case anymore. So I'll take it and clean the rest later.

Thanks,

Phil.

> 
>> +i++, wpnum++, addr += WPGROUP_SIZE) {
> 
> thanks
> -- PMM
> 



Re: [PATCH 1/1] hw/i2c: add remote I2C device

2021-08-02 Thread Shengtan Mao
This patch set was sent in error (duplicates and bad version names). Please
ignore it.

Sorry for the inconvenience,
Shengtan Mao

On Mon, Aug 2, 2021 at 7:03 PM Shengtan Mao  wrote:

> This patch adds the remote I2C device, which supports the usage of
> external I2C devices.
> Signed-off-by: Shengtan Mao 
> ---
>  hw/arm/Kconfig|   1 +
>  hw/i2c/Kconfig|   4 +
>  hw/i2c/meson.build|   1 +
>  hw/i2c/remote-i2c.c   | 117 ++
>  tests/qtest/meson.build   |   1 +
>  tests/qtest/remote-i2c-test.c | 216 ++
>  6 files changed, 340 insertions(+)
>  create mode 100644 hw/i2c/remote-i2c.c
>  create mode 100644 tests/qtest/remote-i2c-test.c
>
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index 90b19c0861..58fdfab90d 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -392,6 +392,7 @@ config NPCM7XX
>  select MAX34451
>  select PL310  # cache controller
>  select PMBUS
> +select REMOTE_I2C
>  select SERIAL
>  select SSI
>  select UNIMP
> diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
> index 8217cb5041..278156991d 100644
> --- a/hw/i2c/Kconfig
> +++ b/hw/i2c/Kconfig
> @@ -1,6 +1,10 @@
>  config I2C
>  bool
>
> +config REMOTE_I2C
> +bool
> +select I2C
> +
>  config SMBUS
>  bool
>  select I2C
> diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build
> index d3df273251..ba0215db61 100644
> --- a/hw/i2c/meson.build
> +++ b/hw/i2c/meson.build
> @@ -6,6 +6,7 @@ i2c_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true:
> files('smbus_ich9.c'))
>  i2c_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_i2c.c'))
>  i2c_ss.add(when: 'CONFIG_BITBANG_I2C', if_true: files('bitbang_i2c.c'))
>  i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_i2c.c'))
> +i2c_ss.add(when: 'CONFIG_REMOTE_I2C', if_true: files('remote-i2c.c'))
>  i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c'))
>  i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c'))
>  i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))
> diff --git a/hw/i2c/remote-i2c.c b/hw/i2c/remote-i2c.c
> new file mode 100644
> index 00..083eaf2210
> --- /dev/null
> +++ b/hw/i2c/remote-i2c.c
> @@ -0,0 +1,117 @@
> +/*
> + * Remote I2C Device
> + *
> + * Copyright (c) 2021 Google LLC
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful, but
> WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * for more details.
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "chardev/char-fe.h"
> +#include "hw/i2c/i2c.h"
> +#include "hw/qdev-properties-system.h"
> +
> +#define TYPE_REMOTE_I2C "remote-i2c"
> +#define REMOTE_I2C(obj) OBJECT_CHECK(RemoteI2CState, (obj),
> TYPE_REMOTE_I2C)
> +#define ONE_BYTE 1
> +
> +typedef struct {
> +I2CSlave parent_obj;
> +CharBackend chr;
> +} RemoteI2CState;
> +
> +typedef enum {
> +REMOTE_I2C_START_RECV = 0,
> +REMOTE_I2C_START_SEND = 1,
> +REMOTE_I2C_FINISH = 2,
> +REMOTE_I2C_NACK = 3,
> +REMOTE_I2C_RECV = 4,
> +REMOTE_I2C_SEND = 5,
> +} RemoteI2CCommand;
> +
> +static uint8_t remote_i2c_recv(I2CSlave *s)
> +{
> +RemoteI2CState *i2c = REMOTE_I2C(s);
> +uint8_t resp = 0;
> +uint8_t type = REMOTE_I2C_RECV;
> +qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
> +
> +qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
> +return resp;
> +}
> +
> +static int remote_i2c_send(I2CSlave *s, uint8_t data)
> +{
> +RemoteI2CState *i2c = REMOTE_I2C(s);
> +uint8_t type = REMOTE_I2C_SEND;
> +uint8_t resp = 1;
> +qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
> +qemu_chr_fe_write_all(&i2c->chr, &data, ONE_BYTE);
> +
> +qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
> +return resp ? -1 : 0;
> +}
> +
> +/* Returns non-zero when no response from the device. */
> +static int remote_i2c_event(I2CSlave *s, enum i2c_event event)
> +{
> +RemoteI2CState *i2c = REMOTE_I2C(s);
> +uint8_t type;
> +uint8_t resp = 1;
> +switch (event) {
> +case I2C_START_RECV:
> +type = REMOTE_I2C_START_RECV;
> +break;
> +case I2C_START_SEND:
> +type = REMOTE_I2C_START_SEND;
> +break;
> +case I2C_FINISH:
> +type = REMOTE_I2C_FINISH;
> +break;
> +case I2C_NACK:
> +type = REMOTE_I2C_NACK;
> +}
> +qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
> +qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
> +return resp ? -1 : 0;
> +}
> +
> +static Property remote_i2c_props[] = {
> +DEFINE_PROP_CHR("chardev", RemoteI2CSta

Re: [PATCH v2 0/1] Add remote I2C device to support external I2C device

2021-08-02 Thread Shengtan Mao
This patch set was sent in error (duplicates and bad version names). Please
ignore it.

Sorry for the inconvenience,
Shengtan Mao

On Mon, Aug 2, 2021 at 7:03 PM Shengtan Mao  wrote:

> This patch implements the remote I2C device.
> The remote I2C device allows an external I2C device to communicate with
> the I2C controller in QEMU through the remote I2C protocol.
> Users no longer have to directly modify QEMU to add new I2C devices and
> can instead implement the emulated device externally and connect it to the
> remote I2C device.
>
> Previous work by Wolfram Sang (
> https://git.kernel.org/pub/scm/virt/qemu/wsa/qemu.git/commit/?h=i2c-passthrough)
> was referenced.
> It shares the similar idea of redirecting the actual I2C device
> functionalities, but Sang focuses on physical devices, and we focus on
> emulated devices.
> The work by Sang mainly utilizes file descriptors while ours utilizes
> character devices, which offers better support for emulated devices.
> The work by Sang is not meant to offer full I2C device support; it only
> implements the receive functionality.
> Our work implements full support for I2C devices: send, recv, and event
> (match_and_add is not applicable for external devices).
>
> Shengtan Mao (1):
>   hw/i2c: add remote I2C device
>
>  hw/arm/Kconfig|   1 +
>  hw/i2c/Kconfig|   4 +
>  hw/i2c/meson.build|   1 +
>  hw/i2c/remote-i2c.c   | 117 ++
>  tests/qtest/meson.build   |   1 +
>  tests/qtest/remote-i2c-test.c | 216 ++
>  6 files changed, 340 insertions(+)
>  create mode 100644 hw/i2c/remote-i2c.c
>  create mode 100644 tests/qtest/remote-i2c-test.c
>
> --
> 2.32.0.554.ge1b32706d8-goog
>
>


Re: [PATCH-for-6.2 3/5] target/mips: Convert Vr54xx MACC* opcodes to decodetree

2021-08-02 Thread Philippe Mathieu-Daudé
On 8/2/21 9:50 PM, Richard Henderson wrote:
> On 8/1/21 1:59 PM, Philippe Mathieu-Daudé wrote:
>> Convert the following Integer Multiply-Accumulate opcodes:
>>
>>   * MACC Multiply, accumulate, and move LO
>>   * MACCHI   Multiply, accumulate, and move HI
>>   * MACCHIU  Unsigned multiply, accumulate, and move HI
>>   * MACCU    Unsigned multiply, accumulate, and move LO
>>
>> Since all opcodes are generated using the same pattern, we
>> add the gen_helper_mult_acc_t typedef and MULT_ACC() macro
>> to remove boilerplate code.
>>
>> Signed-off-by: Philippe Mathieu-Daudé
>> ---
>>   target/mips/tcg/vr54xx.decode  |  9 +++
>>   target/mips/tcg/translate.c    | 16 
>>   target/mips/tcg/vr54xx_translate.c | 40 ++
>>   3 files changed, 49 insertions(+), 16 deletions(-)
> 
> Reviewed-by: Richard Henderson 
> 
> 
>> +#define MULT_ACC(opcode, gen_helper) \
>> +static bool trans_##opcode(DisasContext *ctx, arg_r *a) \
>> +{ \
>> +    return trans_mult_acc(ctx, a, gen_helper); \
>> +}
> 
> Perhaps copy the TRANS macro from ppc/translate.c, so we don't have to
> have so many single-use macros like this?

TIL the recent changes in ppc/translate.c, thanks, I will see what I
can reuse :)



[PATCH v2 0/1] Add remote I2C device to support external I2C device

2021-08-02 Thread Shengtan Mao
This patch implements the remote I2C device.
The remote I2C device allows an external I2C device to communicate with the I2C 
controller in QEMU through the remote I2C protocol.
Users no longer have to directly modify QEMU to add new I2C devices and can 
instead implement the emulated device externally and connect it to the remote 
I2C device.

Previous work by Wolfram Sang 
(https://git.kernel.org/pub/scm/virt/qemu/wsa/qemu.git/commit/?h=i2c-passthrough)
 was referenced.
It shares the similar idea of redirecting the actual I2C device 
functionalities, but Sang focuses on physical devices, and we focus on emulated 
devices.
The work by Sang mainly utilizes file descriptors while ours utilizes character 
devices, which offers better support for emulated devices.
The work by Sang is not meant to offer full I2C device support; it only 
implements the receive functionality.
Our work implements full support for I2C devices: send, recv, and event 
(match_and_add is not applicable for external devices).

Shengtan Mao (1):
  hw/i2c: add remote I2C device

 hw/arm/Kconfig|   1 +
 hw/i2c/Kconfig|   4 +
 hw/i2c/meson.build|   1 +
 hw/i2c/remote-i2c.c   | 117 ++
 tests/qtest/meson.build   |   1 +
 tests/qtest/remote-i2c-test.c | 216 ++
 6 files changed, 340 insertions(+)
 create mode 100644 hw/i2c/remote-i2c.c
 create mode 100644 tests/qtest/remote-i2c-test.c

-- 
2.32.0.554.ge1b32706d8-goog




[PATCH v2 1/1] hw/i2c: add remote I2C device

2021-08-02 Thread Shengtan Mao
This patch adds the remote I2C device, which supports the usage of
external I2C devices.
Signed-off-by: Shengtan Mao 
---
 hw/arm/Kconfig|   1 +
 hw/i2c/Kconfig|   4 +
 hw/i2c/meson.build|   1 +
 hw/i2c/remote-i2c.c   | 117 ++
 tests/qtest/meson.build   |   1 +
 tests/qtest/remote-i2c-test.c | 216 ++
 6 files changed, 340 insertions(+)
 create mode 100644 hw/i2c/remote-i2c.c
 create mode 100644 tests/qtest/remote-i2c-test.c

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 90b19c0861..58fdfab90d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -392,6 +392,7 @@ config NPCM7XX
 select MAX34451
 select PL310  # cache controller
 select PMBUS
+select REMOTE_I2C
 select SERIAL
 select SSI
 select UNIMP
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
index 8217cb5041..278156991d 100644
--- a/hw/i2c/Kconfig
+++ b/hw/i2c/Kconfig
@@ -1,6 +1,10 @@
 config I2C
 bool
 
+config REMOTE_I2C
+bool
+select I2C
+
 config SMBUS
 bool
 select I2C
diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build
index d3df273251..ba0215db61 100644
--- a/hw/i2c/meson.build
+++ b/hw/i2c/meson.build
@@ -6,6 +6,7 @@ i2c_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: 
files('smbus_ich9.c'))
 i2c_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_i2c.c'))
 i2c_ss.add(when: 'CONFIG_BITBANG_I2C', if_true: files('bitbang_i2c.c'))
 i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_i2c.c'))
+i2c_ss.add(when: 'CONFIG_REMOTE_I2C', if_true: files('remote-i2c.c'))
 i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c'))
 i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c'))
 i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))
diff --git a/hw/i2c/remote-i2c.c b/hw/i2c/remote-i2c.c
new file mode 100644
index 00..083eaf2210
--- /dev/null
+++ b/hw/i2c/remote-i2c.c
@@ -0,0 +1,117 @@
+/*
+ * Remote I2C Device
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "chardev/char-fe.h"
+#include "hw/i2c/i2c.h"
+#include "hw/qdev-properties-system.h"
+
+#define TYPE_REMOTE_I2C "remote-i2c"
+#define REMOTE_I2C(obj) OBJECT_CHECK(RemoteI2CState, (obj), TYPE_REMOTE_I2C)
+#define ONE_BYTE 1
+
+typedef struct {
+I2CSlave parent_obj;
+CharBackend chr;
+} RemoteI2CState;
+
+typedef enum {
+REMOTE_I2C_START_RECV = 0,
+REMOTE_I2C_START_SEND = 1,
+REMOTE_I2C_FINISH = 2,
+REMOTE_I2C_NACK = 3,
+REMOTE_I2C_RECV = 4,
+REMOTE_I2C_SEND = 5,
+} RemoteI2CCommand;
+
+static uint8_t remote_i2c_recv(I2CSlave *s)
+{
+RemoteI2CState *i2c = REMOTE_I2C(s);
+uint8_t resp = 0;
+uint8_t type = REMOTE_I2C_RECV;
+qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
+
+qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
+return resp;
+}
+
+static int remote_i2c_send(I2CSlave *s, uint8_t data)
+{
+RemoteI2CState *i2c = REMOTE_I2C(s);
+uint8_t type = REMOTE_I2C_SEND;
+uint8_t resp = 1;
+qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
+qemu_chr_fe_write_all(&i2c->chr, &data, ONE_BYTE);
+
+qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
+return resp ? -1 : 0;
+}
+
+/* Returns non-zero when no response from the device. */
+static int remote_i2c_event(I2CSlave *s, enum i2c_event event)
+{
+RemoteI2CState *i2c = REMOTE_I2C(s);
+uint8_t type;
+uint8_t resp = 1;
+switch (event) {
+case I2C_START_RECV:
+type = REMOTE_I2C_START_RECV;
+break;
+case I2C_START_SEND:
+type = REMOTE_I2C_START_SEND;
+break;
+case I2C_FINISH:
+type = REMOTE_I2C_FINISH;
+break;
+case I2C_NACK:
+type = REMOTE_I2C_NACK;
+}
+qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
+qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
+return resp ? -1 : 0;
+}
+
+static Property remote_i2c_props[] = {
+DEFINE_PROP_CHR("chardev", RemoteI2CState, chr),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void remote_i2c_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+k->recv = &remote_i2c_recv;
+k->send = &remote_i2c_send;
+k->event = &remote_i2c_event;
+device_class_set_props(dc, remote_i2c_props);
+}
+
+static const TypeInfo remote_i2c_type = {
+.name = TYPE_REMOTE_I2C,
+.parent = TYPE_I2C_SLAVE,
+.ins

[PATCH 1/1] hw/i2c: add remote I2C device

2021-08-02 Thread Shengtan Mao
This patch adds the remote I2C device, which supports the usage of
external I2C devices.
Signed-off-by: Shengtan Mao 
---
 hw/arm/Kconfig|   1 +
 hw/i2c/Kconfig|   4 +
 hw/i2c/meson.build|   1 +
 hw/i2c/remote-i2c.c   | 117 ++
 tests/qtest/meson.build   |   1 +
 tests/qtest/remote-i2c-test.c | 216 ++
 6 files changed, 340 insertions(+)
 create mode 100644 hw/i2c/remote-i2c.c
 create mode 100644 tests/qtest/remote-i2c-test.c

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 90b19c0861..58fdfab90d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -392,6 +392,7 @@ config NPCM7XX
 select MAX34451
 select PL310  # cache controller
 select PMBUS
+select REMOTE_I2C
 select SERIAL
 select SSI
 select UNIMP
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
index 8217cb5041..278156991d 100644
--- a/hw/i2c/Kconfig
+++ b/hw/i2c/Kconfig
@@ -1,6 +1,10 @@
 config I2C
 bool
 
+config REMOTE_I2C
+bool
+select I2C
+
 config SMBUS
 bool
 select I2C
diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build
index d3df273251..ba0215db61 100644
--- a/hw/i2c/meson.build
+++ b/hw/i2c/meson.build
@@ -6,6 +6,7 @@ i2c_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: 
files('smbus_ich9.c'))
 i2c_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_i2c.c'))
 i2c_ss.add(when: 'CONFIG_BITBANG_I2C', if_true: files('bitbang_i2c.c'))
 i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_i2c.c'))
+i2c_ss.add(when: 'CONFIG_REMOTE_I2C', if_true: files('remote-i2c.c'))
 i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c'))
 i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c'))
 i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))
diff --git a/hw/i2c/remote-i2c.c b/hw/i2c/remote-i2c.c
new file mode 100644
index 00..083eaf2210
--- /dev/null
+++ b/hw/i2c/remote-i2c.c
@@ -0,0 +1,117 @@
+/*
+ * Remote I2C Device
+ *
+ * Copyright (c) 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+
+#include "chardev/char-fe.h"
+#include "hw/i2c/i2c.h"
+#include "hw/qdev-properties-system.h"
+
+#define TYPE_REMOTE_I2C "remote-i2c"
+#define REMOTE_I2C(obj) OBJECT_CHECK(RemoteI2CState, (obj), TYPE_REMOTE_I2C)
+#define ONE_BYTE 1
+
+typedef struct {
+I2CSlave parent_obj;
+CharBackend chr;
+} RemoteI2CState;
+
+typedef enum {
+REMOTE_I2C_START_RECV = 0,
+REMOTE_I2C_START_SEND = 1,
+REMOTE_I2C_FINISH = 2,
+REMOTE_I2C_NACK = 3,
+REMOTE_I2C_RECV = 4,
+REMOTE_I2C_SEND = 5,
+} RemoteI2CCommand;
+
+static uint8_t remote_i2c_recv(I2CSlave *s)
+{
+RemoteI2CState *i2c = REMOTE_I2C(s);
+uint8_t resp = 0;
+uint8_t type = REMOTE_I2C_RECV;
+qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
+
+qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
+return resp;
+}
+
+static int remote_i2c_send(I2CSlave *s, uint8_t data)
+{
+RemoteI2CState *i2c = REMOTE_I2C(s);
+uint8_t type = REMOTE_I2C_SEND;
+uint8_t resp = 1;
+qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
+qemu_chr_fe_write_all(&i2c->chr, &data, ONE_BYTE);
+
+qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
+return resp ? -1 : 0;
+}
+
+/* Returns non-zero when no response from the device. */
+static int remote_i2c_event(I2CSlave *s, enum i2c_event event)
+{
+RemoteI2CState *i2c = REMOTE_I2C(s);
+uint8_t type;
+uint8_t resp = 1;
+switch (event) {
+case I2C_START_RECV:
+type = REMOTE_I2C_START_RECV;
+break;
+case I2C_START_SEND:
+type = REMOTE_I2C_START_SEND;
+break;
+case I2C_FINISH:
+type = REMOTE_I2C_FINISH;
+break;
+case I2C_NACK:
+type = REMOTE_I2C_NACK;
+}
+qemu_chr_fe_write_all(&i2c->chr, &type, ONE_BYTE);
+qemu_chr_fe_read_all(&i2c->chr, &resp, ONE_BYTE);
+return resp ? -1 : 0;
+}
+
+static Property remote_i2c_props[] = {
+DEFINE_PROP_CHR("chardev", RemoteI2CState, chr),
+DEFINE_PROP_END_OF_LIST(),
+};
+
+static void remote_i2c_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
+
+k->recv = &remote_i2c_recv;
+k->send = &remote_i2c_send;
+k->event = &remote_i2c_event;
+device_class_set_props(dc, remote_i2c_props);
+}
+
+static const TypeInfo remote_i2c_type = {
+.name = TYPE_REMOTE_I2C,
+.parent = TYPE_I2C_SLAVE,
+.ins

[PATCH v2 0/1] Add remote I2C device to support external I2C device

2021-08-02 Thread Shengtan Mao
This patch implements the remote I2C device.
The remote I2C device allows an external I2C device to communicate with the I2C 
controller in QEMU through the remote I2C protocol.
Users no longer have to directly modify QEMU to add new I2C devices and can 
instead implement the emulated device externally and connect it to the remote 
I2C device.

Previous work by Wolfram Sang 
(https://git.kernel.org/pub/scm/virt/qemu/wsa/qemu.git/commit/?h=i2c-passthrough)
 was referenced.
It shares the similar idea of redirecting the actual I2C device 
functionalities, but Sang focuses on physical devices, and we focus on emulated 
devices.
The work by Sang mainly utilizes file descriptors while ours utilizes character 
devices, which offers better support for emulated devices.
The work by Sang is not meant to offer full I2C device support; it only 
implements the receive functionality.
Our work implements full support for I2C devices: send, recv, and event 
(match_and_add is not applicable for external devices).

Shengtan Mao (1):
  hw/i2c: add remote I2C device

 hw/arm/Kconfig|   1 +
 hw/i2c/Kconfig|   4 +
 hw/i2c/meson.build|   1 +
 hw/i2c/remote-i2c.c   | 117 ++
 tests/qtest/meson.build   |   1 +
 tests/qtest/remote-i2c-test.c | 216 ++
 6 files changed, 340 insertions(+)
 create mode 100644 hw/i2c/remote-i2c.c
 create mode 100644 tests/qtest/remote-i2c-test.c

-- 
2.32.0.554.ge1b32706d8-goog




Re: "make check-acceptance" takes way too long

2021-08-02 Thread Cleber Rosa
On Sat, Jul 31, 2021 at 4:33 PM Peter Maydell  wrote:
>
> On Sat, 31 Jul 2021 at 19:43, Alex Bennée  wrote:
> >
> >
> > Peter Maydell  writes:
> >
> > > "make check-acceptance" takes way way too long. I just did a run
> > > on an arm-and-aarch64-targets-only debug build and it took over
> > > half an hour, and this despite it skipping or cancelling 26 out
> > > of 58 tests!
> > >
> > > I think that ~10 minutes runtime is reasonable. 30 is not;
> > > ideally no individual test would take more than a minute or so.
> > >
> > > Output saying where the time went. The first two tests take
> > > more than 10 minutes *each*. I think a good start would be to find
> > > a way of testing what they're testing that is less heavyweight.
> > >
> > >  (01/58) 
> > > tests/acceptance/boot_linux.py:BootLinuxAarch64.test_virt_tcg_gicv2:
> > > PASS (629.74 s)
> > >  (02/58) 
> > > tests/acceptance/boot_linux.py:BootLinuxAarch64.test_virt_tcg_gicv3:
> > > PASS (628.75 s)
> > >  (03/58) tests/acceptance/boot_linux.py:BootLinuxAarch64.test_virt_kvm:
> > > CANCEL: kvm accelerator does not seem to be available (1.18 s)
> >
> > For these tests which purport to exercise the various GIC configurations
> > I think we would be much better served by running kvm-unit-tests which
> > at least try and exercise all the features rather than rely on the side
> > effect of booting an entire OS.
>
> I think "can we boot Linux via UEFI?" is worth testing, as is
> "can we boot Linux and do at least some stuff in userspace?"
> (there's a lot of TCG that doesn't get exercised by pure kernel boot).
> We just need to find a guest OS that isn't so overweight it takes 10
> minutes...
>
> -- PMM
>

I think using alternative guests is absolutely the way to go here.  I
had that in mind in the past, so much that I made sure to include
cirros[1] as one of the supported images[2] in avocado.utils.vmimage
(used in these tests above).  These tests are based on the LinuxTest
class[3], and they support the distro[4] and distro_version[5]
parameters.

But, cirros doesn't ship with a fully capable cloud-init package and I
deferred to support it in avocado.utils.cloudinit, and thus, support
cirrus in those tests.  I gave that idea another try, and the results
are encouraging, with reduction of runtime by almost a factor of 6.
On my system I get:

$ avocado run -p distro=fedora -p distro_version=31
tests/acceptance/boot_linux.py:BootLinuxAarch64.test_virt_tcg_gicv3
 (1/1) tests/acceptance/boot_linux.py:BootLinuxAarch64.test_virt_tcg_gicv3:
PASS (165.48 s)

And with cirros:

$ avocado run -p distro=cirros -p distro_version=0.5.2
tests/acceptance/boot_linux.py:BootLinuxAarch64.test_virt_tcg_gicv3
(1/1) tests/acceptance/boot_linux.py:BootLinuxAarch64.test_virt_tcg_gicv3:
PASS (28.80 s)

I'll work on posting the bits needed to have this working out of the
box, but it'll require new code on the Avocado side too (tentative to
version 91.0).

Regards,
- Cleber.

[1] https://github.com/cirros-dev/cirros
[2] 
https://avocado-framework.readthedocs.io/en/90.0/guides/writer/libs/vmimage.html#supported-images
[3] 
https://qemu-project.gitlab.io/qemu/devel/testing.html#the-avocado-qemu-linuxtest-base-test-class
[4] https://qemu-project.gitlab.io/qemu/devel/testing.html#distro
[5] https://qemu-project.gitlab.io/qemu/devel/testing.html#distro-version




Re: [PATCH 2/2] target/arm: Implement M-profile trapping on division by zero

2021-08-02 Thread Richard Henderson

On 7/30/21 5:16 AM, Peter Maydell wrote:

Unlike A-profile, for M-profile the UDIV and SDIV insns can be
configured to raise an exception on division by zero, using the CCR
DIV_0_TRP bit.

Implement support for setting this bit by making the helper functions
raise the appropriate exception.

Signed-off-by: Peter Maydell
---
  target/arm/cpu.h   |  1 +
  target/arm/helper.h|  4 ++--
  target/arm/helper.c| 19 +--
  target/arm/m_helper.c  |  4 
  target/arm/translate.c |  4 ++--
  5 files changed, 26 insertions(+), 6 deletions(-)


Reviewed-by: Richard Henderson 

r~



[PATCH] tests/acceptance: Allow overwrite smp and memory

2021-08-02 Thread Ahmed Abouzied
Removes the hard-coded values in setUp(). Class inheriting from
avocado_qemu.LinuxTest can overwrite the default smp and memory instead.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/453
Signed-off-by: Ahmed Abouzied 
---
 tests/acceptance/avocado_qemu/__init__.py | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/tests/acceptance/avocado_qemu/__init__.py 
b/tests/acceptance/avocado_qemu/__init__.py
index 2c4fef3e14..2639b89c84 100644
--- a/tests/acceptance/avocado_qemu/__init__.py
+++ b/tests/acceptance/avocado_qemu/__init__.py
@@ -441,6 +441,8 @@ class LinuxTest(Test, LinuxSSHMixIn):
 distro = None
 username = 'root'
 password = 'password'
+smp = '2'
+memory = '1024'
 
 def _set_distro(self):
 distro_name = self.params.get(
@@ -471,8 +473,8 @@ def _set_distro(self):
 def setUp(self, ssh_pubkey=None, network_device_type='virtio-net'):
 super(LinuxTest, self).setUp()
 self._set_distro()
-self.vm.add_args('-smp', '2')
-self.vm.add_args('-m', '1024')
+self.vm.add_args('-smp', self.smp)
+self.vm.add_args('-m', self.memory)
 # The following network device allows for SSH connections
 self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22',
  '-device', '%s,netdev=vnet' % network_device_type)
-- 
2.25.1




Re: [PATCH 1/2] target/arm: Re-indent sdiv and udiv helpers

2021-08-02 Thread Richard Henderson

On 7/30/21 5:16 AM, Peter Maydell wrote:

We're about to make a code change to the sdiv and udiv helper
functions, so first fix their indentation and coding style.

Signed-off-by: Peter Maydell
---
  target/arm/helper.c | 15 +--
  1 file changed, 9 insertions(+), 6 deletions(-)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 0/2] arm: Implement M-profile trapping on division by zero

2021-08-02 Thread Richard Henderson

On 7/30/21 5:16 AM, Peter Maydell wrote:

Unlike A-profile, for M-profile the UDIV and SDIV insns can be
configured to raise an exception on division by zero, using the CCR
DIV_0_TRP bit.  This patchset implements that missing functionality
by having the udiv and sdiv helpers raise an exception if needed.

Some questions:

Is it worth allowing A-profile to retain the mildly better codegen it
gets from not having to pass in 'env' and marking the helper as
no-side-effects (ie having M-specific udiv/sdiv helpers) ?


Probably not.


Is it worth inlining either udiv or sdiv for the A-profile case?


Probably not.


   mov_i32 tmp3,r2
   mov_i32 tmp6,r3
   movcond_i32 tmp3,tmp6,$0x0,$0x0,tmp3,eq
   movcond_i32 tmp6,tmp6,$0x0,$0x1,tmp6,eq
   mov_i32 tmp7,$0x0
   divu2_i32 tmp3,tmp7,tmp3,tmp7,tmp6
   mov_i32 r3,tmp3

but the x86 code is
0x7f5f1807dc0c:  45 33 f6 xorl %r14d, %r14d
0x7f5f1807dc0f:  45 85 ed testl%r13d, %r13d
0x7f5f1807dc12:  45 0f 44 e6  cmovel   %r14d, %r12d



At the start of the first movcond, $0x0 is not allocated to a register, and the 
constraints allow a constant for argument 3.  Then, constraints do not allow a constant 
for argument 4 so we load $0x0 into a register.



0x7f5f1807dc16:  41 bf 01 00 00 00movl $1, %r15d
0x7f5f1807dc1c:  45 3b ee cmpl %r14d, %r13d
0x7f5f1807dc1f:  45 0f 44 ef  cmovel   %r15d, %r13d


At the start of the second movcond, $0x0 is loaded into a register, so we use 
it.


(Ideally of
course it would notice that it already had generated the condition
check and not repeat it.)


Yep.


r~



[PATCH-for-6.2 v6 04/10] tests: Add suffix 'tpm2' or 'tpm12' to ACPI table files

2021-08-02 Thread Stefan Berger
Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Signed-off-by: Stefan Berger 
Reviewed-by: Igor Mammedov 
---
 tests/qtest/bios-tables-test.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 93c9d306b5..4ccbe56158 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1101,7 +1101,8 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
 TPMTestState test;
 test_data data;
 GThread *thread;
-char *args, *variant = g_strdup_printf(".%s", tpm_if);
+const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12";
+char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix);
 
 tpm_tis_base_addr = base;
 
-- 
2.31.1




[PATCH-for-6.2 v6 06/10] tests: tpm: Create TPM 1.2 response in TPM emulator

2021-08-02 Thread Stefan Berger
Signed-off-by: Stefan Berger 
Acked-by: Igor Mammedov 

---
v3:
  - Added TPM_VERSION_1_2 enum for when CONFIG_TPM is not defined
---
 tests/qtest/tpm-emu.c | 5 +
 tests/qtest/tpm-emu.h | 4 
 2 files changed, 9 insertions(+)

diff --git a/tests/qtest/tpm-emu.c b/tests/qtest/tpm-emu.c
index 8baf49eafd..32c704194b 100644
--- a/tests/qtest/tpm-emu.c
+++ b/tests/qtest/tpm-emu.c
@@ -62,6 +62,11 @@ static void *tpm_emu_tpm_thread(void *data)
 s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
 s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE);
 break;
+case TPM_VERSION_1_2:
+s->tpm_msg->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
+s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
+s->tpm_msg->code = cpu_to_be32(TPM_FAIL);
+break;
 default:
 g_debug("unsupport TPM version %u", s->tpm_version);
 g_assert_not_reached();
diff --git a/tests/qtest/tpm-emu.h b/tests/qtest/tpm-emu.h
index 610519883a..fcb5d7a1d6 100644
--- a/tests/qtest/tpm-emu.h
+++ b/tests/qtest/tpm-emu.h
@@ -16,6 +16,9 @@
 #define TPM_RC_FAILURE 0x101
 #define TPM2_ST_NO_SESSIONS 0x8001
 
+#define TPM_FAIL 9
+#define TPM_TAG_RSP_COMMAND 0xc4
+
 #include "qemu/sockets.h"
 #include "io/channel.h"
 #include "sysemu/tpm.h"
@@ -29,6 +32,7 @@ struct tpm_hdr {
 
 #ifndef CONFIG_TPM
 enum TPMVersion {
+TPM_VERSION_1_2 = 1,
 TPM_VERSION_2_0 = 2,
 };
 #endif
-- 
2.31.1




[PATCH-for-6.2 v6 01/10] tests: Rename TestState to TPMTestState

2021-08-02 Thread Stefan Berger
Signed-off-by: Stefan Berger 
Reviewed-by: Igor Mammedov 
---
 tests/qtest/bios-tables-test.c| 2 +-
 tests/qtest/tpm-crb-test.c| 4 ++--
 tests/qtest/tpm-emu.c | 6 +++---
 tests/qtest/tpm-emu.h | 6 +++---
 tests/qtest/tpm-tis-device-test.c | 2 +-
 tests/qtest/tpm-tis-test.c| 2 +-
 tests/qtest/tpm-tis-util.c| 2 +-
 7 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 51d3a4e239..a622f91a37 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1098,7 +1098,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
 gchar *tmp_dir_name = g_strdup_printf("qemu-test_acpi_%s_tcg_%s.XX",
   machine, tpm_if);
 char *tmp_path = g_dir_make_tmp(tmp_dir_name, NULL);
-TestState test;
+TPMTestState test;
 test_data data;
 GThread *thread;
 char *args, *variant = g_strdup_printf(".%s", tpm_if);
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index ed533900d1..50936f1482 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -26,7 +26,7 @@ uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE;
 
 static void tpm_crb_test(const void *data)
 {
-const TestState *s = data;
+const TPMTestState *s = data;
 uint32_t intfid = readl(TPM_CRB_ADDR_BASE + A_CRB_INTF_ID);
 uint32_t csize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE);
 uint64_t caddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
@@ -145,7 +145,7 @@ int main(int argc, char **argv)
 int ret;
 char *args, *tmp_path = g_dir_make_tmp("qemu-tpm-crb-test.XX", NULL);
 GThread *thread;
-TestState test;
+TPMTestState test;
 
 module_call_init(MODULE_INIT_QOM);
 g_test_init(&argc, &argv, NULL);
diff --git a/tests/qtest/tpm-emu.c b/tests/qtest/tpm-emu.c
index 2e8eb7b94f..b9cddcc240 100644
--- a/tests/qtest/tpm-emu.c
+++ b/tests/qtest/tpm-emu.c
@@ -18,7 +18,7 @@
 #include "qapi/error.h"
 #include "tpm-emu.h"
 
-void tpm_emu_test_wait_cond(TestState *s)
+void tpm_emu_test_wait_cond(TPMTestState *s)
 {
 gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
 
@@ -36,7 +36,7 @@ void tpm_emu_test_wait_cond(TestState *s)
 
 static void *tpm_emu_tpm_thread(void *data)
 {
-TestState *s = data;
+TPMTestState *s = data;
 QIOChannel *ioc = s->tpm_ioc;
 
 s->tpm_msg = g_new(struct tpm_hdr, 1);
@@ -71,7 +71,7 @@ static void *tpm_emu_tpm_thread(void *data)
 
 void *tpm_emu_ctrl_thread(void *data)
 {
-TestState *s = data;
+TPMTestState *s = data;
 QIOChannelSocket *lioc = qio_channel_socket_new();
 QIOChannel *ioc;
 
diff --git a/tests/qtest/tpm-emu.h b/tests/qtest/tpm-emu.h
index 73f3bed0c4..b066ad63fb 100644
--- a/tests/qtest/tpm-emu.h
+++ b/tests/qtest/tpm-emu.h
@@ -26,7 +26,7 @@ struct tpm_hdr {
 char buffer[];
 } QEMU_PACKED;
 
-typedef struct TestState {
+typedef struct TPMTestState {
 GMutex data_mutex;
 GCond data_cond;
 bool data_cond_signal;
@@ -34,9 +34,9 @@ typedef struct TestState {
 QIOChannel *tpm_ioc;
 GThread *emu_tpm_thread;
 struct tpm_hdr *tpm_msg;
-} TestState;
+} TPMTestState;
 
-void tpm_emu_test_wait_cond(TestState *s);
+void tpm_emu_test_wait_cond(TPMTestState *s);
 void *tpm_emu_ctrl_thread(void *data);
 
 #endif /* TESTS_TPM_EMU_H */
diff --git a/tests/qtest/tpm-tis-device-test.c 
b/tests/qtest/tpm-tis-device-test.c
index 63ed36440f..d36ae20243 100644
--- a/tests/qtest/tpm-tis-device-test.c
+++ b/tests/qtest/tpm-tis-device-test.c
@@ -33,7 +33,7 @@ int main(int argc, char **argv)
 {
 char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-device-test.XX", NULL);
 GThread *thread;
-TestState test;
+TPMTestState test;
 char *args;
 int ret;
 
diff --git a/tests/qtest/tpm-tis-test.c b/tests/qtest/tpm-tis-test.c
index 79ffbc943e..6fee4779ea 100644
--- a/tests/qtest/tpm-tis-test.c
+++ b/tests/qtest/tpm-tis-test.c
@@ -29,7 +29,7 @@ int main(int argc, char **argv)
 int ret;
 char *args, *tmp_path = g_dir_make_tmp("qemu-tpm-tis-test.XX", NULL);
 GThread *thread;
-TestState test;
+TPMTestState test;
 
 module_call_init(MODULE_INIT_QOM);
 g_test_init(&argc, &argv, NULL);
diff --git a/tests/qtest/tpm-tis-util.c b/tests/qtest/tpm-tis-util.c
index 9aff503fd8..939893bf01 100644
--- a/tests/qtest/tpm-tis-util.c
+++ b/tests/qtest/tpm-tis-util.c
@@ -373,7 +373,7 @@ void tpm_tis_test_check_access_reg_release(const void *data)
  */
 void tpm_tis_test_check_transmit(const void *data)
 {
-const TestState *s = data;
+const TPMTestState *s = data;
 uint8_t access;
 uint32_t sts;
 uint16_t bcount;
-- 
2.31.1




[PATCH-for-6.2 v6 07/10] tests: acpi: prepare for new TPM 1.2 related tables

2021-08-02 Thread Stefan Berger
Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Signed-off-by: Stefan Berger 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/q35/DSDT.tis.tpm12  | 0
 tests/data/acpi/q35/TCPA.tis.tpm12  | 0
 tests/qtest/bios-tables-test-allowed-diff.h | 2 ++
 3 files changed, 2 insertions(+)
 create mode 100644 tests/data/acpi/q35/DSDT.tis.tpm12
 create mode 100644 tests/data/acpi/q35/TCPA.tis.tpm12

diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 
b/tests/data/acpi/q35/DSDT.tis.tpm12
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/q35/TCPA.tis.tpm12 
b/tests/data/acpi/q35/TCPA.tis.tpm12
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..fb093b32b9 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,3 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/q35/DSDT.tis.tpm12",
+"tests/data/acpi/q35/TCPA.tis.tpm12",
-- 
2.31.1




[PATCH-for-6.2 v6 02/10] tests: Add tpm_version field to TPMTestState and fill it

2021-08-02 Thread Stefan Berger
Signed-off-by: Stefan Berger 
Reviewed-by: Igor Mammedov 

---
v3:
 - Added enum TPMVersion for when CONFIG_TPM is not defined
---
 tests/qtest/bios-tables-test.c|  5 +++--
 tests/qtest/tpm-crb-test.c|  1 +
 tests/qtest/tpm-emu.c | 13 ++---
 tests/qtest/tpm-emu.h |  8 
 tests/qtest/tpm-tis-device-test.c |  1 +
 tests/qtest/tpm-tis-test.c|  1 +
 6 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index a622f91a37..93c9d306b5 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1092,7 +1092,7 @@ static void test_acpi_piix4_tcg_numamem(void)
 uint64_t tpm_tis_base_addr;
 
 static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
-  uint64_t base)
+  uint64_t base, enum TPMVersion tpm_version)
 {
 #ifdef CONFIG_TPM
 gchar *tmp_dir_name = g_strdup_printf("qemu-test_acpi_%s_tcg_%s.XX",
@@ -1113,6 +1113,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
 g_mutex_init(&test.data_mutex);
 g_cond_init(&test.data_cond);
 test.data_cond_signal = false;
+test.tpm_version = tpm_version;
 
 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
 tpm_emu_test_wait_cond(&test);
@@ -1145,7 +1146,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
 
 static void test_acpi_q35_tcg_tpm_tis(void)
 {
-test_acpi_tcg_tpm("q35", "tis", 0xFED4);
+test_acpi_tcg_tpm("q35", "tis", 0xFED4, TPM_VERSION_2_0);
 }
 
 static void test_acpi_tcg_dimm_pxm(const char *machine)
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index 50936f1482..7b94453390 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -156,6 +156,7 @@ int main(int argc, char **argv)
 g_mutex_init(&test.data_mutex);
 g_cond_init(&test.data_cond);
 test.data_cond_signal = false;
+test.tpm_version = TPM_VERSION_2_0;
 
 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
 tpm_emu_test_wait_cond(&test);
diff --git a/tests/qtest/tpm-emu.c b/tests/qtest/tpm-emu.c
index b9cddcc240..8baf49eafd 100644
--- a/tests/qtest/tpm-emu.c
+++ b/tests/qtest/tpm-emu.c
@@ -56,9 +56,16 @@ static void *tpm_emu_tpm_thread(void *data)
 s->tpm_msg->code = be32_to_cpu(s->tpm_msg->code);
 
 /* reply error */
-s->tpm_msg->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
-s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
-s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE);
+switch (s->tpm_version) {
+case TPM_VERSION_2_0:
+s->tpm_msg->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
+s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
+s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE);
+break;
+default:
+g_debug("unsupport TPM version %u", s->tpm_version);
+g_assert_not_reached();
+}
 qio_channel_write(ioc, (char *)s->tpm_msg, 
be32_to_cpu(s->tpm_msg->len),
   &error_abort);
 }
diff --git a/tests/qtest/tpm-emu.h b/tests/qtest/tpm-emu.h
index b066ad63fb..610519883a 100644
--- a/tests/qtest/tpm-emu.h
+++ b/tests/qtest/tpm-emu.h
@@ -18,6 +18,7 @@
 
 #include "qemu/sockets.h"
 #include "io/channel.h"
+#include "sysemu/tpm.h"
 
 struct tpm_hdr {
 uint16_t tag;
@@ -26,6 +27,12 @@ struct tpm_hdr {
 char buffer[];
 } QEMU_PACKED;
 
+#ifndef CONFIG_TPM
+enum TPMVersion {
+TPM_VERSION_2_0 = 2,
+};
+#endif
+
 typedef struct TPMTestState {
 GMutex data_mutex;
 GCond data_cond;
@@ -34,6 +41,7 @@ typedef struct TPMTestState {
 QIOChannel *tpm_ioc;
 GThread *emu_tpm_thread;
 struct tpm_hdr *tpm_msg;
+enum TPMVersion tpm_version;
 } TPMTestState;
 
 void tpm_emu_test_wait_cond(TPMTestState *s);
diff --git a/tests/qtest/tpm-tis-device-test.c 
b/tests/qtest/tpm-tis-device-test.c
index d36ae20243..3ddefb51ec 100644
--- a/tests/qtest/tpm-tis-device-test.c
+++ b/tests/qtest/tpm-tis-device-test.c
@@ -46,6 +46,7 @@ int main(int argc, char **argv)
 g_mutex_init(&test.data_mutex);
 g_cond_init(&test.data_cond);
 test.data_cond_signal = false;
+test.tpm_version = TPM_VERSION_2_0;
 
 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
 tpm_emu_test_wait_cond(&test);
diff --git a/tests/qtest/tpm-tis-test.c b/tests/qtest/tpm-tis-test.c
index 6fee4779ea..a4a25ba745 100644
--- a/tests/qtest/tpm-tis-test.c
+++ b/tests/qtest/tpm-tis-test.c
@@ -40,6 +40,7 @@ int main(int argc, char **argv)
 g_mutex_init(&test.data_mutex);
 g_cond_init(&test.data_cond);
 test.data_cond_signal = false;
+test.tpm_version = TPM_VERSION_2_0;
 
 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
 tpm_emu_test_wait_cond(&test);
-- 
2.31.1




[PATCH-for-6.2 v6 10/10] tests: acpi: tpm1.2: Add expected TPM 1.2 ACPI blobs

2021-08-02 Thread Stefan Berger
The TCPA.tis.tpm12 file contains the following:

[000h    4]Signature : "TCPA"[Trusted Computing 
Platform Alliance table]
[004h 0004   4] Table Length : 0032
[008h 0008   1] Revision : 02
[009h 0009   1] Checksum : 32
[00Ah 0010   6]   Oem ID : "BOCHS "
[010h 0016   8] Oem Table ID : "BXPC"
[018h 0024   4] Oem Revision : 0001
[01Ch 0028   4]  Asl Compiler ID : "BXPC"
[020h 0032   4]Asl Compiler Revision : 0001

[024h 0036   2]   Platform Class : 
[026h 0038   4] Min Event Log Length : 0001
[02Ah 0042   8]Event Log Address : 07FF

Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Signed-off-by: Stefan Berger 
Acked-by: Igor Mammedov 
---
 tests/data/acpi/q35/DSDT.tis.tpm12  | Bin 0 -> 8894 bytes
 tests/data/acpi/q35/TCPA.tis.tpm12  | Bin 0 -> 50 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   2 --
 3 files changed, 2 deletions(-)

diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 
b/tests/data/acpi/q35/DSDT.tis.tpm12
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6735e73971c6be95deceb23051a78af6a4573bd8
 100644
GIT binary patch
literal 8894
zcmb7KO>7&-8J*>iv|6sDB}GgAOGG$M+cbegN%?Dwq$PLxXN%N|r0gVg!IkB-lAR)p
zBnFZg0b~V890M)lunu}DKnG0GTYKoa4cc4^}GWq9yH-nGC7^8Fgb}F&6thMdsOKl?&
zi5aac34V@4-b_E{<=0BauQr2^g5dS{0%JX7=RS6BoLdjyxf+~f1iExCv@AMt3RCSy
zzTMh!E#IwV&33us*|}SmX|`Q)7B$;Bug=W&TE%1OSUHf_`V4WbbyW3;ksq39}_RDpf{o}v!9_v}tVr)rk>fH$%%dNXC
z#u!HPtrIjFn(x-m;YuUd=2MLH^B9U>sjo(?z_OiF(~n0bkWj6iCr;%(fW^B!=-!XB&4Grs9
zlO^Mg=o?YfJhshyUUXNgdz?7Xn9UKKJJCB)W*&1m=iz$O-5X7!fB$&bAq$yd9%BZk
zsFu7pN87&JXc~#nY|F&0p}@u5tz~fVGOg`K;UreU=eC6#m!QDSXA38BAz!Q3jl^w1
zqrlDA)~Xr5;ys^f8Tn=R6iYwsyM>dH)QmHZ}KH`q3OXqfpdW
zNQa=04btA2?=`AZ-R1t$xb^g3|Jiu*t?Ko;ud0Xs;#NcI>*b#X-G@3CSoct8%ZgwH
zyv?5@8;|WS>m{Sc6*{n+bKL`-3)Xm;ibvQaTMvV)>x}i*O~2w6S=w&n+Xy!)a(?lG
zK@W@Le#IBEUvK)UQ?G5O5-~iTY`J!-z{I(M^CC;x)NVx(lw=S^P-dyg7{-B>ByjzR
zSO89mYn%tD42g;UIX1$X!1g0zN@#>}CZL>&keC<^$3{6*jv&g2DWOrp1e7xo5>sZu
zx)NC4PmD7qG$xpG@Ca3%aZP8OGbJ=Gm~!w4Rh?s+&N0rE&@o*nLRIIurgL1=Ij-wO
zsOmH|ou;PK)O8|Mb>a=A%=Cn&b3)gNP}ON^IxS77rRzkf>P%=l6PnJ1t`niE6YoOh
ze%hK&Ti1zD)j6r@oYZtq>N*jsI;S+9Q<}~xT_-|S=d`ACTGKhL>qMyPbTplgrqj`N
zB2;xIHJwRKXHwURP}P~zbfz?&DP1Q*Rp*SRb4JrSqw7Sd>P%}o)0)n-t`niE^MI!F
zfTr_+t`niEb5_$itLdE8bs|)C;+F)TKKUM+({#@1IuWWm4{ACOYB~?I$
z|0X=dnfd<9?vP-*_d;TNee7Y4d01l})|m)Z<`Io~L}MP&nFv+pQH^<2V;q10;Cl|6oE_%0~I)KNd_a99G`)t0=j3Q2&FU_sK81CRiI>`0=j3Q2r(LI
zpaR>ED5q+m0=j3Q2r(j#g@FoeKk94bP%=;fm7%H=1}eJcOc=3{*fllMEE0
zyq_>of#pmXr~)Me6;RG314Srx!axOM_lrzad5lWpfP=V!47^ngz0~JutBm+e#b;3XemNQ|X3X}{~
zKsl2P6rt1!0~J`#gn=qhGEf2KOfpb}QYQ>lU^x>8szAv=1(Y+%KoLrvFi?TzOcu&LjgxD0RX>1(q{mpbC@>R6seC3>2Z%2?G^a&V+#~P%=;f=3{*fllMEE0)CmI>
zSk8ojDo`>|0p(0GP=rz^3{+q_69%e4$v_2^Gs!>^N}VuJM2dkTQVkTLYM=-e167zX
zP=!ebsxZkw6($T+VZuNaCK;&0Bm-5LFi?dF167!0pbC==RAItE6($T+VUmF=Ofpb~
z2?IqW?=B1!5$+hDOfpb}xD7HSrkq)IXu
z$7+xMAiX(8U%A$m?>`=;zfx&egZ4WNzrLD-GX0TOKyHYiKjb#IPI5S!?F~DK-&>yD_}K8Q#R$y+}{l>^0l=L1??+v8)_DS#c
z(-#KQ$L=G2K}lcW=?eqt3;U!m^wSpy)5q^4eNjnY5KcMFZR=y2Gft-NBWYI
zzQog)2GW=INnh%xFAt_4zmN1~C4HHvFAtZes_b**h=c%;kU+6ccN`%cSGwkrFVxPAVb}WwvpWptut%^(>jyF@T+8~
zJJB|>yPQ1zc>~83}p4GdD@U;?(JvqOgE}|lv+?$v7^}YcUGPg)rqoo_TG-aUoSM|Q)*#x!kZ>t
ze=Spf<@NC8OFzxL`qFE!TzYlmrPo-?aQ)>|{ik)(vP#C6_LsI{V^<%ZL|f-y+LqnA
z@*N6tEaUoxn&DPz4a2QhPaD_(&(fi2u&C=+J#4b42pM%7h2;$3UapzJUUQ{ZF+)a;
zcbSFCN)-KX~5{|mwJw7yZbl<~`t2D-Sc4-}>y7_eX$srhjGI0AgtY|niF}Mic
zr41@97Gk2ZNFAPI8+6N|ZKJg?THH`y7|*41qo=t#;jT2A_CC`*`e_;JACnhujhLIz
ziVU_A^uk~xrg`M(TJJnV&otIQK3E=juFW1j-B2{LeaFDATexn
z>q7bn7Ej49v135YmcI2+wV=Z(QHu-3=^k)C`J(#
zmv7%?KD}~Lv5sM)M8%p{gL9ZD@tUM|<^3p%mUlEem;Jh!ZYn9?
z>jV=v;$1u3*Jt);ws8<8%SX;4ePgMe8jBeiD9)c~r_7iYv9O_s=t;Uls+=F(yCtoi
z6U8&G@W9E{LUj#~)FPo#*i}dD#GN?3(Vdk?&hj!}=@Gi4t(`<8n-%qAOv!f}*=Iz6
zyJs*Mb7R3{C}84bQJyUElQDW+Kv_9{g8m9?`qjOntc{W`<=5)h>eO#HeSZ<<^3~gS
ztruHYj`Ps>D>V}bKjZs#epscmYGxTnRAT{JV)l#R(7!8CWK>s9pElErO}|*1=uUii
zV-q`EJ(w0QF0fZ^=HI@%$@=I81Fc1~$B!88Vk$<{inFCuoSva{;b0quSG!wEi~mXZ
z&Hw)X?2)JbQ0pE4xnur%w$V+X;Mz;Zt;ntcPr6|ACKpaDvF>B2utxB&5f>R=$TXH<
z9hWb!Ti9jn8DW6ouZE1IpvM10fTJkNZW$r9U!{>445O+pqM(af?q2hf!RWk7kR?0<
zgjwpE;KzC>`J(!3#Y37K4iI2}7(CWPzCs-6@qNdLzp?pntq6e~8k{m}8ZE{pS|HPq
zS`ML8Q}49L`{A``cmn^|j(;_Sr)NIDRQ%v*>GT)>zWrl34ozd!h<0Z%iIN}C&Fr!N
E0|senc>n+a

literal 0
HcmV?d1

diff --git a/tests/data/acpi/q35/TCPA.tis.tpm12 
b/tests/data/acpi/q35/TCPA.tis.tpm12
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a56961b413e7715b3d60f9836d1c8f2f4c7347cb
 100644
GIT binary patch
literal 50
qcmWG>4sbMLU|?V}a`Jcf2v%^42yj*a0!E-1hz+7a07U<12eAOxRtEt9

literal 0
HcmV?d1

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index fb093b32b9..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,3 +1 @@
 /* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/q35/DSDT.ti

  1   2   3   >