Re: [PATCH v14 08/10] Adding info [tb-list|tb] commands to HMP (WIP)

2023-06-06 Thread Wu, Fei
On 6/1/2023 8:12 PM, Wu, Fei wrote:
> On 6/1/2023 10:40 AM, Richard Henderson wrote:
>> On 5/30/23 01:35, Fei Wu wrote:
>>> +static void do_dump_tbs_info(int total, int sort_by)
>>> +{
>>> +    id = 1;
>>> +    GList *i;
>>> +    int count = total;
>>> +
>>> +    g_list_free(last_search);
>>> +    last_search = NULL;
>>> +
>>> +    qht_iter(&tb_ctx.tb_stats, collect_tb_stats, NULL);
>>> +
>>> +    last_search = g_list_sort_with_data(last_search, inverse_sort_tbs,
>>> +    &sort_by);
>>> +
>>
>> Why are you sorting on a list and not an array?
>> Intuitively, sorting a list of 1 million elements seems like the wrong
>> choice.
>>
>> Why did you put all the comparisons in one inverse_sort_tbs function,
>> and require examining sort_by?  Better would be N sorting functions
>> where sort_by is evaluated once before starting the sort.
>>
>>
>>> +++ b/disas/disas.c
>>> @@ -8,6 +8,8 @@
>>>  #include "hw/core/cpu.h"
>>>  #include "exec/memory.h"
>>>  
>>> +#include "qemu/log-for-trace.h"
>>> +
>>>  /* Filled in by elfload.c.  Simplistic, but will do for now. */
>>>  struct syminfo *syminfos = NULL;
>>>  
>>> @@ -199,6 +201,24 @@ static void initialize_debug_host(CPUDebug *s)
>>>  #endif
>>>  }
>>>  
>>> +static int
>>> +__attribute__((format(printf, 2, 3)))
>>> +fprintf_log(FILE *a, const char *b, ...)
>>> +{
>>> +    va_list ap;
>>> +    va_start(ap, b);
>>> +
>>> +    if (!to_string) {
>>> +    vfprintf(a, b, ap);
>>> +    } else {
>>> +    qemu_vlog(b, ap);
>>> +    }
>>> +
>>> +    va_end(ap);
>>> +
>>> +    return 1;
>>> +}
>>> +
>>
>> Not need on this either.  Global variable being checked on each
>> callback, instead of selecting the proper callback earlier -- preferably
>> without the global variable.
>>
>> Did you really need something different than monitor_disas?  You almost
>> certainly want to read physical memory and not virtual anyway.
>>
'info tb' has extra flag to specify dump out_asm, in_asm & op, so there
looks more user cases than monitor_disas, I think it's nice to have, but
not strongly required, usually we have a general idea if we get the IN
ops, plus the other counters such as g/op/... in the output.

Right now I am inclined to switch to monitor_disas, I found it causes
guest kernel panic with the selective virt addr, it happens to the
original v10 too.

--

TB id:1998 | phys:0x9c5f5ce2 virt:0x00ff8ff8ece2 flags:0x00024018 0
inv/1
| exec:68/0 guest inst cov:0.00%
| trans:1 ints: g:1 op:17 op_opt:16 spills:0
| h/g (host bytes / guest insts): 129.00
| time to gen at 2.4GHz => code:1960.42(ns) IR:915.83(ns)


could not gen code for this TB (no longer mapped?)
--
[   98.213363] Unable to handle kernel paging request at virtual address
00ff8ff8ece2
[   98.219153] Oops [#1]
[   98.219299] Modules linked in: binfmt_misc nls_ascii nls_cp437 vfat
fat cfg80211 rfkill drm fuse drm_panel_orientation_quirks configfs
i2c_core ip_tables x_tables autofs4 ext4 crc32c_generic crc16 mbcache
jbd2 virtio_net net_failover virtio_blk failover virtio_mmio virtio
virtio_ring
[   98.220832] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.2.0+ #1
[   98.221122] Hardware name: riscv-virtio,qemu (DT)
[   98.221330] epc : arch_cpu_idle+0x1e/0x28
[   98.221985]  ra : default_idle_call+0x3c/0xb8
[   98.222150] epc : 80004398 ra : 808a0bc2 sp :
ff200068bf40
[   98.222339]  gp : 815688e8 tp : ff607ffcc240 t0 :
ff200064bad8
[   98.222562]  t1 : 0001 t2 : 80e02ed0 s0 :
ff200068bf50
[   98.222780]  s1 : 0001 a0 : 000154ac a1 :
ff627d0f3000
[   98.223001]  a2 : ff607ffcc240 a3 : 0001 a4 :
ff627d0f3000
[   98.223217]  a5 : ff61fdd5d500 a6 : 4000 a7 :

[   98.223427]  s2 : 8156a220 s3 : 8156a418 s4 :
80c6ba18
[   98.223636]  s5 : 815a9588 s6 :  s7 :

[   98.223853]  s8 : fffe s9 : 8003d6a8 s10:

[   98.224065]  s11:  t3 : 8156a438 t4 :

[   98.224272]  t5 :  t6 : 
[   98.224436] status: 00020100 badaddr: 00ff8ff8ece2 cause:
000c
[   98.224778] [] arch_cpu_idle+0x1e/0x28
[   98.226393] ---[ end trace  ]---
[   98.226770] Kernel panic - not syncing: Attempted to kill the idle task!
[   98.227188] SMP: stopping secondary CPUs
[   98.227980] ---[ end Kernel panic - not syncing: Attempted to kill
the idle task! ]---

Thanks,
Fei.

> This makes me think the necessity of 'info tb', the primary extra info
> it adds is guest instruction, which can be gotten from 'x/i' w/o calling
> tb_gen_code.
> 
> (qemu) info tb 1
> --
> 
> TB id:1 | phys:0x79bc86 virt:0x8059bc86 flags:0x01024001 0 inv/1
> | exec:56962444/0 guest i

Re: [PATCH v4 2/3] hw/i386/pc: Default to use SMBIOS 3.0 for newer machine models

2023-06-06 Thread Igor Mammedov
On Mon, 5 Jun 2023 16:39:05 -0500
Suravee Suthikulpanit  wrote:

> Currently, pc-q35 and pc-i44fx machine models are default to use SMBIOS 2.8
> (32-bit entry point). Since SMBIOS 3.0 (64-bit entry point) is now fully
> supported since QEMU 7.0, default to use SMBIOS 3.0 for newer machine
> models. This is necessary to avoid the following message when launching
> a VM with large number of vcpus.
> 
>"SMBIOS 2.1 table length 66822 exceeds 65535"
> 
> Note that user can still override the entry point tyme w/ QEMU option
> "-M ..., smbios-entry-point-type=[32|64].
> 
> Signed-off-by: Suravee Suthikulpanit 
> ---
>  hw/i386/pc.c | 14 +-
>  hw/i386/pc_piix.c|  5 +
>  hw/i386/pc_q35.c |  5 +
>  include/hw/i386/pc.h |  2 ++
>  4 files changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 8fc34f5454..5a87b82185 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -786,6 +786,14 @@ void pc_machine_done(Notifier *notifier, void *data)
>  if (pcmc->smbios_defaults) {
>  MachineClass *mc = MACHINE_GET_CLASS(pcms);
>  
> +/*
> + * Check if user has specified a command line option
> + * to override the SMBIOS default entry point type.
> + */
> +if (!pcms->smbios_use_cmdline_ep_type) {
> +pcms->smbios_entry_point_type = pcmc->default_smbios_ep_type;
> +}

why pcms->smbios_entry_point_type that we already have is not enough
we need to add extra pcms->smbios_use_cmdline_ep_type field?

> +
>  /* These values are guest ABI, do not change */
>  smbios_set_defaults("QEMU", mc->desc,
>  mc->name, pcmc->smbios_legacy_mode,
> @@ -1782,7 +1790,10 @@ static void pc_machine_set_smbios_ep(Object *obj, 
> Visitor *v, const char *name,
>  {
>  PCMachineState *pcms = PC_MACHINE(obj);
>  
> -visit_type_SmbiosEntryPointType(v, name, &pcms->smbios_entry_point_type, 
> errp);
> +pcms->smbios_use_cmdline_ep_type =
> +visit_type_SmbiosEntryPointType(v, name,
> +&pcms->smbios_entry_point_type,
> +errp);
>  }
>  
>  static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v,
> @@ -1992,6 +2003,7 @@ static void pc_machine_class_init(ObjectClass *oc, void 
> *data)
>  mc->nvdimm_supported = true;
>  mc->smp_props.dies_supported = true;
>  mc->default_ram_id = "pc.ram";
> +pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64;
>  
>  object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
>  pc_machine_get_max_ram_below_4g, pc_machine_set_max_ram_below_4g,
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index da6ba4eeb4..1a2bb25c75 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -467,11 +467,16 @@ DEFINE_I440FX_MACHINE(v8_1, "pc-i440fx-8.1", NULL,
>  
>  static void pc_i440fx_8_0_machine_options(MachineClass *m)
>  {
> +PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
> +
>  pc_i440fx_8_1_machine_options(m);
>  m->alias = NULL;
>  m->is_default = false;
>  compat_props_add(m->compat_props, hw_compat_8_0, hw_compat_8_0_len);
>  compat_props_add(m->compat_props, pc_compat_8_0, pc_compat_8_0_len);
> +
> +/* For pc-i44fx-8.0 and older, use SMBIOS 2.8 by default */
> +pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32;
>  }
>  
>  DEFINE_I440FX_MACHINE(v8_0, "pc-i440fx-8.0", NULL,
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index a58cd1d3ea..371cca7484 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -379,10 +379,15 @@ DEFINE_Q35_MACHINE(v8_1, "pc-q35-8.1", NULL,
>  
>  static void pc_q35_8_0_machine_options(MachineClass *m)
>  {
> +PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
> +
>  pc_q35_8_1_machine_options(m);
>  m->alias = NULL;
>  compat_props_add(m->compat_props, hw_compat_8_0, hw_compat_8_0_len);
>  compat_props_add(m->compat_props, pc_compat_8_0, pc_compat_8_0_len);
> +
> +/* For pc-q35-8.0 and older, use SMBIOS 2.8 by default */
> +pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32;
>  }
>  
>  DEFINE_Q35_MACHINE(v8_0, "pc-q35-8.0", NULL,
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index c661e9cc80..f754da5a38 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -50,6 +50,7 @@ typedef struct PCMachineState {
>  bool i8042_enabled;
>  bool default_bus_bypass_iommu;
>  uint64_t max_fw_size;
> +bool smbios_use_cmdline_ep_type;
>  
>  /* ACPI Memory hotplug IO base address */
>  hwaddr memhp_io_base;
> @@ -110,6 +111,7 @@ struct PCMachineClass {
>  bool smbios_defaults;
>  bool smbios_legacy_mode;
>  bool smbios_uuid_encoded;
> +SmbiosEntryPointType default_smbios_ep_type;
>  
>  /* RAM / address space compat: */
>  bool gigabyte_align;




Re: [PATCH v4 1/3] hw/i386/pc: Refactor logic to set SMBIOS set defaults

2023-06-06 Thread Igor Mammedov
On Mon, 5 Jun 2023 16:39:04 -0500
Suravee Suthikulpanit  wrote:

> In preparation for subsequent code to upgrade default SMBIOS
> entry point type. There is no functional change.
> 
> Signed-off-by: Suravee Suthikulpanit 
> ---
>  hw/i386/pc.c  | 12 
>  hw/i386/pc_piix.c |  9 -
>  hw/i386/pc_q35.c  |  8 
>  3 files changed, 12 insertions(+), 17 deletions(-)
> 
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index bb62c994fa..8fc34f5454 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -781,6 +781,18 @@ void pc_machine_done(Notifier *notifier, void *data)
>  
>  acpi_setup();
>  if (x86ms->fw_cfg) {
> +PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
> +
> +if (pcmc->smbios_defaults) {
> +MachineClass *mc = MACHINE_GET_CLASS(pcms);
> +
> +/* These values are guest ABI, do not change */
> +smbios_set_defaults("QEMU", mc->desc,
> +mc->name, pcmc->smbios_legacy_mode,
> +pcmc->smbios_uuid_encoded,
> +pcms->smbios_entry_point_type);
> +}
> 

well, pc_machine_done() is the hack for the last minute changes to
board that can't done earlier otherwise (during machine_initfn time).
So I'd prefer not adding anything there unless we have to.

>  fw_cfg_build_smbios(MACHINE(pcms), x86ms->fw_cfg);
>  fw_cfg_build_feature_control(MACHINE(pcms), x86ms->fw_cfg);
>  /* update FW_CFG_NB_CPUS to account for -device added CPUs */
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index d5b0dcd1fe..da6ba4eeb4 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -198,15 +198,6 @@ static void pc_init1(MachineState *machine,
>  
>  pc_guest_info_init(pcms);
>  
> -if (pcmc->smbios_defaults) {
> -MachineClass *mc = MACHINE_GET_CLASS(machine);
> -/* These values are guest ABI, do not change */
> -smbios_set_defaults("QEMU", mc->desc,
> -mc->name, pcmc->smbios_legacy_mode,
> -pcmc->smbios_uuid_encoded,
> -pcms->smbios_entry_point_type);
> -}
> -
>  /* allocate ram and load rom/bios */
>  if (!xen_enabled()) {
>  pc_memory_init(pcms, system_memory, rom_memory, hole64_size);
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 6155427e48..a58cd1d3ea 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -198,14 +198,6 @@ static void pc_q35_init(MachineState *machine)
>  
>  pc_guest_info_init(pcms);
>  
> -if (pcmc->smbios_defaults) {
> -/* These values are guest ABI, do not change */
> -smbios_set_defaults("QEMU", mc->desc,
> -mc->name, pcmc->smbios_legacy_mode,
> -pcmc->smbios_uuid_encoded,
> -pcms->smbios_entry_point_type);
> -}
> -
>  /* create pci host bus */
>  q35_host = Q35_HOST_DEVICE(qdev_new(TYPE_Q35_HOST_DEVICE));
>  




Re: [PATCH v4 3/3] pc: q35: Bump max_cpus to 1024

2023-06-06 Thread Igor Mammedov
On Mon, 5 Jun 2023 16:39:06 -0500
Suravee Suthikulpanit  wrote:

> Since KVM_MAX_VCPUS is currently defined to 1024 for x86 as shown in
> arch/x86/include/asm/kvm_host.h, update QEMU limits to the same number.
> 
> In case KVM could not support the specified number of vcpus, QEMU would
> return the following error message:
> 
>   qemu-system-x86_64: kvm_init_vcpu: kvm_get_vcpu failed (xxx): Invalid 
> argument
> 
> Cc: Igor Mammedov 
> Cc: Daniel P. Berrangé 
> Cc: Michael S. Tsirkin 
> Cc: Julia Suvorova 
> Signed-off-by: Suravee Suthikulpanit 
> ---
>  hw/i386/pc_q35.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 371cca7484..bd862add94 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -365,7 +365,7 @@ static void pc_q35_machine_options(MachineClass *m)
>  machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE);
>  machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
>  machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
> -m->max_cpus = 288;
> +m->max_cpus = 1024;

did you forgot to preserve value for older machine types?
use commit 00d0f9fd6602a2 as reference 

>  }
>
>  static void pc_q35_8_1_machine_options(MachineClass *m)




Re: [PULL 02/17] block: Collapse padded I/O vecs exceeding IOV_MAX

2023-06-06 Thread Michael Tokarev

05.06.2023 18:45, Hanna Czenczek wrote:

When processing vectored guest requests that are not aligned to the
storage request alignment, we pad them by adding head and/or tail
buffers for a read-modify-write cycle.

The guest can submit I/O vectors up to IOV_MAX (1024) in length, but
with this padding, the vector can exceed that limit.  As of
4c002cef0e9abe7135d7916c51abce47f7fc1ee2 ("util/iov: make
qemu_iovec_init_extended() honest"), we refuse to pad vectors beyond the
limit, instead returning an error to the guest.

To the guest, this appears as a random I/O error.  We should not return
an I/O error to the guest when it issued a perfectly valid request.

Before 4c002cef0e9abe7135d7916c51abce47f7fc1ee2, we just made the vector
longer than IOV_MAX, which generally seems to work (because the guest
assumes a smaller alignment than we really have, file-posix's
raw_co_prw() will generally see bdrv_qiov_is_aligned() return false, and
so emulate the request, so that the IOV_MAX does not matter).  However,
that does not seem exactly great.


Why it is not "exactly great"?  To me, it seems to be the best solution.
I'd say we should be able to tolerate "slight" increase over IOV_MAX for
"internal purposes", so to say.  We can limit guest-supplied vector to
IOV_MAX, but internally guard against integer overflow only.


I see two ways to fix this problem:
1. We split such long requests into two requests.
2. We join some elements of the vector into new buffers to make it
shorter.


This seems to be over-complicated, both of them, no?

/mjt



Re: [PATCH v4 2/3] hw/i386/pc: Default to use SMBIOS 3.0 for newer machine models

2023-06-06 Thread Igor Mammedov
On Tue, 6 Jun 2023 09:35:41 +0200
Igor Mammedov  wrote:

> On Mon, 5 Jun 2023 16:39:05 -0500
> Suravee Suthikulpanit  wrote:
[...]
> > +/* For pc-i44fx-8.0 and older, use SMBIOS 2.8 by default */
> > +pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32;
> >  }
[...]
> >  static void pc_q35_8_0_machine_options(MachineClass *m)
> >  {
[...]
> > +/* For pc-q35-8.0 and older, use SMBIOS 2.8 by default */
> > +pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32;
> >  }
[...]

what Michael referred to as duplication is probably these lines,
however "smbios-entry-point-type: is machine property so we can't
use device compat machinery here (pc_compat_8_0).
What we can do is override "default_machine_opts" value, but then
again it has to be opencoded in  piix4/q35_machine_options, so
don't see a point in doing so.
As you wrote here is what typically do for machine compat knobs,
so it should be fine.

I just doubt that we need extra default_smbios_ep_type field.




[PATCH] mkvenv: always pass locally-installed packages to pip

2023-06-06 Thread Paolo Bonzini
Let pip decide whether a new version should be installed or the current
one is okay.  This ensures that the virtual environment is updated
(either upgraded or downgraded) whenever a new version of a package is
requested.

The hardest part here is figuring out if a package is installed in
the venv (which also has to be done twice to account for the presence
of either setuptools in Python <3.8, or importlib in Python >=3.8).

Suggested-by: Peter Maydell 
Cc: John Snow 
Signed-off-by: Paolo Bonzini 
---
 python/scripts/mkvenv.py | 76 ++--
 1 file changed, 74 insertions(+), 2 deletions(-)

diff --git a/python/scripts/mkvenv.py b/python/scripts/mkvenv.py
index 3a9aef46a51..3957e7d6e08 100644
--- a/python/scripts/mkvenv.py
+++ b/python/scripts/mkvenv.py
@@ -553,6 +553,74 @@ def pkgname_from_depspec(dep_spec: str) -> str:
 return match.group(0)
 
 
+def _get_path_importlib(package: str) -> Optional[str]:
+# pylint: disable=import-outside-toplevel
+# pylint: disable=no-name-in-module
+# pylint: disable=import-error
+try:
+# First preference: Python 3.8+ stdlib
+from importlib.metadata import (  # type: ignore
+PackageNotFoundError,
+distribution,
+)
+except ImportError as exc:
+logger.debug("%s", str(exc))
+# Second preference: Commonly available PyPI backport
+from importlib_metadata import (  # type: ignore
+PackageNotFoundError,
+distribution,
+)
+
+try:
+return str(distribution(package).locate_file("."))
+except PackageNotFoundError:
+return None
+
+
+def _get_path_pkg_resources(package: str) -> Optional[str]:
+# pylint: disable=import-outside-toplevel
+# Bundled with setuptools; has a good chance of being available.
+import pkg_resources
+
+try:
+return str(pkg_resources.get_distribution(package).location)
+except pkg_resources.DistributionNotFound:
+return None
+
+
+def _get_path(package: str) -> Optional[str]:
+try:
+return _get_path_importlib(package)
+except ImportError as exc:
+logger.debug("%s", str(exc))
+
+try:
+return _get_path_pkg_resources(package)
+except ImportError as exc:
+logger.debug("%s", str(exc))
+raise Ouch(
+"Neither importlib.metadata nor pkg_resources found. "
+"Use Python 3.8+, or install importlib-metadata or setuptools."
+) from exc
+
+
+def _path_is_prefix(prefix: Union[str, Path], path: Union[str, Path]) -> bool:
+prefix = str(prefix)
+path = str(path)
+try:
+return os.path.commonpath([prefix, path]) == prefix
+except ValueError:
+return False
+
+
+def _is_system_package(package: str) -> bool:
+path = _get_path(package)
+return path is not None and not (
+_path_is_prefix(sysconfig.get_path("purelib"), path)
+or _path_is_prefix(sysconfig.get_path("platlib"), path)
+)
+
+
 def _get_version_importlib(package: str) -> Optional[str]:
 # pylint: disable=import-outside-toplevel
 # pylint: disable=no-name-in-module
@@ -741,8 +809,12 @@ def _do_ensure(
 for spec in dep_specs:
 matcher = distlib.version.LegacyMatcher(spec)
 ver = _get_version(matcher.name)
-if ver is None or not matcher.match(
-distlib.version.LegacyVersion(ver)
+if (
+ver is None
+# Always pass installed package to pip, so that they can be
+# updated if the requested version changes
+or not _is_system_package(matcher.name)
+or not matcher.match(distlib.version.LegacyVersion(ver))
 ):
 absent.append(spec)
 else:
-- 
2.40.1




[PATCH] target/riscv/vector_helper.c: Remove the check for extra tail elements

2023-06-06 Thread Xiao Wang
Commit 752614cab8e6 ("target/riscv: rvv: Add tail agnostic for vector
load / store instructions") added an extra check for LMUL fragmentation,
intended for setting the "rest tail elements" in the last register for a
segment load insn.

Actually, the max_elements derived in vext_ld*() won't be a fraction of
vector register size, since the lmul encoded in desc is emul, which has
already been adjusted to 1 for LMUL fragmentation case by vext_get_emul()
in trans_rvv.c.inc, for ld_stride(), ld_us(), ld_index() and ldff().

Besides, vext_get_emul() has also taken EEW/SEW into consideration, so no
need to call vext_get_total_elems() which would base on the emul to derive
another emul, the second emul would be incorrect when esz differs from sew.

Thus this patch removes the check for extra tail elements.

Fixes: 752614cab8e6 ("target/riscv: rvv: Add tail agnostic for vector load / 
store instructions")

Signed-off-by: Xiao Wang 
---
 target/riscv/vector_helper.c | 21 ++---
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index f4d0438988..56a79bb5fa 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -264,26 +264,17 @@ GEN_VEXT_ST_ELEM(ste_h, int16_t, H2, stw)
 GEN_VEXT_ST_ELEM(ste_w, int32_t, H4, stl)
 GEN_VEXT_ST_ELEM(ste_d, int64_t, H8, stq)
 
-static void vext_set_tail_elems_1s(CPURISCVState *env, target_ulong vl,
-   void *vd, uint32_t desc, uint32_t nf,
+static void vext_set_tail_elems_1s(target_ulong vl, void *vd,
+   uint32_t desc, uint32_t nf,
uint32_t esz, uint32_t max_elems)
 {
-uint32_t total_elems = vext_get_total_elems(env, desc, esz);
-uint32_t vlenb = riscv_cpu_cfg(env)->vlen >> 3;
 uint32_t vta = vext_vta(desc);
-uint32_t registers_used;
 int k;
 
 for (k = 0; k < nf; ++k) {
 vext_set_elems_1s(vd, vta, (k * max_elems + vl) * esz,
   (k * max_elems + max_elems) * esz);
 }
-
-if (nf * max_elems % total_elems != 0) {
-registers_used = ((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
-vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
-  registers_used * vlenb);
-}
 }
 
 /*
@@ -319,7 +310,7 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
 }
 env->vstart = 0;
 
-vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
+vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
 }
 
 #define GEN_VEXT_LD_STRIDE(NAME, ETYPE, LOAD_FN)\
@@ -378,7 +369,7 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState 
*env, uint32_t desc,
 }
 env->vstart = 0;
 
-vext_set_tail_elems_1s(env, evl, vd, desc, nf, esz, max_elems);
+vext_set_tail_elems_1s(evl, vd, desc, nf, esz, max_elems);
 }
 
 /*
@@ -499,7 +490,7 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
 }
 env->vstart = 0;
 
-vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
+vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
 }
 
 #define GEN_VEXT_LD_INDEX(NAME, ETYPE, INDEX_FN, LOAD_FN)  \
@@ -629,7 +620,7 @@ ProbeSuccess:
 }
 env->vstart = 0;
 
-vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
+vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
 }
 
 #define GEN_VEXT_LDFF(NAME, ETYPE, LOAD_FN)   \
-- 
2.25.1




Re: [PULL 02/17] block: Collapse padded I/O vecs exceeding IOV_MAX

2023-06-06 Thread Hanna Czenczek

On 06.06.23 10:00, Michael Tokarev wrote:

05.06.2023 18:45, Hanna Czenczek wrote:

When processing vectored guest requests that are not aligned to the
storage request alignment, we pad them by adding head and/or tail
buffers for a read-modify-write cycle.

The guest can submit I/O vectors up to IOV_MAX (1024) in length, but
with this padding, the vector can exceed that limit.  As of
4c002cef0e9abe7135d7916c51abce47f7fc1ee2 ("util/iov: make
qemu_iovec_init_extended() honest"), we refuse to pad vectors beyond the
limit, instead returning an error to the guest.

To the guest, this appears as a random I/O error.  We should not return
an I/O error to the guest when it issued a perfectly valid request.

Before 4c002cef0e9abe7135d7916c51abce47f7fc1ee2, we just made the vector
longer than IOV_MAX, which generally seems to work (because the guest
assumes a smaller alignment than we really have, file-posix's
raw_co_prw() will generally see bdrv_qiov_is_aligned() return false, and
so emulate the request, so that the IOV_MAX does not matter). However,
that does not seem exactly great.


Why it is not "exactly great"?  To me, it seems to be the best solution.
I'd say we should be able to tolerate "slight" increase over IOV_MAX for
"internal purposes", so to say.  We can limit guest-supplied vector to
IOV_MAX, but internally guard against integer overflow only.


That’s a good point that may have been worth investigating.

I considered it not great because I assumed that that 
4c002cef0e9abe7135d7916c51abce47f7fc1ee2 was written with intent, i.e. 
that the IOV_MAX limit was put in because we just generally assume in 
the block layer that it isn’t exceeded.  It may have worked out fine 
before for one specific protocol driver (file-posix) most of the 
time[1], but I think it’s reasonable to assume that code in the block 
layer has generally been written under the assumption that vectors will 
not exceed the IOV_MAX limit (or otherwise we wouldn’t use that constant 
in the block layer).  So in addition to file-posix, we’d also need to 
inspect other code (like the blkio driver that will submit vectored 
requests to an external library) what the implications of exceeding that 
limit are in all places.


That is not to say that it might not have been the simpler solution to 
agree to exceed the limit internally, but it is to say that the full 
implications would need to be investigated first.  In contrast, the 
solution added here is more complicated in code, but is localized.


[1] It won’t be fine if all buffers are 4k in size and 4k-aligned, which 
I admit is unlikely for a request whose offset isn’t aligned, but which 
could happen with a partition that isn’t aligned to 4k.



I see two ways to fix this problem:
1. We split such long requests into two requests.
2. We join some elements of the vector into new buffers to make it
    shorter.


This seems to be over-complicated, both of them, no?


I would have preferred to have this discussion while the patch was still 
on-list for review (this specific version was for two months, counting 
from the first version was three).  Do you think it is so complicated 
and thus bug-prone that we must revert this series now and try the other 
route?


I can agree that perhaps the other route could have been simpler, but 
now we already have patches that are reviewed and in master, which solve 
the problem.  So I won’t spend more time on tackling this issue from 
another angle.  If you are happy to do so, patches are always welcome.


Hanna




Re: [PATCH v2 3/5] qemu/uri: Use QueryParams type definition

2023-06-06 Thread Peter Maydell
On Mon, 5 Jun 2023 at 18:57, Philippe Mathieu-Daudé  wrote:
>
> Follow QEMU CODING_STYLE, use the type definition.
>
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  include/qemu/uri.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/include/qemu/uri.h b/include/qemu/uri.h
> index b43f35a6a6..2875c51417 100644
> --- a/include/qemu/uri.h
> +++ b/include/qemu/uri.h
> @@ -96,7 +96,7 @@ typedef struct QueryParams {
>QueryParam *p;   /* array of parameters */
>  } QueryParams;
>
> -struct QueryParams *query_params_new (int init_alloc);
> +QueryParams *query_params_new (int init_alloc);
>  extern QueryParams *query_params_parse (const char *query);
>  extern void query_params_free (QueryParams *ps);

Also makes that prototype match the following two.

Reviewed-by: Peter Maydell 

thanks
-- PMM



Re: [PATCH v2 4/5] bulk: Do not declare function prototypes using 'extern' keyword

2023-06-06 Thread Peter Maydell
On Mon, 5 Jun 2023 at 18:58, Philippe Mathieu-Daudé  wrote:
>
> By default, C function prototypes declared in headers are visible,
> so there is no need to declare them as 'extern' functions.
> Remove this redundancy in a single bulk commit; do not modify:
>
>   - meson.build (used to check function availability at runtime)
>   - pc-bios/
>   - libdecnumber/
>   - tests/
>   - *.c
>
> Signed-off-by: Philippe Mathieu-Daudé 
> ---

Reviewed-by: Peter Maydell 

thanks
-- PMM



Re: [PATCH v3 1/1] hw/arm/sbsa-ref: use XHCI to replace EHCI

2023-06-06 Thread Marcin Juszkiewicz

W dniu 5.06.2023 o 11:55, Yuquan Wang pisze:

The current sbsa-ref cannot use EHCI controller which is only
able to do 32-bit DMA, since sbsa-ref doesn't have RAM below 4GB.
Hence, this uses XHCI to provide a usb controller with 64-bit
DMA capablity instead of EHCI.

Signed-off-by: Yuquan Wang


Reviewed-by: Marcin Juszkiewicz 

Without EDK2 changes Linux behaves same way (no USB found), with EDK2 
changes (EHCI->XHCI) Linux gets USB devices.




[PULL 09/42] hw: arm: Add bananapi M2-Ultra and allwinner-r40 support

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

Allwinner R40 (sun8i) SoC features a Quad-Core Cortex-A7 ARM CPU,
and a Mali400 MP2 GPU from ARM. It's also known as the Allwinner T3
for In-Car Entertainment usage, A40i and A40pro are variants that
differ in applicable temperatures range (industrial and military).

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 
Signed-off-by: Peter Maydell 
---
 include/hw/arm/allwinner-r40.h | 110 +
 hw/arm/allwinner-r40.c | 415 +
 hw/arm/bananapi_m2u.c  | 129 ++
 hw/arm/Kconfig |  10 +
 hw/arm/meson.build |   1 +
 5 files changed, 665 insertions(+)
 create mode 100644 include/hw/arm/allwinner-r40.h
 create mode 100644 hw/arm/allwinner-r40.c
 create mode 100644 hw/arm/bananapi_m2u.c

diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
new file mode 100644
index 000..348bf25d6be
--- /dev/null
+++ b/include/hw/arm/allwinner-r40.h
@@ -0,0 +1,110 @@
+/*
+ * Allwinner R40/A40i/T3 System on Chip emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#ifndef HW_ARM_ALLWINNER_R40_H
+#define HW_ARM_ALLWINNER_R40_H
+
+#include "qom/object.h"
+#include "hw/arm/boot.h"
+#include "hw/timer/allwinner-a10-pit.h"
+#include "hw/intc/arm_gic.h"
+#include "hw/sd/allwinner-sdhost.h"
+#include "target/arm/cpu.h"
+#include "sysemu/block-backend.h"
+
+enum {
+AW_R40_DEV_SRAM_A1,
+AW_R40_DEV_SRAM_A2,
+AW_R40_DEV_SRAM_A3,
+AW_R40_DEV_SRAM_A4,
+AW_R40_DEV_MMC0,
+AW_R40_DEV_MMC1,
+AW_R40_DEV_MMC2,
+AW_R40_DEV_MMC3,
+AW_R40_DEV_CCU,
+AW_R40_DEV_PIT,
+AW_R40_DEV_UART0,
+AW_R40_DEV_GIC_DIST,
+AW_R40_DEV_GIC_CPU,
+AW_R40_DEV_GIC_HYP,
+AW_R40_DEV_GIC_VCPU,
+AW_R40_DEV_SDRAM
+};
+
+#define AW_R40_NUM_CPUS  (4)
+
+/**
+ * Allwinner R40 object model
+ * @{
+ */
+
+/** Object type for the Allwinner R40 SoC */
+#define TYPE_AW_R40 "allwinner-r40"
+
+/** Convert input object to Allwinner R40 state object */
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40State, AW_R40)
+
+/** @} */
+
+/**
+ * Allwinner R40 object
+ *
+ * This struct contains the state of all the devices
+ * which are currently emulated by the R40 SoC code.
+ */
+#define AW_R40_NUM_MMCS 4
+
+struct AwR40State {
+/*< private >*/
+DeviceState parent_obj;
+/*< public >*/
+
+ARMCPU cpus[AW_R40_NUM_CPUS];
+const hwaddr *memmap;
+AwA10PITState timer;
+AwSdHostState mmc[AW_R40_NUM_MMCS];
+GICState gic;
+MemoryRegion sram_a1;
+MemoryRegion sram_a2;
+MemoryRegion sram_a3;
+MemoryRegion sram_a4;
+};
+
+/**
+ * Emulate Boot ROM firmware setup functionality.
+ *
+ * A real Allwinner R40 SoC contains a Boot ROM
+ * which is the first code that runs right after
+ * the SoC is powered on. The Boot ROM is responsible
+ * for loading user code (e.g. a bootloader) from any
+ * of the supported external devices and writing the
+ * downloaded code to internal SRAM. After loading the SoC
+ * begins executing the code written to SRAM.
+ *
+ * This function emulates the Boot ROM by copying 32 KiB
+ * of data from the given block device and writes it to
+ * the start of the first internal SRAM memory.
+ *
+ * @s: Allwinner R40 state object pointer
+ * @blk: Block backend device object pointer
+ * @unit: the mmc control's unit
+ */
+bool allwinner_r40_bootrom_setup(AwR40State *s, BlockBackend *blk, int unit);
+
+#endif /* HW_ARM_ALLWINNER_R40_H */
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
new file mode 100644
index 000..97f2aa92fdf
--- /dev/null
+++ b/hw/arm/allwinner-r40.c
@@ -0,0 +1,415 @@
+/*
+ * Allwinner R40/A40i/T3 System on Chip emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along wi

[PULL 14/42] hw/arm/allwinner-r40: add SDRAM controller device

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

Types of memory that the SDRAM controller supports are DDR2/DDR3
and capacities of up to 2GiB. This commit adds emulation support
of the Allwinner R40 SDRAM controller.

This driver only support 256M, 512M and 1024M memory now.

Signed-off-by: qianfan Zhao 
Signed-off-by: Peter Maydell 
---
 include/hw/arm/allwinner-r40.h|  13 +-
 include/hw/misc/allwinner-r40-dramc.h | 108 ++
 hw/arm/allwinner-r40.c|  21 +-
 hw/arm/bananapi_m2u.c |   7 +
 hw/misc/allwinner-r40-dramc.c | 513 ++
 hw/misc/meson.build   |   1 +
 hw/misc/trace-events  |  14 +
 7 files changed, 674 insertions(+), 3 deletions(-)
 create mode 100644 include/hw/misc/allwinner-r40-dramc.h
 create mode 100644 hw/misc/allwinner-r40-dramc.c

diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index 95366f4eeef..8243e8903b1 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -26,6 +26,7 @@
 #include "hw/intc/arm_gic.h"
 #include "hw/sd/allwinner-sdhost.h"
 #include "hw/misc/allwinner-r40-ccu.h"
+#include "hw/misc/allwinner-r40-dramc.h"
 #include "hw/i2c/allwinner-i2c.h"
 #include "target/arm/cpu.h"
 #include "sysemu/block-backend.h"
@@ -54,7 +55,10 @@ enum {
 AW_R40_DEV_GIC_CPU,
 AW_R40_DEV_GIC_HYP,
 AW_R40_DEV_GIC_VCPU,
-AW_R40_DEV_SDRAM
+AW_R40_DEV_SDRAM,
+AW_R40_DEV_DRAMCOM,
+AW_R40_DEV_DRAMCTL,
+AW_R40_DEV_DRAMPHY,
 };
 
 #define AW_R40_NUM_CPUS  (4)
@@ -86,11 +90,18 @@ struct AwR40State {
 DeviceState parent_obj;
 /*< public >*/
 
+/** Physical base address for start of RAM */
+hwaddr ram_addr;
+
+/** Total RAM size in megabytes */
+uint32_t ram_size;
+
 ARMCPU cpus[AW_R40_NUM_CPUS];
 const hwaddr *memmap;
 AwA10PITState timer;
 AwSdHostState mmc[AW_R40_NUM_MMCS];
 AwR40ClockCtlState ccu;
+AwR40DramCtlState dramc;
 AWI2CState i2c0;
 GICState gic;
 MemoryRegion sram_a1;
diff --git a/include/hw/misc/allwinner-r40-dramc.h 
b/include/hw/misc/allwinner-r40-dramc.h
new file mode 100644
index 000..6a1a3a78935
--- /dev/null
+++ b/include/hw/misc/allwinner-r40-dramc.h
@@ -0,0 +1,108 @@
+/*
+ * Allwinner R40 SDRAM Controller emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#ifndef HW_MISC_ALLWINNER_R40_DRAMC_H
+#define HW_MISC_ALLWINNER_R40_DRAMC_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "exec/hwaddr.h"
+
+/**
+ * Constants
+ * @{
+ */
+
+/** Highest register address used by DRAMCOM module */
+#define AW_R40_DRAMCOM_REGS_MAXADDR  (0x804)
+
+/** Total number of known DRAMCOM registers */
+#define AW_R40_DRAMCOM_REGS_NUM  (AW_R40_DRAMCOM_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** Highest register address used by DRAMCTL module */
+#define AW_R40_DRAMCTL_REGS_MAXADDR  (0x88c)
+
+/** Total number of known DRAMCTL registers */
+#define AW_R40_DRAMCTL_REGS_NUM  (AW_R40_DRAMCTL_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** Highest register address used by DRAMPHY module */
+#define AW_R40_DRAMPHY_REGS_MAXADDR  (0x4)
+
+/** Total number of known DRAMPHY registers */
+#define AW_R40_DRAMPHY_REGS_NUM  (AW_R40_DRAMPHY_REGS_MAXADDR / \
+ sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * Object model
+ * @{
+ */
+
+#define TYPE_AW_R40_DRAMC "allwinner-r40-dramc"
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40DramCtlState, AW_R40_DRAMC)
+
+/** @} */
+
+/**
+ * Allwinner R40 SDRAM Controller object instance state.
+ */
+struct AwR40DramCtlState {
+/*< private >*/
+SysBusDevice parent_obj;
+/*< public >*/
+
+/** Physical base address for start of RAM */
+hwaddr ram_addr;
+
+/** Total RAM size in megabytes */
+uint32_t ram_size;
+
+uint8_t set_row_bits;
+uint8_t set_bank_bits;
+uint8_t set_col_bits;
+
+/**
+ * @name Memory Regions
+ * @{
+ */
+MemoryRegion dramcom_iomem;/**< DRAMCOM module I/O registers */
+MemoryRegion dramctl_iomem;/**< DRAMCTL module I/O registers */
+MemoryRegion dramphy_iomem;/**< DRAMPHY module I/O registers */
+MemoryRegion dram_high;/**< The high 1G dram for dualrank detect */
+MemoryRegion detec

[PULL 25/42] target/arm: Use tcg_gen_qemu_st_i128 for STZG, STZ2G

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

This fixes a bug in that these two insns should have been using atomic
16-byte stores, since MTE is ARMv8.5 and LSE2 is mandatory from ARMv8.4.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-7-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 3674fc1bc16..35eac7729b0 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -4058,15 +4058,18 @@ static void disas_ldst_tag(DisasContext *s, uint32_t 
insn)
 
 if (is_zero) {
 TCGv_i64 clean_addr = clean_data_tbi(s, addr);
-TCGv_i64 tcg_zero = tcg_constant_i64(0);
+TCGv_i64 zero64 = tcg_constant_i64(0);
+TCGv_i128 zero128 = tcg_temp_new_i128();
 int mem_index = get_mem_index(s);
-int i, n = (1 + is_pair) << LOG2_TAG_GRANULE;
+MemOp mop = finalize_memop(s, MO_128 | MO_ALIGN);
 
-tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index,
-MO_UQ | MO_ALIGN_16);
-for (i = 8; i < n; i += 8) {
-tcg_gen_addi_i64(clean_addr, clean_addr, 8);
-tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, MO_UQ);
+tcg_gen_concat_i64_i128(zero128, zero64, zero64);
+
+/* This is 1 or 2 atomic 16-byte operations. */
+tcg_gen_qemu_st_i128(zero128, clean_addr, mem_index, mop);
+if (is_pair) {
+tcg_gen_addi_i64(clean_addr, clean_addr, 16);
+tcg_gen_qemu_st_i128(zero128, clean_addr, mem_index, mop);
 }
 }
 
-- 
2.34.1




[PULL 06/42] xlnx-versal: Connect Xilinx VERSAL CANFD controllers

2023-06-06 Thread Peter Maydell
From: Vikram Garhwal 

Connect CANFD0 and CANFD1 on the Versal-virt machine and update xlnx-versal-virt
document with CANFD command line examples.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Peter Maydell 
Reviewed-by: Francisco Iglesias 
Signed-off-by: Peter Maydell 
---
 docs/system/arm/xlnx-versal-virt.rst | 31 
 include/hw/arm/xlnx-versal.h | 12 +++
 hw/arm/xlnx-versal-virt.c| 53 
 hw/arm/xlnx-versal.c | 37 +++
 4 files changed, 133 insertions(+)

diff --git a/docs/system/arm/xlnx-versal-virt.rst 
b/docs/system/arm/xlnx-versal-virt.rst
index 92ad10d2da4..d2d1b266926 100644
--- a/docs/system/arm/xlnx-versal-virt.rst
+++ b/docs/system/arm/xlnx-versal-virt.rst
@@ -34,6 +34,7 @@ Implemented devices:
 - DDR memory
 - BBRAM (36 bytes of Battery-backed RAM)
 - eFUSE (3072 bytes of one-time field-programmable bit array)
+- 2 CANFDs
 
 QEMU does not yet model any other devices, including the PL and the AI Engine.
 
@@ -224,3 +225,33 @@ To use a different index value, N, from default of 1, add:
 
   Better yet, do not use actual product data when running guest image
   on this Xilinx Versal Virt board.
+
+Using CANFDs for Versal Virt
+
+Versal CANFD controller is developed based on SocketCAN and QEMU CAN bus
+implementation. Bus connection and socketCAN connection for each CAN module
+can be set through command lines.
+
+To connect both CANFD0 and CANFD1 on the same bus:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
+
+To connect CANFD0 and CANFD1 to separate buses:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
+-machine canbus0=canbus0 -machine canbus1=canbus1
+
+The SocketCAN interface can connect to a Physical or a Virtual CAN interfaces 
on
+the host machine. Please check this document to learn about CAN interface on
+Linux: docs/system/devices/can.rst
+
+To connect CANFD0 and CANFD1 to host machine's CAN interface can0:
+
+.. code-block:: bash
+
+-object can-bus,id=canbus -machine canbus0=canbus -machine canbus1=canbus
+-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
index b6786e9832d..39ee31185c3 100644
--- a/include/hw/arm/xlnx-versal.h
+++ b/include/hw/arm/xlnx-versal.h
@@ -31,6 +31,7 @@
 #include "hw/dma/xlnx_csu_dma.h"
 #include "hw/misc/xlnx-versal-crl.h"
 #include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
+#include "hw/net/xlnx-versal-canfd.h"
 
 #define TYPE_XLNX_VERSAL "xlnx-versal"
 OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
@@ -43,6 +44,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
 #define XLNX_VERSAL_NR_SDS 2
 #define XLNX_VERSAL_NR_XRAM4
 #define XLNX_VERSAL_NR_IRQS192
+#define XLNX_VERSAL_NR_CANFD   2
+#define XLNX_VERSAL_CANFD_REF_CLK (24 * 1000 * 1000)
 
 struct Versal {
 /*< private >*/
@@ -73,6 +76,8 @@ struct Versal {
 CadenceGEMState gem[XLNX_VERSAL_NR_GEMS];
 XlnxZDMA adma[XLNX_VERSAL_NR_ADMAS];
 VersalUsb2 usb;
+CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
+XlnxVersalCANFDState canfd[XLNX_VERSAL_NR_CANFD];
 } iou;
 
 /* Real-time Processing Unit.  */
@@ -133,6 +138,8 @@ struct Versal {
 #define VERSAL_CRL_IRQ 10
 #define VERSAL_UART0_IRQ_0 18
 #define VERSAL_UART1_IRQ_0 19
+#define VERSAL_CANFD0_IRQ_020
+#define VERSAL_CANFD1_IRQ_021
 #define VERSAL_USB0_IRQ_0  22
 #define VERSAL_GEM0_IRQ_0  56
 #define VERSAL_GEM0_WAKE_IRQ_0 57
@@ -163,6 +170,11 @@ struct Versal {
 #define MM_UART10xff01U
 #define MM_UART1_SIZE   0x1
 
+#define MM_CANFD0   0xff06U
+#define MM_CANFD0_SIZE  0x1
+#define MM_CANFD1   0xff07U
+#define MM_CANFD1_SIZE  0x1
+
 #define MM_GEM0 0xff0cU
 #define MM_GEM0_SIZE0x1
 #define MM_GEM1 0xff0dU
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 668a9d65a43..1ee2b8697fe 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -40,9 +40,11 @@ struct VersalVirt {
 uint32_t clk_25Mhz;
 uint32_t usb;
 uint32_t dwc;
+uint32_t canfd[2];
 } phandle;
 struct arm_boot_info binfo;
 
+CanBusState *canbus[XLNX_VERSAL_NR_CANFD];
 struct {
 bool secure;
 } cfg;
@@ -235,6 +237,38 @@ static void fdt_add_uart_nodes(VersalVirt *s)
 }
 }
 
+static void fdt_add_canfd_nodes(VersalVirt *s)
+{
+uint64_t addrs[] = { MM_CANFD1, MM_CANFD0 };
+uint32_t size[] = { MM_CANFD1_SIZE, MM_CANFD0_SIZE };
+unsigned int irqs[] = { VERSAL_CANFD1_IRQ_0, VERSAL_CANFD0_IRQ_0 };
+const char clocknames[] = "can_clk\0s_axi_aclk";
+int i;

[PULL 31/42] target/arm: Pass memop to gen_mte_check1*

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Pass the completed memop to gen_mte_check1_mmuidx.
For the moment, do nothing more than extract the size.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-13-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.h |  2 +-
 target/arm/tcg/translate-a64.c | 82 ++
 target/arm/tcg/translate-sve.c |  7 +--
 3 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/target/arm/tcg/translate-a64.h b/target/arm/tcg/translate-a64.h
index 0576c4ea120..cecf2bab8f6 100644
--- a/target/arm/tcg/translate-a64.h
+++ b/target/arm/tcg/translate-a64.h
@@ -49,7 +49,7 @@ static inline bool sme_smza_enabled_check(DisasContext *s)
 
 TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
 TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
-bool tag_checked, int log2_size);
+bool tag_checked, MemOp memop);
 TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
 bool tag_checked, int size);
 
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 3e93f6e848e..85d896e9752 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -253,7 +253,7 @@ static void gen_probe_access(DisasContext *s, TCGv_i64 ptr,
  */
 static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr,
   bool is_write, bool tag_checked,
-  int log2_size, bool is_unpriv,
+  MemOp memop, bool is_unpriv,
   int core_idx)
 {
 if (tag_checked && s->mte_active[is_unpriv]) {
@@ -264,7 +264,7 @@ static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, 
TCGv_i64 addr,
 desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
 desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
 desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
-desc = FIELD_DP32(desc, MTEDESC, SIZEM1, (1 << log2_size) - 1);
+desc = FIELD_DP32(desc, MTEDESC, SIZEM1, memop_size(memop) - 1);
 
 ret = tcg_temp_new_i64();
 gen_helper_mte_check(ret, cpu_env, tcg_constant_i32(desc), addr);
@@ -275,9 +275,9 @@ static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, 
TCGv_i64 addr,
 }
 
 TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
-bool tag_checked, int log2_size)
+bool tag_checked, MemOp memop)
 {
-return gen_mte_check1_mmuidx(s, addr, is_write, tag_checked, log2_size,
+return gen_mte_check1_mmuidx(s, addr, is_write, tag_checked, memop,
  false, get_mem_index(s));
 }
 
@@ -2369,19 +2369,31 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2, int rn,
int size, bool is_pair)
 {
 int idx = get_mem_index(s);
-MemOp memop;
 TCGv_i64 dirty_addr, clean_addr;
+MemOp memop;
+
+/*
+ * For pairs:
+ * if size == 2, the operation is single-copy atomic for the doubleword.
+ * if size == 3, the operation is single-copy atomic for *each* doubleword,
+ * not the entire quadword, however it must be quadword aligned.
+ */
+memop = size + is_pair;
+if (memop == MO_128) {
+memop = finalize_memop_atom(s, MO_128 | MO_ALIGN,
+MO_ATOM_IFALIGN_PAIR);
+} else {
+memop = finalize_memop(s, memop | MO_ALIGN);
+}
 
 s->is_ldex = true;
 dirty_addr = cpu_reg_sp(s, rn);
-clean_addr = gen_mte_check1(s, dirty_addr, false, rn != 31, size);
+clean_addr = gen_mte_check1(s, dirty_addr, false, rn != 31, memop);
 
 g_assert(size <= 3);
 if (is_pair) {
 g_assert(size >= 2);
 if (size == 2) {
-/* The pair must be single-copy atomic for the doubleword.  */
-memop = finalize_memop(s, MO_64 | MO_ALIGN);
 tcg_gen_qemu_ld_i64(cpu_exclusive_val, clean_addr, idx, memop);
 if (s->be_data == MO_LE) {
 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
@@ -2391,16 +2403,8 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2, int rn,
 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 0, 32);
 }
 } else {
-/*
- * The pair must be single-copy atomic for *each* doubleword, not
- * the entire quadword, however it must be quadword aligned.
- * Expose the complete load to tcg, for ease of tlb lookup,
- * but indicate that only 8-byte atomicity is required.
- */
 TCGv_i128 t16 = tcg_temp_new_i128();
 
-memop = finalize_memop_atom(s, MO_128 | MO_ALIGN_16,
-MO_ATOM_IFALIGN_PAIR);
 tcg_gen_q

[PULL 15/42] hw: sd: allwinner-sdhost: Add sun50i-a64 SoC support

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

A64's sd register was similar to H3, and it introduced a new register
named SAMP_DL_REG location at 0x144. The dma descriptor buffer size of
mmc2 is only 8K and the other mmc controllers has 64K.

Also fix allwinner-r40's mmc controller type.

Signed-off-by: qianfan Zhao 
Signed-off-by: Peter Maydell 
---
 include/hw/sd/allwinner-sdhost.h |  9 
 hw/arm/allwinner-r40.c   |  2 +-
 hw/sd/allwinner-sdhost.c | 72 ++--
 3 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/include/hw/sd/allwinner-sdhost.h b/include/hw/sd/allwinner-sdhost.h
index 30c1e604041..1b951177dda 100644
--- a/include/hw/sd/allwinner-sdhost.h
+++ b/include/hw/sd/allwinner-sdhost.h
@@ -38,6 +38,12 @@
 /** Allwinner sun5i family and newer (A13, H2+, H3, etc) */
 #define TYPE_AW_SDHOST_SUN5I TYPE_AW_SDHOST "-sun5i"
 
+/** Allwinner sun50i-a64 */
+#define TYPE_AW_SDHOST_SUN50I_A64 TYPE_AW_SDHOST "-sun50i-a64"
+
+/** Allwinner sun50i-a64 emmc */
+#define TYPE_AW_SDHOST_SUN50I_A64_EMMC  TYPE_AW_SDHOST "-sun50i-a64-emmc"
+
 /** @} */
 
 /**
@@ -110,6 +116,7 @@ struct AwSdHostState {
 uint32_t startbit_detect;   /**< eMMC DDR Start Bit Detection Control */
 uint32_t response_crc;  /**< Response CRC */
 uint32_t data_crc[8];   /**< Data CRC */
+uint32_t sample_delay;  /**< Sample delay control */
 uint32_t status_crc;/**< Status CRC */
 
 /** @} */
@@ -132,6 +139,8 @@ struct AwSdHostClass {
 size_t max_desc_size;
 bool   is_sun4i;
 
+/** does the IP block support autocalibration? */
+bool can_calibrate;
 };
 
 #endif /* HW_SD_ALLWINNER_SDHOST_H */
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index 0e4542d35f2..b148c564498 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -271,7 +271,7 @@ static void allwinner_r40_init(Object *obj)
 
 for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
 object_initialize_child(obj, mmc_names[i], &s->mmc[i],
-TYPE_AW_SDHOST_SUN5I);
+TYPE_AW_SDHOST_SUN50I_A64);
 }
 
 object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
index 92a0f42708d..286e0095098 100644
--- a/hw/sd/allwinner-sdhost.c
+++ b/hw/sd/allwinner-sdhost.c
@@ -77,6 +77,7 @@ enum {
 REG_SD_DATA1_CRC  = 0x12C, /* CRC Data 1 from card/eMMC */
 REG_SD_DATA0_CRC  = 0x130, /* CRC Data 0 from card/eMMC */
 REG_SD_CRC_STA= 0x134, /* CRC status from card/eMMC during write */
+REG_SD_SAMP_DL= 0x144, /* Sample Delay Control (sun50i-a64) */
 REG_SD_FIFO   = 0x200, /* Read/Write FIFO */
 };
 
@@ -158,6 +159,7 @@ enum {
 REG_SD_RES_CRC_RST  = 0x0,
 REG_SD_DATA_CRC_RST = 0x0,
 REG_SD_CRC_STA_RST  = 0x0,
+REG_SD_SAMPLE_DL_RST= 0x2000,
 REG_SD_FIFO_RST = 0x0,
 };
 
@@ -459,6 +461,7 @@ static uint64_t allwinner_sdhost_read(void *opaque, hwaddr 
offset,
 {
 AwSdHostState *s = AW_SDHOST(opaque);
 AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s);
+bool out_of_bounds = false;
 uint32_t res = 0;
 
 switch (offset) {
@@ -577,13 +580,24 @@ static uint64_t allwinner_sdhost_read(void *opaque, 
hwaddr offset,
 case REG_SD_FIFO:  /* Read/Write FIFO */
 res = allwinner_sdhost_fifo_read(s);
 break;
+case REG_SD_SAMP_DL: /* Sample Delay */
+if (sc->can_calibrate) {
+res = s->sample_delay;
+} else {
+out_of_bounds = true;
+}
+break;
 default:
-qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
-  HWADDR_PRIx"\n", __func__, offset);
+out_of_bounds = true;
 res = 0;
 break;
 }
 
+if (out_of_bounds) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
+  HWADDR_PRIx"\n", __func__, offset);
+}
+
 trace_allwinner_sdhost_read(offset, res, size);
 return res;
 }
@@ -602,6 +616,7 @@ static void allwinner_sdhost_write(void *opaque, hwaddr 
offset,
 {
 AwSdHostState *s = AW_SDHOST(opaque);
 AwSdHostClass *sc = AW_SDHOST_GET_CLASS(s);
+bool out_of_bounds = false;
 
 trace_allwinner_sdhost_write(offset, value, size);
 
@@ -725,10 +740,21 @@ static void allwinner_sdhost_write(void *opaque, hwaddr 
offset,
 case REG_SD_DATA0_CRC: /* CRC Data 0 from card/eMMC */
 case REG_SD_CRC_STA:   /* CRC status from card/eMMC in write operation */
 break;
+case REG_SD_SAMP_DL: /* Sample delay control */
+if (sc->can_calibrate) {
+s->sample_delay = value;
+} else {
+out_of_bounds = true;
+}
+break;
 default:
+out_of_bounds = true;
+break;
+}
+
+if (out_of_bounds) {
 qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %"
   HWADDR_PRIx"\n", __func__, 

[PULL 24/42] target/arm: Use tcg_gen_qemu_{st, ld}_i128 for do_fp_{st, ld}

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

While we don't require 16-byte atomicity here, using a single larger
operation simplifies the code.  Introduce finalize_memop_asimd for this.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-6-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate.h | 24 +++
 target/arm/tcg/translate-a64.c | 35 +++---
 2 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index c1e57a52ca2..3aa486a1ab6 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -609,6 +609,30 @@ static inline MemOp finalize_memop_pair(DisasContext *s, 
MemOp opc)
 return finalize_memop_atom(s, opc, atom);
 }
 
+/**
+ * finalize_memop_asimd:
+ * @s: DisasContext
+ * @opc: size+sign+align of the memory operation
+ *
+ * Like finalize_memop_atom, but with atomicity of AccessType_ASIMD.
+ */
+static inline MemOp finalize_memop_asimd(DisasContext *s, MemOp opc)
+{
+/*
+ * In the pseudocode for Mem[], with AccessType_ASIMD, size == 16,
+ * if IsAligned(8), the first case provides separate atomicity for
+ * the pair of 64-bit accesses.  If !IsAligned(8), the middle cases
+ * do not apply, and we're left with the final case of no atomicity.
+ * Thus MO_ATOM_IFALIGN_PAIR.
+ *
+ * For other sizes, normal LSE2 rules apply.
+ */
+if ((opc & MO_SIZE) == MO_128) {
+return finalize_memop_atom(s, opc, MO_ATOM_IFALIGN_PAIR);
+}
+return finalize_memop(s, opc);
+}
+
 /**
  * asimd_imm_const: Expand an encoded SIMD constant value
  *
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 1fff74c73a0..3674fc1bc16 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -911,26 +911,20 @@ static void do_fp_st(DisasContext *s, int srcidx, 
TCGv_i64 tcg_addr, int size)
 {
 /* This writes the bottom N bits of a 128 bit wide vector to memory */
 TCGv_i64 tmplo = tcg_temp_new_i64();
-MemOp mop;
+MemOp mop = finalize_memop_asimd(s, size);
 
 tcg_gen_ld_i64(tmplo, cpu_env, fp_reg_offset(s, srcidx, MO_64));
 
-if (size < 4) {
-mop = finalize_memop(s, size);
+if (size < MO_128) {
 tcg_gen_qemu_st_i64(tmplo, tcg_addr, get_mem_index(s), mop);
 } else {
-bool be = s->be_data == MO_BE;
-TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
 TCGv_i64 tmphi = tcg_temp_new_i64();
+TCGv_i128 t16 = tcg_temp_new_i128();
 
 tcg_gen_ld_i64(tmphi, cpu_env, fp_reg_hi_offset(s, srcidx));
+tcg_gen_concat_i64_i128(t16, tmplo, tmphi);
 
-mop = s->be_data | MO_UQ;
-tcg_gen_qemu_st_i64(be ? tmphi : tmplo, tcg_addr, get_mem_index(s),
-mop | (s->align_mem ? MO_ALIGN_16 : 0));
-tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
-tcg_gen_qemu_st_i64(be ? tmplo : tmphi, tcg_hiaddr,
-get_mem_index(s), mop);
+tcg_gen_qemu_st_i128(t16, tcg_addr, get_mem_index(s), mop);
 }
 }
 
@@ -942,24 +936,17 @@ static void do_fp_ld(DisasContext *s, int destidx, 
TCGv_i64 tcg_addr, int size)
 /* This always zero-extends and writes to a full 128 bit wide vector */
 TCGv_i64 tmplo = tcg_temp_new_i64();
 TCGv_i64 tmphi = NULL;
-MemOp mop;
+MemOp mop = finalize_memop_asimd(s, size);
 
-if (size < 4) {
-mop = finalize_memop(s, size);
+if (size < MO_128) {
 tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), mop);
 } else {
-bool be = s->be_data == MO_BE;
-TCGv_i64 tcg_hiaddr;
+TCGv_i128 t16 = tcg_temp_new_i128();
+
+tcg_gen_qemu_ld_i128(t16, tcg_addr, get_mem_index(s), mop);
 
 tmphi = tcg_temp_new_i64();
-tcg_hiaddr = tcg_temp_new_i64();
-
-mop = s->be_data | MO_UQ;
-tcg_gen_qemu_ld_i64(be ? tmphi : tmplo, tcg_addr, get_mem_index(s),
-mop | (s->align_mem ? MO_ALIGN_16 : 0));
-tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
-tcg_gen_qemu_ld_i64(be ? tmplo : tmphi, tcg_hiaddr,
-get_mem_index(s), mop);
+tcg_gen_extr_i128_i64(tmplo, tmphi, t16);
 }
 
 tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
-- 
2.34.1




[PULL 03/42] hvf: add breakpoint handlers

2023-06-06 Thread Peter Maydell
From: Francesco Cagnin 

Required for guest debugging. The code has been structured like the KVM
counterpart.

Signed-off-by: Francesco Cagnin 
Message-id: 20230601153107.81955-4-fcag...@quarkslab.com
Reviewed-by: Peter Maydell 
Signed-off-by: Peter Maydell 
---
 include/sysemu/hvf.h  |  22 
 include/sysemu/hvf_int.h  |   1 +
 accel/hvf/hvf-accel-ops.c | 109 ++
 accel/hvf/hvf-all.c   |  17 ++
 target/arm/hvf/hvf.c  |  63 ++
 target/i386/hvf/hvf.c |  24 +
 6 files changed, 236 insertions(+)

diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h
index bb70082e458..386020a29cc 100644
--- a/include/sysemu/hvf.h
+++ b/include/sysemu/hvf.h
@@ -17,6 +17,7 @@
 #include "qom/object.h"
 
 #ifdef NEED_CPU_H
+#include "cpu.h"
 
 #ifdef CONFIG_HVF
 uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
@@ -36,4 +37,25 @@ typedef struct HVFState HVFState;
 DECLARE_INSTANCE_CHECKER(HVFState, HVF_STATE,
  TYPE_HVF_ACCEL)
 
+#ifdef NEED_CPU_H
+struct hvf_sw_breakpoint {
+target_ulong pc;
+target_ulong saved_insn;
+int use_count;
+QTAILQ_ENTRY(hvf_sw_breakpoint) entry;
+};
+
+struct hvf_sw_breakpoint *hvf_find_sw_breakpoint(CPUState *cpu,
+ target_ulong pc);
+int hvf_sw_breakpoints_active(CPUState *cpu);
+
+int hvf_arch_insert_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp);
+int hvf_arch_remove_sw_breakpoint(CPUState *cpu, struct hvf_sw_breakpoint *bp);
+int hvf_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len,
+  int type);
+int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len,
+  int type);
+void hvf_arch_remove_all_hw_breakpoints(void);
+#endif /* NEED_CPU_H */
+
 #endif
diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
index 6545f7cd613..3592239fdcb 100644
--- a/include/sysemu/hvf_int.h
+++ b/include/sysemu/hvf_int.h
@@ -45,6 +45,7 @@ struct HVFState {
 
 hvf_vcpu_caps *hvf_caps;
 uint64_t vtimer_offset;
+QTAILQ_HEAD(, hvf_sw_breakpoint) hvf_sw_breakpoints;
 };
 extern HVFState *hvf_state;
 
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
index 24913ca9c49..92601b1369d 100644
--- a/accel/hvf/hvf-accel-ops.c
+++ b/accel/hvf/hvf-accel-ops.c
@@ -52,6 +52,7 @@
 #include "qemu/main-loop.h"
 #include "exec/address-spaces.h"
 #include "exec/exec-all.h"
+#include "exec/gdbstub.h"
 #include "sysemu/cpus.h"
 #include "sysemu/hvf.h"
 #include "sysemu/hvf_int.h"
@@ -334,6 +335,8 @@ static int hvf_accel_init(MachineState *ms)
 s->slots[x].slot_id = x;
 }
 
+QTAILQ_INIT(&s->hvf_sw_breakpoints);
+
 hvf_state = s;
 memory_listener_register(&hvf_memory_listener, &address_space_memory);
 
@@ -462,6 +465,108 @@ static void hvf_start_vcpu_thread(CPUState *cpu)
cpu, QEMU_THREAD_JOINABLE);
 }
 
+static int hvf_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr 
len)
+{
+struct hvf_sw_breakpoint *bp;
+int err;
+
+if (type == GDB_BREAKPOINT_SW) {
+bp = hvf_find_sw_breakpoint(cpu, addr);
+if (bp) {
+bp->use_count++;
+return 0;
+}
+
+bp = g_new(struct hvf_sw_breakpoint, 1);
+bp->pc = addr;
+bp->use_count = 1;
+err = hvf_arch_insert_sw_breakpoint(cpu, bp);
+if (err) {
+g_free(bp);
+return err;
+}
+
+QTAILQ_INSERT_HEAD(&hvf_state->hvf_sw_breakpoints, bp, entry);
+} else {
+err = hvf_arch_insert_hw_breakpoint(addr, len, type);
+if (err) {
+return err;
+}
+}
+
+CPU_FOREACH(cpu) {
+err = hvf_update_guest_debug(cpu);
+if (err) {
+return err;
+}
+}
+return 0;
+}
+
+static int hvf_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr 
len)
+{
+struct hvf_sw_breakpoint *bp;
+int err;
+
+if (type == GDB_BREAKPOINT_SW) {
+bp = hvf_find_sw_breakpoint(cpu, addr);
+if (!bp) {
+return -ENOENT;
+}
+
+if (bp->use_count > 1) {
+bp->use_count--;
+return 0;
+}
+
+err = hvf_arch_remove_sw_breakpoint(cpu, bp);
+if (err) {
+return err;
+}
+
+QTAILQ_REMOVE(&hvf_state->hvf_sw_breakpoints, bp, entry);
+g_free(bp);
+} else {
+err = hvf_arch_remove_hw_breakpoint(addr, len, type);
+if (err) {
+return err;
+}
+}
+
+CPU_FOREACH(cpu) {
+err = hvf_update_guest_debug(cpu);
+if (err) {
+return err;
+}
+}
+return 0;
+}
+
+static void hvf_remove_all_breakpoints(CPUState *cpu)
+{
+struct hvf_sw_breakpoint *bp, *next;
+CPUState *tmpcpu;
+
+QTAILQ_FOREACH_SAFE(bp, &hvf_state->hvf_sw_breakpoints, entry, next) {
+   

[PULL 17/42] hw: arm: allwinner-sramc: Add SRAM Controller support for R40

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

Only a few important registers are added, especially the SRAM_VER
register.

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 
Signed-off-by: Peter Maydell 
---
 include/hw/arm/allwinner-r40.h|   3 +
 include/hw/misc/allwinner-sramc.h |  69 +++
 hw/arm/allwinner-r40.c|   7 +-
 hw/misc/allwinner-sramc.c | 184 ++
 hw/arm/Kconfig|   1 +
 hw/misc/Kconfig   |   3 +
 hw/misc/meson.build   |   1 +
 hw/misc/trace-events  |   4 +
 8 files changed, 271 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/misc/allwinner-sramc.h
 create mode 100644 hw/misc/allwinner-sramc.c

diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index 5f2d08489eb..72710d3edce 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -27,6 +27,7 @@
 #include "hw/sd/allwinner-sdhost.h"
 #include "hw/misc/allwinner-r40-ccu.h"
 #include "hw/misc/allwinner-r40-dramc.h"
+#include "hw/misc/allwinner-sramc.h"
 #include "hw/i2c/allwinner-i2c.h"
 #include "hw/net/allwinner_emac.h"
 #include "hw/net/allwinner-sun8i-emac.h"
@@ -38,6 +39,7 @@ enum {
 AW_R40_DEV_SRAM_A2,
 AW_R40_DEV_SRAM_A3,
 AW_R40_DEV_SRAM_A4,
+AW_R40_DEV_SRAMC,
 AW_R40_DEV_EMAC,
 AW_R40_DEV_MMC0,
 AW_R40_DEV_MMC1,
@@ -102,6 +104,7 @@ struct AwR40State {
 
 ARMCPU cpus[AW_R40_NUM_CPUS];
 const hwaddr *memmap;
+AwSRAMCState sramc;
 AwA10PITState timer;
 AwSdHostState mmc[AW_R40_NUM_MMCS];
 AwR40ClockCtlState ccu;
diff --git a/include/hw/misc/allwinner-sramc.h 
b/include/hw/misc/allwinner-sramc.h
new file mode 100644
index 000..66b01b8d044
--- /dev/null
+++ b/include/hw/misc/allwinner-sramc.h
@@ -0,0 +1,69 @@
+/*
+ * Allwinner SRAM controller emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#ifndef HW_MISC_ALLWINNER_SRAMC_H
+#define HW_MISC_ALLWINNER_SRAMC_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+#include "qemu/uuid.h"
+
+/**
+ * Object model
+ * @{
+ */
+#define TYPE_AW_SRAMC   "allwinner-sramc"
+#define TYPE_AW_SRAMC_SUN8I_R40 TYPE_AW_SRAMC "-sun8i-r40"
+OBJECT_DECLARE_TYPE(AwSRAMCState, AwSRAMCClass, AW_SRAMC)
+
+/** @} */
+
+/**
+ * Allwinner SRAMC object instance state
+ */
+struct AwSRAMCState {
+/*< private >*/
+SysBusDevice parent_obj;
+/*< public >*/
+
+/** Maps I/O registers in physical memory */
+MemoryRegion iomem;
+
+/* registers */
+uint32_t sram_ctl1;
+uint32_t sram_ver;
+uint32_t sram_soft_entry_reg0;
+};
+
+/**
+ * Allwinner SRAM Controller class-level struct.
+ *
+ * This struct is filled by each sunxi device specific code
+ * such that the generic code can use this struct to support
+ * all devices.
+ */
+struct AwSRAMCClass {
+/*< private >*/
+SysBusDeviceClass parent_class;
+/*< public >*/
+
+uint32_t sram_version_code;
+};
+
+#endif /* HW_MISC_ALLWINNER_SRAMC_H */
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index c018ad231ad..7d29eb224f6 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -39,6 +39,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_SRAM_A2]= 0x4000,
 [AW_R40_DEV_SRAM_A3]= 0x8000,
 [AW_R40_DEV_SRAM_A4]= 0xb400,
+[AW_R40_DEV_SRAMC]  = 0x01c0,
 [AW_R40_DEV_EMAC]   = 0x01c0b000,
 [AW_R40_DEV_MMC0]   = 0x01c0f000,
 [AW_R40_DEV_MMC1]   = 0x01c1,
@@ -76,7 +77,6 @@ struct AwR40Unimplemented {
 static struct AwR40Unimplemented r40_unimplemented[] = {
 { "d-engine",   0x0100, 4 * MiB },
 { "d-inter",0x0140, 128 * KiB },
-{ "sram-c", 0x01c0, 4 * KiB },
 { "dma",0x01c02000, 4 * KiB },
 { "nfdc",   0x01c03000, 4 * KiB },
 { "ts", 0x01c04000, 4 * KiB },
@@ -288,6 +288,8 @@ static void allwinner_r40_init(Object *obj)
  "ram-addr");
 object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
   "ram-size");
+
+object_initialize_child(obj, "sramc", &s->sramc, TYPE_AW_SRAMC_SUN8I_R40);
 }
 
 static void allwinner_r40_realize(DeviceState *dev, Error **errp)
@@ -382,6 +384,9 @@ static void allwinner_r40_realize(DeviceState

[PULL 02/42] hvf: handle access for more registers

2023-06-06 Thread Peter Maydell
From: Francesco Cagnin 

Required for guest debugging.

Signed-off-by: Francesco Cagnin 
Message-id: 20230601153107.81955-3-fcag...@quarkslab.com
Reviewed-by: Peter Maydell 
Signed-off-by: Peter Maydell 
---
 target/arm/hvf/hvf.c | 213 +++
 1 file changed, 213 insertions(+)

diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index ad65603445e..e221e370553 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -107,6 +107,72 @@
 #define SYSREG_ICC_SGI1R_EL1 SYSREG(3, 0, 12, 11, 5)
 #define SYSREG_ICC_SRE_EL1   SYSREG(3, 0, 12, 12, 5)
 
+#define SYSREG_MDSCR_EL1  SYSREG(2, 0, 0, 2, 2)
+#define SYSREG_DBGBVR0_EL1SYSREG(2, 0, 0, 0, 4)
+#define SYSREG_DBGBCR0_EL1SYSREG(2, 0, 0, 0, 5)
+#define SYSREG_DBGWVR0_EL1SYSREG(2, 0, 0, 0, 6)
+#define SYSREG_DBGWCR0_EL1SYSREG(2, 0, 0, 0, 7)
+#define SYSREG_DBGBVR1_EL1SYSREG(2, 0, 0, 1, 4)
+#define SYSREG_DBGBCR1_EL1SYSREG(2, 0, 0, 1, 5)
+#define SYSREG_DBGWVR1_EL1SYSREG(2, 0, 0, 1, 6)
+#define SYSREG_DBGWCR1_EL1SYSREG(2, 0, 0, 1, 7)
+#define SYSREG_DBGBVR2_EL1SYSREG(2, 0, 0, 2, 4)
+#define SYSREG_DBGBCR2_EL1SYSREG(2, 0, 0, 2, 5)
+#define SYSREG_DBGWVR2_EL1SYSREG(2, 0, 0, 2, 6)
+#define SYSREG_DBGWCR2_EL1SYSREG(2, 0, 0, 2, 7)
+#define SYSREG_DBGBVR3_EL1SYSREG(2, 0, 0, 3, 4)
+#define SYSREG_DBGBCR3_EL1SYSREG(2, 0, 0, 3, 5)
+#define SYSREG_DBGWVR3_EL1SYSREG(2, 0, 0, 3, 6)
+#define SYSREG_DBGWCR3_EL1SYSREG(2, 0, 0, 3, 7)
+#define SYSREG_DBGBVR4_EL1SYSREG(2, 0, 0, 4, 4)
+#define SYSREG_DBGBCR4_EL1SYSREG(2, 0, 0, 4, 5)
+#define SYSREG_DBGWVR4_EL1SYSREG(2, 0, 0, 4, 6)
+#define SYSREG_DBGWCR4_EL1SYSREG(2, 0, 0, 4, 7)
+#define SYSREG_DBGBVR5_EL1SYSREG(2, 0, 0, 5, 4)
+#define SYSREG_DBGBCR5_EL1SYSREG(2, 0, 0, 5, 5)
+#define SYSREG_DBGWVR5_EL1SYSREG(2, 0, 0, 5, 6)
+#define SYSREG_DBGWCR5_EL1SYSREG(2, 0, 0, 5, 7)
+#define SYSREG_DBGBVR6_EL1SYSREG(2, 0, 0, 6, 4)
+#define SYSREG_DBGBCR6_EL1SYSREG(2, 0, 0, 6, 5)
+#define SYSREG_DBGWVR6_EL1SYSREG(2, 0, 0, 6, 6)
+#define SYSREG_DBGWCR6_EL1SYSREG(2, 0, 0, 6, 7)
+#define SYSREG_DBGBVR7_EL1SYSREG(2, 0, 0, 7, 4)
+#define SYSREG_DBGBCR7_EL1SYSREG(2, 0, 0, 7, 5)
+#define SYSREG_DBGWVR7_EL1SYSREG(2, 0, 0, 7, 6)
+#define SYSREG_DBGWCR7_EL1SYSREG(2, 0, 0, 7, 7)
+#define SYSREG_DBGBVR8_EL1SYSREG(2, 0, 0, 8, 4)
+#define SYSREG_DBGBCR8_EL1SYSREG(2, 0, 0, 8, 5)
+#define SYSREG_DBGWVR8_EL1SYSREG(2, 0, 0, 8, 6)
+#define SYSREG_DBGWCR8_EL1SYSREG(2, 0, 0, 8, 7)
+#define SYSREG_DBGBVR9_EL1SYSREG(2, 0, 0, 9, 4)
+#define SYSREG_DBGBCR9_EL1SYSREG(2, 0, 0, 9, 5)
+#define SYSREG_DBGWVR9_EL1SYSREG(2, 0, 0, 9, 6)
+#define SYSREG_DBGWCR9_EL1SYSREG(2, 0, 0, 9, 7)
+#define SYSREG_DBGBVR10_EL1   SYSREG(2, 0, 0, 10, 4)
+#define SYSREG_DBGBCR10_EL1   SYSREG(2, 0, 0, 10, 5)
+#define SYSREG_DBGWVR10_EL1   SYSREG(2, 0, 0, 10, 6)
+#define SYSREG_DBGWCR10_EL1   SYSREG(2, 0, 0, 10, 7)
+#define SYSREG_DBGBVR11_EL1   SYSREG(2, 0, 0, 11, 4)
+#define SYSREG_DBGBCR11_EL1   SYSREG(2, 0, 0, 11, 5)
+#define SYSREG_DBGWVR11_EL1   SYSREG(2, 0, 0, 11, 6)
+#define SYSREG_DBGWCR11_EL1   SYSREG(2, 0, 0, 11, 7)
+#define SYSREG_DBGBVR12_EL1   SYSREG(2, 0, 0, 12, 4)
+#define SYSREG_DBGBCR12_EL1   SYSREG(2, 0, 0, 12, 5)
+#define SYSREG_DBGWVR12_EL1   SYSREG(2, 0, 0, 12, 6)
+#define SYSREG_DBGWCR12_EL1   SYSREG(2, 0, 0, 12, 7)
+#define SYSREG_DBGBVR13_EL1   SYSREG(2, 0, 0, 13, 4)
+#define SYSREG_DBGBCR13_EL1   SYSREG(2, 0, 0, 13, 5)
+#define SYSREG_DBGWVR13_EL1   SYSREG(2, 0, 0, 13, 6)
+#define SYSREG_DBGWCR13_EL1   SYSREG(2, 0, 0, 13, 7)
+#define SYSREG_DBGBVR14_EL1   SYSREG(2, 0, 0, 14, 4)
+#define SYSREG_DBGBCR14_EL1   SYSREG(2, 0, 0, 14, 5)
+#define SYSREG_DBGWVR14_EL1   SYSREG(2, 0, 0, 14, 6)
+#define SYSREG_DBGWCR14_EL1   SYSREG(2, 0, 0, 14, 7)
+#define SYSREG_DBGBVR15_EL1   SYSREG(2, 0, 0, 15, 4)
+#define SYSREG_DBGBCR15_EL1   SYSREG(2, 0, 0, 15, 5)
+#define SYSREG_DBGWVR15_EL1   SYSREG(2, 0, 0, 15, 6)
+#define SYSREG_DBGWCR15_EL1   SYSREG(2, 0, 0, 15, 7)
+
 #define WFX_IS_WFE (1 << 0)
 
 #define TMR_CTL_ENABLE  (1 << 0)
@@ -933,6 +999,78 @@ static int hvf_sysreg_read(CPUState *cpu, uint32_t reg, 
uint32_t rt)
 hvf_raise_exception(cpu, EXCP_UDEF, syn_uncategorized());
 }
 break;
+case SYSREG_DBGBVR0_EL1:
+case SYSREG_DBGBVR1_EL1:
+case SYSREG_DBGBVR2_EL1:
+case SYSREG_DBGBVR3_EL1:
+case SYSREG_DBGBVR4_EL1:
+case SYSREG_DBGBVR5_EL1:
+case SYSREG_DBGBVR6_EL1:
+case SYSREG_DBGBVR7_EL1:
+case SYSREG_DBGBVR8_EL1:
+case SYSREG_DBGBVR9_EL1:
+case SYSREG_DBGBVR10_EL1:
+case SYSREG_DBGBVR11_EL1:
+case SYSREG_DBGBVR12_EL1:
+case SYSREG_DBGBVR13_EL1:
+case SYSREG_DBGBVR14_EL1:
+case SYSREG_DBGBVR15_EL1:
+val = env->cp15.dbgbvr[SYSREG_CRM(reg)];
+break;
+case SYSREG_DBGBCR0_EL1:
+case SYSREG_DBGBCR1_EL1:
+case SYSREG_DBGBCR2_EL1:
+case SYSREG_DBGBCR3_EL1

[PULL 29/42] target/arm: Hoist finalize_memop out of do_gpr_{ld, st}

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

We are going to need the complete memop beforehand,
so let's not compute it twice.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-11-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.c | 61 +++---
 1 file changed, 35 insertions(+), 26 deletions(-)

diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 88183f9dca1..d90e8661ca5 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -838,7 +838,6 @@ static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 
source,
  unsigned int iss_srt,
  bool iss_sf, bool iss_ar)
 {
-memop = finalize_memop(s, memop);
 tcg_gen_qemu_st_i64(source, tcg_addr, memidx, memop);
 
 if (iss_valid) {
@@ -873,7 +872,6 @@ static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 
dest, TCGv_i64 tcg_addr,
  bool iss_valid, unsigned int iss_srt,
  bool iss_sf, bool iss_ar)
 {
-memop = finalize_memop(s, memop);
 tcg_gen_qemu_ld_i64(dest, tcg_addr, memidx, memop);
 
 if (extend && (memop & MO_SIGN)) {
@@ -2625,6 +2623,7 @@ static void disas_ldst_excl(DisasContext *s, uint32_t 
insn)
 int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
 int size = extract32(insn, 30, 2);
 TCGv_i64 clean_addr;
+MemOp memop;
 
 switch (o2_L_o1_o0) {
 case 0x0: /* STXR */
@@ -2661,10 +2660,11 @@ static void disas_ldst_excl(DisasContext *s, uint32_t 
insn)
 gen_check_sp_alignment(s);
 }
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
+/* TODO: ARMv8.4-LSE SCTLR.nAA */
+memop = finalize_memop(s, size | MO_ALIGN);
 clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
 true, rn != 31, size);
-/* TODO: ARMv8.4-LSE SCTLR.nAA */
-do_gpr_st(s, cpu_reg(s, rt), clean_addr, size | MO_ALIGN, true, rt,
+do_gpr_st(s, cpu_reg(s, rt), clean_addr, memop, true, rt,
   disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
 return;
 
@@ -2679,10 +2679,11 @@ static void disas_ldst_excl(DisasContext *s, uint32_t 
insn)
 if (rn == 31) {
 gen_check_sp_alignment(s);
 }
+/* TODO: ARMv8.4-LSE SCTLR.nAA */
+memop = finalize_memop(s, size | MO_ALIGN);
 clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
 false, rn != 31, size);
-/* TODO: ARMv8.4-LSE SCTLR.nAA */
-do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size | MO_ALIGN, false, true,
+do_gpr_ld(s, cpu_reg(s, rt), clean_addr, memop, false, true,
   rt, disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
 return;
@@ -2790,9 +2791,9 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
 } else {
 /* Only unsigned 32bit loads target 32bit registers.  */
 bool iss_sf = opc != 0;
+MemOp memop = finalize_memop(s, size + is_signed * MO_SIGN);
 
-do_gpr_ld(s, tcg_rt, clean_addr, size + is_signed * MO_SIGN,
-  false, true, rt, iss_sf, false);
+do_gpr_ld(s, tcg_rt, clean_addr, memop, false, true, rt, iss_sf, 
false);
 }
 }
 
@@ -3046,7 +3047,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t 
insn,
 bool post_index;
 bool writeback;
 int memidx;
-
+MemOp memop;
 TCGv_i64 clean_addr, dirty_addr;
 
 if (is_vector) {
@@ -3073,7 +3074,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t 
insn,
 return;
 }
 is_store = (opc == 0);
-is_signed = extract32(opc, 1, 1);
+is_signed = !is_store && extract32(opc, 1, 1);
 is_extended = (size < 3) && extract32(opc, 0, 1);
 }
 
@@ -3107,6 +3108,8 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t 
insn,
 }
 
 memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
+memop = finalize_memop(s, size + is_signed * MO_SIGN);
+
 clean_addr = gen_mte_check1_mmuidx(s, dirty_addr, is_store,
writeback || rn != 31,
size, is_unpriv, memidx);
@@ -3122,10 +3125,10 @@ static void disas_ldst_reg_imm9(DisasContext *s, 
uint32_t insn,
 bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
 
 if (is_store) {
-do_gpr_st_memidx(s, tcg_rt, clean_addr, size, memidx,
+do_gpr_st_memidx(s, tcg_rt, clean_addr, memop, memidx,
  iss_valid, rt, iss_sf, false);
 } else {
-do_gpr_ld_memidx(s, tcg_rt, clean_addr, size + is_signed * MO_SIGN,
+do_gpr_ld_memidx(s, tcg_rt, clean_addr, memop,
  is_extended, memidx,
   

[PULL 00/42] target-arm queue

2023-06-06 Thread Peter Maydell
Hi; this pullreq includes FEAT_LSE2 support, the new
bpim2u board, and some other smaller patchsets.

thanks
-- PMM

The following changes since commit 369081c4558e7e940fa36ce59bf17b2e390f55d3:

  Merge tag 'pull-tcg-20230605' of https://gitlab.com/rth7680/qemu into staging 
(2023-06-05 13:16:56 -0700)

are available in the Git repository at:

  https://git.linaro.org/people/pmaydell/qemu-arm.git 
tags/pull-target-arm-20230606

for you to fetch changes up to f9ac778898cb28307e0f91421aba34d43c34b679:

  target/arm: trap DCC access in user mode emulation (2023-06-06 10:19:40 +0100)


target-arm queue:
 * Support gdbstub (guest debug) in HVF
 * xnlx-versal: Support CANFD controller
 * bpim2u: New board model: Banana Pi BPI-M2 Ultra
 * Emulate FEAT_LSE2
 * allow DC CVA[D]P in user mode emulation
 * trap DCC access in user mode emulation


Francesco Cagnin (4):
  arm: move KVM breakpoints helpers
  hvf: handle access for more registers
  hvf: add breakpoint handlers
  hvf: add guest debugging handlers for Apple Silicon hosts

Richard Henderson (20):
  target/arm: Add commentary for CPUARMState.exclusive_high
  target/arm: Add feature test for FEAT_LSE2
  target/arm: Introduce finalize_memop_{atom,pair}
  target/arm: Use tcg_gen_qemu_ld_i128 for LDXP
  target/arm: Use tcg_gen_qemu_{st, ld}_i128 for do_fp_{st, ld}
  target/arm: Use tcg_gen_qemu_st_i128 for STZG, STZ2G
  target/arm: Use tcg_gen_qemu_{ld, st}_i128 in gen_sve_{ld, st}r
  target/arm: Sink gen_mte_check1 into load/store_exclusive
  target/arm: Load/store integer pair with one tcg operation
  target/arm: Hoist finalize_memop out of do_gpr_{ld, st}
  target/arm: Hoist finalize_memop out of do_fp_{ld, st}
  target/arm: Pass memop to gen_mte_check1*
  target/arm: Pass single_memop to gen_mte_checkN
  target/arm: Check alignment in helper_mte_check
  target/arm: Add SCTLR.nAA to TBFLAG_A64
  target/arm: Relax ordered/atomic alignment checks for LSE2
  target/arm: Move mte check for store-exclusive
  tests/tcg/aarch64: Use stz2g in mte-7.c
  tests/tcg/multiarch: Adjust sigbus.c
  target/arm: Enable FEAT_LSE2 for -cpu max

Vikram Garhwal (4):
  hw/net/can: Introduce Xilinx Versal CANFD controller
  xlnx-versal: Connect Xilinx VERSAL CANFD controllers
  MAINTAINERS: Include canfd tests under Xilinx CAN
  tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

Zhuojia Shen (3):
  target/arm: allow DC CVA[D]P in user mode emulation
  tests/tcg/aarch64: add DC CVA[D]P tests
  target/arm: trap DCC access in user mode emulation

qianfan Zhao (11):
  hw: arm: Add bananapi M2-Ultra and allwinner-r40 support
  hw/arm/allwinner-r40: add Clock Control Unit
  hw: allwinner-r40: Complete uart devices
  hw: arm: allwinner-r40: Add i2c0 device
  hw/misc: Rename axp209 to axp22x and add support AXP221 PMU
  hw/arm/allwinner-r40: add SDRAM controller device
  hw: sd: allwinner-sdhost: Add sun50i-a64 SoC support
  hw: arm: allwinner-r40: Add emac and gmac support
  hw: arm: allwinner-sramc: Add SRAM Controller support for R40
  tests: avocado: boot_linux_console: Add test case for bpim2u
  docs: system: arm: Introduce bananapi_m2u

 MAINTAINERS   |2 +-
 docs/system/arm/bananapi_m2u.rst  |  139 +++
 docs/system/arm/emulation.rst |1 +
 docs/system/arm/xlnx-versal-virt.rst  |   31 +
 docs/system/target-arm.rst|1 +
 include/hw/arm/allwinner-r40.h|  143 +++
 include/hw/arm/xlnx-versal.h  |   12 +
 include/hw/misc/allwinner-r40-ccu.h   |   65 +
 include/hw/misc/allwinner-r40-dramc.h |  108 ++
 include/hw/misc/allwinner-sramc.h |   69 ++
 include/hw/net/xlnx-versal-canfd.h|   87 ++
 include/hw/sd/allwinner-sdhost.h  |9 +
 include/sysemu/hvf.h  |   37 +
 include/sysemu/hvf_int.h  |2 +
 target/arm/cpu.h  |   16 +-
 target/arm/hvf_arm.h  |7 +
 target/arm/internals.h|   53 +-
 target/arm/tcg/helper-a64.h   |3 +
 target/arm/tcg/translate-a64.h|4 +-
 target/arm/tcg/translate.h|   65 +-
 accel/hvf/hvf-accel-ops.c |  119 ++
 accel/hvf/hvf-all.c   |   23 +
 hw/arm/allwinner-r40.c|  526 
 hw/arm/bananapi_m2u.c |  145 +++
 hw/arm/xlnx-versal-virt.c |   53 +
 hw/arm/xlnx-versal.c  |   37 +
 hw/misc/allwinner-r40-ccu.c   |  209 
 hw/misc/allwinner-r40-dramc.c |  513 
 hw/misc/allwinner-sramc.c |  184 +++
 hw/misc/axp209.c  |  238 
 hw/misc/axp2xx.c  |  283 +
 hw/net/can/xlnx-versal-canfd.c

[PULL 30/42] target/arm: Hoist finalize_memop out of do_fp_{ld, st}

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

We are going to need the complete memop beforehand,
so let's not compute it twice.

Reviewed-by: Peter Maydell 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-12-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.c | 43 ++
 1 file changed, 23 insertions(+), 20 deletions(-)

diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index d90e8661ca5..3e93f6e848e 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -905,15 +905,14 @@ static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, 
TCGv_i64 tcg_addr,
 /*
  * Store from FP register to memory
  */
-static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
+static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, MemOp mop)
 {
 /* This writes the bottom N bits of a 128 bit wide vector to memory */
 TCGv_i64 tmplo = tcg_temp_new_i64();
-MemOp mop = finalize_memop_asimd(s, size);
 
 tcg_gen_ld_i64(tmplo, cpu_env, fp_reg_offset(s, srcidx, MO_64));
 
-if (size < MO_128) {
+if ((mop & MO_SIZE) < MO_128) {
 tcg_gen_qemu_st_i64(tmplo, tcg_addr, get_mem_index(s), mop);
 } else {
 TCGv_i64 tmphi = tcg_temp_new_i64();
@@ -929,14 +928,13 @@ static void do_fp_st(DisasContext *s, int srcidx, 
TCGv_i64 tcg_addr, int size)
 /*
  * Load from memory to FP register
  */
-static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
+static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, MemOp 
mop)
 {
 /* This always zero-extends and writes to a full 128 bit wide vector */
 TCGv_i64 tmplo = tcg_temp_new_i64();
 TCGv_i64 tmphi = NULL;
-MemOp mop = finalize_memop_asimd(s, size);
 
-if (size < MO_128) {
+if ((mop & MO_SIZE) < MO_128) {
 tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), mop);
 } else {
 TCGv_i128 t16 = tcg_temp_new_i128();
@@ -2763,6 +2761,7 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
 bool is_signed = false;
 int size = 2;
 TCGv_i64 tcg_rt, clean_addr;
+MemOp memop;
 
 if (is_vector) {
 if (opc == 3) {
@@ -2773,6 +2772,7 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
 if (!fp_access_check(s)) {
 return;
 }
+memop = finalize_memop_asimd(s, size);
 } else {
 if (opc == 3) {
 /* PRFM (literal) : prefetch */
@@ -2780,19 +2780,19 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
 }
 size = 2 + extract32(opc, 0, 1);
 is_signed = extract32(opc, 1, 1);
+memop = finalize_memop(s, size + is_signed * MO_SIGN);
 }
 
 tcg_rt = cpu_reg(s, rt);
 
 clean_addr = tcg_temp_new_i64();
 gen_pc_plus_diff(s, clean_addr, imm);
+
 if (is_vector) {
-do_fp_ld(s, rt, clean_addr, size);
+do_fp_ld(s, rt, clean_addr, memop);
 } else {
 /* Only unsigned 32bit loads target 32bit registers.  */
 bool iss_sf = opc != 0;
-MemOp memop = finalize_memop(s, size + is_signed * MO_SIGN);
-
 do_gpr_ld(s, tcg_rt, clean_addr, memop, false, true, rt, iss_sf, 
false);
 }
 }
@@ -2929,16 +2929,18 @@ static void disas_ldst_pair(DisasContext *s, uint32_t 
insn)
 (wback || rn != 31) && !set_tag, 2 << size);
 
 if (is_vector) {
+MemOp mop = finalize_memop_asimd(s, size);
+
 if (is_load) {
-do_fp_ld(s, rt, clean_addr, size);
+do_fp_ld(s, rt, clean_addr, mop);
 } else {
-do_fp_st(s, rt, clean_addr, size);
+do_fp_st(s, rt, clean_addr, mop);
 }
 tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
 if (is_load) {
-do_fp_ld(s, rt2, clean_addr, size);
+do_fp_ld(s, rt2, clean_addr, mop);
 } else {
-do_fp_st(s, rt2, clean_addr, size);
+do_fp_st(s, rt2, clean_addr, mop);
 }
 } else {
 TCGv_i64 tcg_rt = cpu_reg(s, rt);
@@ -3060,6 +3062,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t 
insn,
 if (!fp_access_check(s)) {
 return;
 }
+memop = finalize_memop_asimd(s, size);
 } else {
 if (size == 3 && opc == 2) {
 /* PRFM - prefetch */
@@ -3076,6 +3079,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t 
insn,
 is_store = (opc == 0);
 is_signed = !is_store && extract32(opc, 1, 1);
 is_extended = (size < 3) && extract32(opc, 0, 1);
+memop = finalize_memop(s, size + is_signed * MO_SIGN);
 }
 
 switch (idx) {
@@ -3108,7 +3112,6 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t 
insn,
 }
 
 memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
-memop = finalize_memop(s, size + 

[PULL 27/42] target/arm: Sink gen_mte_check1 into load/store_exclusive

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

No need to duplicate this check across multiple call sites.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-9-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.c | 44 --
 1 file changed, 21 insertions(+), 23 deletions(-)

diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 35eac7729b0..729947b11a4 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2369,11 +2369,16 @@ static void disas_b_exc_sys(DisasContext *s, uint32_t 
insn)
  * races in multi-threaded linux-user and when MTTCG softmmu is
  * enabled.
  */
-static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
-   TCGv_i64 addr, int size, bool is_pair)
+static void gen_load_exclusive(DisasContext *s, int rt, int rt2, int rn,
+   int size, bool is_pair)
 {
 int idx = get_mem_index(s);
 MemOp memop;
+TCGv_i64 dirty_addr, clean_addr;
+
+s->is_ldex = true;
+dirty_addr = cpu_reg_sp(s, rn);
+clean_addr = gen_mte_check1(s, dirty_addr, false, rn != 31, size);
 
 g_assert(size <= 3);
 if (is_pair) {
@@ -2381,7 +2386,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2,
 if (size == 2) {
 /* The pair must be single-copy atomic for the doubleword.  */
 memop = finalize_memop(s, MO_64 | MO_ALIGN);
-tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
+tcg_gen_qemu_ld_i64(cpu_exclusive_val, clean_addr, idx, memop);
 if (s->be_data == MO_LE) {
 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 32, 
32);
@@ -2400,7 +2405,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2,
 
 memop = finalize_memop_atom(s, MO_128 | MO_ALIGN_16,
 MO_ATOM_IFALIGN_PAIR);
-tcg_gen_qemu_ld_i128(t16, addr, idx, memop);
+tcg_gen_qemu_ld_i128(t16, clean_addr, idx, memop);
 
 if (s->be_data == MO_LE) {
 tcg_gen_extr_i128_i64(cpu_exclusive_val,
@@ -2414,14 +2419,14 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2,
 }
 } else {
 memop = finalize_memop(s, size | MO_ALIGN);
-tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
+tcg_gen_qemu_ld_i64(cpu_exclusive_val, clean_addr, idx, memop);
 tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
 }
-tcg_gen_mov_i64(cpu_exclusive_addr, addr);
+tcg_gen_mov_i64(cpu_exclusive_addr, clean_addr);
 }
 
 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
-TCGv_i64 addr, int size, int is_pair)
+int rn, int size, int is_pair)
 {
 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
  * && (!is_pair || env->exclusive_high == [addr + datasize])) {
@@ -2437,9 +2442,12 @@ static void gen_store_exclusive(DisasContext *s, int rd, 
int rt, int rt2,
  */
 TCGLabel *fail_label = gen_new_label();
 TCGLabel *done_label = gen_new_label();
-TCGv_i64 tmp;
+TCGv_i64 tmp, dirty_addr, clean_addr;
 
-tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
+dirty_addr = cpu_reg_sp(s, rn);
+clean_addr = gen_mte_check1(s, dirty_addr, true, rn != 31, size);
+
+tcg_gen_brcond_i64(TCG_COND_NE, clean_addr, cpu_exclusive_addr, 
fail_label);
 
 tmp = tcg_temp_new_i64();
 if (is_pair) {
@@ -2627,9 +2635,7 @@ static void disas_ldst_excl(DisasContext *s, uint32_t 
insn)
 if (is_lasr) {
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
 }
-clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
-true, rn != 31, size);
-gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, false);
+gen_store_exclusive(s, rs, rt, rt2, rn, size, false);
 return;
 
 case 0x4: /* LDXR */
@@ -2637,10 +2643,7 @@ static void disas_ldst_excl(DisasContext *s, uint32_t 
insn)
 if (rn == 31) {
 gen_check_sp_alignment(s);
 }
-clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
-false, rn != 31, size);
-s->is_ldex = true;
-gen_load_exclusive(s, rt, rt2, clean_addr, size, false);
+gen_load_exclusive(s, rt, rt2, rn, size, false);
 if (is_lasr) {
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
 }
@@ -2692,9 +2695,7 @@ static void disas_ldst_excl(DisasContext *s, uint32_t 
insn)
 if (is_lasr) {
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
 }
-clean_addr = gen_mte_check1(s, cpu_reg_sp(s, rn),
-  

[PULL 16/42] hw: arm: allwinner-r40: Add emac and gmac support

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

R40 has two ethernet controllers named as emac and gmac. The emac is
compatibled with A10, and the GMAC is compatibled with H3.

Signed-off-by: qianfan Zhao 
Signed-off-by: Peter Maydell 
---
 include/hw/arm/allwinner-r40.h |  6 
 hw/arm/allwinner-r40.c | 50 --
 hw/arm/bananapi_m2u.c  |  3 ++
 3 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index 8243e8903b1..5f2d08489eb 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -28,6 +28,8 @@
 #include "hw/misc/allwinner-r40-ccu.h"
 #include "hw/misc/allwinner-r40-dramc.h"
 #include "hw/i2c/allwinner-i2c.h"
+#include "hw/net/allwinner_emac.h"
+#include "hw/net/allwinner-sun8i-emac.h"
 #include "target/arm/cpu.h"
 #include "sysemu/block-backend.h"
 
@@ -36,6 +38,7 @@ enum {
 AW_R40_DEV_SRAM_A2,
 AW_R40_DEV_SRAM_A3,
 AW_R40_DEV_SRAM_A4,
+AW_R40_DEV_EMAC,
 AW_R40_DEV_MMC0,
 AW_R40_DEV_MMC1,
 AW_R40_DEV_MMC2,
@@ -51,6 +54,7 @@ enum {
 AW_R40_DEV_UART6,
 AW_R40_DEV_UART7,
 AW_R40_DEV_TWI0,
+AW_R40_DEV_GMAC,
 AW_R40_DEV_GIC_DIST,
 AW_R40_DEV_GIC_CPU,
 AW_R40_DEV_GIC_HYP,
@@ -103,6 +107,8 @@ struct AwR40State {
 AwR40ClockCtlState ccu;
 AwR40DramCtlState dramc;
 AWI2CState i2c0;
+AwEmacState emac;
+AwSun8iEmacState gmac;
 GICState gic;
 MemoryRegion sram_a1;
 MemoryRegion sram_a2;
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index b148c564498..c018ad231ad 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -39,6 +39,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_SRAM_A2]= 0x4000,
 [AW_R40_DEV_SRAM_A3]= 0x8000,
 [AW_R40_DEV_SRAM_A4]= 0xb400,
+[AW_R40_DEV_EMAC]   = 0x01c0b000,
 [AW_R40_DEV_MMC0]   = 0x01c0f000,
 [AW_R40_DEV_MMC1]   = 0x01c1,
 [AW_R40_DEV_MMC2]   = 0x01c11000,
@@ -54,6 +55,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_UART6]  = 0x01c29800,
 [AW_R40_DEV_UART7]  = 0x01c29c00,
 [AW_R40_DEV_TWI0]   = 0x01c2ac00,
+[AW_R40_DEV_GMAC]   = 0x01c5,
 [AW_R40_DEV_DRAMCOM]= 0x01c62000,
 [AW_R40_DEV_DRAMCTL]= 0x01c63000,
 [AW_R40_DEV_DRAMPHY]= 0x01c65000,
@@ -82,7 +84,6 @@ static struct AwR40Unimplemented r40_unimplemented[] = {
 { "spi1",   0x01c06000, 4 * KiB },
 { "cs0",0x01c09000, 4 * KiB },
 { "keymem", 0x01c0a000, 4 * KiB },
-{ "emac",   0x01c0b000, 4 * KiB },
 { "usb0-otg",   0x01c13000, 4 * KiB },
 { "usb0-host",  0x01c14000, 4 * KiB },
 { "crypto", 0x01c15000, 4 * KiB },
@@ -131,7 +132,6 @@ static struct AwR40Unimplemented r40_unimplemented[] = {
 { "tvd2",   0x01c33000, 4 * KiB },
 { "tvd3",   0x01c34000, 4 * KiB },
 { "gpu",0x01c4, 64 * KiB },
-{ "gmac",   0x01c5, 64 * KiB },
 { "hstmr",  0x01c6, 4 * KiB },
 { "tcon-top",   0x01c7, 4 * KiB },
 { "lcd0",   0x01c71000, 4 * KiB },
@@ -180,6 +180,8 @@ enum {
 AW_R40_GIC_SPI_MMC1  = 33,
 AW_R40_GIC_SPI_MMC2  = 34,
 AW_R40_GIC_SPI_MMC3  = 35,
+AW_R40_GIC_SPI_EMAC  = 55,
+AW_R40_GIC_SPI_GMAC  = 85,
 };
 
 /* Allwinner R40 general constants */
@@ -276,6 +278,11 @@ static void allwinner_r40_init(Object *obj)
 
 object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
 
+object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
+object_initialize_child(obj, "gmac", &s->gmac, TYPE_AW_SUN8I_EMAC);
+object_property_add_alias(obj, "gmac-phy-addr",
+  OBJECT(&s->gmac), "phy-addr");
+
 object_initialize_child(obj, "dramc", &s->dramc, TYPE_AW_R40_DRAMC);
 object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc),
  "ram-addr");
@@ -285,6 +292,7 @@ static void allwinner_r40_init(Object *obj)
 
 static void allwinner_r40_realize(DeviceState *dev, Error **errp)
 {
+const char *r40_nic_models[] = { "gmac", "emac", NULL };
 AwR40State *s = AW_R40(dev);
 unsigned i;
 
@@ -442,6 +450,44 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 2,
 s->memmap[AW_R40_DEV_DRAMPHY]);
 
+/* nic support gmac and emac */
+for (int i = 0; i < ARRAY_SIZE(r40_nic_models) - 1; i++) {
+NICInfo *nic = &nd_table[i];
+
+if (!nic->used) {
+continue;
+}
+if (qemu_show_nic_models(nic->model, r40_nic_models)) {
+exit(0);
+}
+
+switch (qemu_find_nic_model(nic, r40_nic_models, r40_nic_models[0])) {
+case 0: /* gmac */
+qdev_set_nic_properties(DEVICE(&s->gmac), nic);
+break;
+case 1: /* emac */
+qdev_set_nic_properties(DEVICE(&

[PULL 11/42] hw: allwinner-r40: Complete uart devices

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

R40 has eight UARTs, support both 16450 and 16550 compatible modes.

Signed-off-by: qianfan Zhao 
Signed-off-by: Peter Maydell 
---
 include/hw/arm/allwinner-r40.h |  8 
 hw/arm/allwinner-r40.c | 34 +++---
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index 3be9dc962be..959b5dc4e04 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -41,6 +41,13 @@ enum {
 AW_R40_DEV_CCU,
 AW_R40_DEV_PIT,
 AW_R40_DEV_UART0,
+AW_R40_DEV_UART1,
+AW_R40_DEV_UART2,
+AW_R40_DEV_UART3,
+AW_R40_DEV_UART4,
+AW_R40_DEV_UART5,
+AW_R40_DEV_UART6,
+AW_R40_DEV_UART7,
 AW_R40_DEV_GIC_DIST,
 AW_R40_DEV_GIC_CPU,
 AW_R40_DEV_GIC_HYP,
@@ -70,6 +77,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(AwR40State, AW_R40)
  * which are currently emulated by the R40 SoC code.
  */
 #define AW_R40_NUM_MMCS 4
+#define AW_R40_NUM_UARTS8
 
 struct AwR40State {
 /*< private >*/
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index 72973f69ff0..537a90b23d8 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -45,6 +45,13 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_CCU]= 0x01c2,
 [AW_R40_DEV_PIT]= 0x01c20c00,
 [AW_R40_DEV_UART0]  = 0x01c28000,
+[AW_R40_DEV_UART1]  = 0x01c28400,
+[AW_R40_DEV_UART2]  = 0x01c28800,
+[AW_R40_DEV_UART3]  = 0x01c28c00,
+[AW_R40_DEV_UART4]  = 0x01c29000,
+[AW_R40_DEV_UART5]  = 0x01c29400,
+[AW_R40_DEV_UART6]  = 0x01c29800,
+[AW_R40_DEV_UART7]  = 0x01c29c00,
 [AW_R40_DEV_GIC_DIST]   = 0x01c81000,
 [AW_R40_DEV_GIC_CPU]= 0x01c82000,
 [AW_R40_DEV_GIC_HYP]= 0x01c84000,
@@ -157,6 +164,13 @@ enum {
 /* Shared Processor Interrupts */
 enum {
 AW_R40_GIC_SPI_UART0 =  1,
+AW_R40_GIC_SPI_UART1 =  2,
+AW_R40_GIC_SPI_UART2 =  3,
+AW_R40_GIC_SPI_UART3 =  4,
+AW_R40_GIC_SPI_UART4 = 17,
+AW_R40_GIC_SPI_UART5 = 18,
+AW_R40_GIC_SPI_UART6 = 19,
+AW_R40_GIC_SPI_UART7 = 20,
 AW_R40_GIC_SPI_TIMER0= 22,
 AW_R40_GIC_SPI_TIMER1= 23,
 AW_R40_GIC_SPI_MMC0  = 32,
@@ -384,9 +398,23 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 }
 
 /* UART0. For future clocktree API: All UARTS are connected to APB2_CLK. */
-serial_mm_init(get_system_memory(), s->memmap[AW_R40_DEV_UART0], 2,
-   qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_UART0),
-   115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
+for (int i = 0; i < AW_R40_NUM_UARTS; i++) {
+static const int uart_irqs[AW_R40_NUM_UARTS] = {
+AW_R40_GIC_SPI_UART0,
+AW_R40_GIC_SPI_UART1,
+AW_R40_GIC_SPI_UART2,
+AW_R40_GIC_SPI_UART3,
+AW_R40_GIC_SPI_UART4,
+AW_R40_GIC_SPI_UART5,
+AW_R40_GIC_SPI_UART6,
+AW_R40_GIC_SPI_UART7,
+};
+const hwaddr addr = s->memmap[AW_R40_DEV_UART0 + i];
+
+serial_mm_init(get_system_memory(), addr, 2,
+   qdev_get_gpio_in(DEVICE(&s->gic), uart_irqs[i]),
+   115200, serial_hd(i), DEVICE_NATIVE_ENDIAN);
+}
 
 /* Unimplemented devices */
 for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
-- 
2.34.1




[PULL 42/42] target/arm: trap DCC access in user mode emulation

2023-06-06 Thread Peter Maydell
From: Zhuojia Shen 

Accessing EL0-accessible Debug Communication Channel (DCC) registers in
user mode emulation is currently enabled.  However, it does not match
Linux behavior as Linux sets MDSCR_EL1.TDCC on startup to disable EL0
access to DCC (see __cpu_setup() in arch/arm64/mm/proc.S).

This patch fixes access_tdcc() to check MDSCR_EL1.TDCC for EL0 and sets
MDSCR_EL1.TDCC for user mode emulation to match Linux.

Signed-off-by: Zhuojia Shen 
Reviewed-by: Richard Henderson 
Message-id: 
ds7pr12mb630905198dd8e69f6817544cac...@ds7pr12mb6309.namprd12.prod.outlook.com
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.c  | 2 ++
 target/arm/debug_helper.c | 5 +
 2 files changed, 7 insertions(+)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5182ed0c911..4d5bb57f079 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -289,6 +289,8 @@ static void arm_cpu_reset_hold(Object *obj)
  * This is not yet exposed from the Linux kernel in any way.
  */
 env->cp15.sctlr_el[1] |= SCTLR_TSCXT;
+/* Disable access to Debug Communication Channel (DCC). */
+env->cp15.mdscr_el1 |= 1 << 12;
 #else
 /* Reset into the highest available EL */
 if (arm_feature(env, ARM_FEATURE_EL3)) {
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
index d41cc643b1b..8362462a07e 100644
--- a/target/arm/debug_helper.c
+++ b/target/arm/debug_helper.c
@@ -842,12 +842,14 @@ static CPAccessResult access_tda(CPUARMState *env, const 
ARMCPRegInfo *ri,
  * is implemented then these are controlled by MDCR_EL2.TDCC for
  * EL2 and MDCR_EL3.TDCC for EL3. They are also controlled by
  * the general debug access trap bits MDCR_EL2.TDA and MDCR_EL3.TDA.
+ * For EL0, they are also controlled by MDSCR_EL1.TDCC.
  */
 static CPAccessResult access_tdcc(CPUARMState *env, const ARMCPRegInfo *ri,
   bool isread)
 {
 int el = arm_current_el(env);
 uint64_t mdcr_el2 = arm_mdcr_el2_eff(env);
+bool mdscr_el1_tdcc = extract32(env->cp15.mdscr_el1, 12, 1);
 bool mdcr_el2_tda = (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) ||
 (arm_hcr_el2_eff(env) & HCR_TGE);
 bool mdcr_el2_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&
@@ -855,6 +857,9 @@ static CPAccessResult access_tdcc(CPUARMState *env, const 
ARMCPRegInfo *ri,
 bool mdcr_el3_tdcc = cpu_isar_feature(aa64_fgt, env_archcpu(env)) &&
   (env->cp15.mdcr_el3 & MDCR_TDCC);
 
+if (el < 1 && mdscr_el1_tdcc) {
+return CP_ACCESS_TRAP;
+}
 if (el < 2 && (mdcr_el2_tda || mdcr_el2_tdcc)) {
 return CP_ACCESS_TRAP_EL2;
 }
-- 
2.34.1




[PULL 41/42] tests/tcg/aarch64: add DC CVA[D]P tests

2023-06-06 Thread Peter Maydell
From: Zhuojia Shen 

Test execution of DC CVAP and DC CVADP instructions under user mode
emulation.

Signed-off-by: Zhuojia Shen 
Reviewed-by: Peter Maydell 
Reviewed-by: Richard Henderson 
Signed-off-by: Peter Maydell 
---
 tests/tcg/aarch64/dcpodp.c| 63 +++
 tests/tcg/aarch64/dcpop.c | 63 +++
 tests/tcg/aarch64/Makefile.target | 11 ++
 3 files changed, 137 insertions(+)
 create mode 100644 tests/tcg/aarch64/dcpodp.c
 create mode 100644 tests/tcg/aarch64/dcpop.c

diff --git a/tests/tcg/aarch64/dcpodp.c b/tests/tcg/aarch64/dcpodp.c
new file mode 100644
index 000..2cf7df2e073
--- /dev/null
+++ b/tests/tcg/aarch64/dcpodp.c
@@ -0,0 +1,63 @@
+/*
+ * Test execution of DC CVADP instruction.
+ *
+ * Copyright (c) 2023 Zhuojia Shen 
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef HWCAP2_DCPODP
+#define HWCAP2_DCPODP (1 << 0)
+#endif
+
+bool should_fail = false;
+
+static void signal_handler(int sig, siginfo_t *si, void *data)
+{
+ucontext_t *uc = (ucontext_t *)data;
+
+if (should_fail) {
+uc->uc_mcontext.pc += 4;
+} else {
+exit(EXIT_FAILURE);
+}
+}
+
+static int do_dc_cvadp(void)
+{
+struct sigaction sa = {
+.sa_flags = SA_SIGINFO,
+.sa_sigaction = signal_handler,
+};
+
+sigemptyset(&sa.sa_mask);
+if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+perror("sigaction");
+return EXIT_FAILURE;
+}
+
+asm volatile("dc cvadp, %0\n\t" :: "r"(&sa));
+
+should_fail = true;
+asm volatile("dc cvadp, %0\n\t" :: "r"(NULL));
+should_fail = false;
+
+return EXIT_SUCCESS;
+}
+
+int main(void)
+{
+if (getauxval(AT_HWCAP2) & HWCAP2_DCPODP) {
+return do_dc_cvadp();
+} else {
+printf("SKIP: no HWCAP2_DCPODP on this system\n");
+return EXIT_SUCCESS;
+}
+}
diff --git a/tests/tcg/aarch64/dcpop.c b/tests/tcg/aarch64/dcpop.c
new file mode 100644
index 000..a332a804a41
--- /dev/null
+++ b/tests/tcg/aarch64/dcpop.c
@@ -0,0 +1,63 @@
+/*
+ * Test execution of DC CVAP instruction.
+ *
+ * Copyright (c) 2023 Zhuojia Shen 
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef HWCAP_DCPOP
+#define HWCAP_DCPOP (1 << 16)
+#endif
+
+bool should_fail = false;
+
+static void signal_handler(int sig, siginfo_t *si, void *data)
+{
+ucontext_t *uc = (ucontext_t *)data;
+
+if (should_fail) {
+uc->uc_mcontext.pc += 4;
+} else {
+exit(EXIT_FAILURE);
+}
+}
+
+static int do_dc_cvap(void)
+{
+struct sigaction sa = {
+.sa_flags = SA_SIGINFO,
+.sa_sigaction = signal_handler,
+};
+
+sigemptyset(&sa.sa_mask);
+if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+perror("sigaction");
+return EXIT_FAILURE;
+}
+
+asm volatile("dc cvap, %0\n\t" :: "r"(&sa));
+
+should_fail = true;
+asm volatile("dc cvap, %0\n\t" :: "r"(NULL));
+should_fail = false;
+
+return EXIT_SUCCESS;
+}
+
+int main(void)
+{
+if (getauxval(AT_HWCAP) & HWCAP_DCPOP) {
+return do_dc_cvap();
+} else {
+printf("SKIP: no HWCAP_DCPOP on this system\n");
+return EXIT_SUCCESS;
+}
+}
diff --git a/tests/tcg/aarch64/Makefile.target 
b/tests/tcg/aarch64/Makefile.target
index 03157954871..3430fd3cd80 100644
--- a/tests/tcg/aarch64/Makefile.target
+++ b/tests/tcg/aarch64/Makefile.target
@@ -21,12 +21,23 @@ config-cc.mak: Makefile
$(quiet-@)( \
$(call cc-option,-march=armv8.1-a+sve,  CROSS_CC_HAS_SVE); \
$(call cc-option,-march=armv8.1-a+sve2, CROSS_CC_HAS_SVE2); 
\
+   $(call cc-option,-march=armv8.2-a,  
CROSS_CC_HAS_ARMV8_2); \
$(call cc-option,-march=armv8.3-a,  
CROSS_CC_HAS_ARMV8_3); \
+   $(call cc-option,-march=armv8.5-a,  
CROSS_CC_HAS_ARMV8_5); \
$(call cc-option,-mbranch-protection=standard,  
CROSS_CC_HAS_ARMV8_BTI); \
$(call cc-option,-march=armv8.5-a+memtag,   
CROSS_CC_HAS_ARMV8_MTE); \
$(call cc-option,-march=armv9-a+sme,
CROSS_CC_HAS_ARMV9_SME)) 3> config-cc.mak
 -include config-cc.mak
 
+ifneq ($(CROSS_CC_HAS_ARMV8_2),)
+AARCH64_TESTS += dcpop
+dcpop: CFLAGS += -march=armv8.2-a
+endif
+ifneq ($(CROSS_CC_HAS_ARMV8_5),)
+AARCH64_TESTS += dcpodp
+dcpodp: CFLAGS += -march=armv8.5-a
+endif
+
 # Pauth Tests
 ifneq ($(CROSS_CC_HAS_ARMV8_3),)
 AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5
-- 
2.34.1




[PULL 23/42] target/arm: Use tcg_gen_qemu_ld_i128 for LDXP

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

While we don't require 16-byte atomicity here, using a single larger
load simplifies the code, and makes it a closer match to STXP.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-5-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.c | 31 ---
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 1d34c5a7031..1fff74c73a0 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2386,14 +2386,14 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2,
TCGv_i64 addr, int size, bool is_pair)
 {
 int idx = get_mem_index(s);
-MemOp memop = s->be_data;
+MemOp memop;
 
 g_assert(size <= 3);
 if (is_pair) {
 g_assert(size >= 2);
 if (size == 2) {
 /* The pair must be single-copy atomic for the doubleword.  */
-memop |= MO_64 | MO_ALIGN;
+memop = finalize_memop(s, MO_64 | MO_ALIGN);
 tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
 if (s->be_data == MO_LE) {
 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
@@ -2403,21 +2403,30 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2,
 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 0, 32);
 }
 } else {
-/* The pair must be single-copy atomic for *each* doubleword, not
-   the entire quadword, however it must be quadword aligned.  */
-memop |= MO_64;
-tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx,
-memop | MO_ALIGN_16);
+/*
+ * The pair must be single-copy atomic for *each* doubleword, not
+ * the entire quadword, however it must be quadword aligned.
+ * Expose the complete load to tcg, for ease of tlb lookup,
+ * but indicate that only 8-byte atomicity is required.
+ */
+TCGv_i128 t16 = tcg_temp_new_i128();
 
-TCGv_i64 addr2 = tcg_temp_new_i64();
-tcg_gen_addi_i64(addr2, addr, 8);
-tcg_gen_qemu_ld_i64(cpu_exclusive_high, addr2, idx, memop);
+memop = finalize_memop_atom(s, MO_128 | MO_ALIGN_16,
+MO_ATOM_IFALIGN_PAIR);
+tcg_gen_qemu_ld_i128(t16, addr, idx, memop);
 
+if (s->be_data == MO_LE) {
+tcg_gen_extr_i128_i64(cpu_exclusive_val,
+  cpu_exclusive_high, t16);
+} else {
+tcg_gen_extr_i128_i64(cpu_exclusive_high,
+  cpu_exclusive_val, t16);
+}
 tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
 tcg_gen_mov_i64(cpu_reg(s, rt2), cpu_exclusive_high);
 }
 } else {
-memop |= size | MO_ALIGN;
+memop = finalize_memop(s, size | MO_ALIGN);
 tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
 tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
 }
-- 
2.34.1




[PULL 13/42] hw/misc: Rename axp209 to axp22x and add support AXP221 PMU

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

This patch adds minimal support for AXP-221 PMU and connect it to
bananapi M2U board.

Signed-off-by: qianfan Zhao 
Signed-off-by: Peter Maydell 
---
 hw/arm/bananapi_m2u.c |   6 +
 hw/misc/axp209.c  | 238 ---
 hw/misc/axp2xx.c  | 283 ++
 hw/arm/Kconfig|   3 +-
 hw/misc/Kconfig   |   2 +-
 hw/misc/meson.build   |   2 +-
 hw/misc/trace-events  |   8 +-
 7 files changed, 297 insertions(+), 245 deletions(-)
 delete mode 100644 hw/misc/axp209.c
 create mode 100644 hw/misc/axp2xx.c

diff --git a/hw/arm/bananapi_m2u.c b/hw/arm/bananapi_m2u.c
index 1d49a006b53..9c5360a41bd 100644
--- a/hw/arm/bananapi_m2u.c
+++ b/hw/arm/bananapi_m2u.c
@@ -23,6 +23,7 @@
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "hw/boards.h"
+#include "hw/i2c/i2c.h"
 #include "hw/qdev-properties.h"
 #include "hw/arm/allwinner-r40.h"
 
@@ -61,6 +62,7 @@ static void bpim2u_init(MachineState *machine)
 {
 bool bootroom_loaded = false;
 AwR40State *r40;
+I2CBus *i2c;
 
 /* BIOS is not supported by this board */
 if (machine->firmware) {
@@ -104,6 +106,10 @@ static void bpim2u_init(MachineState *machine)
 }
 }
 
+/* Connect AXP221 */
+i2c = I2C_BUS(qdev_get_child_bus(DEVICE(&r40->i2c0), "i2c"));
+i2c_slave_create_simple(i2c, "axp221_pmu", 0x34);
+
 /* SDRAM */
 memory_region_add_subregion(get_system_memory(),
 r40->memmap[AW_R40_DEV_SDRAM], machine->ram);
diff --git a/hw/misc/axp209.c b/hw/misc/axp209.c
deleted file mode 100644
index 2908ed99a6f..000
--- a/hw/misc/axp209.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * AXP-209 PMU Emulation
- *
- * Copyright (C) 2022 Strahinja Jankovic 
- *
- * 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.
- *
- * SPDX-License-Identifier: MIT
- */
-
-#include "qemu/osdep.h"
-#include "qemu/log.h"
-#include "trace.h"
-#include "hw/i2c/i2c.h"
-#include "migration/vmstate.h"
-
-#define TYPE_AXP209_PMU "axp209_pmu"
-
-#define AXP209(obj) \
-OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP209_PMU)
-
-/* registers */
-enum {
-REG_POWER_STATUS = 0x0u,
-REG_OPERATING_MODE,
-REG_OTG_VBUS_STATUS,
-REG_CHIP_VERSION,
-REG_DATA_CACHE_0,
-REG_DATA_CACHE_1,
-REG_DATA_CACHE_2,
-REG_DATA_CACHE_3,
-REG_DATA_CACHE_4,
-REG_DATA_CACHE_5,
-REG_DATA_CACHE_6,
-REG_DATA_CACHE_7,
-REG_DATA_CACHE_8,
-REG_DATA_CACHE_9,
-REG_DATA_CACHE_A,
-REG_DATA_CACHE_B,
-REG_POWER_OUTPUT_CTRL = 0x12u,
-REG_DC_DC2_OUT_V_CTRL = 0x23u,
-REG_DC_DC2_DVS_CTRL = 0x25u,
-REG_DC_DC3_OUT_V_CTRL = 0x27u,
-REG_LDO2_4_OUT_V_CTRL,
-REG_LDO3_OUT_V_CTRL,
-REG_VBUS_CH_MGMT = 0x30u,
-REG_SHUTDOWN_V_CTRL,
-REG_SHUTDOWN_CTRL,
-REG_CHARGE_CTRL_1,
-REG_CHARGE_CTRL_2,
-REG_SPARE_CHARGE_CTRL,
-REG_PEK_KEY_CTRL,
-REG_DC_DC_FREQ_SET,
-REG_CHR_TEMP_TH_SET,
-REG_CHR_HIGH_TEMP_TH_CTRL,
-REG_IPSOUT_WARN_L1,
-REG_IPSOUT_WARN_L2,
-REG_DISCHR_TEMP_TH_SET,
-REG_DISCHR_HIGH_TEMP_TH_CTRL,
-REG_IRQ_BANK_1_CTRL = 0x40u,
-REG_IRQ_BANK_2_CTRL,
-REG_IRQ_BANK_3_CTRL,
-REG_IRQ_BANK_4_CTRL,
-REG_IRQ_BANK_5_CTRL,
-REG_IRQ_BANK_1_STAT = 0x48u,
-REG_IRQ_BANK_2_STAT,
-REG_IRQ_BANK_3_STAT,
-REG_IRQ_BANK_4_STAT,
-REG_IRQ_BANK_5_STAT,
-REG_ADC_ACIN_V_H = 0x56u,
-REG_ADC_ACIN_V_L,
-REG_ADC_ACIN_CURR_H,
-REG_ADC_ACIN_CURR_L,
-REG_ADC_VBUS_V_H,
-REG_ADC_VBUS_V_L,
-REG_ADC_VBUS_CURR_H,
-REG_ADC_VBUS_CURR_L,
-REG_ADC_INT_TEMP_H,
-REG_ADC_INT_TEMP_L,
-REG_ADC_TEMP_SENS_V_H = 0x62u,
-REG_ADC_TEMP_SENS_V_L,
-REG_ADC_BAT_V_H = 0x78u,
-REG_ADC_BAT_V_L,
-REG_ADC_BAT_DISCHR_CURR_H,
-REG_ADC_BAT_DISCHR_CURR_L,
-REG_ADC_BAT_CHR_CURR_H,
-REG_ADC_BAT_CHR_CURR_L,
-REG_ADC_IPSOUT_V_H,
-REG_ADC_IPSOUT_V_L,
-REG_DC_DC_MOD_SEL = 0

[PULL 10/42] hw/arm/allwinner-r40: add Clock Control Unit

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

The CCU provides the registers to program the PLLs and the controls
most of the clock generation, division, distribution, synchronization
and gating.

This commit adds support for the Clock Control Unit which emulates
a simple read/write register interface.

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 
Signed-off-by: Peter Maydell 
---
 include/hw/arm/allwinner-r40.h  |   2 +
 include/hw/misc/allwinner-r40-ccu.h |  65 +
 hw/arm/allwinner-r40.c  |   8 +-
 hw/misc/allwinner-r40-ccu.c | 209 
 hw/misc/meson.build |   1 +
 5 files changed, 284 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/misc/allwinner-r40-ccu.h
 create mode 100644 hw/misc/allwinner-r40-ccu.c

diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index 348bf25d6be..3be9dc962be 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -25,6 +25,7 @@
 #include "hw/timer/allwinner-a10-pit.h"
 #include "hw/intc/arm_gic.h"
 #include "hw/sd/allwinner-sdhost.h"
+#include "hw/misc/allwinner-r40-ccu.h"
 #include "target/arm/cpu.h"
 #include "sysemu/block-backend.h"
 
@@ -79,6 +80,7 @@ struct AwR40State {
 const hwaddr *memmap;
 AwA10PITState timer;
 AwSdHostState mmc[AW_R40_NUM_MMCS];
+AwR40ClockCtlState ccu;
 GICState gic;
 MemoryRegion sram_a1;
 MemoryRegion sram_a2;
diff --git a/include/hw/misc/allwinner-r40-ccu.h 
b/include/hw/misc/allwinner-r40-ccu.h
new file mode 100644
index 000..ceb74eff923
--- /dev/null
+++ b/include/hw/misc/allwinner-r40-ccu.h
@@ -0,0 +1,65 @@
+/*
+ * Allwinner R40 Clock Control Unit emulation
+ *
+ * Copyright (C) 2023 qianfan Zhao 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see .
+ */
+
+#ifndef HW_MISC_ALLWINNER_R40_CCU_H
+#define HW_MISC_ALLWINNER_R40_CCU_H
+
+#include "qom/object.h"
+#include "hw/sysbus.h"
+
+/**
+ * @name Constants
+ * @{
+ */
+
+/** Size of register I/O address space used by CCU device */
+#define AW_R40_CCU_IOSIZE(0x400)
+
+/** Total number of known registers */
+#define AW_R40_CCU_REGS_NUM  (AW_R40_CCU_IOSIZE / sizeof(uint32_t))
+
+/** @} */
+
+/**
+ * @name Object model
+ * @{
+ */
+
+#define TYPE_AW_R40_CCU"allwinner-r40-ccu"
+OBJECT_DECLARE_SIMPLE_TYPE(AwR40ClockCtlState, AW_R40_CCU)
+
+/** @} */
+
+/**
+ * Allwinner R40 CCU object instance state.
+ */
+struct AwR40ClockCtlState {
+/*< private >*/
+SysBusDevice parent_obj;
+/*< public >*/
+
+/** Maps I/O registers in physical memory */
+MemoryRegion iomem;
+
+/** Array of hardware registers */
+uint32_t regs[AW_R40_CCU_REGS_NUM];
+
+};
+
+#endif /* HW_MISC_ALLWINNER_R40_CCU_H */
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index 97f2aa92fdf..72973f69ff0 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -42,6 +42,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_MMC1]   = 0x01c1,
 [AW_R40_DEV_MMC2]   = 0x01c11000,
 [AW_R40_DEV_MMC3]   = 0x01c12000,
+[AW_R40_DEV_CCU]= 0x01c2,
 [AW_R40_DEV_PIT]= 0x01c20c00,
 [AW_R40_DEV_UART0]  = 0x01c28000,
 [AW_R40_DEV_GIC_DIST]   = 0x01c81000,
@@ -80,7 +81,6 @@ static struct AwR40Unimplemented r40_unimplemented[] = {
 { "usb2-host",  0x01c1c000, 4 * KiB },
 { "cs1",0x01c1d000, 4 * KiB },
 { "spi3",   0x01c1f000, 4 * KiB },
-{ "ccu",0x01c2, 1 * KiB },
 { "rtc",0x01c20400, 1 * KiB },
 { "pio",0x01c20800, 1 * KiB },
 { "owa",0x01c21000, 1 * KiB },
@@ -250,6 +250,8 @@ static void allwinner_r40_init(Object *obj)
 object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
   "clk1-freq");
 
+object_initialize_child(obj, "ccu", &s->ccu, TYPE_AW_R40_CCU);
+
 for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
 object_initialize_child(obj, mmc_names[i], &s->mmc[i],
 TYPE_AW_SDHOST_SUN5I);
@@ -364,6 +366,10 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
 memory_region_add_subregion(get_system_memory(),
 s->memmap[AW_R40_DEV_SRAM_A4], &s->sram_a4);
 
+/* Clock Control Unit */
+sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal);
+sysbus_mmio_map(

[PULL 22/42] target/arm: Introduce finalize_memop_{atom,pair}

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Let finalize_memop_atom be the new basic function, with
finalize_memop and finalize_memop_pair testing FEAT_LSE2
to apply the appropriate atomicity.

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-4-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate.h | 39 +-
 target/arm/tcg/translate-a64.c |  2 ++
 target/arm/tcg/translate.c |  1 +
 3 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index 4d88197715b..c1e57a52ca2 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -90,6 +90,7 @@ typedef struct DisasContext {
 uint64_t features; /* CPU features bits */
 bool aarch64;
 bool thumb;
+bool lse2;
 /* Because unallocated encodings generate different exception syndrome
  * information from traps due to FP being disabled, we can't do a single
  * "is fp access disabled" check at a high level in the decode tree.
@@ -557,12 +558,13 @@ static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour 
flavour)
 }
 
 /**
- * finalize_memop:
+ * finalize_memop_atom:
  * @s: DisasContext
  * @opc: size+sign+align of the memory operation
+ * @atom: atomicity of the memory operation
  *
- * Build the complete MemOp for a memory operation, including alignment
- * and endianness.
+ * Build the complete MemOp for a memory operation, including alignment,
+ * endianness, and atomicity.
  *
  * If (op & MO_AMASK) then the operation already contains the required
  * alignment, e.g. for AccType_ATOMIC.  Otherwise, this an optionally
@@ -572,12 +574,39 @@ static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour 
flavour)
  * and this is applied here.  Note that there is no way to indicate that
  * no alignment should ever be enforced; this must be handled manually.
  */
-static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
+static inline MemOp finalize_memop_atom(DisasContext *s, MemOp opc, MemOp atom)
 {
 if (s->align_mem && !(opc & MO_AMASK)) {
 opc |= MO_ALIGN;
 }
-return opc | s->be_data;
+return opc | atom | s->be_data;
+}
+
+/**
+ * finalize_memop:
+ * @s: DisasContext
+ * @opc: size+sign+align of the memory operation
+ *
+ * Like finalize_memop_atom, but with default atomicity.
+ */
+static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
+{
+MemOp atom = s->lse2 ? MO_ATOM_WITHIN16 : MO_ATOM_IFALIGN;
+return finalize_memop_atom(s, opc, atom);
+}
+
+/**
+ * finalize_memop_pair:
+ * @s: DisasContext
+ * @opc: size+sign+align of the memory operation
+ *
+ * Like finalize_memop_atom, but with atomicity for a pair.
+ * C.f. Pseudocode for Mem[], operand ispair.
+ */
+static inline MemOp finalize_memop_pair(DisasContext *s, MemOp opc)
+{
+MemOp atom = s->lse2 ? MO_ATOM_WITHIN16_PAIR : MO_ATOM_IFALIGN_PAIR;
+return finalize_memop_atom(s, opc, atom);
 }
 
 /**
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index d9800337cf4..1d34c5a7031 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -14098,6 +14098,8 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 tcg_debug_assert(dc->tbid & 1);
 #endif
 
+dc->lse2 = dc_isar_feature(aa64_lse2, dc);
+
 /* Single step state. The code-generation logic here is:
  *  SS_ACTIVE == 0:
  *   generate code with no special handling for single-stepping (except
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index a68d3c7f6da..13c88ba1b9f 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -9168,6 +9168,7 @@ static void arm_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 dc->sme_trap_nonstreaming =
 EX_TBFLAG_A32(tb_flags, SME_TRAP_NONSTREAMING);
 }
+dc->lse2 = false; /* applies only to aarch64 */
 dc->cp_regs = cpu->cp_regs;
 dc->features = env->features;
 
-- 
2.34.1




[PULL 37/42] tests/tcg/aarch64: Use stz2g in mte-7.c

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

We have many other instances of stg in the testsuite;
change these to provide an instance of stz2g.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-19-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 tests/tcg/aarch64/mte-7.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tests/tcg/aarch64/mte-7.c b/tests/tcg/aarch64/mte-7.c
index a981de62d4a..04974f9ebbd 100644
--- a/tests/tcg/aarch64/mte-7.c
+++ b/tests/tcg/aarch64/mte-7.c
@@ -19,8 +19,7 @@ int main(int ac, char **av)
 p = (void *)((unsigned long)p | (1ul << 56));
 
 /* Store tag in sequential granules. */
-asm("stg %0, [%0]" : : "r"(p + 0x0ff0));
-asm("stg %0, [%0]" : : "r"(p + 0x1000));
+asm("stz2g %0, [%0]" : : "r"(p + 0x0ff0));
 
 /*
  * Perform an unaligned store with tag 1 crossing the pages.
-- 
2.34.1




[PULL 36/42] target/arm: Move mte check for store-exclusive

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Push the mte check behind the exclusive_addr check.
Document the several ways that we are still out of spec
with this implementation.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-18-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.c | 42 +-
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index adedebd1c22..aa93f37e216 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2512,17 +2512,47 @@ static void gen_store_exclusive(DisasContext *s, int 
rd, int rt, int rt2,
  */
 TCGLabel *fail_label = gen_new_label();
 TCGLabel *done_label = gen_new_label();
-TCGv_i64 tmp, dirty_addr, clean_addr;
+TCGv_i64 tmp, clean_addr;
 MemOp memop;
 
-memop = (size + is_pair) | MO_ALIGN;
-memop = finalize_memop(s, memop);
-
-dirty_addr = cpu_reg_sp(s, rn);
-clean_addr = gen_mte_check1(s, dirty_addr, true, rn != 31, memop);
+/*
+ * FIXME: We are out of spec here.  We have recorded only the address
+ * from load_exclusive, not the entire range, and we assume that the
+ * size of the access on both sides match.  The architecture allows the
+ * store to be smaller than the load, so long as the stored bytes are
+ * within the range recorded by the load.
+ */
 
+/* See AArch64.ExclusiveMonitorsPass() and AArch64.IsExclusiveVA(). */
+clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
 tcg_gen_brcond_i64(TCG_COND_NE, clean_addr, cpu_exclusive_addr, 
fail_label);
 
+/*
+ * The write, and any associated faults, only happen if the virtual
+ * and physical addresses pass the exclusive monitor check.  These
+ * faults are exceedingly unlikely, because normally the guest uses
+ * the exact same address register for the load_exclusive, and we
+ * would have recognized these faults there.
+ *
+ * It is possible to trigger an alignment fault pre-LSE2, e.g. with an
+ * unaligned 4-byte write within the range of an aligned 8-byte load.
+ * With LSE2, the store would need to cross a 16-byte boundary when the
+ * load did not, which would mean the store is outside the range
+ * recorded for the monitor, which would have failed a corrected monitor
+ * check above.  For now, we assume no size change and retain the
+ * MO_ALIGN to let tcg know what we checked in the load_exclusive.
+ *
+ * It is possible to trigger an MTE fault, by performing the load with
+ * a virtual address with a valid tag and performing the store with the
+ * same virtual address and a different invalid tag.
+ */
+memop = size + is_pair;
+if (memop == MO_128 || !dc_isar_feature(aa64_lse2, s)) {
+memop |= MO_ALIGN;
+}
+memop = finalize_memop(s, memop);
+gen_mte_check1(s, cpu_reg_sp(s, rn), true, rn != 31, memop);
+
 tmp = tcg_temp_new_i64();
 if (is_pair) {
 if (size == 2) {
-- 
2.34.1




[PULL 05/42] hw/net/can: Introduce Xilinx Versal CANFD controller

2023-06-06 Thread Peter Maydell
From: Vikram Garhwal 

The Xilinx Versal CANFD controller is developed based on SocketCAN, QEMU CAN bus
implementation. Bus connection and socketCAN connection for each CAN module
can be set through command lines.

Signed-off-by: Vikram Garhwal 
Reviewed-by: Francisco Iglesias 
Signed-off-by: Peter Maydell 
---
 include/hw/net/xlnx-versal-canfd.h |   87 ++
 hw/net/can/xlnx-versal-canfd.c | 2107 
 hw/net/can/meson.build |1 +
 hw/net/can/trace-events|7 +
 4 files changed, 2202 insertions(+)
 create mode 100644 include/hw/net/xlnx-versal-canfd.h
 create mode 100644 hw/net/can/xlnx-versal-canfd.c

diff --git a/include/hw/net/xlnx-versal-canfd.h 
b/include/hw/net/xlnx-versal-canfd.h
new file mode 100644
index 000..ad3104dd13f
--- /dev/null
+++ b/include/hw/net/xlnx-versal-canfd.h
@@ -0,0 +1,87 @@
+/*
+ * QEMU model of the Xilinx Versal CANFD Controller.
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ *
+ * Written-by: Vikram Garhwal
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa.
+ * 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 HW_CANFD_XILINX_H
+#define HW_CANFD_XILINX_H
+
+#include "hw/register.h"
+#include "hw/ptimer.h"
+#include "net/can_emu.h"
+#include "hw/qdev-clock.h"
+
+#define TYPE_XILINX_CANFD "xlnx.versal-canfd"
+
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCANFDState, XILINX_CANFD)
+
+#define NUM_REGS_PER_MSG_SPACE 18 /* 1 ID + 1 DLC + 16 Data(DW0 - DW15) regs. 
*/
+#define MAX_NUM_RX 64
+#define OFFSET_RX1_DW15(0x4144 / 4)
+#define CANFD_TIMER_MAX0xUL
+#define CANFD_DEFAULT_CLOCK(25 * 1000 * 1000)
+
+#define XLNX_VERSAL_CANFD_R_MAX (OFFSET_RX1_DW15 + \
+((MAX_NUM_RX - 1) * NUM_REGS_PER_MSG_SPACE) + 1)
+
+typedef struct XlnxVersalCANFDState {
+SysBusDeviceparent_obj;
+MemoryRegioniomem;
+
+qemu_irqirq_canfd_int;
+qemu_irqirq_addr_err;
+
+RegisterInforeg_info[XLNX_VERSAL_CANFD_R_MAX];
+RegisterAccessInfo  *tx_regs;
+RegisterAccessInfo  *rx0_regs;
+RegisterAccessInfo  *rx1_regs;
+RegisterAccessInfo  *af_regs;
+RegisterAccessInfo  *txe_regs;
+RegisterAccessInfo  *rx_mailbox_regs;
+RegisterAccessInfo  *af_mask_regs_mailbox;
+
+uint32_tregs[XLNX_VERSAL_CANFD_R_MAX];
+
+ptimer_state*canfd_timer;
+
+CanBusClientState   bus_client;
+CanBusState *canfdbus;
+
+struct {
+uint8_t rx0_fifo;
+uint8_t rx1_fifo;
+uint8_t tx_fifo;
+boolenable_rx_fifo1;
+uint32_text_clk_freq;
+   } cfg;
+
+} XlnxVersalCANFDState;
+
+typedef struct tx_ready_reg_info {
+uint32_t can_id;
+uint32_t reg_num;
+} tx_ready_reg_info;
+
+#endif
diff --git a/hw/net/can/xlnx-versal-canfd.c b/hw/net/can/xlnx-versal-canfd.c
new file mode 100644
index 000..5b8ce0a285e
--- /dev/null
+++ b/hw/net/can/xlnx-versal-canfd.c
@@ -0,0 +1,2107 @@
+/*
+ * QEMU model of the Xilinx Versal CANFD device.
+ *
+ * This implementation is based on the following datasheet:
+ * https://docs.xilinx.com/v/u/2.0-English/pg223-canfd
+ *
+ * Copyright (c) 2023 Advanced Micro Devices, Inc.
+ *
+ * Written-by: Vikram Garhwal 
+ *
+ * Based on QEMU CANFD Device emulation implemented by Jin Yang, Deniz Eren and
+ * Pavel Pisa
+ *
+ * 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 s

[PULL 04/42] hvf: add guest debugging handlers for Apple Silicon hosts

2023-06-06 Thread Peter Maydell
From: Francesco Cagnin 

Guests can now be debugged through the gdbstub. Support is added for
single-stepping, software breakpoints, hardware breakpoints and
watchpoints. The code has been structured like the KVM counterpart.

While guest debugging is enabled, the guest can still read and write the
DBG*_EL1 registers but they don't have any effect.

Signed-off-by: Francesco Cagnin 
Message-id: 20230601153107.81955-5-fcag...@quarkslab.com
Reviewed-by: Peter Maydell 
Signed-off-by: Peter Maydell 
---
 include/sysemu/hvf.h  |  15 ++
 include/sysemu/hvf_int.h  |   1 +
 target/arm/hvf_arm.h  |   7 +
 accel/hvf/hvf-accel-ops.c |  10 +
 accel/hvf/hvf-all.c   |   6 +
 target/arm/hvf/hvf.c  | 474 +-
 target/i386/hvf/hvf.c |   9 +
 7 files changed, 520 insertions(+), 2 deletions(-)

diff --git a/include/sysemu/hvf.h b/include/sysemu/hvf.h
index 386020a29cc..70549b91588 100644
--- a/include/sysemu/hvf.h
+++ b/include/sysemu/hvf.h
@@ -56,6 +56,21 @@ int hvf_arch_insert_hw_breakpoint(target_ulong addr, 
target_ulong len,
 int hvf_arch_remove_hw_breakpoint(target_ulong addr, target_ulong len,
   int type);
 void hvf_arch_remove_all_hw_breakpoints(void);
+
+/*
+ * hvf_update_guest_debug:
+ * @cs: CPUState for the CPU to update
+ *
+ * Update guest to enable or disable debugging. Per-arch specifics will be
+ * handled by calling down to hvf_arch_update_guest_debug.
+ */
+int hvf_update_guest_debug(CPUState *cpu);
+void hvf_arch_update_guest_debug(CPUState *cpu);
+
+/*
+ * Return whether the guest supports debugging.
+ */
+bool hvf_arch_supports_guest_debug(void);
 #endif /* NEED_CPU_H */
 
 #endif
diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h
index 3592239fdcb..6ab119e49f7 100644
--- a/include/sysemu/hvf_int.h
+++ b/include/sysemu/hvf_int.h
@@ -54,6 +54,7 @@ struct hvf_vcpu_state {
 void *exit;
 bool vtimer_masked;
 sigset_t unblock_ipi_mask;
+bool guest_debug_enabled;
 };
 
 void assert_hvf_ok(hv_return_t ret);
diff --git a/target/arm/hvf_arm.h b/target/arm/hvf_arm.h
index 9a9d1a0bf59..e848c1d27d4 100644
--- a/target/arm/hvf_arm.h
+++ b/target/arm/hvf_arm.h
@@ -13,6 +13,13 @@
 
 #include "cpu.h"
 
+/**
+ * hvf_arm_init_debug() - initialize guest debug capabilities
+ *
+ * Should be called only once before using guest debug capabilities.
+ */
+void hvf_arm_init_debug(void);
+
 void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu);
 
 #endif
diff --git a/accel/hvf/hvf-accel-ops.c b/accel/hvf/hvf-accel-ops.c
index 92601b1369d..9c3da03c948 100644
--- a/accel/hvf/hvf-accel-ops.c
+++ b/accel/hvf/hvf-accel-ops.c
@@ -343,12 +343,18 @@ static int hvf_accel_init(MachineState *ms)
 return hvf_arch_init();
 }
 
+static inline int hvf_gdbstub_sstep_flags(void)
+{
+return SSTEP_ENABLE | SSTEP_NOIRQ;
+}
+
 static void hvf_accel_class_init(ObjectClass *oc, void *data)
 {
 AccelClass *ac = ACCEL_CLASS(oc);
 ac->name = "HVF";
 ac->init_machine = hvf_accel_init;
 ac->allowed = &hvf_allowed;
+ac->gdbstub_supported_sstep_flags = hvf_gdbstub_sstep_flags;
 }
 
 static const TypeInfo hvf_accel_type = {
@@ -398,6 +404,8 @@ static int hvf_init_vcpu(CPUState *cpu)
 cpu->vcpu_dirty = 1;
 assert_hvf_ok(r);
 
+cpu->hvf->guest_debug_enabled = false;
+
 return hvf_arch_init_vcpu(cpu);
 }
 
@@ -582,6 +590,8 @@ static void hvf_accel_ops_class_init(ObjectClass *oc, void 
*data)
 ops->insert_breakpoint = hvf_insert_breakpoint;
 ops->remove_breakpoint = hvf_remove_breakpoint;
 ops->remove_all_breakpoints = hvf_remove_all_breakpoints;
+ops->update_guest_debug = hvf_update_guest_debug;
+ops->supports_guest_debug = hvf_arch_supports_guest_debug;
 };
 static const TypeInfo hvf_accel_ops_type = {
 .name = ACCEL_OPS_NAME("hvf"),
diff --git a/accel/hvf/hvf-all.c b/accel/hvf/hvf-all.c
index e983c23ad7f..754707dbfb3 100644
--- a/accel/hvf/hvf-all.c
+++ b/accel/hvf/hvf-all.c
@@ -61,3 +61,9 @@ int hvf_sw_breakpoints_active(CPUState *cpu)
 {
 return !QTAILQ_EMPTY(&hvf_state->hvf_sw_breakpoints);
 }
+
+int hvf_update_guest_debug(CPUState *cpu)
+{
+hvf_arch_update_guest_debug(cpu);
+return 0;
+}
diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c
index bb83627727c..2bd0a35cbab 100644
--- a/target/arm/hvf/hvf.c
+++ b/target/arm/hvf/hvf.c
@@ -33,6 +33,116 @@
 
 #include "exec/gdbstub.h"
 
+#define MDSCR_EL1_SS_SHIFT  0
+#define MDSCR_EL1_MDE_SHIFT 15
+
+static uint16_t dbgbcr_regs[] = {
+HV_SYS_REG_DBGBCR0_EL1,
+HV_SYS_REG_DBGBCR1_EL1,
+HV_SYS_REG_DBGBCR2_EL1,
+HV_SYS_REG_DBGBCR3_EL1,
+HV_SYS_REG_DBGBCR4_EL1,
+HV_SYS_REG_DBGBCR5_EL1,
+HV_SYS_REG_DBGBCR6_EL1,
+HV_SYS_REG_DBGBCR7_EL1,
+HV_SYS_REG_DBGBCR8_EL1,
+HV_SYS_REG_DBGBCR9_EL1,
+HV_SYS_REG_DBGBCR10_EL1,
+HV_SYS_REG_DBGBCR11_EL1,
+HV_SYS_REG_DBGBCR12_EL1,
+HV_SYS_REG_DBGBCR13_EL1,
+HV_SYS_REG_DBGBCR14_EL1,
+HV_SYS_REG_DBGBCR15_EL1,
+};
+static uint16_t d

[PULL 26/42] target/arm: Use tcg_gen_qemu_{ld, st}_i128 in gen_sve_{ld, st}r

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Round len_align to 16 instead of 8, handling an odd 8-byte as part
of the tail.  Use MO_ATOM_NONE to indicate that all of these memory
ops have only byte atomicity.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-8-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-sve.c | 95 +-
 1 file changed, 70 insertions(+), 25 deletions(-)

diff --git a/target/arm/tcg/translate-sve.c b/target/arm/tcg/translate-sve.c
index d9d5810ddea..57051a4729a 100644
--- a/target/arm/tcg/translate-sve.c
+++ b/target/arm/tcg/translate-sve.c
@@ -4167,11 +4167,12 @@ TRANS_FEAT(UCVTF_dd, aa64_sve, gen_gvec_fpst_arg_zpz,
 void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int vofs,
  int len, int rn, int imm)
 {
-int len_align = QEMU_ALIGN_DOWN(len, 8);
-int len_remain = len % 8;
-int nparts = len / 8 + ctpop8(len_remain);
+int len_align = QEMU_ALIGN_DOWN(len, 16);
+int len_remain = len % 16;
+int nparts = len / 16 + ctpop8(len_remain);
 int midx = get_mem_index(s);
 TCGv_i64 dirty_addr, clean_addr, t0, t1;
+TCGv_i128 t16;
 
 dirty_addr = tcg_temp_new_i64();
 tcg_gen_addi_i64(dirty_addr, cpu_reg_sp(s, rn), imm);
@@ -4188,10 +4189,16 @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int 
vofs,
 int i;
 
 t0 = tcg_temp_new_i64();
-for (i = 0; i < len_align; i += 8) {
-tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
+t1 = tcg_temp_new_i64();
+t16 = tcg_temp_new_i128();
+
+for (i = 0; i < len_align; i += 16) {
+tcg_gen_qemu_ld_i128(t16, clean_addr, midx,
+ MO_LE | MO_128 | MO_ATOM_NONE);
+tcg_gen_extr_i128_i64(t0, t1, t16);
 tcg_gen_st_i64(t0, base, vofs + i);
-tcg_gen_addi_i64(clean_addr, clean_addr, 8);
+tcg_gen_st_i64(t1, base, vofs + i + 8);
+tcg_gen_addi_i64(clean_addr, clean_addr, 16);
 }
 } else {
 TCGLabel *loop = gen_new_label();
@@ -4200,14 +4207,21 @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int 
vofs,
 tcg_gen_movi_ptr(i, 0);
 gen_set_label(loop);
 
-t0 = tcg_temp_new_i64();
-tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ);
-tcg_gen_addi_i64(clean_addr, clean_addr, 8);
+t16 = tcg_temp_new_i128();
+tcg_gen_qemu_ld_i128(t16, clean_addr, midx,
+ MO_LE | MO_128 | MO_ATOM_NONE);
+tcg_gen_addi_i64(clean_addr, clean_addr, 16);
 
 tp = tcg_temp_new_ptr();
 tcg_gen_add_ptr(tp, base, i);
-tcg_gen_addi_ptr(i, i, 8);
+tcg_gen_addi_ptr(i, i, 16);
+
+t0 = tcg_temp_new_i64();
+t1 = tcg_temp_new_i64();
+tcg_gen_extr_i128_i64(t0, t1, t16);
+
 tcg_gen_st_i64(t0, tp, vofs);
+tcg_gen_st_i64(t1, tp, vofs + 8);
 
 tcg_gen_brcondi_ptr(TCG_COND_LTU, i, len_align, loop);
 }
@@ -4216,6 +4230,16 @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int 
vofs,
  * Predicate register loads can be any multiple of 2.
  * Note that we still store the entire 64-bit unit into cpu_env.
  */
+if (len_remain >= 8) {
+t0 = tcg_temp_new_i64();
+tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ | MO_ATOM_NONE);
+tcg_gen_st_i64(t0, base, vofs + len_align);
+len_remain -= 8;
+len_align += 8;
+if (len_remain) {
+tcg_gen_addi_i64(clean_addr, clean_addr, 8);
+}
+}
 if (len_remain) {
 t0 = tcg_temp_new_i64();
 switch (len_remain) {
@@ -4223,14 +4247,14 @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int 
vofs,
 case 4:
 case 8:
 tcg_gen_qemu_ld_i64(t0, clean_addr, midx,
-MO_LE | ctz32(len_remain));
+MO_LE | ctz32(len_remain) | MO_ATOM_NONE);
 break;
 
 case 6:
 t1 = tcg_temp_new_i64();
-tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUL);
+tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUL | MO_ATOM_NONE);
 tcg_gen_addi_i64(clean_addr, clean_addr, 4);
-tcg_gen_qemu_ld_i64(t1, clean_addr, midx, MO_LEUW);
+tcg_gen_qemu_ld_i64(t1, clean_addr, midx, MO_LEUW | MO_ATOM_NONE);
 tcg_gen_deposit_i64(t0, t0, t1, 32, 32);
 break;
 
@@ -4245,11 +4269,12 @@ void gen_sve_ldr(DisasContext *s, TCGv_ptr base, int 
vofs,
 void gen_sve_str(DisasContext *s, TCGv_ptr base, int vofs,
  int len, int rn, int imm)
 {
-int len_align = QEMU_ALIGN_DOWN(len, 8);
-int len_remain = len % 8;
-int nparts = len / 8 + ctpop8(len_remain);
+int len_align = QEMU_ALIGN_DOWN(len, 16);
+int len_remain = len % 16;
+int nparts = len / 16 + ctpop8(len_remain);
 int midx = get_mem_index(s);
-   

[PULL 01/42] arm: move KVM breakpoints helpers

2023-06-06 Thread Peter Maydell
From: Francesco Cagnin 

These helpers will be also used for HVF. Aside from reformatting a
couple of comments for 'checkpatch.pl' and updating meson to compile
'hyp_gdbstub.c', this is just code motion.

Signed-off-by: Francesco Cagnin 
Reviewed-by: Alex Bennée 
Reviewed-by: Peter Maydell 
Message-id: 20230601153107.81955-2-fcag...@quarkslab.com
Signed-off-by: Peter Maydell 
---
 target/arm/internals.h   |  50 +++
 target/arm/hyp_gdbstub.c | 253 +++
 target/arm/kvm64.c   | 276 ---
 target/arm/meson.build   |   3 +-
 4 files changed, 305 insertions(+), 277 deletions(-)
 create mode 100644 target/arm/hyp_gdbstub.c

diff --git a/target/arm/internals.h b/target/arm/internals.h
index c869d18c38c..ce26299f7f0 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1447,4 +1447,54 @@ static inline bool arm_fgt_active(CPUARMState *env, int 
el)
 }
 
 void assert_hflags_rebuild_correctly(CPUARMState *env);
+
+/*
+ * Although the ARM implementation of hardware assisted debugging
+ * allows for different breakpoints per-core, the current GDB
+ * interface treats them as a global pool of registers (which seems to
+ * be the case for x86, ppc and s390). As a result we store one copy
+ * of registers which is used for all active cores.
+ *
+ * Write access is serialised by virtue of the GDB protocol which
+ * updates things. Read access (i.e. when the values are copied to the
+ * vCPU) is also gated by GDB's run control.
+ *
+ * This is not unreasonable as most of the time debugging kernels you
+ * never know which core will eventually execute your function.
+ */
+
+typedef struct {
+uint64_t bcr;
+uint64_t bvr;
+} HWBreakpoint;
+
+/*
+ * The watchpoint registers can cover more area than the requested
+ * watchpoint so we need to store the additional information
+ * somewhere. We also need to supply a CPUWatchpoint to the GDB stub
+ * when the watchpoint is hit.
+ */
+typedef struct {
+uint64_t wcr;
+uint64_t wvr;
+CPUWatchpoint details;
+} HWWatchpoint;
+
+/* Maximum and current break/watch point counts */
+extern int max_hw_bps, max_hw_wps;
+extern GArray *hw_breakpoints, *hw_watchpoints;
+
+#define cur_hw_wps  (hw_watchpoints->len)
+#define cur_hw_bps  (hw_breakpoints->len)
+#define get_hw_bp(i)(&g_array_index(hw_breakpoints, HWBreakpoint, i))
+#define get_hw_wp(i)(&g_array_index(hw_watchpoints, HWWatchpoint, i))
+
+bool find_hw_breakpoint(CPUState *cpu, target_ulong pc);
+int insert_hw_breakpoint(target_ulong pc);
+int delete_hw_breakpoint(target_ulong pc);
+
+bool check_watchpoint_in_range(int i, target_ulong addr);
+CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr);
+int insert_hw_watchpoint(target_ulong addr, target_ulong len, int type);
+int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type);
 #endif
diff --git a/target/arm/hyp_gdbstub.c b/target/arm/hyp_gdbstub.c
new file mode 100644
index 000..ebde2899cd8
--- /dev/null
+++ b/target/arm/hyp_gdbstub.c
@@ -0,0 +1,253 @@
+/*
+ * ARM implementation of KVM and HVF hooks, 64 bit specific code
+ *
+ * Copyright Mian-M. Hamayun 2013, Virtual Open Systems
+ * Copyright Alex Bennée 2014, Linaro
+ *
+ * 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 "cpu.h"
+#include "internals.h"
+#include "exec/gdbstub.h"
+
+/* Maximum and current break/watch point counts */
+int max_hw_bps, max_hw_wps;
+GArray *hw_breakpoints, *hw_watchpoints;
+
+/**
+ * insert_hw_breakpoint()
+ * @addr: address of breakpoint
+ *
+ * See ARM ARM D2.9.1 for details but here we are only going to create
+ * simple un-linked breakpoints (i.e. we don't chain breakpoints
+ * together to match address and context or vmid). The hardware is
+ * capable of fancier matching but that will require exposing that
+ * fanciness to GDB's interface
+ *
+ * DBGBCR_EL1, Debug Breakpoint Control Registers
+ *
+ *  31  24 23  20 19   16 15 14  13  12   9 8   5 43 2   1  0
+ * +--+--+---+-++--+-+--+-+---+
+ * | RES0 |  BT  |  LBN  | SSC | HMC| RES0 | BAS | RES0 | PMC | E |
+ * +--+--+---+-++--+-+--+-+---+
+ *
+ * BT: Breakpoint type (0 = unlinked address match)
+ * LBN: Linked BP number (0 = unused)
+ * SSC/HMC/PMC: Security, Higher and Priv access control (Table D-12)
+ * BAS: Byte Address Select (RES1 for AArch64)
+ * E: Enable bit
+ *
+ * DBGBVR_EL1, Debug Breakpoint Value Registers
+ *
+ *  63  53 52   49 48   2  1 0
+ * +--+---+--+-+
+ * | RESS | VA[52:49] | VA[48:2] | 0 0 |
+ * +--+---+--+-+
+ *
+ * Depending on the addressing mode bits the top bits of the register
+ * are a sign extension of the highest applicable VA bit. Some
+ * versions of GDB don't do it correctly so we ensure they are correct
+

[PULL 38/42] tests/tcg/multiarch: Adjust sigbus.c

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

With -cpu max and FEAT_LSE2, the __aarch64__ section will only raise
an alignment exception when the load crosses a 16-byte boundary.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-20-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 tests/tcg/multiarch/sigbus.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/tests/tcg/multiarch/sigbus.c b/tests/tcg/multiarch/sigbus.c
index 8134c5fd568..f47c7390e76 100644
--- a/tests/tcg/multiarch/sigbus.c
+++ b/tests/tcg/multiarch/sigbus.c
@@ -6,8 +6,13 @@
 #include 
 
 
-unsigned long long x = 0x8877665544332211ull;
-void * volatile p = (void *)&x + 1;
+char x[32] __attribute__((aligned(16))) = {
+  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+  0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+};
+void * volatile p = (void *)&x + 15;
 
 void sigbus(int sig, siginfo_t *info, void *uc)
 {
@@ -60,9 +65,9 @@ int main()
  * We might as well validate the unaligned load worked.
  */
 if (BYTE_ORDER == LITTLE_ENDIAN) {
-assert(tmp == 0x55443322);
+assert(tmp == 0x13121110);
 } else {
-assert(tmp == 0x77665544);
+assert(tmp == 0x10111213);
 }
 return EXIT_SUCCESS;
 }
-- 
2.34.1




[PULL 35/42] target/arm: Relax ordered/atomic alignment checks for LSE2

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

FEAT_LSE2 only requires that atomic operations not cross a
16-byte boundary.  Ordered operations may be completely
unaligned if SCTLR.nAA is set.

Because this alignment check is so special, do it by hand.
Make sure not to keep TCG temps live across the branch.

Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-17-richard.hender...@linaro.org
Reviewed-by: Peter Maydell 
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/helper-a64.h|   3 +
 target/arm/tcg/helper-a64.c|   7 ++
 target/arm/tcg/translate-a64.c | 120 ++---
 3 files changed, 104 insertions(+), 26 deletions(-)

diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
index ff56807247f..3d5957c11f4 100644
--- a/target/arm/tcg/helper-a64.h
+++ b/target/arm/tcg/helper-a64.h
@@ -110,3 +110,6 @@ DEF_HELPER_FLAGS_2(st2g_stub, TCG_CALL_NO_WG, void, env, 
i64)
 DEF_HELPER_FLAGS_2(ldgm, TCG_CALL_NO_WG, i64, env, i64)
 DEF_HELPER_FLAGS_3(stgm, TCG_CALL_NO_WG, void, env, i64, i64)
 DEF_HELPER_FLAGS_3(stzgm_tags, TCG_CALL_NO_WG, void, env, i64, i64)
+
+DEF_HELPER_FLAGS_4(unaligned_access, TCG_CALL_NO_WG,
+   noreturn, env, i64, i32, i32)
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index c3edf163be4..1c9370f07bd 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -952,3 +952,10 @@ void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
 
 memset(mem, 0, blocklen);
 }
+
+void HELPER(unaligned_access)(CPUARMState *env, uint64_t addr,
+  uint32_t access_type, uint32_t mmu_idx)
+{
+arm_cpu_do_unaligned_access(env_cpu(env), addr, access_type,
+mmu_idx, GETPC());
+}
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 91d28f86620..adedebd1c22 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -307,6 +307,89 @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, 
bool is_write,
 return clean_data_tbi(s, addr);
 }
 
+/*
+ * Generate the special alignment check that applies to AccType_ATOMIC
+ * and AccType_ORDERED insns under FEAT_LSE2: the access need not be
+ * naturally aligned, but it must not cross a 16-byte boundary.
+ * See AArch64.CheckAlignment().
+ */
+static void check_lse2_align(DisasContext *s, int rn, int imm,
+ bool is_write, MemOp mop)
+{
+TCGv_i32 tmp;
+TCGv_i64 addr;
+TCGLabel *over_label;
+MMUAccessType type;
+int mmu_idx;
+
+tmp = tcg_temp_new_i32();
+tcg_gen_extrl_i64_i32(tmp, cpu_reg_sp(s, rn));
+tcg_gen_addi_i32(tmp, tmp, imm & 15);
+tcg_gen_andi_i32(tmp, tmp, 15);
+tcg_gen_addi_i32(tmp, tmp, memop_size(mop));
+
+over_label = gen_new_label();
+tcg_gen_brcondi_i32(TCG_COND_LEU, tmp, 16, over_label);
+
+addr = tcg_temp_new_i64();
+tcg_gen_addi_i64(addr, cpu_reg_sp(s, rn), imm);
+
+type = is_write ? MMU_DATA_STORE : MMU_DATA_LOAD,
+mmu_idx = get_mem_index(s);
+gen_helper_unaligned_access(cpu_env, addr, tcg_constant_i32(type),
+tcg_constant_i32(mmu_idx));
+
+gen_set_label(over_label);
+
+}
+
+/* Handle the alignment check for AccType_ATOMIC instructions. */
+static MemOp check_atomic_align(DisasContext *s, int rn, MemOp mop)
+{
+MemOp size = mop & MO_SIZE;
+
+if (size == MO_8) {
+return mop;
+}
+
+/*
+ * If size == MO_128, this is a LDXP, and the operation is single-copy
+ * atomic for each doubleword, not the entire quadword; it still must
+ * be quadword aligned.
+ */
+if (size == MO_128) {
+return finalize_memop_atom(s, MO_128 | MO_ALIGN,
+   MO_ATOM_IFALIGN_PAIR);
+}
+if (dc_isar_feature(aa64_lse2, s)) {
+check_lse2_align(s, rn, 0, true, mop);
+} else {
+mop |= MO_ALIGN;
+}
+return finalize_memop(s, mop);
+}
+
+/* Handle the alignment check for AccType_ORDERED instructions. */
+static MemOp check_ordered_align(DisasContext *s, int rn, int imm,
+ bool is_write, MemOp mop)
+{
+MemOp size = mop & MO_SIZE;
+
+if (size == MO_8) {
+return mop;
+}
+if (size == MO_128) {
+return finalize_memop_atom(s, MO_128 | MO_ALIGN,
+   MO_ATOM_IFALIGN_PAIR);
+}
+if (!dc_isar_feature(aa64_lse2, s)) {
+mop |= MO_ALIGN;
+} else if (!s->naa) {
+check_lse2_align(s, rn, imm, is_write, mop);
+}
+return finalize_memop(s, mop);
+}
+
 typedef struct DisasCompare64 {
 TCGCond cond;
 TCGv_i64 value;
@@ -2372,21 +2455,7 @@ static void gen_load_exclusive(DisasContext *s, int rt, 
int rt2, int rn,
 {
 int idx = get_mem_index(s);
 TCGv_i64 dirty_addr, clean_addr;
-MemOp memop;
-
-/*
- * For pairs:
- * if size == 2, the operation is single-copy atomic for the doubleword.
-   

[PULL 12/42] hw: arm: allwinner-r40: Add i2c0 device

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

TWI(i2c) is designed to be used as an interface between CPU host and the
serial 2-Wire bus. It can support all standard 2-Wire transfer, can be
operated in standard mode(100kbit/s) or fast-mode, supporting data rate
up to 400kbit/s.

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 
Signed-off-by: Peter Maydell 
---
 include/hw/arm/allwinner-r40.h |  3 +++
 hw/arm/allwinner-r40.c | 11 ++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/include/hw/arm/allwinner-r40.h b/include/hw/arm/allwinner-r40.h
index 959b5dc4e04..95366f4eeef 100644
--- a/include/hw/arm/allwinner-r40.h
+++ b/include/hw/arm/allwinner-r40.h
@@ -26,6 +26,7 @@
 #include "hw/intc/arm_gic.h"
 #include "hw/sd/allwinner-sdhost.h"
 #include "hw/misc/allwinner-r40-ccu.h"
+#include "hw/i2c/allwinner-i2c.h"
 #include "target/arm/cpu.h"
 #include "sysemu/block-backend.h"
 
@@ -48,6 +49,7 @@ enum {
 AW_R40_DEV_UART5,
 AW_R40_DEV_UART6,
 AW_R40_DEV_UART7,
+AW_R40_DEV_TWI0,
 AW_R40_DEV_GIC_DIST,
 AW_R40_DEV_GIC_CPU,
 AW_R40_DEV_GIC_HYP,
@@ -89,6 +91,7 @@ struct AwR40State {
 AwA10PITState timer;
 AwSdHostState mmc[AW_R40_NUM_MMCS];
 AwR40ClockCtlState ccu;
+AWI2CState i2c0;
 GICState gic;
 MemoryRegion sram_a1;
 MemoryRegion sram_a2;
diff --git a/hw/arm/allwinner-r40.c b/hw/arm/allwinner-r40.c
index 537a90b23d8..4bc582630c4 100644
--- a/hw/arm/allwinner-r40.c
+++ b/hw/arm/allwinner-r40.c
@@ -52,6 +52,7 @@ const hwaddr allwinner_r40_memmap[] = {
 [AW_R40_DEV_UART5]  = 0x01c29400,
 [AW_R40_DEV_UART6]  = 0x01c29800,
 [AW_R40_DEV_UART7]  = 0x01c29c00,
+[AW_R40_DEV_TWI0]   = 0x01c2ac00,
 [AW_R40_DEV_GIC_DIST]   = 0x01c81000,
 [AW_R40_DEV_GIC_CPU]= 0x01c82000,
 [AW_R40_DEV_GIC_HYP]= 0x01c84000,
@@ -115,7 +116,6 @@ static struct AwR40Unimplemented r40_unimplemented[] = {
 { "uart7",  0x01c29c00, 1 * KiB },
 { "ps20",   0x01c2a000, 1 * KiB },
 { "ps21",   0x01c2a400, 1 * KiB },
-{ "twi0",   0x01c2ac00, 1 * KiB },
 { "twi1",   0x01c2b000, 1 * KiB },
 { "twi2",   0x01c2b400, 1 * KiB },
 { "twi3",   0x01c2b800, 1 * KiB },
@@ -167,6 +167,7 @@ enum {
 AW_R40_GIC_SPI_UART1 =  2,
 AW_R40_GIC_SPI_UART2 =  3,
 AW_R40_GIC_SPI_UART3 =  4,
+AW_R40_GIC_SPI_TWI0  =  7,
 AW_R40_GIC_SPI_UART4 = 17,
 AW_R40_GIC_SPI_UART5 = 18,
 AW_R40_GIC_SPI_UART6 = 19,
@@ -270,6 +271,8 @@ static void allwinner_r40_init(Object *obj)
 object_initialize_child(obj, mmc_names[i], &s->mmc[i],
 TYPE_AW_SDHOST_SUN5I);
 }
+
+object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
 }
 
 static void allwinner_r40_realize(DeviceState *dev, Error **errp)
@@ -416,6 +419,12 @@ static void allwinner_r40_realize(DeviceState *dev, Error 
**errp)
115200, serial_hd(i), DEVICE_NATIVE_ENDIAN);
 }
 
+/* I2C */
+sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, s->memmap[AW_R40_DEV_TWI0]);
+sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0,
+   qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_TWI0));
+
 /* Unimplemented devices */
 for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
 create_unimplemented_device(r40_unimplemented[i].device_name,
-- 
2.34.1




[PULL 07/42] MAINTAINERS: Include canfd tests under Xilinx CAN

2023-06-06 Thread Peter Maydell
From: Vikram Garhwal 

Signed-off-by: Vikram Garhwal 
Reviewed-by: Peter Maydell 
Reviewed-by: Francisco Iglesias 
Signed-off-by: Peter Maydell 
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 55668d63368..4b2639def6d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1819,7 +1819,7 @@ M: Francisco Iglesias 
 S: Maintained
 F: hw/net/can/xlnx-*
 F: include/hw/net/xlnx-*
-F: tests/qtest/xlnx-can-test*
+F: tests/qtest/xlnx-can*-test*
 
 EDU
 M: Jiri Slaby 
-- 
2.34.1




[PULL 21/42] target/arm: Add feature test for FEAT_LSE2

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-3-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 81c0df9c259..c1db26b2998 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3851,6 +3851,11 @@ static inline bool isar_feature_aa64_st(const 
ARMISARegisters *id)
 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
 }
 
+static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id)
+{
+return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0;
+}
+
 static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id)
 {
 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0;
-- 
2.34.1




[PULL 39/42] target/arm: Enable FEAT_LSE2 for -cpu max

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-21-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 docs/system/arm/emulation.rst | 1 +
 target/arm/tcg/cpu64.c| 1 +
 2 files changed, 2 insertions(+)

diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 73389878755..ecbbd63adf6 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -50,6 +50,7 @@ the following architecture extensions:
 - FEAT_LRCPC (Load-acquire RCpc instructions)
 - FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
 - FEAT_LSE (Large System Extensions)
+- FEAT_LSE2 (Large System Extensions v2)
 - FEAT_LVA (Large Virtual Address space)
 - FEAT_MTE (Memory Tagging Extension)
 - FEAT_MTE2 (Memory Tagging Extension)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 886674a4436..2976f94ae45 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -644,6 +644,7 @@ void aarch64_max_tcg_initfn(Object *obj)
 t = FIELD_DP64(t, ID_AA64MMFR2, IESB, 1); /* FEAT_IESB */
 t = FIELD_DP64(t, ID_AA64MMFR2, VARANGE, 1);  /* FEAT_LVA */
 t = FIELD_DP64(t, ID_AA64MMFR2, ST, 1);   /* FEAT_TTST */
+t = FIELD_DP64(t, ID_AA64MMFR2, AT, 1);   /* FEAT_LSE2 */
 t = FIELD_DP64(t, ID_AA64MMFR2, IDS, 1);  /* FEAT_IDST */
 t = FIELD_DP64(t, ID_AA64MMFR2, FWB, 1);  /* FEAT_S2FWB */
 t = FIELD_DP64(t, ID_AA64MMFR2, TTL, 1);  /* FEAT_TTL */
-- 
2.34.1




[PULL 34/42] target/arm: Add SCTLR.nAA to TBFLAG_A64

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-16-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h   | 3 ++-
 target/arm/tcg/translate.h | 2 ++
 target/arm/tcg/hflags.c| 6 ++
 target/arm/tcg/translate-a64.c | 1 +
 4 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c1db26b2998..36c608f0e6e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1248,7 +1248,7 @@ void pmu_init(ARMCPU *cpu);
 #define SCTLR_D   (1U << 5) /* up to v5; RAO in v6 */
 #define SCTLR_CP15BEN (1U << 5) /* v7 onward */
 #define SCTLR_L   (1U << 6) /* up to v5; RAO in v6 and v7; RAZ in v8 */
-#define SCTLR_nAA (1U << 6) /* when v8.4-LSE is implemented */
+#define SCTLR_nAA (1U << 6) /* when FEAT_LSE2 is implemented */
 #define SCTLR_B   (1U << 7) /* up to v6; RAZ in v7 */
 #define SCTLR_ITD (1U << 7) /* v8 onward */
 #define SCTLR_S   (1U << 8) /* up to v6; RAZ in v7 */
@@ -3044,6 +3044,7 @@ FIELD(TBFLAG_A64, SVL, 24, 4)
 /* Indicates that SME Streaming mode is active, and SMCR_ELx.FA64 is not. */
 FIELD(TBFLAG_A64, SME_TRAP_NONSTREAMING, 28, 1)
 FIELD(TBFLAG_A64, FGT_ERET, 29, 1)
+FIELD(TBFLAG_A64, NAA, 30, 1)
 
 /*
  * Helpers for using the above.
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index 3aa486a1ab6..d1cacff0b2f 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -142,6 +142,8 @@ typedef struct DisasContext {
 bool fgt_eret;
 /* True if fine-grained trap on SVC is enabled */
 bool fgt_svc;
+/* True if FEAT_LSE2 SCTLR_ELx.nAA is set */
+bool naa;
 /*
  * >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
  *  < 0, set by the current instruction.
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
index b2ccd77cffc..616c5fa7237 100644
--- a/target/arm/tcg/hflags.c
+++ b/target/arm/tcg/hflags.c
@@ -248,6 +248,12 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, 
int el, int fp_el,
 }
 }
 
+if (cpu_isar_feature(aa64_lse2, env_archcpu(env))) {
+if (sctlr & SCTLR_nAA) {
+DP_TBFLAG_A64(flags, NAA, 1);
+}
+}
+
 /* Compute the condition for using AccType_UNPRIV for LDTR et al. */
 if (!(env->pstate & PSTATE_UAO)) {
 switch (mmu_idx) {
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 77073a9c1d8..91d28f86620 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -14151,6 +14151,7 @@ static void 
aarch64_tr_init_disas_context(DisasContextBase *dcbase,
 dc->pstate_sm = EX_TBFLAG_A64(tb_flags, PSTATE_SM);
 dc->pstate_za = EX_TBFLAG_A64(tb_flags, PSTATE_ZA);
 dc->sme_trap_nonstreaming = EX_TBFLAG_A64(tb_flags, SME_TRAP_NONSTREAMING);
+dc->naa = EX_TBFLAG_A64(tb_flags, NAA);
 dc->vec_len = 0;
 dc->vec_stride = 0;
 dc->cp_regs = arm_cpu->cp_regs;
-- 
2.34.1




[PULL 33/42] target/arm: Check alignment in helper_mte_check

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Fixes a bug in that with SCTLR.A set, we should raise any
alignment fault before raising any MTE check fault.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-15-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/internals.h |  3 ++-
 target/arm/tcg/mte_helper.c| 18 ++
 target/arm/tcg/translate-a64.c |  2 ++
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/target/arm/internals.h b/target/arm/internals.h
index ce26299f7f0..e3029bdc37a 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1242,7 +1242,8 @@ FIELD(MTEDESC, MIDX,  0, 4)
 FIELD(MTEDESC, TBI,   4, 2)
 FIELD(MTEDESC, TCMA,  6, 2)
 FIELD(MTEDESC, WRITE, 8, 1)
-FIELD(MTEDESC, SIZEM1, 9, SIMD_DATA_BITS - 9)  /* size - 1 */
+FIELD(MTEDESC, ALIGN, 9, 3)
+FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12)  /* size - 1 */
 
 bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
 uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t 
ra);
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
index a4f3f92bc02..9c64def0816 100644
--- a/target/arm/tcg/mte_helper.c
+++ b/target/arm/tcg/mte_helper.c
@@ -785,6 +785,24 @@ uint64_t mte_check(CPUARMState *env, uint32_t desc, 
uint64_t ptr, uintptr_t ra)
 
 uint64_t HELPER(mte_check)(CPUARMState *env, uint32_t desc, uint64_t ptr)
 {
+/*
+ * R_XCHFJ: Alignment check not caused by memory type is priority 1,
+ * higher than any translation fault.  When MTE is disabled, tcg
+ * performs the alignment check during the code generated for the
+ * memory access.  With MTE enabled, we must check this here before
+ * raising any translation fault in allocation_tag_mem.
+ */
+unsigned align = FIELD_EX32(desc, MTEDESC, ALIGN);
+if (unlikely(align)) {
+align = (1u << align) - 1;
+if (unlikely(ptr & align)) {
+int idx = FIELD_EX32(desc, MTEDESC, MIDX);
+bool w = FIELD_EX32(desc, MTEDESC, WRITE);
+MMUAccessType type = w ? MMU_DATA_STORE : MMU_DATA_LOAD;
+arm_cpu_do_unaligned_access(env_cpu(env), ptr, type, idx, GETPC());
+}
+}
+
 return mte_check(env, desc, ptr, GETPC());
 }
 
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 0b600695965..77073a9c1d8 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -264,6 +264,7 @@ static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, 
TCGv_i64 addr,
 desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
 desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
 desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
+desc = FIELD_DP32(desc, MTEDESC, ALIGN, get_alignment_bits(memop));
 desc = FIELD_DP32(desc, MTEDESC, SIZEM1, memop_size(memop) - 1);
 
 ret = tcg_temp_new_i64();
@@ -295,6 +296,7 @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, 
bool is_write,
 desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
 desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
 desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
+desc = FIELD_DP32(desc, MTEDESC, ALIGN, 
get_alignment_bits(single_mop));
 desc = FIELD_DP32(desc, MTEDESC, SIZEM1, total_size - 1);
 
 ret = tcg_temp_new_i64();
-- 
2.34.1




[PULL 28/42] target/arm: Load/store integer pair with one tcg operation

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

This is required for LSE2, where the pair must be treated atomically if
it does not cross a 16-byte boundary.  But it simplifies the code to do
this always.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-10-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.c | 70 ++
 1 file changed, 55 insertions(+), 15 deletions(-)

diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 729947b11a4..88183f9dca1 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2942,26 +2942,66 @@ static void disas_ldst_pair(DisasContext *s, uint32_t 
insn)
 } else {
 TCGv_i64 tcg_rt = cpu_reg(s, rt);
 TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
+MemOp mop = size + 1;
+
+/*
+ * With LSE2, non-sign-extending pairs are treated atomically if
+ * aligned, and if unaligned one of the pair will be completely
+ * within a 16-byte block and that element will be atomic.
+ * Otherwise each element is separately atomic.
+ * In all cases, issue one operation with the correct atomicity.
+ *
+ * This treats sign-extending loads like zero-extending loads,
+ * since that reuses the most code below.
+ */
+if (s->align_mem) {
+mop |= (size == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
+}
+mop = finalize_memop_pair(s, mop);
 
 if (is_load) {
-TCGv_i64 tmp = tcg_temp_new_i64();
+if (size == 2) {
+int o2 = s->be_data == MO_LE ? 32 : 0;
+int o1 = o2 ^ 32;
 
-/* Do not modify tcg_rt before recognizing any exception
- * from the second load.
- */
-do_gpr_ld(s, tmp, clean_addr, size + is_signed * MO_SIGN,
-  false, false, 0, false, false);
-tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
-do_gpr_ld(s, tcg_rt2, clean_addr, size + is_signed * MO_SIGN,
-  false, false, 0, false, false);
+tcg_gen_qemu_ld_i64(tcg_rt, clean_addr, get_mem_index(s), mop);
+if (is_signed) {
+tcg_gen_sextract_i64(tcg_rt2, tcg_rt, o2, 32);
+tcg_gen_sextract_i64(tcg_rt, tcg_rt, o1, 32);
+} else {
+tcg_gen_extract_i64(tcg_rt2, tcg_rt, o2, 32);
+tcg_gen_extract_i64(tcg_rt, tcg_rt, o1, 32);
+}
+} else {
+TCGv_i128 tmp = tcg_temp_new_i128();
 
-tcg_gen_mov_i64(tcg_rt, tmp);
+tcg_gen_qemu_ld_i128(tmp, clean_addr, get_mem_index(s), mop);
+if (s->be_data == MO_LE) {
+tcg_gen_extr_i128_i64(tcg_rt, tcg_rt2, tmp);
+} else {
+tcg_gen_extr_i128_i64(tcg_rt2, tcg_rt, tmp);
+}
+}
 } else {
-do_gpr_st(s, tcg_rt, clean_addr, size,
-  false, 0, false, false);
-tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
-do_gpr_st(s, tcg_rt2, clean_addr, size,
-  false, 0, false, false);
+if (size == 2) {
+TCGv_i64 tmp = tcg_temp_new_i64();
+
+if (s->be_data == MO_LE) {
+tcg_gen_concat32_i64(tmp, tcg_rt, tcg_rt2);
+} else {
+tcg_gen_concat32_i64(tmp, tcg_rt2, tcg_rt);
+}
+tcg_gen_qemu_st_i64(tmp, clean_addr, get_mem_index(s), mop);
+} else {
+TCGv_i128 tmp = tcg_temp_new_i128();
+
+if (s->be_data == MO_LE) {
+tcg_gen_concat_i64_i128(tmp, tcg_rt, tcg_rt2);
+} else {
+tcg_gen_concat_i64_i128(tmp, tcg_rt2, tcg_rt);
+}
+tcg_gen_qemu_st_i128(tmp, clean_addr, get_mem_index(s), mop);
+}
 }
 }
 
-- 
2.34.1




[PULL 40/42] target/arm: allow DC CVA[D]P in user mode emulation

2023-06-06 Thread Peter Maydell
From: Zhuojia Shen 

DC CVAP and DC CVADP instructions can be executed in EL0 on Linux,
either directly when SCTLR_EL1.UCI == 1 or emulated by the kernel (see
user_cache_maint_handler() in arch/arm64/kernel/traps.c).

This patch enables execution of the two instructions in user mode
emulation.

Signed-off-by: Zhuojia Shen 
Reviewed-by: Peter Maydell 
Reviewed-by: Richard Henderson 
Signed-off-by: Peter Maydell 
---
 target/arm/helper.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0b7fd2e7e6c..d4bee43bd01 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7405,7 +7405,6 @@ static const ARMCPRegInfo rndr_reginfo[] = {
   .access = PL0_R, .readfn = rndr_readfn },
 };
 
-#ifndef CONFIG_USER_ONLY
 static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
   uint64_t value)
 {
@@ -7420,6 +7419,7 @@ static void dccvap_writefn(CPUARMState *env, const 
ARMCPRegInfo *opaque,
 /* This won't be crossing page boundaries */
 haddr = probe_read(env, vaddr, dline_size, mem_idx, GETPC());
 if (haddr) {
+#ifndef CONFIG_USER_ONLY
 
 ram_addr_t offset;
 MemoryRegion *mr;
@@ -7430,6 +7430,7 @@ static void dccvap_writefn(CPUARMState *env, const 
ARMCPRegInfo *opaque,
 if (mr) {
 memory_region_writeback(mr, offset, dline_size);
 }
+#endif /*CONFIG_USER_ONLY*/
 }
 }
 
@@ -7448,7 +7449,6 @@ static const ARMCPRegInfo dcpodp_reg[] = {
   .fgt = FGT_DCCVADP,
   .accessfn = aa64_cacheop_poc_access, .writefn = dccvap_writefn },
 };
-#endif /*CONFIG_USER_ONLY*/
 
 static CPAccessResult access_aa64_tid5(CPUARMState *env, const ARMCPRegInfo 
*ri,
bool isread)
@@ -9092,7 +9092,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 if (cpu_isar_feature(aa64_tlbios, cpu)) {
 define_arm_cp_regs(cpu, tlbios_reginfo);
 }
-#ifndef CONFIG_USER_ONLY
 /* Data Cache clean instructions up to PoP */
 if (cpu_isar_feature(aa64_dcpop, cpu)) {
 define_one_arm_cp_reg(cpu, dcpop_reg);
@@ -9101,7 +9100,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
 define_one_arm_cp_reg(cpu, dcpodp_reg);
 }
 }
-#endif /*CONFIG_USER_ONLY*/
 
 /*
  * If full MTE is enabled, add all of the system registers.
-- 
2.34.1




[PULL 19/42] docs: system: arm: Introduce bananapi_m2u

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

Add documents for Banana Pi M2U

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 
[PMM: Minor format fixes to correct sphinx errors]
Signed-off-by: Peter Maydell 
---
 docs/system/arm/bananapi_m2u.rst | 139 +++
 docs/system/target-arm.rst   |   1 +
 2 files changed, 140 insertions(+)
 create mode 100644 docs/system/arm/bananapi_m2u.rst

diff --git a/docs/system/arm/bananapi_m2u.rst b/docs/system/arm/bananapi_m2u.rst
new file mode 100644
index 000..b09ba5c5486
--- /dev/null
+++ b/docs/system/arm/bananapi_m2u.rst
@@ -0,0 +1,139 @@
+Banana Pi BPI-M2U (``bpim2u``)
+^^
+
+Banana Pi BPI-M2 Ultra is a quad-core mini single board computer built with
+Allwinner A40i/R40/V40 SoC. It features 2GB of RAM and 8GB eMMC. It also
+has onboard WiFi and BT. On the ports side, the BPI-M2 Ultra has 2 USB A
+2.0 ports, 1 USB OTG port, 1 HDMI port, 1 audio jack, a DC power port,
+and last but not least, a SATA port.
+
+Supported devices
+"
+
+The Banana Pi M2U machine supports the following devices:
+
+ * SMP (Quad Core Cortex-A7)
+ * Generic Interrupt Controller configuration
+ * SRAM mappings
+ * SDRAM controller
+ * Timer device (re-used from Allwinner A10)
+ * UART
+ * SD/MMC storage controller
+ * EMAC ethernet
+ * GMAC ethernet
+ * Clock Control Unit
+ * TWI (I2C)
+
+Limitations
+"""
+
+Currently, Banana Pi M2U does *not* support the following features:
+
+- Graphical output via HDMI, GPU and/or the Display Engine
+- Audio output
+- Hardware Watchdog
+- Real Time Clock
+- USB 2.0 interfaces
+
+Also see the 'unimplemented' array in the Allwinner R40 SoC module
+for a complete list of unimplemented I/O devices: ``./hw/arm/allwinner-r40.c``
+
+Boot options
+
+
+The Banana Pi M2U machine can start using the standard -kernel functionality
+for loading a Linux kernel or ELF executable. Additionally, the Banana Pi M2U
+machine can also emulate the BootROM which is present on an actual Allwinner 
R40
+based SoC, which loads the bootloader from a SD card, specified via the -sd
+argument to qemu-system-arm.
+
+Running mainline Linux
+""
+
+To build a Linux mainline kernel that can be booted by the Banana Pi M2U 
machine,
+simply configure the kernel using the sunxi_defconfig configuration:
+
+.. code-block:: bash
+
+  $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make mrproper
+  $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- make sunxi_defconfig
+
+To boot the newly build linux kernel in QEMU with the Banana Pi M2U machine, 
use:
+
+.. code-block:: bash
+
+  $ qemu-system-arm -M bpim2u -nographic \
+  -kernel /path/to/linux/arch/arm/boot/zImage \
+  -append 'console=ttyS0,115200' \
+  -dtb /path/to/linux/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dtb
+
+Banana Pi M2U images
+
+
+Note that the mainline kernel does not have a root filesystem. You can choose
+to build you own image with buildroot using the bananapi_m2_ultra_defconfig.
+Also see https://buildroot.org for more information.
+
+Another possibility is to run an OpenWrt image for Banana Pi M2U which
+can be downloaded from:
+
+   https://downloads.openwrt.org/releases/22.03.3/targets/sunxi/cortexa7/
+
+When using an image as an SD card, it must be resized to a power of two. This 
can be
+done with the ``qemu-img`` command. It is recommended to only increase the 
image size
+instead of shrinking it to a power of two, to avoid loss of data. For example,
+to prepare a downloaded Armbian image, first extract it and then increase
+its size to one gigabyte as follows:
+
+.. code-block:: bash
+
+  $ qemu-img resize \
+openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img \
+1G
+
+Instead of providing a custom Linux kernel via the -kernel command you may also
+choose to let the Banana Pi M2U machine load the bootloader from SD card, just 
like
+a real board would do using the BootROM. Simply pass the selected image via 
the -sd
+argument and remove the -kernel, -append, -dbt and -initrd arguments:
+
+.. code-block:: bash
+
+  $ qemu-system-arm -M bpim2u -nic user -nographic \
+-sd 
openwrt-22.03.3-sunxi-cortexa7-sinovoip_bananapi-m2-ultra-ext4-sdcard.img
+
+Running U-Boot
+""
+
+U-Boot mainline can be build and configured using the 
Bananapi_M2_Ultra_defconfig
+using similar commands as describe above for Linux. Note that it is recommended
+for development/testing to select the following configuration setting in 
U-Boot:
+
+  Device Tree Control > Provider for DTB for DT Control > Embedded DTB
+
+The BootROM of allwinner R40 loading u-boot from the 8KiB offset of sdcard.
+Let's create an bootable disk image:
+
+.. code-block:: bash
+
+  $ dd if=/dev/zero of=sd.img bs=32M count=1
+  $ dd if=u-boot-sunxi-with-spl.bin of=sd.img bs=1k seek=8 conv=notrunc
+
+And then boot it.
+
+.. code-block:: bash
+
+  $ qemu-system-arm -M bpim2u -nographic -sd sd.img
+
+Bana

[PULL 18/42] tests: avocado: boot_linux_console: Add test case for bpim2u

2023-06-06 Thread Peter Maydell
From: qianfan Zhao 

Add test case for booting from initrd and sd card.

Signed-off-by: qianfan Zhao 
Reviewed-by: Niek Linnenbank 
Tested-by: Niek Linnenbank 
Signed-off-by: Peter Maydell 
---
 tests/avocado/boot_linux_console.py | 176 
 1 file changed, 176 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index c0675809e64..6ed660611fe 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -769,6 +769,182 @@ def test_arm_quanta_gsj_initrd(self):
 self.wait_for_console_pattern(
 'Give root password for system maintenance')
 
+def test_arm_bpim2u(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=machine:bpim2u
+:avocado: tags=accel:tcg
+"""
+deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
+   'linux-image-current-sunxi_21.02.2_armhf.deb')
+deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path,
+'/boot/vmlinuz-5.10.16-sunxi')
+dtb_path = ('/usr/lib/linux-image-current-sunxi/'
+'sun8i-r40-bananapi-m2-ultra.dtb')
+dtb_path = self.extract_from_deb(deb_path, dtb_path)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'console=ttyS0,115200n8 '
+   'earlycon=uart,mmio32,0x1c28000')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-append', kernel_command_line)
+self.vm.launch()
+console_pattern = 'Kernel command line: %s' % kernel_command_line
+self.wait_for_console_pattern(console_pattern)
+
+def test_arm_bpim2u_initrd(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=accel:tcg
+:avocado: tags=machine:bpim2u
+"""
+deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
+   'linux-image-current-sunxi_21.02.2_armhf.deb')
+deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path,
+'/boot/vmlinuz-5.10.16-sunxi')
+dtb_path = ('/usr/lib/linux-image-current-sunxi/'
+'sun8i-r40-bananapi-m2-ultra.dtb')
+dtb_path = self.extract_from_deb(deb_path, dtb_path)
+initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
+  '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
+  'arm/rootfs-armv7a.cpio.gz')
+initrd_hash = '604b2e45cdf35045846b8bbfbf2129b1891bdc9c'
+initrd_path_gz = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
+initrd_path = os.path.join(self.workdir, 'rootfs.cpio')
+archive.gzip_uncompress(initrd_path_gz, initrd_path)
+
+self.vm.set_console()
+kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
+   'console=ttyS0,115200 '
+   'panic=-1 noreboot')
+self.vm.add_args('-kernel', kernel_path,
+ '-dtb', dtb_path,
+ '-initrd', initrd_path,
+ '-append', kernel_command_line,
+ '-no-reboot')
+self.vm.launch()
+self.wait_for_console_pattern('Boot successful.')
+
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
+'Allwinner sun8i Family')
+exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
+'system-control@1c0')
+exec_command_and_wait_for_pattern(self, 'reboot',
+'reboot: Restarting system')
+# Wait for VM to shut down gracefully
+self.vm.wait()
+
+def test_arm_bpim2u_gmac(self):
+"""
+:avocado: tags=arch:arm
+:avocado: tags=accel:tcg
+:avocado: tags=machine:bpim2u
+:avocado: tags=device:sd
+"""
+self.require_netdev('user')
+
+deb_url = ('https://apt.armbian.com/pool/main/l/linux-5.10.16-sunxi/'
+   'linux-image-current-sunxi_21.02.2_armhf.deb')
+deb_hash = '9fa84beda245cabf0b4fa84cf6eaa7738ead1da0'
+deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
+kernel_path = self.extract_from_deb(deb_path,
+'/boot/vmlinuz-5.10.16-sunxi')
+dtb_path = ('/usr/lib/linux-image-current-sunxi/'
+'sun8i-r40-bananapi-m2-ultra.dtb')
+dtb_pat

[PULL 32/42] target/arm: Pass single_memop to gen_mte_checkN

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Pass the individual memop to gen_mte_checkN.
For the moment, do nothing with it.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-14-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/tcg/translate-a64.h |  2 +-
 target/arm/tcg/translate-a64.c | 31 +++
 target/arm/tcg/translate-sve.c |  4 ++--
 3 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/target/arm/tcg/translate-a64.h b/target/arm/tcg/translate-a64.h
index cecf2bab8f6..b55dc435fc5 100644
--- a/target/arm/tcg/translate-a64.h
+++ b/target/arm/tcg/translate-a64.h
@@ -51,7 +51,7 @@ TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr);
 TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, bool is_write,
 bool tag_checked, MemOp memop);
 TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
-bool tag_checked, int size);
+bool tag_checked, int total_size, MemOp memop);
 
 /* We should have at some point before trying to access an FP register
  * done the necessary access check, so assert that
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 85d896e9752..0b600695965 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -285,7 +285,7 @@ TCGv_i64 gen_mte_check1(DisasContext *s, TCGv_i64 addr, 
bool is_write,
  * For MTE, check multiple logical sequential accesses.
  */
 TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
-bool tag_checked, int size)
+bool tag_checked, int total_size, MemOp single_mop)
 {
 if (tag_checked && s->mte_active[0]) {
 TCGv_i64 ret;
@@ -295,7 +295,7 @@ TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, 
bool is_write,
 desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
 desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
 desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
-desc = FIELD_DP32(desc, MTEDESC, SIZEM1, size - 1);
+desc = FIELD_DP32(desc, MTEDESC, SIZEM1, total_size - 1);
 
 ret = tcg_temp_new_i64();
 gen_helper_mte_check(ret, cpu_env, tcg_constant_i32(desc), addr);
@@ -2841,14 +2841,12 @@ static void disas_ldst_pair(DisasContext *s, uint32_t 
insn)
 bool is_vector = extract32(insn, 26, 1);
 bool is_load = extract32(insn, 22, 1);
 int opc = extract32(insn, 30, 2);
-
 bool is_signed = false;
 bool postindex = false;
 bool wback = false;
 bool set_tag = false;
-
 TCGv_i64 clean_addr, dirty_addr;
-
+MemOp mop;
 int size;
 
 if (opc == 3) {
@@ -2931,12 +2929,17 @@ static void disas_ldst_pair(DisasContext *s, uint32_t 
insn)
 }
 }
 
+if (is_vector) {
+mop = finalize_memop_asimd(s, size);
+} else {
+mop = finalize_memop(s, size);
+}
 clean_addr = gen_mte_checkN(s, dirty_addr, !is_load,
-(wback || rn != 31) && !set_tag, 2 << size);
+(wback || rn != 31) && !set_tag,
+2 << size, mop);
 
 if (is_vector) {
-MemOp mop = finalize_memop_asimd(s, size);
-
+/* LSE2 does not merge FP pairs; leave these as separate operations. */
 if (is_load) {
 do_fp_ld(s, rt, clean_addr, mop);
 } else {
@@ -2951,9 +2954,11 @@ static void disas_ldst_pair(DisasContext *s, uint32_t 
insn)
 } else {
 TCGv_i64 tcg_rt = cpu_reg(s, rt);
 TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
-MemOp mop = size + 1;
 
 /*
+ * We built mop above for the single logical access -- rebuild it
+ * now for the paired operation.
+ *
  * With LSE2, non-sign-extending pairs are treated atomically if
  * aligned, and if unaligned one of the pair will be completely
  * within a 16-byte block and that element will be atomic.
@@ -2963,6 +2968,7 @@ static void disas_ldst_pair(DisasContext *s, uint32_t 
insn)
  * This treats sign-extending loads like zero-extending loads,
  * since that reuses the most code below.
  */
+mop = size + 1;
 if (s->align_mem) {
 mop |= (size == 2 ? MO_ALIGN_4 : MO_ALIGN_8);
 }
@@ -3741,7 +3747,7 @@ static void disas_ldst_multiple_struct(DisasContext *s, 
uint32_t insn)
  * promote consecutive little-endian elements below.
  */
 clean_addr = gen_mte_checkN(s, tcg_rn, is_store, is_postidx || rn != 31,
-total);
+total, finalize_memop(s, size));
 
 /*
  * Consecutive little-endian elements from a single register
@@ -3899,10 +3905,11 @@ static void disas_ldst_single_struct(DisasContext *s, 
uint32_t insn)
 total = selem << scale;
 tcg_rn = cpu_reg_sp(s, rn);
 
-clean_addr = gen_mte_check

[PULL 08/42] tests/qtest: Introduce tests for Xilinx VERSAL CANFD controller

2023-06-06 Thread Peter Maydell
From: Vikram Garhwal 

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

Signed-off-by: Vikram Garhwal 
Acked-by: Thomas Huth 
Reviewed-by: Francisco Iglesias 
Reviewed-by: Peter Maydell 
Signed-off-by: Peter Maydell 
---
 tests/qtest/xlnx-canfd-test.c | 423 ++
 tests/qtest/meson.build   |   1 +
 2 files changed, 424 insertions(+)
 create mode 100644 tests/qtest/xlnx-canfd-test.c

diff --git a/tests/qtest/xlnx-canfd-test.c b/tests/qtest/xlnx-canfd-test.c
new file mode 100644
index 000..76ee106d4f4
--- /dev/null
+++ b/tests/qtest/xlnx-canfd-test.c
@@ -0,0 +1,423 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * QTests for the Xilinx Versal CANFD controller.
+ *
+ * Copyright (c) 2022 AMD Inc.
+ *
+ * Written-by: Vikram Garhwal
+ *
+ * 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.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+/* Base address. */
+#define CANFD0_BASE_ADDR0xff06
+#define CANFD1_BASE_ADDR0xff07
+
+/* Register addresses. */
+#define R_SRR_OFFSET0x00
+#define R_MSR_OFFSET0x04
+#define R_FILTER_CONTROL_REGISTER   0xe0
+#define R_SR_OFFSET 0x18
+#define R_ISR_OFFSET0x1c
+#define R_IER_OFFSET0x20
+#define R_ICR_OFFSET0x24
+#define R_TX_READY_REQ_REGISTER 0x90
+#define RX_FIFO_STATUS_REGISTER 0xe8
+#define R_TXID_OFFSET   0x100
+#define R_TXDLC_OFFSET  0x104
+#define R_TXDATA1_OFFSET0x108
+#define R_TXDATA2_OFFSET0x10c
+#define R_AFMR_REGISTER00xa00
+#define R_AFIR_REGISTER00xa04
+#define R_RX0_ID_OFFSET 0x2100
+#define R_RX0_DLC_OFFSET0x2104
+#define R_RX0_DATA1_OFFSET  0x2108
+#define R_RX0_DATA2_OFFSET  0x210c
+
+/* CANFD modes. */
+#define SRR_CONFIG_MODE 0x00
+#define MSR_NORMAL_MODE 0x00
+#define MSR_LOOPBACK_MODE   (1 << 1)
+#define ENABLE_CANFD(1 << 1)
+
+/* CANFD status. */
+#define STATUS_CONFIG_MODE  (1 << 0)
+#define STATUS_NORMAL_MODE  (1 << 3)
+#define STATUS_LOOPBACK_MODE(1 << 1)
+#define ISR_TXOK(1 << 1)
+#define ISR_RXOK(1 << 4)
+
+#define ENABLE_ALL_FILTERS  0x
+#define ENABLE_ALL_INTERRUPTS   0x
+
+/* We are sending one canfd message. */
+#define TX_READY_REG_VAL0x1
+
+#define FIRST_RX_STORE_INDEX0x1
+#define STATUS_REG_MASK 0xf
+#define DLC_FD_BIT_SHIFT0x1b
+#define DLC_FD_BIT_MASK 0xf800
+#define FIFO_STATUS_READ_INDEX_MASK 0x3f
+#define FIFO_STATUS_FILL_LEVEL_MASK 0x7f00
+#define FILL_LEVEL_SHIFT0x8
+
+/* CANFD frame size ID, DLC and 16 DATA word. */
+#define CANFD_FRAME_SIZE18
+/* CAN frame size ID, DLC and 2 DATA word. */
+#define CAN_FRAME_SIZE  4
+
+/* Set the filters for CANFD controller. */
+static void enable_filters(QTestState *qts)
+{
+ const uint32_t arr_afmr[32] = { 0xb423deaa, 0xa2a40bdc, 0x1b64f486,
+ 0x95c0d4ee, 0xe0c44528, 0x4b407904,
+ 0xd2673f46, 0x9fc638d6, 0x8844f3d8,
+ 0xa607d1e8, 0x67871bf4, 0xc2557dc,
+ 0x9ea5b53e, 0x3643c0cc, 0x5a05ea8e,
+ 0x83a46d84, 0x4a25c2b8, 0x93a66008,
+ 0x2e467470, 0xedc66118, 0x9086f9f2,
+ 0xf

[PULL 20/42] target/arm: Add commentary for CPUARMState.exclusive_high

2023-06-06 Thread Peter Maydell
From: Richard Henderson 

Document the meaning of exclusive_high in a big-endian context,
and why we can't change it now.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
Message-id: 20230530191438.411344-2-richard.hender...@linaro.org
Signed-off-by: Peter Maydell 
---
 target/arm/cpu.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index d469a2637b3..81c0df9c259 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -677,8 +677,16 @@ typedef struct CPUArchState {
 uint64_t zcr_el[4];   /* ZCR_EL[1-3] */
 uint64_t smcr_el[4];  /* SMCR_EL[1-3] */
 } vfp;
+
 uint64_t exclusive_addr;
 uint64_t exclusive_val;
+/*
+ * Contains the 'val' for the second 64-bit register of LDXP, which comes
+ * from the higher address, not the high part of a complete 128-bit value.
+ * In some ways it might be more convenient to record the exclusive value
+ * as the low and high halves of a 128 bit data value, but the current
+ * semantics of these fields are baked into the migration format.
+ */
 uint64_t exclusive_high;
 
 /* iwMMXt coprocessor state.  */
-- 
2.34.1




Re: [PATCH 05/10] meson: subprojects: replace submodules with wrap files

2023-06-06 Thread Daniel P . Berrangé
On Mon, Jun 05, 2023 at 11:52:18AM +0200, Paolo Bonzini wrote:
> Compared to submodules, .wrap files have several advantages:
> 
> * option parsing and downloading is delegated to meson
> 
> * the commit is stored in a text file instead of a magic entry in the
>   git tree object
> 
> * we could stop shipping external dependencies that are only used as a
>   fallback, but not break compilation on platforms that lack them.
>   For example it may make sense to download dtc at build time, controlled
>   by --enable-download, even when building from a tarball.  Right now,
>   this patch does the opposite: make-release treats dtc like libvfio-user
>   (which is not stable API and therefore hasn't found its way into any
>   distros) and keycodemap (which is a copylib, for better or worse).
> 
> dependency() can fall back to a wrap automatically.  However, this
> is only possible for libraries that come with a .pc file, and this
> is not very common for libfdt even though the upstream project in
> principle provides it; it also removes the control that we provide with
> --enable-fdt={system,internal}.  Therefore, the logic to pick system
> vs. internal libfdt is left untouched.
> 
> --enable-fdt=git is removed; it was already a synonym for
> --enable-fdt=internal.
> 
> Signed-off-by: Paolo Bonzini 
> ---
>  .gitlab-ci.d/buildtest-template.yml |  1 +
>  .gitmodules |  9 
>  configure   | 77 -
>  meson.build | 15 +-
>  scripts/archive-source.sh   | 11 -
>  scripts/make-release|  5 ++
>  subprojects/.gitignore  |  3 ++
>  subprojects/dtc |  1 -
>  subprojects/dtc.wrap|  4 ++
>  subprojects/keycodemapdb|  1 -
>  subprojects/keycodemapdb.wrap   |  4 ++
>  subprojects/libvfio-user|  1 -
>  subprojects/libvfio-user.wrap   |  4 ++
>  13 files changed, 63 insertions(+), 73 deletions(-)
>  delete mode 16 subprojects/dtc
>  create mode 100644 subprojects/dtc.wrap
>  delete mode 16 subprojects/keycodemapdb
>  create mode 100644 subprojects/keycodemapdb.wrap
>  delete mode 16 subprojects/libvfio-user
>  create mode 100644 subprojects/libvfio-user.wrap

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v3 0/3] Trivial cleanups

2023-06-06 Thread BALATON Zoltan

On Tue, 6 Jun 2023, Mark Cave-Ayland wrote:

On 05/06/2023 07:58, Bernhard Beschow wrote:
Am 1. Juni 2023 12:45:47 UTC schrieb Mark Cave-Ayland 
:

On 01/06/2023 13:07, Michael S. Tsirkin wrote:


On Thu, May 25, 2023 at 05:03:15PM +0100, Mark Cave-Ayland wrote:

On 23/05/2023 20:56, Bernhard Beschow wrote:


This series:
* Removes dead code from omap_uart and i82378
* Resolves redundant code in the i8254 timer devices

v3:
* Drop TYPE_ISA_PARALLEL since they became obsolete by
 
https://lore.kernel.org/qemu-devel/20230522115014.1110840-9-th...@redhat.com/


Oh I didn't see that this had already been merged :/

It's not a reason to block this series, but I'd still like to see your
changes to ParallelState and ISAParallelState merged separately since 
they

are a better match for our QOM coding standards.


v2:
* Export ParallelState and ISAParallelState (Mark)

Testing done:
* `make check`

Bernhard Beschow (3):
 hw/timer/i8254_common: Share "iobase" property via base class
 hw/arm/omap: Remove unused omap_uart_attach()
 hw/isa/i82378: Remove unused "io" attribute

include/hw/arm/omap.h   | 1 -
hw/char/omap_uart.c | 9 -
hw/i386/kvm/i8254.c | 1 -
hw/isa/i82378.c | 1 -
hw/timer/i8254.c| 6 --
hw/timer/i8254_common.c | 6 ++
6 files changed, 6 insertions(+), 18 deletions(-)


Do we know who is going to pick up these series? I can send a PR if 
no-one minds?





Go ahead:

Acked-by: Michael S. Tsirkin 


Thanks Michael! Is there any objection to also including 
https://patchew.org/QEMU/20230531211043.41724-1-shen...@gmail.com/ at the 
same time?


Bernhard: if you are able to submit a rebased version of the ISA_PARALLEL 
cleanups at 
https://patchew.org/QEMU/20230521123049.312349-1-shen...@gmail.com/ I 
think it is worth considering those for inclusion in the PR as well (note 
the comments re: an updated commit message and register definitions, but I 
can't really do this myself because of the missing SoB).


What could I put into the commit message?


That comment came from Zoltan (see 
https://patchew.org/QEMU/20230521123049.312349-1-shen...@gmail.com/20230521123049.312349-5-shen...@gmail.com/#77413450-244e-287b-ad21-e57cb5e2a...@eik.bme.hu). 
Zoltan, would you like to suggest some alternative wording?


If not, feel free to take my message at 
https://patchew.org/QEMU/20230604131450.428797-1-mark.cave-ayl...@ilande.co.uk/20230604131450.428797-14-mark.cave-ayl...@ilande.co.uk/ 
and tweak it accordingly.


I'm OK with your suggestion too or maybe something like:

Export ParallelState to allow embedding it in other devices.

If you just want the

#define TYPE_ISA_PARALLEL "isa-parallel"
OBJECT_DECLARE_SIMPLE_TYPE(ISAParallelState, ISA_PARALLEL)

part to be in a header then moving the structure there as well is not 
necessary, only when you also want to use the structure somewhere where 
its size is needed like adding it to another structure.


I'm also wondering: Why export the structure but not the register 
definitions? Are the register definitions not part of the interface? I 
think these could be used in unittests -- if we had any -- to avoid magic 
numbers.


In theory that could be possible, but it's not something that people have 
requested (yet). From the QEMU perspective a device is something with memory 
regions and gpios that can be wired up within a board, so unless the #defines 
are used directly within ParallelState it doesn't make too much sense to 
export them currently.


On the other hand keeping the structure and defines in the c file ensures 
encapsulation so nothing else will mess with the internals of the object 
and keep these as implementation detail (it's also easier to work with a 
single file than having to look up struct definition elsewhere) so I'd 
prefer keeping things together unless the struct is needed elsewhere. The 
coding style does not clearly say which is preferred, in fact it only 
mentions thet OBJECT_DECLARE_SIMPLE_TYPE ofthen goes in a header but the 
struct is declared separately. The moving of structs to headers only 
started with preferring embedded objects over allocating them so we don't 
have to care about freeing them which needs the struct definition in the 
header breaking encapsulation.


Regards,
BALATON Zoltan



Re: [PATCH 06/10] configure: move SLOF submodule handling to pc-bios/s390-ccw

2023-06-06 Thread Daniel P . Berrangé
On Mon, Jun 05, 2023 at 11:52:19AM +0200, Paolo Bonzini wrote:
> Move the handling of the roms/SLOF submodule out of the main Makefile,
> since we are going to remove submodules from the build process of QEMU.
> 
> Signed-off-by: Paolo Bonzini 
> ---
>  .gitlab-ci.d/buildtest-template.yml |  2 +-
>  configure   |  7 +++
>  pc-bios/s390-ccw/Makefile   | 11 +++
>  3 files changed, 15 insertions(+), 5 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 07/10] pc-bios/s390-ccw: always build network bootloader

2023-06-06 Thread Daniel P . Berrangé
On Mon, Jun 05, 2023 at 11:52:20AM +0200, Paolo Bonzini wrote:
> In the beginning, the network bootloader was considered experimental and
> thus optional, but it is well established nowadays and configure always
> checks for roms/SLOF before compiling pc-bios/s390-ccw.
> 
> Therefore, it makes sense to always build it together with the other
> part of the s390-ccw bios.
> 
> Signed-off-by: Paolo Bonzini 
> ---
>  pc-bios/s390-ccw/Makefile | 5 -
>  1 file changed, 5 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 08/10] meson: subprojects: replace berkeley-{soft,test}float-3 with wraps

2023-06-06 Thread Daniel P . Berrangé
On Mon, Jun 05, 2023 at 11:52:21AM +0200, Paolo Bonzini wrote:
> Unlike other subprojects, these require an overlay directory to include
> meson rules to build the libraries.  The rules are basically lifted
> from tests/fp/meson.build, with a few changes to create platform.h
> and publish a dependency.
> 
> The build defines are passed through a subproject option, and posted
> back to users of the library via the dependency's compile_args.
> 
> The only remaining user of GIT_SUBMODULES and GIT_SUBMODULES_ACTION
> is roms/SLOF, which is used to build pc-bios/s390-ccw.  All other
> roms submodules are only present to satisfy the license on pre-built
> firmware blobs.
> 
> Best reviewed with --color-moved.
> 
> Signed-off-by: Paolo Bonzini 
> ---
>  .gitmodules   |   6 -
>  configure |  27 -
>  scripts/archive-source.sh |  22 +-
>  scripts/make-release  |   2 +-
>  subprojects/.gitignore|   2 +
>  subprojects/berkeley-softfloat-3.wrap |   5 +
>  subprojects/berkeley-testfloat-3.wrap |   5 +
>  .../berkeley-softfloat-3/meson.build  | 339 +++
>  .../berkeley-softfloat-3/meson_options.txt|   1 +
>  .../berkeley-testfloat-3/meson.build  | 220 +++
>  .../berkeley-testfloat-3/meson_options.txt|   1 +
>  tests/fp/meson.build  | 541 +-
>  12 files changed, 590 insertions(+), 581 deletions(-)
>  create mode 100644 subprojects/berkeley-softfloat-3.wrap
>  create mode 100644 subprojects/berkeley-testfloat-3.wrap
>  create mode 100644 subprojects/packagefiles/berkeley-softfloat-3/meson.build
>  create mode 100644 
> subprojects/packagefiles/berkeley-softfloat-3/meson_options.txt
>  create mode 100644 subprojects/packagefiles/berkeley-testfloat-3/meson.build
>  create mode 100644 
> subprojects/packagefiles/berkeley-testfloat-3/meson_options.txt

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 09/10] build: remove git submodule handling from main makefile

2023-06-06 Thread Daniel P . Berrangé
On Mon, Jun 05, 2023 at 11:52:22AM +0200, Paolo Bonzini wrote:
> The only remaining user of submodules at build time is roms/SLOF,
> which is handled in pc-bios/s390-ccw/Makefile.  Remove the relevant
> code from the main makefile.
> 
> Signed-off-by: Paolo Bonzini 
> ---
>  .gitlab-ci.d/buildtest-template.yml |  3 +--
>  Makefile| 10 --
>  configure   |  7 ---
>  meson.build |  1 -
>  4 files changed, 1 insertion(+), 20 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH 10/10] configure: remove --with-git-submodules=

2023-06-06 Thread Daniel P . Berrangé
On Mon, Jun 05, 2023 at 11:52:23AM +0200, Paolo Bonzini wrote:
> Reuse --enable/--disable-download to control git submodules as well.
> Adjust the error messages of git-submodule.sh to refer to the new
> option.
> 
> Signed-off-by: Paolo Bonzini 
> ---
>  configure | 40 +--
>  .../ci/org.centos/stream/8/x86_64/configure   |  1 -
>  scripts/git-submodule.sh  |  8 ++--
>  3 files changed, 12 insertions(+), 37 deletions(-)

Reviewed-by: Daniel P. Berrangé 


With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v3 1/1] hw/arm/sbsa-ref: use XHCI to replace EHCI

2023-06-06 Thread Peter Maydell
On Tue, 6 Jun 2023 at 10:47, Marcin Juszkiewicz
 wrote:
>
> W dniu 5.06.2023 o 11:55, Yuquan Wang pisze:
> > The current sbsa-ref cannot use EHCI controller which is only
> > able to do 32-bit DMA, since sbsa-ref doesn't have RAM below 4GB.
> > Hence, this uses XHCI to provide a usb controller with 64-bit
> > DMA capablity instead of EHCI.
> >
> > Signed-off-by: Yuquan Wang
>
> Reviewed-by: Marcin Juszkiewicz 
>
> Without EDK2 changes Linux behaves same way (no USB found), with EDK2
> changes (EHCI->XHCI) Linux gets USB devices.

So it doesn't break (cause to crash) old EDK2 images? That's a
pleasant surprise.

-- PMM



Re: [PATCH 06/10] configure: move SLOF submodule handling to pc-bios/s390-ccw

2023-06-06 Thread Thomas Huth

On 05/06/2023 11.52, Paolo Bonzini wrote:

Move the handling of the roms/SLOF submodule out of the main Makefile,
since we are going to remove submodules from the build process of QEMU.

Signed-off-by: Paolo Bonzini 
---
  .gitlab-ci.d/buildtest-template.yml |  2 +-
  configure   |  7 +++
  pc-bios/s390-ccw/Makefile   | 11 +++
  3 files changed, 15 insertions(+), 5 deletions(-)


Acked-by: Thomas Huth 




Re: [PATCH 07/10] pc-bios/s390-ccw: always build network bootloader

2023-06-06 Thread Thomas Huth

On 05/06/2023 11.52, Paolo Bonzini wrote:

In the beginning, the network bootloader was considered experimental and
thus optional, but it is well established nowadays and configure always
checks for roms/SLOF before compiling pc-bios/s390-ccw.

Therefore, it makes sense to always build it together with the other
part of the s390-ccw bios.

Signed-off-by: Paolo Bonzini 
---
  pc-bios/s390-ccw/Makefile | 5 -
  1 file changed, 5 deletions(-)

diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 9c5276f8ade..2e8cc015aa0 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -67,12 +67,7 @@ s390-ccw.img: s390-ccw.elf
  
  $(OBJECTS): Makefile
  
-ifneq ($(wildcard $(SRC_PATH)/../../roms/SLOF/lib/libnet),)

  include $(SRC_PATH)/netboot.mak
-else
-s390-netboot.img:
-   @echo "s390-netboot.img not built since roms/SLOF/ is not available."
-endif
  
  ALL_OBJS = $(sort $(OBJECTS) $(NETOBJS) $(LIBCOBJS) $(LIBNETOBJS))

  -include $(ALL_OBJS:%.o=%.d)


Reviewed-by: Thomas Huth 




[PATCH v6 3/9] migration: convert socket backend to accept MigrateAddress struct

2023-06-06 Thread Het Gala
Socket transport backend for 'migrate'/'migrate-incoming' QAPIs accept
new wire protocol of MigrateAddress struct.

It is achived by parsing 'uri' string and storing migration parameters
required for socket connection into well defined SocketAddress struct.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
---
 migration/migration.c | 32 +++-
 migration/socket.c| 34 +-
 migration/socket.h|  7 ---
 3 files changed, 28 insertions(+), 45 deletions(-)

diff --git a/migration/migration.c b/migration/migration.c
index 0eb25bb5a4..0554536b7f 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -479,18 +479,21 @@ static void qemu_start_incoming_migration(const char 
*uri, Error **errp)
 }
 
 qapi_event_send_migration(MIGRATION_STATUS_SETUP);
-if (strstart(uri, "tcp:", &p) ||
-strstart(uri, "unix:", NULL) ||
-strstart(uri, "vsock:", NULL)) {
-socket_start_incoming_migration(p ? p : uri, errp);
+if (channel->transport == MIGRATION_ADDRESS_TYPE_SOCKET) {
+SocketAddress *saddr = &channel->u.socket;
+if (saddr->type == SOCKET_ADDRESS_TYPE_INET ||
+saddr->type == SOCKET_ADDRESS_TYPE_UNIX ||
+saddr->type == SOCKET_ADDRESS_TYPE_VSOCK) {
+socket_start_incoming_migration(saddr, errp);
+} else if (saddr->type == SOCKET_ADDRESS_TYPE_FD) {
+fd_start_incoming_migration(saddr->u.fd.str, errp);
+}
 #ifdef CONFIG_RDMA
 } else if (strstart(uri, "rdma:", &p)) {
 rdma_start_incoming_migration(p, errp);
 #endif
 } else if (strstart(uri, "exec:", &p)) {
 exec_start_incoming_migration(p, errp);
-} else if (strstart(uri, "fd:", &p)) {
-fd_start_incoming_migration(p, errp);
 } else {
 error_setg(errp, "unknown migration protocol: %s", uri);
 }
@@ -1688,7 +1691,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
 return;
 }
 
-if (!migrate_uri_parse(uri, &channel, &local_err)) {
+if (!migrate_uri_parse(uri, &channel, errp)) {
 return;
 }
 
@@ -1704,18 +1707,21 @@ void qmp_migrate(const char *uri, bool has_blk, bool 
blk,
 }
 }
 
-if (strstart(uri, "tcp:", &p) ||
-strstart(uri, "unix:", NULL) ||
-strstart(uri, "vsock:", NULL)) {
-socket_start_outgoing_migration(s, p ? p : uri, &local_err);
+if (channel->transport == MIGRATION_ADDRESS_TYPE_SOCKET) {
+SocketAddress *saddr = &channel->u.socket;
+if (saddr->type == SOCKET_ADDRESS_TYPE_INET ||
+saddr->type == SOCKET_ADDRESS_TYPE_UNIX ||
+saddr->type == SOCKET_ADDRESS_TYPE_VSOCK) {
+socket_start_outgoing_migration(s, saddr, &local_err);
+} else if (saddr->type == SOCKET_ADDRESS_TYPE_FD) {
+fd_start_outgoing_migration(s, saddr->u.fd.str, &local_err);
+}
 #ifdef CONFIG_RDMA
 } else if (strstart(uri, "rdma:", &p)) {
 rdma_start_outgoing_migration(s, p, &local_err);
 #endif
 } else if (strstart(uri, "exec:", &p)) {
 exec_start_outgoing_migration(s, p, &local_err);
-} else if (strstart(uri, "fd:", &p)) {
-fd_start_outgoing_migration(s, p, &local_err);
 } else {
 if (!(has_resume && resume)) {
 yank_unregister_instance(MIGRATION_YANK_INSTANCE);
diff --git a/migration/socket.c b/migration/socket.c
index 1b6f5baefb..8e7430b266 100644
--- a/migration/socket.c
+++ b/migration/socket.c
@@ -108,10 +108,9 @@ out:
 object_unref(OBJECT(sioc));
 }
 
-static void
-socket_start_outgoing_migration_internal(MigrationState *s,
- SocketAddress *saddr,
- Error **errp)
+void socket_start_outgoing_migration(MigrationState *s,
+ SocketAddress *saddr,
+ Error **errp)
 {
 QIOChannelSocket *sioc = qio_channel_socket_new();
 struct SocketConnectData *data = g_new0(struct SocketConnectData, 1);
@@ -135,18 +134,6 @@ socket_start_outgoing_migration_internal(MigrationState *s,
  NULL);
 }
 
-void socket_start_outgoing_migration(MigrationState *s,
- const char *str,
- Error **errp)
-{
-Error *err = NULL;
-SocketAddress *saddr = socket_parse(str, &err);
-if (!err) {
-socket_start_outgoing_migration_internal(s, saddr, &err);
-}
-error_propagate(errp, err);
-}
-
 static void socket_accept_incoming_migration(QIONetListener *listener,
  QIOChannelSocket *cioc,
  gpointer opaque)
@@ -172,9 +159,8 @@ socket_incoming_migration_end(void *opaque)
 object_unref(OBJECT(listener));
 }
 
-static void
-socket_start_incoming_migration_internal(SocketAddress *saddr,
-   

[PATCH v6 8/9] migration: Introduced MigrateChannelList struct to migration code flow.

2023-06-06 Thread Het Gala
Integrated MigrateChannelList with all transport backends (socket, exec
and rdma) for both source and destination migration code flow.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
---
 migration/migration.c | 77 ---
 migration/socket.c|  5 ++-
 2 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/migration/migration.c b/migration/migration.c
index 98b797679b..9a0aec3ecb 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -425,9 +425,10 @@ void migrate_add_address(SocketAddress *address)
 }
 
 static bool migrate_uri_parse(const char *uri,
-  MigrationAddress **channel,
+  MigrationChannel **channel,
   Error **errp)
 {
+g_autoptr(MigrationChannel) val = g_new0(MigrationChannel, 1);
 g_autoptr(MigrationAddress) addrs = g_new0(MigrationAddress, 1);
 SocketAddress *saddr = &addrs->u.socket;
 InetSocketAddress *isock = &addrs->u.rdma;
@@ -463,7 +464,9 @@ static bool migrate_uri_parse(const char *uri,
 return false;
 }
 
-*channel = addrs;
+val->channel_type = MIGRATION_CHANNEL_TYPE_MAIN;
+val->addr = addrs;
+*channel = val;
 return true;
 }
 
@@ -471,7 +474,8 @@ static void qemu_start_incoming_migration(const char *uri, 
bool has_channels,
   MigrationChannelList *channels,
   Error **errp)
 {
-g_autoptr(MigrationAddress) channel = g_new0(MigrationAddress, 1);
+g_autoptr(MigrationChannel) channel = g_new0(MigrationChannel, 1);
+g_autoptr(MigrationAddress) addrs = g_new0(MigrationAddress, 1);
 
 /*
  * Having preliminary checks for uri and channel
@@ -481,20 +485,29 @@ static void qemu_start_incoming_migration(const char 
*uri, bool has_channels,
"exclusive; exactly one of the two should be present in "
"'migrate-incoming' qmp command ");
 return;
-}
-
-if (uri && !migrate_uri_parse(uri, &channel, errp)) {
-return;
+} else if (channels) {
+/* To verify that Migrate channel list has only item */
+if (channels->next) {
+error_setg(errp, "Channel list has more than one entries");
+return;
+}
+channel = channels->value;
+addrs = channel->addr;
+} else {
+/* caller uses the old URI syntax */
+if (uri && !migrate_uri_parse(uri, &channel, errp)) {
+return;
+}
 }
 
 /* transport mechanism not suitable for migration? */
-if (!migration_channels_and_transport_compatible(channel, errp)) {
+if (!migration_channels_and_transport_compatible(addrs, errp)) {
 return;
 }
 
 qapi_event_send_migration(MIGRATION_STATUS_SETUP);
-if (channel->transport == MIGRATION_ADDRESS_TYPE_SOCKET) {
-SocketAddress *saddr = &channel->u.socket;
+if (addrs->transport == MIGRATION_ADDRESS_TYPE_SOCKET) {
+SocketAddress *saddr = &addrs->u.socket;
 if (saddr->type == SOCKET_ADDRESS_TYPE_INET ||
 saddr->type == SOCKET_ADDRESS_TYPE_UNIX ||
 saddr->type == SOCKET_ADDRESS_TYPE_VSOCK) {
@@ -503,11 +516,11 @@ static void qemu_start_incoming_migration(const char 
*uri, bool has_channels,
 fd_start_incoming_migration(saddr->u.fd.str, errp);
 }
 #ifdef CONFIG_RDMA
-} else if (channel->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
-rdma_start_incoming_migration(&channel->u.rdma, errp);
-#endif
-} else if (channel->transport == MIGRATION_ADDRESS_TYPE_EXEC) {
-exec_start_incoming_migration(channel->u.exec.args, errp);
+} else if (addrs->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
+rdma_start_incoming_migration(&addrs->u.rdma, errp);
+ #endif
+} else if (addrs->transport == MIGRATION_ADDRESS_TYPE_EXEC) {
+exec_start_incoming_migration(addrs->u.exec.args, errp);
 } else {
 error_setg(errp, "unknown migration protocol: %s", uri);
 }
@@ -1699,7 +1712,8 @@ void qmp_migrate(const char *uri, bool has_channels,
 {
 Error *local_err = NULL;
 MigrationState *s = migrate_get_current();
-g_autoptr(MigrationAddress) channel = g_new0(MigrationAddress, 1);
+g_autoptr(MigrationChannel) channel = g_new0(MigrationChannel, 1);
+g_autoptr(MigrationAddress) addrs = g_new0(MigrationAddress, 1);
 
 /*
  * Having preliminary checks for uri and channel
@@ -1709,14 +1723,23 @@ void qmp_migrate(const char *uri, bool has_channels,
"exclusive; exactly one of the two should be present in "
"'migrate' qmp command ");
 return;
-}
-
-if (!migrate_uri_parse(uri, &channel, errp)) {
-return;
+} else if (channels) {
+/* To verify that Migrate channel list has only item */
+if (channels->next) {
+error_setg(errp, "Channel list has m

[PATCH v6 4/9] migration: convert rdma backend to accept MigrateAddress struct

2023-06-06 Thread Het Gala
RDMA based transport backend for 'migrate'/'migrate-incoming' QAPIs
accept new wire protocol of MigrateAddress struct.

It is achived by parsing 'uri' string and storing migration parameters
required for RDMA connection into well defined InetSocketAddress struct.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
---
 migration/migration.c |  8 
 migration/rdma.c  | 34 --
 migration/rdma.h  |  6 --
 3 files changed, 20 insertions(+), 28 deletions(-)

diff --git a/migration/migration.c b/migration/migration.c
index 0554536b7f..ff020656fb 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -489,8 +489,8 @@ static void qemu_start_incoming_migration(const char *uri, 
Error **errp)
 fd_start_incoming_migration(saddr->u.fd.str, errp);
 }
 #ifdef CONFIG_RDMA
-} else if (strstart(uri, "rdma:", &p)) {
-rdma_start_incoming_migration(p, errp);
+} else if (channel->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
+rdma_start_incoming_migration(&channel->u.rdma, errp);
 #endif
 } else if (strstart(uri, "exec:", &p)) {
 exec_start_incoming_migration(p, errp);
@@ -1717,8 +1717,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
 fd_start_outgoing_migration(s, saddr->u.fd.str, &local_err);
 }
 #ifdef CONFIG_RDMA
-} else if (strstart(uri, "rdma:", &p)) {
-rdma_start_outgoing_migration(s, p, &local_err);
+} else if (channel->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
+rdma_start_outgoing_migration(s, &channel->u.rdma, &local_err);
 #endif
 } else if (strstart(uri, "exec:", &p)) {
 exec_start_outgoing_migration(s, p, &local_err);
diff --git a/migration/rdma.c b/migration/rdma.c
index dd1c039e6c..4d64fae492 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -319,7 +319,6 @@ typedef struct RDMALocalBlocks {
 typedef struct RDMAContext {
 char *host;
 int port;
-char *host_port;
 
 RDMAWorkRequestData wr_data[RDMA_WRID_MAX];
 
@@ -2455,9 +2454,7 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
 rdma->channel = NULL;
 }
 g_free(rdma->host);
-g_free(rdma->host_port);
 rdma->host = NULL;
-rdma->host_port = NULL;
 }
 
 
@@ -2739,28 +2736,17 @@ static void qemu_rdma_return_path_dest_init(RDMAContext 
*rdma_return_path,
 rdma_return_path->is_return_path = true;
 }
 
-static void *qemu_rdma_data_init(const char *host_port, Error **errp)
+static void *qemu_rdma_data_init(InetSocketAddress *saddr, Error **errp)
 {
 RDMAContext *rdma = NULL;
-InetSocketAddress *addr;
 
-if (host_port) {
+if (saddr) {
 rdma = g_new0(RDMAContext, 1);
 rdma->current_index = -1;
 rdma->current_chunk = -1;
 
-addr = g_new(InetSocketAddress, 1);
-if (!inet_parse(addr, host_port, NULL)) {
-rdma->port = atoi(addr->port);
-rdma->host = g_strdup(addr->host);
-rdma->host_port = g_strdup(host_port);
-} else {
-ERROR(errp, "bad RDMA migration address '%s'", host_port);
-g_free(rdma);
-rdma = NULL;
-}
-
-qapi_free_InetSocketAddress(addr);
+rdma->host = g_strdup(saddr->host);
+rdma->port = atoi(saddr->port);
 }
 
 return rdma;
@@ -3359,6 +3345,7 @@ static int qemu_rdma_accept(RDMAContext *rdma)
 .private_data_len = sizeof(cap),
  };
 RDMAContext *rdma_return_path = NULL;
+g_autoptr(InetSocketAddress) isock = g_new0(InetSocketAddress, 1);
 struct rdma_cm_event *cm_event;
 struct ibv_context *verbs;
 int ret = -EINVAL;
@@ -3374,13 +3361,16 @@ static int qemu_rdma_accept(RDMAContext *rdma)
 goto err_rdma_dest_wait;
 }
 
+isock->host = rdma->host;
+isock->port = g_strdup_printf("%d", rdma->port);
+
 /*
  * initialize the RDMAContext for return path for postcopy after first
  * connection request reached.
  */
 if ((migrate_postcopy() || migrate_return_path())
 && !rdma->is_return_path) {
-rdma_return_path = qemu_rdma_data_init(rdma->host_port, NULL);
+rdma_return_path = qemu_rdma_data_init(isock, NULL);
 if (rdma_return_path == NULL) {
 rdma_ack_cm_event(cm_event);
 goto err_rdma_dest_wait;
@@ -4113,7 +4103,8 @@ static void rdma_accept_incoming_migration(void *opaque)
 }
 }
 
-void rdma_start_incoming_migration(const char *host_port, Error **errp)
+void rdma_start_incoming_migration(InetSocketAddress *host_port,
+   Error **errp)
 {
 int ret;
 RDMAContext *rdma;
@@ -4159,13 +4150,12 @@ err:
 error_propagate(errp, local_err);
 if (rdma) {
 g_free(rdma->host);
-g_free(rdma->host_port);
 }
 g_free(rdma);
 }
 
 void rdma_start_outgoing_migration(void *opaque,
-

[PATCH v6 1/9] migration: introduced 'MigrateAddress' in QAPI for migration wire protocol.

2023-06-06 Thread Het Gala
This patch introduces well defined MigrateAddress struct and its related
child objects.

The existing argument of 'migrate' and 'migrate-incoming' QAPI - 'uri'
is of string type. The current migration flow follows double encoding
scheme for  fetching migration parameters such as 'uri' and this is
not an ideal design.

Motive for intoducing struct level design is to prevent double encoding
of QAPI arguments, as Qemu should be able to directly use the QAPI
arguments without any level of encoding.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
Reviewed-by: Juan Quintela 
Reviewed-by: Daniel P. Berrangé 
---
 qapi/migration.json | 45 +
 1 file changed, 45 insertions(+)

diff --git a/qapi/migration.json b/qapi/migration.json
index 179af0c4d8..e61d25eba2 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -1407,6 +1407,51 @@
 ##
 { 'command': 'migrate-continue', 'data': {'state': 'MigrationStatus'} }
 
+##
+# @MigrationAddressType:
+#
+# The migration stream transport mechanisms.
+#
+# @socket: Migrate via socket.
+#
+# @exec: Direct the migration stream to another process.
+#
+# @rdma: Migrate via RDMA.
+#
+# Since 8.1
+##
+{ 'enum': 'MigrationAddressType',
+  'data': ['socket', 'exec', 'rdma'] }
+
+##
+# @MigrationExecCommand:
+#
+# @args: list of commands for migraton stream execution to a file.
+#
+# Notes:
+#
+# 1. @args[0] needs to be the path to the new program.
+#
+# Since 8.1
+##
+{ 'struct': 'MigrationExecCommand',
+  'data': {'args': [ 'str' ] } }
+
+##
+# @MigrationAddress:
+#
+# Migration endpoint configuration.
+#
+# Since 8.1
+##
+{ 'union': 'MigrationAddress',
+  'base': { 'transport' : 'MigrationAddressType'},
+  'discriminator': 'transport',
+  'data': {
+'socket': 'SocketAddress',
+'exec': 'MigrationExecCommand',
+'rdma': 'InetSocketAddress' } }
+
 ##
 # @migrate:
 #
-- 
2.22.3




[PATCH v6 9/9] migration: adding test case for modified QAPI syntax

2023-06-06 Thread Het Gala
Adding multifd tcp common test case for modified QAPI syntax defined.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
---
 tests/qtest/migration-test.c | 45 
 1 file changed, 45 insertions(+)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b0c355bbd9..310484f6d5 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -2059,6 +2059,32 @@ test_migrate_precopy_tcp_multifd_start_common(QTestState 
*from,
 return NULL;
 }
 
+static void *
+test_migrate_precopy_tcp_multifd_start_new_syntax_common(QTestState *from,
+ QTestState *to,
+ const char *method)
+{
+migrate_set_parameter_int(from, "multifd-channels", 16);
+migrate_set_parameter_int(to, "multifd-channels", 16);
+
+migrate_set_parameter_str(from, "multifd-compression", method);
+migrate_set_parameter_str(to, "multifd-compression", method);
+
+migrate_set_capability(from, "multifd", true);
+migrate_set_capability(to, "multifd", true);
+
+/* Start incoming migration from the 1st socket */
+qtest_qmp_assert_success(to, "{ 'execute': 'migrate-incoming',"
+ "  'arguments': { "
+ "  'channels': [ { 'channeltype': 'main',"
+ "  'addr': { 'transport': 'socket',"
+ "'type': 'inet',"
+ "'host': '127.0.0.1',"
+ "'port': '0' } } ] } }");
+
+return NULL;
+}
+
 static void *
 test_migrate_precopy_tcp_multifd_start(QTestState *from,
QTestState *to)
@@ -2066,6 +2092,14 @@ test_migrate_precopy_tcp_multifd_start(QTestState *from,
 return test_migrate_precopy_tcp_multifd_start_common(from, to, "none");
 }
 
+static void *
+test_migrate_precopy_tcp_multifd_new_syntax_start(QTestState *from,
+  QTestState *to)
+{
+return test_migrate_precopy_tcp_multifd_start_new_syntax_common(from,
+  to, "none");
+}
+
 static void *
 test_migrate_precopy_tcp_multifd_zlib_start(QTestState *from,
 QTestState *to)
@@ -2097,6 +2131,15 @@ static void test_multifd_tcp_none(void)
 test_precopy_common(&args);
 }
 
+static void test_multifd_tcp_new_syntax_none(void)
+{
+MigrateCommon args = {
+.listen_uri = "defer",
+.start_hook = test_migrate_precopy_tcp_multifd_new_syntax_start,
+};
+test_precopy_common(&args);
+}
+
 static void test_multifd_tcp_zlib(void)
 {
 MigrateCommon args = {
@@ -2778,6 +2821,8 @@ int main(int argc, char **argv)
 }
 qtest_add_func("/migration/multifd/tcp/plain/none",
test_multifd_tcp_none);
+qtest_add_func("/migration/multifd/tcp/plain/none",
+   test_multifd_tcp_new_syntax_none);
 /*
  * This test is flaky and sometimes fails in CI and otherwise:
  * don't run unless user opts in via environment variable.
-- 
2.22.3




[PATCH v6 7/9] migration: modify migration_channels_and_uri_compatible() to incorporate newer migration QAPI syntax

2023-06-06 Thread Het Gala
migration_channels_and_uri_compatible() check for transport mechanism
suitable for multifd migration gets executed when the caller calls old
uri syntax. It needs it to be run when using the mordern MigrateCHannel
QAPI syntax too.

After URI -> 'MigrateChannel' object conversion,
migration_channels_and_uri_compatible() ->
migration_channels_and_transport_compatible() passes object as argument
and checks for valid transport mechanism.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
---
 migration/migration.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/migration/migration.c b/migration/migration.c
index a5ca9e0e27..98b797679b 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -103,17 +103,20 @@ static bool migration_needs_multiple_sockets(void)
 return migrate_multifd() || migrate_postcopy_preempt();
 }
 
-static bool uri_supports_multi_channels(const char *uri)
+static bool transport_supports_multi_channels(SocketAddress *saddr)
 {
-return strstart(uri, "tcp:", NULL) || strstart(uri, "unix:", NULL) ||
-   strstart(uri, "vsock:", NULL);
+return saddr->type == SOCKET_ADDRESS_TYPE_INET ||
+   saddr->type == SOCKET_ADDRESS_TYPE_UNIX ||
+   saddr->type == SOCKET_ADDRESS_TYPE_VSOCK;
 }
 
 static bool
-migration_channels_and_uri_compatible(const char *uri, Error **errp)
+migration_channels_and_transport_compatible(MigrationAddress *addrs,
+Error **errp)
 {
 if (migration_needs_multiple_sockets() &&
-!uri_supports_multi_channels(uri)) {
+(addrs->transport == MIGRATION_ADDRESS_TYPE_SOCKET) &&
+!transport_supports_multi_channels(&addrs->u.socket)) {
 error_setg(errp, "Migration requires multi-channel URIs (e.g. tcp)");
 return false;
 }
@@ -480,12 +483,12 @@ static void qemu_start_incoming_migration(const char 
*uri, bool has_channels,
 return;
 }
 
-/* URI is not suitable for migration? */
-if (!migration_channels_and_uri_compatible(uri, errp)) {
+if (uri && !migrate_uri_parse(uri, &channel, errp)) {
 return;
 }
 
-if (uri && !migrate_uri_parse(uri, &channel, errp)) {
+/* transport mechanism not suitable for migration? */
+if (!migration_channels_and_transport_compatible(channel, errp)) {
 return;
 }
 
@@ -1708,12 +1711,12 @@ void qmp_migrate(const char *uri, bool has_channels,
 return;
 }
 
-/* URI is not suitable for migration? */
-if (!migration_channels_and_uri_compatible(uri, errp)) {
+if (!migrate_uri_parse(uri, &channel, errp)) {
 return;
 }
 
-if (!migrate_uri_parse(uri, &channel, errp)) {
+/* transport mechanism not suitable for migration? */
+if (!migration_channels_and_transport_compatible(channel, errp)) {
 return;
 }
 
-- 
2.22.3




[PATCH v6 2/9] migration: convert uri parameter into 'MigrateAddress' struct

2023-06-06 Thread Het Gala
This patch parses 'migrate' and 'migrate-incoming' QAPI's 'uri' parameter
with all the migration connection related information and stores them
inside well defined 'MigrateAddress' struct.

Misc: limit line width in exec.c to 80 characters recommended by Qemu.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
---
 migration/exec.c  |  4 ++--
 migration/exec.h  |  4 
 migration/migration.c | 54 +++
 3 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/migration/exec.c b/migration/exec.c
index 2bf882bbe1..c4a3293246 100644
--- a/migration/exec.c
+++ b/migration/exec.c
@@ -27,7 +27,6 @@
 #include "qemu/cutils.h"
 
 #ifdef WIN32
-const char *exec_get_cmd_path(void);
 const char *exec_get_cmd_path(void)
 {
 g_autofree char *detected_path = g_new(char, MAX_PATH);
@@ -40,7 +39,8 @@ const char *exec_get_cmd_path(void)
 }
 #endif
 
-void exec_start_outgoing_migration(MigrationState *s, const char *command, 
Error **errp)
+void exec_start_outgoing_migration(MigrationState *s, const char *command,
+   Error **errp)
 {
 QIOChannel *ioc;
 
diff --git a/migration/exec.h b/migration/exec.h
index b210ffde7a..736cd71028 100644
--- a/migration/exec.h
+++ b/migration/exec.h
@@ -19,6 +19,10 @@
 
 #ifndef QEMU_MIGRATION_EXEC_H
 #define QEMU_MIGRATION_EXEC_H
+
+#ifdef WIN32
+const char *exec_get_cmd_path(void);
+#endif
 void exec_start_incoming_migration(const char *host_port, Error **errp);
 
 void exec_start_outgoing_migration(MigrationState *s, const char *host_port,
diff --git a/migration/migration.c b/migration/migration.c
index dc05c6f6ea..0eb25bb5a4 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -64,6 +64,7 @@
 #include "yank_functions.h"
 #include "sysemu/qtest.h"
 #include "options.h"
+#include "qemu/sockets.h"
 
 static NotifierList migration_state_notifiers =
 NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
@@ -420,15 +421,63 @@ void migrate_add_address(SocketAddress *address)
   QAPI_CLONE(SocketAddress, address));
 }
 
+static bool migrate_uri_parse(const char *uri,
+  MigrationAddress **channel,
+  Error **errp)
+{
+g_autoptr(MigrationAddress) addrs = g_new0(MigrationAddress, 1);
+SocketAddress *saddr = &addrs->u.socket;
+InetSocketAddress *isock = &addrs->u.rdma;
+strList **tail = &addrs->u.exec.args;
+
+if (strstart(uri, "exec:", NULL)) {
+addrs->transport = MIGRATION_ADDRESS_TYPE_EXEC;
+#ifdef WIN32
+QAPI_LIST_APPEND(tail, g_strdup(exec_get_cmd_path()));
+#else
+QAPI_LIST_APPEND(tail, g_strdup("/bin/sh"));
+#endif
+QAPI_LIST_APPEND(tail, g_strdup("-c"));
+QAPI_LIST_APPEND(tail, g_strdup(uri + strlen("exec:")));
+} else if (strstart(uri, "rdma:", NULL)) {
+if (inet_parse(isock, uri + strlen("rdma:"), errp)) {
+qapi_free_InetSocketAddress(isock);
+return false;
+}
+addrs->transport = MIGRATION_ADDRESS_TYPE_RDMA;
+} else if (strstart(uri, "tcp:", NULL) ||
+strstart(uri, "unix:", NULL) ||
+strstart(uri, "vsock:", NULL) ||
+strstart(uri, "fd:", NULL)) {
+addrs->transport = MIGRATION_ADDRESS_TYPE_SOCKET;
+saddr = socket_parse(uri, errp);
+if (!saddr) {
+qapi_free_SocketAddress(saddr);
+return false;
+}
+} else {
+error_setg(errp, "unknown migration protocol: %s", uri);
+return false;
+}
+
+*channel = addrs;
+return true;
+}
+
 static void qemu_start_incoming_migration(const char *uri, Error **errp)
 {
 const char *p = NULL;
+g_autoptr(MigrationAddress) channel = g_new0(MigrationAddress, 1);
 
 /* URI is not suitable for migration? */
 if (!migration_channels_and_uri_compatible(uri, errp)) {
 return;
 }
 
+if (uri && !migrate_uri_parse(uri, &channel, errp)) {
+return;
+}
+
 qapi_event_send_migration(MIGRATION_STATUS_SETUP);
 if (strstart(uri, "tcp:", &p) ||
 strstart(uri, "unix:", NULL) ||
@@ -1632,12 +1681,17 @@ void qmp_migrate(const char *uri, bool has_blk, bool 
blk,
 Error *local_err = NULL;
 MigrationState *s = migrate_get_current();
 const char *p = NULL;
+g_autoptr(MigrationAddress) channel = g_new0(MigrationAddress, 1);
 
 /* URI is not suitable for migration? */
 if (!migration_channels_and_uri_compatible(uri, errp)) {
 return;
 }
 
+if (!migrate_uri_parse(uri, &channel, &local_err)) {
+return;
+}
+
 if (!migrate_prepare(s, has_blk && blk, has_inc && inc,
  has_resume && resume, errp)) {
 /* Error detected, put into errp */
-- 
2.22.3




[PATCH v6 6/9] migration: modified migration QAPIs to accept 'channels' argument for migration

2023-06-06 Thread Het Gala
MigrateChannelList allows to connect accross multiple interfaces. Added
MigrateChannelList struct as argument to migration QAPIs.

Future patchset series plans to include multiple MigrateChannels
for multiple interfaces to be connected. That is the reason,
'MigrateChannelList'
is the preferred choice of argument over 'MigrateChannel' and making
migration QAPIs future proof.

For current patchset series, have limited the size of the list to single
element (single interface) as runtime check.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
---
 migration/migration-hmp-cmds.c |  16 +++--
 migration/migration.c  |  34 --
 qapi/migration.json| 109 -
 softmmu/vl.c   |   2 +-
 4 files changed, 147 insertions(+), 14 deletions(-)

diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
index 9885d7c9f7..5f04598202 100644
--- a/migration/migration-hmp-cmds.c
+++ b/migration/migration-hmp-cmds.c
@@ -423,10 +423,12 @@ void hmp_migrate_incoming(Monitor *mon, const QDict 
*qdict)
 {
 Error *err = NULL;
 const char *uri = qdict_get_str(qdict, "uri");
+MigrationChannelList *caps = NULL;
+g_autoptr(MigrationChannel) channel = g_new0(MigrationChannel, 1);
 
-qmp_migrate_incoming(uri, &err);
-
-hmp_handle_error(mon, err);
+QAPI_LIST_PREPEND(caps, channel);
+qmp_migrate_incoming(uri, false, caps, &err);
+qapi_free_MigrationChannelList(caps);
 }
 
 void hmp_migrate_recover(Monitor *mon, const QDict *qdict)
@@ -704,9 +706,13 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
 bool resume = qdict_get_try_bool(qdict, "resume", false);
 const char *uri = qdict_get_str(qdict, "uri");
 Error *err = NULL;
+MigrationChannelList *caps = NULL;
+g_autoptr(MigrationChannel) channel = g_new0(MigrationChannel, 1);
 
-qmp_migrate(uri, !!blk, blk, !!inc, inc,
-false, false, true, resume, &err);
+QAPI_LIST_PREPEND(caps, channel);
+qmp_migrate(uri, false, caps, !!blk, blk, !!inc, inc,
+ false, false, true, resume, &err);
+qapi_free_MigrationChannelList(caps);
 if (hmp_handle_error(mon, err)) {
 return;
 }
diff --git a/migration/migration.c b/migration/migration.c
index f482de5df3..a5ca9e0e27 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -464,10 +464,22 @@ static bool migrate_uri_parse(const char *uri,
 return true;
 }
 
-static void qemu_start_incoming_migration(const char *uri, Error **errp)
+static void qemu_start_incoming_migration(const char *uri, bool has_channels,
+  MigrationChannelList *channels,
+  Error **errp)
 {
 g_autoptr(MigrationAddress) channel = g_new0(MigrationAddress, 1);
 
+/*
+ * Having preliminary checks for uri and channel
+ */
+if (uri && has_channels) {
+error_setg(errp, "'uri' and 'channels' arguments are mutually "
+   "exclusive; exactly one of the two should be present in "
+   "'migrate-incoming' qmp command ");
+return;
+}
+
 /* URI is not suitable for migration? */
 if (!migration_channels_and_uri_compatible(uri, errp)) {
 return;
@@ -1489,7 +1501,8 @@ void migrate_del_blocker(Error *reason)
 migration_blockers = g_slist_remove(migration_blockers, reason);
 }
 
-void qmp_migrate_incoming(const char *uri, Error **errp)
+void qmp_migrate_incoming(const char *uri, bool has_channels,
+  MigrationChannelList *channels, Error **errp)
 {
 Error *local_err = NULL;
 static bool once = true;
@@ -1507,7 +1520,7 @@ void qmp_migrate_incoming(const char *uri, Error **errp)
 return;
 }
 
-qemu_start_incoming_migration(uri, &local_err);
+qemu_start_incoming_migration(uri, has_channels, channels, &local_err);
 
 if (local_err) {
 yank_unregister_instance(MIGRATION_YANK_INSTANCE);
@@ -1543,7 +1556,7 @@ void qmp_migrate_recover(const char *uri, Error **errp)
  * only re-setup the migration stream and poke existing migration
  * to continue using that newly established channel.
  */
-qemu_start_incoming_migration(uri, errp);
+qemu_start_incoming_migration(uri, false, NULL, errp);
 }
 
 void qmp_migrate_pause(Error **errp)
@@ -1676,7 +1689,8 @@ static bool migrate_prepare(MigrationState *s, bool blk, 
bool blk_inc,
 return true;
 }
 
-void qmp_migrate(const char *uri, bool has_blk, bool blk,
+void qmp_migrate(const char *uri, bool has_channels,
+ MigrationChannelList *channels, bool has_blk, bool blk,
  bool has_inc, bool inc, bool has_detach, bool detach,
  bool has_resume, bool resume, Error **errp)
 {
@@ -1684,6 +1698,16 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
 MigrationState *s = migrate_get_current();
 g_autoptr(MigrationAddress) channel = g_new0(

[PATCH v6 0/9] migration: Modify 'migrate' and 'migrate-incoming' QAPI commands for migration

2023-06-06 Thread Het Gala
This is v6 patchset of modified 'migrate' and 'migrate-incoming' QAPI design
for upstream review.

Would like to thank all the maintainers that actively participated in the v5
patchset discussion and gave insightful suggestions to improve the patches.


Link to previous upstream community patchset links:
v1: https://lists.gnu.org/archive/html/qemu-devel/2022-12/msg04339.html
v2: https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg02106.html
v3: https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg02473.html
v4: https://lists.gnu.org/archive/html/qemu-devel/2023-05/msg03064.html
v5: https://lists.gnu.org/archive/html/qemu-devel/2023-05/msg04845.html

v5 -> v6 changelog:
---
- Most changes on the QAPI side, i.e. Patch 1 and Patch 6.
- Formatting, improvemnt around migration qapi documentation.
- Resolved build issue while building Qemu with compiler as Clang.
- Restructured migration unit tests due to recent change aca0406
  (tests/qtest: replace wait_command() with qtest..) 

Abstract:
-

Current QAPI 'migrate' command design (for initiating a migration
stream) contains information regarding different migrate transport mechanism
(tcp / unix / exec), dest-host IP address, and binding port number in form of
a string. Thus the design does seem to have some design issues. Some of the
issues, stated below are:

1. Use of string URIs is a data encoding scheme within a data encoding scheme.
   QEMU code should directly be able to work with the results from QAPI,
   without resorting to do a second level of parsing (eg. socket_parse()).
2. For features / parameters related to migration, the migration tunables needs
   to be defined and updated upfront. For example, 'migrate-set-capability'
   and 'migrate-set-parameter' is required to enable multifd capability and
   multifd-number of channels respectively. Instead, 'Multifd-channels' can
   directly be represented as a single additional parameter to 'migrate'
   QAPI. 'migrate-set-capability' and 'migrate-set-parameter' commands could
   be used for runtime tunables that need setting after migration has already
   started.

The current patchset focuses on solving the first problem of multi-level
encoding of URIs. The patch defines 'migrate' command as a QAPI discriminated
union for the various transport backends (like socket, exec and rdma), and on
basis of transport backends, different migration parameters are defined.

(uri) string -->  (channel) Channel-type
Transport-type
Migration parameters based on transport type
--
Het Gala (9):
  migration: introduced 'MigrateAddress' in QAPI for migration wire
protocol.
  migration: convert uri parameter into 'MigrateAddress' struct
  migration: convert socket backend to accept MigrateAddress struct
  migration: convert rdma backend to accept MigrateAddress struct
  migration: convert exec backend to accept MigrateAddress struct.
  migration: modified migration QAPIs to accept 'channels' argument for
migration
  migration: modify migration_channels_and_uri_compatible() to
incorporate newer migration QAPI syntax
  migration: Introduced MigrateChannelList struct to migration code
flow.
  migration: adding test case for modified QAPI syntax

 migration/exec.c   |  72 +
 migration/exec.h   |   8 +-
 migration/migration-hmp-cmds.c |  16 ++-
 migration/migration.c  | 182 ++---
 migration/rdma.c   |  34 +++---
 migration/rdma.h   |   6 +-
 migration/socket.c |  39 ++-
 migration/socket.h |   7 +-
 qapi/migration.json| 154 +++-
 softmmu/vl.c   |   2 +-
 tests/qtest/migration-test.c   |  45 
 11 files changed, 439 insertions(+), 126 deletions(-)

-- 
2.22.3




[PATCH v6 5/9] migration: convert exec backend to accept MigrateAddress struct.

2023-06-06 Thread Het Gala
Exec transport backend for 'migrate'/'migrate-incoming' QAPIs accept
new wire protocol of MigrateAddress struct.

It is achived by parsing 'uri' string and storing migration parameters
required for exec connection into strList struct.

Suggested-by: Aravind Retnakaran 
Signed-off-by: Het Gala 
---
 migration/exec.c  | 70 ++-
 migration/exec.h  |  4 +--
 migration/migration.c | 10 +++
 3 files changed, 56 insertions(+), 28 deletions(-)

diff --git a/migration/exec.c b/migration/exec.c
index c4a3293246..8bc321c66b 100644
--- a/migration/exec.c
+++ b/migration/exec.c
@@ -39,21 +39,50 @@ const char *exec_get_cmd_path(void)
 }
 #endif
 
-void exec_start_outgoing_migration(MigrationState *s, const char *command,
+/* provides the length of strList */
+static int
+str_list_length(strList *list)
+{
+int len = 0;
+strList *elem;
+
+for (elem = list; elem != NULL; elem = elem->next) {
+len++;
+}
+
+return len;
+}
+
+static void
+init_exec_array(strList *command, char **argv, Error **errp)
+{
+int i = 0;
+strList *lst;
+
+for (lst = command; lst; lst = lst->next) {
+argv[i++] = lst->value;
+}
+
+argv[i] = NULL;
+return;
+}
+
+void exec_start_outgoing_migration(MigrationState *s, strList *command,
Error **errp)
 {
 QIOChannel *ioc;
 
-#ifdef WIN32
-const char *argv[] = { exec_get_cmd_path(), "/c", command, NULL };
-#else
-const char *argv[] = { "/bin/sh", "-c", command, NULL };
-#endif
+int length = str_list_length(command);
+g_auto(GStrv) argv = (char **) g_new0(const char *, length);
 
-trace_migration_exec_outgoing(command);
-ioc = QIO_CHANNEL(qio_channel_command_new_spawn(argv,
-O_RDWR,
-errp));
+init_exec_array(command, argv, errp);
+g_autofree char *new_command = g_strjoinv(" ", (char **)argv);
+
+trace_migration_exec_outgoing(new_command);
+ioc = QIO_CHANNEL(
+qio_channel_command_new_spawn((const char * const *) argv,
+  O_RDWR,
+  errp));
 if (!ioc) {
 return;
 }
@@ -72,20 +101,21 @@ static gboolean exec_accept_incoming_migration(QIOChannel 
*ioc,
 return G_SOURCE_REMOVE;
 }
 
-void exec_start_incoming_migration(const char *command, Error **errp)
+void exec_start_incoming_migration(strList *command, Error **errp)
 {
 QIOChannel *ioc;
 
-#ifdef WIN32
-const char *argv[] = { exec_get_cmd_path(), "/c", command, NULL };
-#else
-const char *argv[] = { "/bin/sh", "-c", command, NULL };
-#endif
+int length = str_list_length(command);
+g_auto(GStrv) argv = (char **) g_new0(const char *, length);
+
+init_exec_array(command, argv, errp);
+g_autofree char *new_command = g_strjoinv(" ", (char **)argv);
 
-trace_migration_exec_incoming(command);
-ioc = QIO_CHANNEL(qio_channel_command_new_spawn(argv,
-O_RDWR,
-errp));
+trace_migration_exec_incoming(new_command);
+ioc = QIO_CHANNEL(
+qio_channel_command_new_spawn((const char * const *) argv,
+  O_RDWR,
+  errp));
 if (!ioc) {
 return;
 }
diff --git a/migration/exec.h b/migration/exec.h
index 736cd71028..3107f205e3 100644
--- a/migration/exec.h
+++ b/migration/exec.h
@@ -23,8 +23,8 @@
 #ifdef WIN32
 const char *exec_get_cmd_path(void);
 #endif
-void exec_start_incoming_migration(const char *host_port, Error **errp);
+void exec_start_incoming_migration(strList *host_port, Error **errp);
 
-void exec_start_outgoing_migration(MigrationState *s, const char *host_port,
+void exec_start_outgoing_migration(MigrationState *s, strList *host_port,
Error **errp);
 #endif
diff --git a/migration/migration.c b/migration/migration.c
index ff020656fb..f482de5df3 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -466,7 +466,6 @@ static bool migrate_uri_parse(const char *uri,
 
 static void qemu_start_incoming_migration(const char *uri, Error **errp)
 {
-const char *p = NULL;
 g_autoptr(MigrationAddress) channel = g_new0(MigrationAddress, 1);
 
 /* URI is not suitable for migration? */
@@ -492,8 +491,8 @@ static void qemu_start_incoming_migration(const char *uri, 
Error **errp)
 } else if (channel->transport == MIGRATION_ADDRESS_TYPE_RDMA) {
 rdma_start_incoming_migration(&channel->u.rdma, errp);
 #endif
-} else if (strstart(uri, "exec:", &p)) {
-exec_start_incoming_migration(p, errp);
+} else if (channel->transport == MIGRATION_ADDRESS_TYPE_EXEC) {
+exec_start_incoming_migration(channel->u.exec.args, errp);
 } else {
 error_setg(errp, "unknown migration pr

[PATCH v2 1/2] migration: enfocre multifd and postcopy preempt to be set before incoming

2023-06-06 Thread Wei Wang
qemu_start_incoming_migration needs to check the number of multifd
channels or postcopy ram channels to configure the backlog parameter (i.e.
the maximum length to which the queue of pending connections for sockfd
may grow) of listen(). So enforce the usage of postcopy-preempt and
multifd as below:
- need to use "-incoming defer" on the destination; and
- set_capability and set_parameter need to be done before migrate_incoming

Otherwise, disable the use of the features and report error messages to
remind users to adjust the commands.

Signed-off-by: Wei Wang 
Reviewed-by: Peter Xu 
---
 migration/options.c | 36 +++-
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/migration/options.c b/migration/options.c
index b62ab30cd5..01403e5eaa 100644
--- a/migration/options.c
+++ b/migration/options.c
@@ -415,6 +415,11 @@ INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
 MIGRATION_CAPABILITY_VALIDATE_UUID,
 MIGRATION_CAPABILITY_ZERO_COPY_SEND);
 
+static bool migrate_incoming_started(void)
+{
+return !!migration_incoming_get_current()->transport_data;
+}
+
 /**
  * @migration_caps_check - check capability compatibility
  *
@@ -538,6 +543,12 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, 
Error **errp)
 error_setg(errp, "Postcopy preempt not compatible with compress");
 return false;
 }
+
+if (migrate_incoming_started()) {
+error_setg(errp,
+   "Postcopy preempt must be set before incoming starts");
+return false;
+}
 }
 
 if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
@@ -545,6 +556,10 @@ bool migrate_caps_check(bool *old_caps, bool *new_caps, 
Error **errp)
 error_setg(errp, "Multifd is not compatible with compress");
 return false;
 }
+if (migrate_incoming_started()) {
+error_setg(errp, "Multifd must be set before incoming starts");
+return false;
+}
 }
 
 return true;
@@ -998,11 +1013,22 @@ bool migrate_params_check(MigrationParameters *params, 
Error **errp)
 
 /* x_checkpoint_delay is now always positive */
 
-if (params->has_multifd_channels && (params->multifd_channels < 1)) {
-error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
-   "multifd_channels",
-   "a value between 1 and 255");
-return false;
+if (params->has_multifd_channels) {
+if (params->multifd_channels < 1) {
+error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+   "multifd_channels",
+   "a value between 1 and 255");
+return false;
+}
+if (migrate_incoming_started()) {
+MigrationState *ms = migrate_get_current();
+
+ms->capabilities[MIGRATION_CAPABILITY_MULTIFD] = false;
+error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+   "multifd_channels",
+   "must be set before incoming starts");
+return false;
+}
 }
 
 if (params->has_multifd_zlib_level &&
-- 
2.27.0




[PATCH v2 2/2] qtest/migration-tests.c: use "-incoming defer" for postcopy tests

2023-06-06 Thread Wei Wang
The Postcopy preempt capability is expected to be set before incoming
starts, so change the postcopy tests to start with deferred incoming and
call migrate-incoming after the cap has been set.

Why the existing tests (without this patch) didn't fail?
There could be two reasons:
1) "backlog" specifies the number of pending connections. As long as the
   server accepts the connections faster than the clients side connecting,
   connection will succeed. For the preempt test, it uses only 2 channels,
   so very likely to not have pending connections.
2) per my tests (on kernel 6.2), the number of pending connections allowed
   is actually "backlog + 1", which is 2 in this case.
That said, the implementation of socket_start_incoming_migration_internal
expects "migrate defer" to be used, and for safety, change the test to
work with the expected usage.

Signed-off-by: Wei Wang 
Reviewed-by: Peter Xu 
---
 tests/qtest/migration-test.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index b0c355bbd9..cbdbc932de 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1143,10 +1143,11 @@ static int migrate_postcopy_prepare(QTestState 
**from_ptr,
 QTestState **to_ptr,
 MigrateCommon *args)
 {
-g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+g_autofree char *uri = NULL;
 QTestState *from, *to;
+QDict *rsp;
 
-if (test_migrate_start(&from, &to, uri, &args->start)) {
+if (test_migrate_start(&from, &to, "defer", &args->start)) {
 return -1;
 }
 
@@ -1165,9 +1166,14 @@ static int migrate_postcopy_prepare(QTestState 
**from_ptr,
 
 migrate_ensure_non_converge(from);
 
+rsp = wait_command(to, "{ 'execute': 'migrate-incoming',"
+   "  'arguments': { 'uri': 'tcp:127.0.0.1:0' }}");
+qobject_unref(rsp);
+
 /* Wait for the first serial output from the source */
 wait_for_serial("src_serial");
 
+uri = migrate_get_socket_address(to, "socket-address");
 migrate_qmp(from, uri, "{}");
 
 wait_for_migration_pass(from);
-- 
2.27.0




[PATCH RESEND v2 0/2] Enfore multifd and postcopy preempt setting

2023-06-06 Thread Wei Wang
Setting the cap/params of multifd and postcopy preempt is expected
to be done before incoming starts, as the number of multifd channels or
postcopy ram channels is used by qemu_start_incoming_migration (to
listen on the number of pending connections).

Enfocre the cap/params of multifd and postcopy preempt to be set
before incoming. If not, disable the feature and return with error
messages to remind users to adjust the commands. Fix the
qtest/migration-test to do so.

v2 RESEND change:
- Only patch commit change with more explanations

Wei Wang (2):
  migration: enfocre multifd and postcopy preempt to be set before
incoming
  qtest/migration-tests.c: use "-incoming defer" for postcopy tests

 migration/options.c  | 36 +++-
 tests/qtest/migration-test.c | 10 --
 2 files changed, 39 insertions(+), 7 deletions(-)

-- 
2.27.0




Re: [PATCH v3 1/1] hw/arm/sbsa-ref: use XHCI to replace EHCI

2023-06-06 Thread Marcin Juszkiewicz

W dniu 6.06.2023 o 12:04, Peter Maydell pisze:

On Tue, 6 Jun 2023 at 10:47, Marcin Juszkiewicz
 wrote:


W dniu 5.06.2023 o 11:55, Yuquan Wang pisze:

The current sbsa-ref cannot use EHCI controller which is only
able to do 32-bit DMA, since sbsa-ref doesn't have RAM below 4GB.
Hence, this uses XHCI to provide a usb controller with 64-bit
DMA capablity instead of EHCI.

Signed-off-by: Yuquan Wang


Reviewed-by: Marcin Juszkiewicz 

Without EDK2 changes Linux behaves same way (no USB found), with EDK2
changes (EHCI->XHCI) Linux gets USB devices.


So it doesn't break (cause to crash) old EDK2 images? That's a
pleasant surprise.


In both cases with not modified EDK2 Linux behaves the same:

ehci-platform LNRO0D20:00: Error: DMA mask configuration failed
ehci-platform: probe of LNRO0D20:00 failed with error -5





Re: [PATCH] target/riscv/vector_helper.c: Remove the check for extra tail elements

2023-06-06 Thread Daniel Henrique Barboza

Hi,


On 6/6/23 05:34, Xiao Wang wrote:

Commit 752614cab8e6 ("target/riscv: rvv: Add tail agnostic for vector
load / store instructions") added an extra check for LMUL fragmentation,
intended for setting the "rest tail elements" in the last register for a
segment load insn.

Actually, the max_elements derived in vext_ld*() won't be a fraction of
vector register size, since the lmul encoded in desc is emul, which has
already been adjusted to 1 for LMUL fragmentation case by vext_get_emul()
in trans_rvv.c.inc, for ld_stride(), ld_us(), ld_index() and ldff().

Besides, vext_get_emul() has also taken EEW/SEW into consideration, so no
need to call vext_get_total_elems() which would base on the emul to derive
another emul, the second emul would be incorrect when esz differs from sew.

Thus this patch removes the check for extra tail elements.

Fixes: 752614cab8e6 ("target/riscv: rvv: Add tail agnostic for vector load / store 
instructions")

Signed-off-by: Xiao Wang 
---
  target/riscv/vector_helper.c | 21 ++---
  1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index f4d0438988..56a79bb5fa 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -264,26 +264,17 @@ GEN_VEXT_ST_ELEM(ste_h, int16_t, H2, stw)
  GEN_VEXT_ST_ELEM(ste_w, int32_t, H4, stl)
  GEN_VEXT_ST_ELEM(ste_d, int64_t, H8, stq)
  
-static void vext_set_tail_elems_1s(CPURISCVState *env, target_ulong vl,

-   void *vd, uint32_t desc, uint32_t nf,
+static void vext_set_tail_elems_1s(target_ulong vl, void *vd,
+   uint32_t desc, uint32_t nf,
 uint32_t esz, uint32_t max_elems)
  {
-uint32_t total_elems = vext_get_total_elems(env, desc, esz);
-uint32_t vlenb = riscv_cpu_cfg(env)->vlen >> 3;
  uint32_t vta = vext_vta(desc);
-uint32_t registers_used;
  int k;
  
  for (k = 0; k < nf; ++k) {

  vext_set_elems_1s(vd, vta, (k * max_elems + vl) * esz,
(k * max_elems + max_elems) * esz);
  }
-
-if (nf * max_elems % total_elems != 0) {
-registers_used = ((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
-vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
-  registers_used * vlenb);
-}
  }



Can you please rebase it on top of master? This function has at least one
change (a vta check right at the start) that isn't accounted for in this
patch.

Code LGTM otherwise. Thanks,


Daniel

  
  /*

@@ -319,7 +310,7 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
  }
  env->vstart = 0;
  
-vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);

+vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
  }
  
  #define GEN_VEXT_LD_STRIDE(NAME, ETYPE, LOAD_FN)\

@@ -378,7 +369,7 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState 
*env, uint32_t desc,
  }
  env->vstart = 0;
  
-vext_set_tail_elems_1s(env, evl, vd, desc, nf, esz, max_elems);

+vext_set_tail_elems_1s(evl, vd, desc, nf, esz, max_elems);
  }
  
  /*

@@ -499,7 +490,7 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
  }
  env->vstart = 0;
  
-vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);

+vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
  }
  
  #define GEN_VEXT_LD_INDEX(NAME, ETYPE, INDEX_FN, LOAD_FN)  \

@@ -629,7 +620,7 @@ ProbeSuccess:
  }
  env->vstart = 0;
  
-vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);

+vext_set_tail_elems_1s(env->vl, vd, desc, nf, esz, max_elems);
  }
  
  #define GEN_VEXT_LDFF(NAME, ETYPE, LOAD_FN)   \




Re: [PULL 31/35] hw/intc/allwinner-a10-pic: Don't use set_bit()/clear_bit()

2023-06-06 Thread Peter Maydell
On Mon, 5 Jun 2023 at 14:35, Guenter Roeck  wrote:
>
> On 6/5/23 02:40, Peter Maydell wrote:
> > If you can provide a link to the zImage and the dtb to reproduce
> > as well, that would be helpful.
>
>
> Please see http://server.roeck-us.net/qemu/arm-v7/.

Thanks. I've identified the cause of the regression; will send
a patch shortly.

-- PMM



[PATCH 2/2] hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels

2023-06-06 Thread Peter Maydell
QEMU allows qemu_irq lines to transfer arbitrary integers.  However
the convention is that for a simple IRQ line the values transferred
are always 0 and 1.  The A10 SD controller device instead assumes a
0-vs-non-0 convention, which happens to work with the interrupt
controller it is wired up to.

Coerce the value to boolean to follow our usual convention.

Signed-off-by: Peter Maydell 
---
 hw/sd/allwinner-sdhost.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c
index 92a0f42708d..62df8f3d396 100644
--- a/hw/sd/allwinner-sdhost.c
+++ b/hw/sd/allwinner-sdhost.c
@@ -191,7 +191,7 @@ static void allwinner_sdhost_update_irq(AwSdHostState *s)
 }
 
 trace_allwinner_sdhost_update_irq(irq);
-qemu_set_irq(s->irq, irq);
+qemu_set_irq(s->irq, !!irq);
 }
 
 static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,
-- 
2.34.1




[PATCH 1/2] hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1

2023-06-06 Thread Peter Maydell
In commit 2c5fa0778c3b430 we fixed an endianness bug in the Allwinner
A10 PIC model; however in the process we introduced a regression.
This is because the old code was robust against the incoming 'level'
argument being something other than 0 or 1, whereas the new code was
not.

In particular, the allwinner-sdhost code treats its IRQ line
as 0-vs-non-0 rather than 0-vs-1, so when the SD controller
set its IRQ line for any reason other than transmit the
interrupt controller would ignore it. The observed effect
was a guest timeout when rebooting the guest kernel.

Handle level values other than 0 or 1, to restore the old
behaviour.

Fixes: 2c5fa0778c3b430 ("hw/intc/allwinner-a10-pic: Don't use 
set_bit()/clear_bit()")
Cc: qemu-sta...@nongnu.org
Signed-off-by: Peter Maydell 
---
 hw/intc/allwinner-a10-pic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
index 4875e68ba6a..d0bf8d545ba 100644
--- a/hw/intc/allwinner-a10-pic.c
+++ b/hw/intc/allwinner-a10-pic.c
@@ -51,7 +51,7 @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int 
level)
 AwA10PICState *s = opaque;
 uint32_t *pending_reg = &s->irq_pending[irq / 32];
 
-*pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
+*pending_reg = deposit32(*pending_reg, irq % 32, 1, !!level);
 aw_a10_pic_update(s);
 }
 
-- 
2.34.1




[PATCH 0/2] allwinner-a10: Fix interrupt controller regression

2023-06-06 Thread Peter Maydell
In commit 2c5fa0778c3b430 we fixed an endianness bug in the Allwinner
A10 PIC model; however in the process we introduced a regression.
This is because the old code was robust against the incoming 'level'
argument being something other than 0 or 1, whereas the new code was
not.

In particular, the allwinner-sdhost code treats its IRQ line as
0-vs-non-0 rather than 0-vs-1, so when the SD controller set its IRQ
line for any reason other than transmit the interrupt controller would
ignore it. The observed effect was a guest timeout when rebooting the
guest kernel.

Patch 1 in this series fixes the regression by restoring the
old behaviour of aw_a10_pic_set_irq() for non-0 levels; it
is stable material.

Patch 2 changes the SD controller to follow our usual convention that
simple IRQ lines only send 0 or 1; this isn't strictly necessary with
patch 1, but it avoids future surprises. It doesn't need to go to
stable.

thanks
-- PMM

Peter Maydell (2):
  hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
  hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels

 hw/intc/allwinner-a10-pic.c | 2 +-
 hw/sd/allwinner-sdhost.c| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

-- 
2.34.1




Re: [PULL 02/17] block: Collapse padded I/O vecs exceeding IOV_MAX

2023-06-06 Thread Michael Tokarev

06.06.2023 11:45, Hanna Czenczek wrote:

On 06.06.23 10:00, Michael Tokarev wrote:

..

This seems to be over-complicated, both of them, no?


I would have preferred to have this discussion while the patch was still on-list for review (this specific version was for two months, counting from 
the first version was three).  Do you think it is so complicated and thus bug-prone that we must revert this series now and try the other route?


Well. I come across this change only now when reviewing patches applied to 
qemu/master.
This one fixes a real bug which people were hitting, which is also quite 
difficult to
diagnose and which has a possibility for data corruption and other 
"interesting" effects,
so it is quite a natural thing to at least think about back-porting this change 
to
previous -stable qemu release.  Bugs like this should be fixed in -stable IMHO.

Sadly I haven't noticed this change before, sure I'd have exactly the same 
thoughts
by then, and would be glad to help analyzing other parts of the code with 
potential
of having issues with IOV_MAX-exceeding vectors.

I can agree that perhaps the other route could have been simpler, but now we already have patches that are reviewed and in master, which solve the 
problem.  So I won’t spend more time on tackling this issue from another angle.  If you are happy to do so, patches are always welcome.


That's a good point too.

Thanks,

/mjt




Re: [PATCH v3 03/15] hw/pci: Add a pci_device_iommu_memory_region() helper

2023-06-06 Thread Joao Martins
On 05/06/2023 17:57, Peter Xu wrote:
> On Tue, May 30, 2023 at 06:59:25PM +0100, Joao Martins wrote:
>> Much like pci_device_iommu_address_space() fetches the IOMMU AS, add a
>> pci_device_iommu_memory_region() which lets it return an the IOMMU MR
>> associated with it. The IOMMU MR is returned correctly for vIOMMUs using
>> pci_setup_iommu_info(). Note that today most vIOMMUs create the address
>> space and IOMMU MR at the same time, it's just mainly that there's API
>> to make the latter available.
> 
> Have you looked into other archs outside x86?  IIRC on some other arch one
> address space can have >1 IOMMU memory regions.. at least with such AS and
> MR layering it seems always possible?  Thanks,
> 

I looked at all callers of pci_setup_iommu() restricting to those that actually
track an IOMMUMemoryRegion when they create a address space... as this is where
pci_device_iommu_memory_region() is applicable. From looking at those[*], I see
always a 1:1 association between the AS and the IOMMU-MR in their initialization
when iommu_fn is called. Unless I missed something... Is there an arch you were
thinking specifically?

[I am not sure we can track today an 1:N AS->IOMMU association today in Qemu]

[*] alpha, arm smmu, ppc, s390, virtio, and some pci bridges (pnv_phb3 and 
pnv_phb4)

Joao



[PATCH] Add epmp to extensions list and rename it to smepmp

2023-06-06 Thread Himanshu Chauhan
Smepmp is a ratified extension which qemu refers to as epmp.
Rename epmp to smepmp and add it to extension list so that
it is added to the isa string.

Signed-off-by: Himanshu Chauhan 
---
 target/riscv/cpu.c |  9 +
 target/riscv/cpu_cfg.h |  2 +-
 target/riscv/csr.c |  6 +++---
 target/riscv/pmp.c | 12 ++--
 4 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 881bddf393..cf3d1c3207 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -127,6 +127,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
 ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
 ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
+ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
 ISA_EXT_DATA_ENTRY(xtheadba, PRIV_VERSION_1_11_0, ext_xtheadba),
 ISA_EXT_DATA_ENTRY(xtheadbb, PRIV_VERSION_1_11_0, ext_xtheadbb),
 ISA_EXT_DATA_ENTRY(xtheadbs, PRIV_VERSION_1_11_0, ext_xtheadbs),
@@ -547,7 +548,7 @@ static void rv32_ibex_cpu_init(Object *obj)
 #ifndef CONFIG_USER_ONLY
 set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
 #endif
-cpu->cfg.epmp = true;
+cpu->cfg.ext_smepmp = true;
 
 /* inherited from parent obj via riscv_cpu_init() */
 cpu->cfg.ext_ifencei = true;
@@ -1336,12 +1337,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
-if (cpu->cfg.epmp && !cpu->cfg.pmp) {
+if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) {
 /*
  * Enhanced PMP should only be available
  * on harts with PMP support
  */
-error_setg(errp, "Invalid configuration: EPMP requires PMP support");
+error_setg(errp, "Invalid configuration: SMEPMP requires PMP support");
 return;
 }
 
@@ -1676,7 +1677,7 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
 
 /* ePMP 0.9.3 */
-DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
+DEFINE_PROP_BOOL("smepmp", RISCVCPU, cfg.ext_smepmp, false),
 DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
 DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
 
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index c4a627d335..d79b022e35 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -87,6 +87,7 @@ struct RISCVCPUConfig {
 bool ext_zvfh;
 bool ext_zvfhmin;
 bool ext_smaia;
+bool ext_smepmp;
 bool ext_ssaia;
 bool ext_sscofpmf;
 bool rvv_ta_all_1s;
@@ -121,7 +122,6 @@ struct RISCVCPUConfig {
 uint16_t cboz_blocksize;
 bool mmu;
 bool pmp;
-bool epmp;
 bool debug;
 bool misa_w;
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 58499b5afc..d9bc591348 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -523,9 +523,9 @@ static RISCVException pmp(CPURISCVState *env, int csrno)
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
-static RISCVException epmp(CPURISCVState *env, int csrno)
+static RISCVException smepmp(CPURISCVState *env, int csrno)
 {
-if (riscv_cpu_cfg(env)->epmp) {
+if (riscv_cpu_cfg(env)->ext_smepmp) {
 return RISCV_EXCP_NONE;
 }
 
@@ -4356,7 +4356,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_VSIPH]   = { "vsiph",   aia_hmode32, NULL, NULL, rmw_vsiph },
 
 /* Physical Memory Protection */
-[CSR_MSECCFG]= { "mseccfg",  epmp, read_mseccfg, write_mseccfg,
+[CSR_MSECCFG]= { "mseccfg", smepmp, read_mseccfg, write_mseccfg,
  .min_priv_ver = PRIV_VERSION_1_11_0   },
 [CSR_PMPCFG0]= { "pmpcfg0",   pmp, read_pmpcfg,  write_pmpcfg  },
 [CSR_PMPCFG1]= { "pmpcfg1",   pmp, read_pmpcfg,  write_pmpcfg  },
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 418738afd8..18246e1737 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -87,7 +87,7 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t 
pmp_index, uint8_t val)
 if (pmp_index < MAX_RISCV_PMPS) {
 bool locked = true;
 
-if (riscv_cpu_cfg(env)->epmp) {
+if (riscv_cpu_cfg(env)->ext_smepmp) {
 /* mseccfg.RLB is set */
 if (MSECCFG_RLB_ISSET(env)) {
 locked = false;
@@ -337,9 +337,9 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong 
addr,
 
 /*
  * Convert the PMP permissions to match the truth table in the
- * ePMP spec.
+ * SMEPMP spec.
  */
-const uint8_t epmp_operation =
+const uint8_t smepmp_operation =
 ((env->pmp_state.pmp[i].cfg_reg & PMP_LOCK) >> 4) |
 ((env->pmp_state.pmp[i].cfg_reg & PMP_READ) << 2) |
 (env->pmp_state.pmp[i].cfg_reg & PMP_WRITE) |
@@ -364,7 +364,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong 
addr,
  * 

[PATCH 01/21] ui/egl: export qemu_egl_get_error_string()

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

It will be used from other units.

Signed-off-by: Marc-André Lureau 
---
 include/ui/egl-helpers.h |  2 ++
 ui/egl-helpers.c | 12 +---
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index 53d953ddf4..2cf6633ad2 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -67,4 +67,6 @@ bool qemu_egl_has_dmabuf(void);
 
 bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp);
 
+const char *qemu_egl_get_error_string(void);
+
 #endif /* EGL_HELPERS_H */
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 4203163ace..3c94b3f216 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -28,8 +28,7 @@ DisplayGLMode qemu_egl_mode;
 
 /* -- */
 
-#if defined(CONFIG_X11) || defined(CONFIG_GBM)
-static const char *egl_get_error_string(void)
+const char *qemu_egl_get_error_string(void)
 {
 EGLint error = eglGetError();
 
@@ -68,7 +67,6 @@ static const char *egl_get_error_string(void)
 return "Unknown EGL error";
 }
 }
-#endif
 
 static void egl_fb_delete_texture(egl_fb *fb)
 {
@@ -482,20 +480,20 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
 
 qemu_egl_display = qemu_egl_get_display(dpy, platform);
 if (qemu_egl_display == EGL_NO_DISPLAY) {
-error_report("egl: eglGetDisplay failed: %s", egl_get_error_string());
+error_report("egl: eglGetDisplay failed: %s", 
qemu_egl_get_error_string());
 return -1;
 }
 
 b = eglInitialize(qemu_egl_display, &major, &minor);
 if (b == EGL_FALSE) {
-error_report("egl: eglInitialize failed: %s", egl_get_error_string());
+error_report("egl: eglInitialize failed: %s", 
qemu_egl_get_error_string());
 return -1;
 }
 
 b = eglBindAPI(gles ?  EGL_OPENGL_ES_API : EGL_OPENGL_API);
 if (b == EGL_FALSE) {
 error_report("egl: eglBindAPI failed (%s mode): %s",
- gles ? "gles" : "core", egl_get_error_string());
+ gles ? "gles" : "core", qemu_egl_get_error_string());
 return -1;
 }
 
@@ -504,7 +502,7 @@ static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
 &qemu_egl_config, 1, &n);
 if (b == EGL_FALSE || n != 1) {
 error_report("egl: eglChooseConfig failed (%s mode): %s",
- gles ? "gles" : "core", egl_get_error_string());
+ gles ? "gles" : "core", qemu_egl_get_error_string());
 return -1;
 }
 
-- 
2.40.1




[PATCH 00/21] -display dbus: add win32 support

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

Hi,

The D-Bus display doesn't work on Windows, since it relies on FDs transfer over
Unix domain socket. This isn't (yet) supported on Windows. To make it work, the
interfaces are adapted to use 'ay' WSASocketW data instead of 'h' (in a similar
fashion as QMP 'get-win32-socket').

A simple XML preprocessor helps generating the target-specific OS interfaces.

The performance on Windows isn't great though, since there is no DMABUF scanout
sharing between QEMU and the client for example. The first improvement
introduces a org.qemu.Display1.Listener.Win32.Map interface for shared
display/console memory. This can work regardless of 3d accelerated or not, and
should work across various GL implementations as well.

The second improvement relies on ANGLE/EGL Direct3D extensions enabled in virgl
(pending review at
https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1103) to
create shareable Texture2Ds and share them when the client implements the
org.qemu.Display1.Listener.Win32.D3D11 interface. This should give comparable
performance as in-process display hopefully.

Marc-André Lureau (21):
  ui/egl: export qemu_egl_get_error_string()
  ui/egl: fix make_context_current() callback return value
  ui/dbus: compile without gio/gunixfdlist.h
  scripts: add a XML preprocessor script
  ui/dbus: win32 support
  qtest: add qtest_pid()
  tests: make dbus-display-test work on win32
  ui/dbus: introduce "Interfaces" properties
  console/win32: allocate shareable display surface
  virtio-gpu/win32: allocate shareable 2d resources/images
  ui/dbus: use shared memory when possible on win32
  ui: add egl-headless support on win32
  ui/egl: default to GLES on windows
  ui: add egl_fb_read_rect()
  ui/dbus: add GL support on win32
  ui/dbus: add some GL traces
  virtio-gpu-virgl: teach it to get the QEMU EGL display
  ui/egl: query ANGLE d3d device
  ui: add optional d3d texture pointer to scanout texture
  virtio-gpu-virgl: use D3D11_SHARE_TEXTURE when available
  ui/dbus: use shared D3D11 Texture2D when possible

 MAINTAINERS |   1 +
 meson.build |  10 +-
 qapi/ui.json|   5 +-
 include/hw/virtio/virtio-gpu.h  |   3 +
 include/sysemu/os-win32.h   |   3 +
 include/ui/console.h|  15 +-
 include/ui/egl-helpers.h|  11 +-
 include/ui/gtk.h|   6 +-
 include/ui/sdl2.h   |   3 +-
 tests/qtest/libqtest.h  |   9 +
 ui/dbus.h   |   6 +
 audio/dbusaudio.c   |  43 ++-
 hw/display/virtio-gpu-virgl.c   |  43 ++-
 hw/display/virtio-gpu.c |  46 ++-
 tests/qtest/dbus-display-test.c |  43 ++-
 tests/qtest/libqtest.c  |   5 +
 ui/console.c|  70 -
 ui/dbus-chardev.c   |  20 +-
 ui/dbus-console.c   |  64 +++-
 ui/dbus-listener.c  | 527 +---
 ui/dbus.c   |   4 -
 ui/egl-context.c|  10 +-
 ui/egl-headless.c   |  25 +-
 ui/egl-helpers.c|  98 +-
 ui/gtk-egl.c|  14 +-
 ui/gtk-gl-area.c|   5 +-
 ui/qemu-pixman.c|   1 +
 ui/sdl2-gl.c|   3 +-
 ui/spice-display.c  |   3 +-
 util/oslib-win32.c  |  33 ++
 scripts/meson.build |   2 +
 scripts/xml-preprocess-test.py  | 136 +
 scripts/xml-preprocess.py   | 293 ++
 tests/qtest/meson.build |   2 +-
 ui/dbus-display1.xml| 240 ++-
 ui/meson.build  |  15 +-
 ui/trace-events |   8 +-
 util/trace-events   |   4 +
 38 files changed, 1704 insertions(+), 125 deletions(-)
 create mode 100644 scripts/xml-preprocess-test.py
 create mode 100755 scripts/xml-preprocess.py

-- 
2.40.1




[PATCH 07/21] tests: make dbus-display-test work on win32

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
---
 tests/qtest/dbus-display-test.c | 43 ++---
 tests/qtest/meson.build |  2 +-
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/tests/qtest/dbus-display-test.c b/tests/qtest/dbus-display-test.c
index fef025ac6f..21edaa1e32 100644
--- a/tests/qtest/dbus-display-test.c
+++ b/tests/qtest/dbus-display-test.c
@@ -1,4 +1,5 @@
 #include "qemu/osdep.h"
+#include "qemu/sockets.h"
 #include "qemu/dbus.h"
 #include "qemu/sockets.h"
 #include 
@@ -14,7 +15,11 @@ test_dbus_p2p_from_fd(int fd)
 g_autoptr(GSocketConnection) socketc = NULL;
 GDBusConnection *conn;
 
+#ifdef WIN32
+socket = g_socket_new_from_fd(_get_osfhandle(fd), &err);
+#else
 socket = g_socket_new_from_fd(fd, &err);
+#endif
 g_assert_no_error(err);
 
 socketc = g_socket_connection_factory_create_connection(socket);
@@ -126,7 +131,10 @@ test_dbus_console_registered(GObject *source_object,
 
 qemu_dbus_display1_console_call_register_listener_finish(
 QEMU_DBUS_DISPLAY1_CONSOLE(source_object),
-NULL, res, &err);
+#ifndef WIN32
+NULL,
+#endif
+res, &err);
 g_assert_no_error(err);
 
 test->listener_conn = g_thread_join(test->thread);
@@ -145,17 +153,25 @@ test_dbus_display_console(void)
 g_autoptr(GError) err = NULL;
 g_autoptr(GDBusConnection) conn = NULL;
 g_autoptr(QemuDBusDisplay1ConsoleProxy) console = NULL;
-g_autoptr(GUnixFDList) fd_list = NULL;
 g_autoptr(GMainLoop) loop = NULL;
 QTestState *qts = NULL;
-int pair[2], idx;
+int pair[2];
 TestDBusConsoleRegister test;
+#ifdef WIN32
+WSAPROTOCOL_INFOW info;
+g_autoptr(GVariant) listener = NULL;
+#else
+g_autoptr(GUnixFDList) fd_list = NULL;
+int idx;
+#endif
 
 test_setup(&qts, &conn);
 
 g_assert_cmpint(qemu_socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0);
+#ifndef WIN32
 fd_list = g_unix_fd_list_new();
 idx = g_unix_fd_list_append(fd_list, pair[1], NULL);
+#endif
 
 console = QEMU_DBUS_DISPLAY1_CONSOLE_PROXY(
 qemu_dbus_display1_console_proxy_new_sync(
@@ -171,12 +187,33 @@ test_dbus_display_console(void)
 test.thread = g_thread_new(NULL, test_dbus_p2p_server_setup_thread,
GINT_TO_POINTER(pair[0]));
 
+#ifdef WIN32
+if (WSADuplicateSocketW(_get_osfhandle(pair[1]),
+GetProcessId((HANDLE) qtest_pid(qts)),
+&info) == SOCKET_ERROR)
+{
+g_autofree char *emsg = g_win32_error_message(WSAGetLastError());
+g_error("WSADuplicateSocket failed: %s", emsg);
+}
+close(pair[1]);
+listener = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
+ &info,
+ sizeof(info),
+ 1);
+#endif
+
 qemu_dbus_display1_console_call_register_listener(
 QEMU_DBUS_DISPLAY1_CONSOLE(console),
+#ifdef WIN32
+listener,
+#else
 g_variant_new_handle(idx),
+#endif
 G_DBUS_CALL_FLAGS_NONE,
 -1,
+#ifndef WIN32
 fd_list,
+#endif
 NULL,
 test_dbus_console_registered,
 &test);
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 087f2dc9d7..bbbcd47e6c 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -103,7 +103,7 @@ qtests_i386 = \
'numa-test'
   ]
 
-if dbus_display and targetos != 'windows'
+if dbus_display
   qtests_i386 += ['dbus-display-test']
 endif
 
-- 
2.40.1




[PATCH 12/21] ui: add egl-headless support on win32

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

Make GBM optional for EGL code, and enable the build for win32.

Signed-off-by: Marc-André Lureau 
---
 qapi/ui.json |  5 ++---
 include/ui/egl-helpers.h |  7 ++-
 ui/egl-headless.c| 20 +---
 ui/egl-helpers.c | 38 +++---
 ui/meson.build   |  6 +++---
 5 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/qapi/ui.json b/qapi/ui.json
index 2755395483..bb06fb6039 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1484,8 +1484,7 @@
 { 'name': 'none' },
 { 'name': 'gtk', 'if': 'CONFIG_GTK' },
 { 'name': 'sdl', 'if': 'CONFIG_SDL' },
-{ 'name': 'egl-headless',
-  'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } },
+{ 'name': 'egl-headless', 'if': 'CONFIG_OPENGL' },
 { 'name': 'curses', 'if': 'CONFIG_CURSES' },
 { 'name': 'cocoa', 'if': 'CONFIG_COCOA' },
 { 'name': 'spice-app', 'if': 'CONFIG_SPICE' },
@@ -1525,7 +1524,7 @@
   'cocoa': { 'type': 'DisplayCocoa', 'if': 'CONFIG_COCOA' },
   'curses': { 'type': 'DisplayCurses', 'if': 'CONFIG_CURSES' },
   'egl-headless': { 'type': 'DisplayEGLHeadless',
-'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } },
+'if': 'CONFIG_OPENGL' },
   'dbus': { 'type': 'DisplayDBus', 'if': 'CONFIG_DBUS_DISPLAY' },
   'sdl': { 'type': 'DisplaySDL', 'if': 'CONFIG_SDL' }
   }
diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index 2cf6633ad2..6c4eb5dd70 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -36,11 +36,12 @@ void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, 
egl_fb *src, bool flip);
 void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip,
int x, int y, double scale_x, double scale_y);
 
+extern EGLContext qemu_egl_rn_ctx;
+
 #ifdef CONFIG_GBM
 
 extern int qemu_egl_rn_fd;
 extern struct gbm_device *qemu_egl_rn_gbm_dev;
-extern EGLContext qemu_egl_rn_ctx;
 
 int egl_rendernode_init(const char *rendernode, DisplayGLMode mode);
 int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc,
@@ -62,6 +63,10 @@ int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, 
DisplayGLMode mode);
 
 #endif
 
+#ifdef WIN32
+int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode);
+#endif
+
 EGLContext qemu_egl_init_ctx(void);
 bool qemu_egl_has_dmabuf(void);
 
diff --git a/ui/egl-headless.c b/ui/egl-headless.c
index ef70e6a18e..e4177206f2 100644
--- a/ui/egl-headless.c
+++ b/ui/egl-headless.c
@@ -79,6 +79,8 @@ static void egl_scanout_texture(DisplayChangeListener *dcl,
 }
 }
 
+#ifdef CONFIG_GBM
+
 static void egl_scanout_dmabuf(DisplayChangeListener *dcl,
QemuDmaBuf *dmabuf)
 {
@@ -110,6 +112,14 @@ static void egl_cursor_dmabuf(DisplayChangeListener *dcl,
 }
 }
 
+static void egl_release_dmabuf(DisplayChangeListener *dcl,
+   QemuDmaBuf *dmabuf)
+{
+egl_dmabuf_release_texture(dmabuf);
+}
+
+#endif
+
 static void egl_cursor_position(DisplayChangeListener *dcl,
 uint32_t pos_x, uint32_t pos_y)
 {
@@ -119,12 +129,6 @@ static void egl_cursor_position(DisplayChangeListener *dcl,
 edpy->pos_y = pos_y;
 }
 
-static void egl_release_dmabuf(DisplayChangeListener *dcl,
-   QemuDmaBuf *dmabuf)
-{
-egl_dmabuf_release_texture(dmabuf);
-}
-
 static void egl_scanout_flush(DisplayChangeListener *dcl,
   uint32_t x, uint32_t y,
   uint32_t w, uint32_t h)
@@ -160,10 +164,12 @@ static const DisplayChangeListenerOps egl_ops = {
 
 .dpy_gl_scanout_disable  = egl_scanout_disable,
 .dpy_gl_scanout_texture  = egl_scanout_texture,
+#ifdef CONFIG_GBM
 .dpy_gl_scanout_dmabuf   = egl_scanout_dmabuf,
 .dpy_gl_cursor_dmabuf= egl_cursor_dmabuf,
-.dpy_gl_cursor_position  = egl_cursor_position,
 .dpy_gl_release_dmabuf   = egl_release_dmabuf,
+#endif
+.dpy_gl_cursor_position  = egl_cursor_position,
 .dpy_gl_update   = egl_scanout_flush,
 };
 
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 3c94b3f216..4b29dda7ed 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -199,11 +199,12 @@ void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, 
egl_fb *src, bool flip,
 
 /* -- */
 
+EGLContext qemu_egl_rn_ctx;
+
 #ifdef CONFIG_GBM
 
 int qemu_egl_rn_fd;
 struct gbm_device *qemu_egl_rn_gbm_dev;
-EGLContext qemu_egl_rn_ctx;
 
 int egl_rendernode_init(const char *rendernode, DisplayGLMode mode)
 {
@@ -400,7 +401,7 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, 
EGLNativeWindowType win)
 
 /* -- */
 
-#if defined(CONFIG_X11) || defined(CONFIG_GBM)
+#if defined(CONFIG_X11) || defined(CONFIG_GBM) || defined

[PATCH 06/21] qtest: add qtest_pid()

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

Used in the following test on win32, to share sockets with the QEMU
process.

Signed-off-by: Marc-André Lureau 
---
 tests/qtest/libqtest.h | 9 +
 tests/qtest/libqtest.c | 5 +
 2 files changed, 14 insertions(+)

diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
index a12acf7fa9..913acc3d5c 100644
--- a/tests/qtest/libqtest.h
+++ b/tests/qtest/libqtest.h
@@ -985,4 +985,13 @@ void qtest_qom_set_bool(QTestState *s, const char *path, 
const char *property,
  * Returns: Value retrieved from property.
  */
 bool qtest_qom_get_bool(QTestState *s, const char *path, const char *property);
+
+/**
+ * qtest_pid:
+ * @s: QTestState instance to operate on.
+ *
+ * Returns: the PID of the QEMU process, or <= 0
+ */
+pid_t qtest_pid(QTestState *s);
+
 #endif
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index 77de16227f..6dd47a9a3d 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -142,6 +142,11 @@ static int socket_accept(int sock)
 return ret;
 }
 
+pid_t qtest_pid(QTestState *s)
+{
+return s->qemu_pid;
+}
+
 bool qtest_probe_child(QTestState *s)
 {
 pid_t pid = s->qemu_pid;
-- 
2.40.1




[PATCH 14/21] ui: add egl_fb_read_rect()

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

Similar to egl_fb_read(), same limitations, but with extra arguments to
read a subset of the framebuffer. Used in following commits.

Signed-off-by: Marc-André Lureau 
---
 include/ui/egl-helpers.h |  1 +
 ui/egl-helpers.c | 14 ++
 2 files changed, 15 insertions(+)

diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h
index 6c4eb5dd70..6e2f0c49a6 100644
--- a/include/ui/egl-helpers.h
+++ b/include/ui/egl-helpers.h
@@ -31,6 +31,7 @@ void egl_fb_setup_for_tex(egl_fb *fb, int width, int height,
 void egl_fb_setup_new_tex(egl_fb *fb, int width, int height);
 void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip);
 void egl_fb_read(DisplaySurface *dst, egl_fb *src);
+void egl_fb_read_rect(DisplaySurface *dst, egl_fb *src, int x, int y, int w, 
int h);
 
 void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip);
 void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip,
diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 1c718b0b98..1169e19adb 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -169,6 +169,20 @@ void egl_fb_read(DisplaySurface *dst, egl_fb *src)
  GL_BGRA, GL_UNSIGNED_BYTE, surface_data(dst));
 }
 
+void egl_fb_read_rect(DisplaySurface *dst, egl_fb *src, int x, int y, int w, 
int h)
+{
+assert(surface_width(dst) == src->width);
+assert(surface_height(dst) == src->height);
+assert(surface_format(dst) == PIXMAN_x8r8g8b8);
+
+glBindFramebuffer(GL_READ_FRAMEBUFFER, src->framebuffer);
+glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+glPixelStorei(GL_PACK_ROW_LENGTH, surface_stride(dst) / 4);
+glReadPixels(x, y, w, h,
+ GL_BGRA, GL_UNSIGNED_BYTE, surface_data(dst) + x * 4);
+glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+}
+
 void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip)
 {
 glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer);
-- 
2.40.1




[PATCH 16/21] ui/dbus: add some GL traces

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
---
 ui/dbus-listener.c | 6 ++
 ui/trace-events| 3 +++
 2 files changed, 9 insertions(+)

diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index e92eff66e3..8605dffd8a 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -102,6 +102,8 @@ static void dbus_call_update_gl(DisplayChangeListener *dcl,
 {
 DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
 
+trace_dbus_update_gl(x, y, w, h);
+
 glFlush();
 #ifdef CONFIG_GBM
 graphic_hw_gl_block(ddl->dcl.con, true);
@@ -212,6 +214,8 @@ static void dbus_scanout_texture(DisplayChangeListener *dcl,
  uint32_t x, uint32_t y,
  uint32_t w, uint32_t h)
 {
+trace_dbus_scanout_texture(tex_id, backing_y_0_top,
+   backing_width, backing_height, x, y, w, h);
 #ifdef CONFIG_GBM
 QemuDmaBuf dmabuf = {
 .width = backing_width,
@@ -421,6 +425,8 @@ static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
 {
 DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
 
+trace_dbus_gl_gfx_switch(new_surface);
+
 ddl->ds = new_surface;
 if (ddl->ds) {
 int width = surface_width(ddl->ds);
diff --git a/ui/trace-events b/ui/trace-events
index 712c4b2273..b17c3d7893 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -155,6 +155,9 @@ dbus_mouse_release(unsigned int button) "button %u"
 dbus_mouse_set_pos(unsigned int x, unsigned int y) "x=%u, y=%u"
 dbus_mouse_rel_motion(int dx, int dy) "dx=%d, dy=%d"
 dbus_update(int x, int y, int w, int h) "x=%d, y=%d, w=%d, h=%d"
+dbus_update_gl(int x, int y, int w, int h) "x=%d, y=%d, w=%d, h=%d"
 dbus_clipboard_grab_failed(void) ""
 dbus_clipboard_register(const char *bus_name) "peer %s"
 dbus_clipboard_unregister(const char *bus_name) "peer %s"
+dbus_scanout_texture(uint32_t tex_id, bool backing_y_0_top, uint32_t 
backing_width, uint32_t backing_height, uint32_t x, uint32_t y, uint32_t w, 
uint32_t h) "tex_id:%u y0top:%d back:%ux%u %u+%u-%ux%u"
+dbus_gl_gfx_switch(void *p) "surf: %p"
-- 
2.40.1




Re: [PATCH v5 8/9] vfio/migration: Add x-allow-pre-copy VFIO device property

2023-06-06 Thread Avihai Horon



On 05/06/2023 17:56, Alex Williamson wrote:

External email: Use caution opening links or attachments


On Sun, 4 Jun 2023 12:33:43 +0300
Avihai Horon  wrote:


On 01/06/2023 23:22, Alex Williamson wrote:

External email: Use caution opening links or attachments


On Tue, 30 May 2023 17:48:20 +0300
Avihai Horon  wrote:


Add a new VFIO device property x-allow-pre-copy to keep migration
compatibility to/from older QEMU versions that don't have VFIO pre-copy
support.

This doesn't make sense to me, vfio migration is not currently
supported, it can only be enabled via an experimental flag.  AFAIK we
have no obligation to maintain migration compatibility against
experimental features.  Is there any other reason we need a flag to
disable pre-copy?

This could give flexibility to do migration between hosts without
matching VFIO device kernel drivers. E.g., source driver doesn't have
precopy support and dest driver has or vice versa.

If these are valid scenarios, the protocol should support negotiation
without requiring an experimental flag to do so.


Thinking again, the two intree drivers we have support precopy and as 
you said, this is still experimental, so I assume that we can drop this 
patch in v6.





OTOH, should this series finally remove the experimental migration
flag?  Do we require Joao's vIOMMU support to finally make it
supportable?  Is there something else?

I think that after precopy is accepted we can remove the experimental
flag, as we'll have the major parts of VFIO migration upstream.
After that we will still need to add Joao's vIOMMU support and P2P support.
Do you want me to add a patch to this series that makes VFIO migration
non-experimental?

I'd keep it as a separate patch with a clearly described dependency on
this series so that we can discuss it separately.


Sure, so I will post it separately.

Thanks.


Signed-off-by: Avihai Horon 
Reviewed-by: Cédric Le Goater 
---
   include/hw/vfio/vfio-common.h | 1 +
   hw/core/machine.c | 1 +
   hw/vfio/migration.c   | 3 ++-
   hw/vfio/pci.c | 2 ++
   4 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 1db901c194..a53ecbe2e0 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -146,6 +146,7 @@ typedef struct VFIODevice {
   VFIOMigration *migration;
   Error *migration_blocker;
   OnOffAuto pre_copy_dirty_page_tracking;
+bool allow_pre_copy;
   bool dirty_pages_supported;
   bool dirty_tracking;
   } VFIODevice;
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 1000406211..64ac3fe38e 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -41,6 +41,7 @@

   GlobalProperty hw_compat_8_0[] = {
   { "migration", "multifd-flush-after-each-section", "on"},
+{ "vfio-pci", "x-allow-pre-copy", "false" },
   };
   const size_t hw_compat_8_0_len = G_N_ELEMENTS(hw_compat_8_0);

diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
index d8f6a22ae1..cb6923ed3f 100644
--- a/hw/vfio/migration.c
+++ b/hw/vfio/migration.c
@@ -323,7 +323,8 @@ static bool vfio_precopy_supported(VFIODevice *vbasedev)
   {
   VFIOMigration *migration = vbasedev->migration;

-return migration->mig_flags & VFIO_MIGRATION_PRE_COPY;
+return vbasedev->allow_pre_copy &&
+   migration->mig_flags & VFIO_MIGRATION_PRE_COPY;
   }

   /* -- */
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 73874a94de..c69813af7f 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3335,6 +3335,8 @@ static Property vfio_pci_dev_properties[] = {
   DEFINE_PROP_ON_OFF_AUTO("x-pre-copy-dirty-page-tracking", VFIOPCIDevice,
   vbasedev.pre_copy_dirty_page_tracking,
   ON_OFF_AUTO_ON),
+DEFINE_PROP_BOOL("x-allow-pre-copy", VFIOPCIDevice,
+ vbasedev.allow_pre_copy, true),
   DEFINE_PROP_ON_OFF_AUTO("display", VFIOPCIDevice,
   display, ON_OFF_AUTO_OFF),
   DEFINE_PROP_UINT32("xres", VFIOPCIDevice, display_xres, 0),




[PATCH 08/21] ui/dbus: introduce "Interfaces" properties

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

This property is similar to ``org.freedesktop.DBus.Interfaces`` property
on the bus interface: it's an array of strings listing the extra
interfaces and capabilities available, in a convenient way.

Most interfaces are implicit, as they are required. For
``org/qemu/Display1_$id``, we can list the Keyboard And Mouse
interfaces. Those could be optional.

Signed-off-by: Marc-André Lureau 
---
 ui/dbus-console.c|   6 +++
 ui/dbus-display1.xml | 118 ++-
 2 files changed, 122 insertions(+), 2 deletions(-)

diff --git a/ui/dbus-console.c b/ui/dbus-console.c
index f0a060dc81..2f4d3439d1 100644
--- a/ui/dbus-console.c
+++ b/ui/dbus-console.c
@@ -494,6 +494,11 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole 
*con)
 char device_addr[256] = "";
 DBusDisplayConsole *ddc;
 int idx;
+const char *interfaces[] = {
+"org.qemu.Display1.Keyboard",
+"org.qemu.Display1.Mouse",
+NULL
+};
 
 assert(display);
 assert(con);
@@ -518,6 +523,7 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole 
*con)
 "width", qemu_console_get_width(con, 0),
 "height", qemu_console_get_height(con, 0),
 "device-address", device_addr,
+"interfaces", interfaces,
 NULL);
 g_object_connect(ddc->iface,
 "swapped-signal::handle-register-listener",
diff --git a/ui/dbus-display1.xml b/ui/dbus-display1.xml
index 80eae363f0..2c4acce593 100644
--- a/ui/dbus-display1.xml
+++ b/ui/dbus-display1.xml
@@ -26,6 +26,20 @@
 The list of consoles available on ``/org/qemu/Display1/Console_$id``.
 -->
 
+
+
+
   
 
   
 
+
+
+
   
 
   
   
@@ -170,7 +199,8 @@
   
+
   
 
   
+
   
 
   
+
   
 
   
+
   
 
   
+
   
 
   
 
+
+
+
   
 
-- 
2.40.1




[PATCH 10/21] virtio-gpu/win32: allocate shareable 2d resources/images

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

Allocate pixman bits for scanouts with qemu_win32_map_alloc() so we can
set a shareable handle on the associated display surface.

Note: when bits are provided to pixman_image_create_bits(), you must also give
the rowstride (the argument is ignored when bits is NULL)

Signed-off-by: Marc-André Lureau 
---
 include/hw/virtio/virtio-gpu.h |  3 +++
 hw/display/virtio-gpu.c| 46 +++---
 2 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 2e28507efe..7a5f8056ea 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -48,6 +48,9 @@ struct virtio_gpu_simple_resource {
 unsigned int iov_cnt;
 uint32_t scanout_bitmask;
 pixman_image_t *image;
+#ifdef WIN32
+HANDLE handle;
+#endif
 uint64_t hostmem;
 
 uint64_t blob_size;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 66cddd94d9..2871563c40 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -258,6 +258,16 @@ static uint32_t calc_image_hostmem(pixman_format_code_t 
pformat,
 return height * stride;
 }
 
+#ifdef WIN32
+static void
+win32_pixman_image_destroy(pixman_image_t *image, void *data)
+{
+HANDLE handle = data;
+
+qemu_win32_map_free(pixman_image_get_data(image), handle, &error_warn);
+}
+#endif
+
 static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
   struct virtio_gpu_ctrl_command *cmd)
 {
@@ -304,12 +314,27 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
 
 res->hostmem = calc_image_hostmem(pformat, c2d.width, c2d.height);
 if (res->hostmem + g->hostmem < g->conf_max_hostmem) {
+void *bits = NULL;
+#ifdef WIN32
+bits = qemu_win32_map_alloc(res->hostmem, &res->handle, &error_warn);
+if (!bits) {
+goto end;
+}
+#endif
 res->image = pixman_image_create_bits(pformat,
   c2d.width,
   c2d.height,
-  NULL, 0);
+  bits, res->hostmem / c2d.height);
+#ifdef WIN32
+if (res->image) {
+pixman_image_set_destroy_function(res->image, 
win32_pixman_image_destroy, res->handle);
+}
+#endif
 }
 
+#ifdef WIN32
+end:
+#endif
 if (!res->image) {
 qemu_log_mask(LOG_GUEST_ERROR,
   "%s: resource creation failed %d %d %d\n",
@@ -666,6 +691,9 @@ static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
 *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
 return;
 }
+#ifdef WIN32
+qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 
fb->offset);
+#endif
 
 pixman_image_unref(rect);
 dpy_gfx_replace_surface(g->parent_obj.scanout[scanout_id].con,
@@ -1209,6 +1237,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, 
size_t size,
 struct virtio_gpu_simple_resource *res;
 struct virtio_gpu_scanout *scanout;
 uint32_t resource_id, pformat;
+void *bits = NULL;
 int i;
 
 g->hostmem = 0;
@@ -1233,15 +1262,23 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, 
size_t size,
 g_free(res);
 return -EINVAL;
 }
+
+res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
+#ifdef WIN32
+bits = qemu_win32_map_alloc(res->hostmem, &res->handle, &error_warn);
+if (!bits) {
+g_free(res);
+return -EINVAL;
+}
+#endif
 res->image = pixman_image_create_bits(pformat,
   res->width, res->height,
-  NULL, 0);
+  bits, res->hostmem / 
res->height);
 if (!res->image) {
 g_free(res);
 return -EINVAL;
 }
 
-res->hostmem = calc_image_hostmem(pformat, res->width, res->height);
 
 res->addrs = g_new(uint64_t, res->iov_cnt);
 res->iov = g_new(struct iovec, res->iov_cnt);
@@ -1302,6 +1339,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, 
size_t size,
 if (!scanout->ds) {
 return -EINVAL;
 }
+#ifdef WIN32
+qemu_displaysurface_win32_set_handle(scanout->ds, res->handle, 0);
+#endif
 
 dpy_gfx_replace_surface(scanout->con, scanout->ds);
 dpy_gfx_update_full(scanout->con);
-- 
2.40.1




[PATCH 05/21] ui/dbus: win32 support

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

D-Bus doesn't support fd-passing on Windows (AF_UNIX doesn't have
SCM_RIGHTS yet, but there are other means to share objects. I have
proposed various solutions upstream, but none seem fitting enough atm).

To make the "-display dbus" work on Windows, implement an alternative
D-Bus interface where all the 'h' (FDs) arguments are replaced with
'ay' (WSASocketW data), and sockets are passed to the other end via
WSADuplicateSocket().

Signed-off-by: Marc-André Lureau 
---
 meson.build  |  4 +--
 ui/dbus.h|  6 +
 audio/dbusaudio.c| 44 +++--
 ui/dbus-chardev.c| 22 +
 ui/dbus-console.c| 59 ++--
 ui/dbus-display1.xml | 28 +
 ui/meson.build   |  9 ++-
 7 files changed, 149 insertions(+), 23 deletions(-)

diff --git a/meson.build b/meson.build
index a61d3e9b06..ce7138a69f 100644
--- a/meson.build
+++ b/meson.build
@@ -838,6 +838,8 @@ if gdbus_codegen.found() and get_option('cfi')
   gdbus_codegen_error = '@0@ uses gdbus-codegen, which does not support 
control flow integrity'
 endif
 
+xml_pp = find_program('scripts/xml-preprocess.py')
+
 lttng = not_found
 if 'ust' in get_option('trace_backends')
   lttng = dependency('lttng-ust', required: true, version: '>= 2.1',
@@ -2008,8 +2010,6 @@ dbus_display = get_option('dbus_display') \
error_message: '-display dbus requires glib>=2.64') \
   .require(gdbus_codegen.found(),
error_message: gdbus_codegen_error.format('-display dbus')) \
-  .require(targetos != 'windows',
-   error_message: '-display dbus is not available on Windows') \
   .allowed()
 
 have_virtfs = get_option('virtfs') \
diff --git a/ui/dbus.h b/ui/dbus.h
index 9c149e7b41..1e8c24a48e 100644
--- a/ui/dbus.h
+++ b/ui/dbus.h
@@ -62,6 +62,12 @@ struct DBusDisplay {
 Notifier notifier;
 };
 
+#ifdef WIN32
+bool
+dbus_win32_import_socket(GDBusMethodInvocation *invocation,
+ GVariant *arg_listener, int *socket);
+#endif
+
 #define TYPE_DBUS_DISPLAY "dbus-display"
 OBJECT_DECLARE_SIMPLE_TYPE(DBusDisplay, DBUS_DISPLAY)
 
diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c
index de59467d9e..7a11fbfb42 100644
--- a/audio/dbusaudio.c
+++ b/audio/dbusaudio.c
@@ -33,6 +33,7 @@
 #include 
 #endif
 
+#include "ui/dbus.h"
 #include "ui/dbus-display1.h"
 
 #define AUDIO_CAP "dbus"
@@ -422,7 +423,6 @@ dbus_audio_fini(void *opaque)
 g_free(da);
 }
 
-#ifdef G_OS_UNIX
 static void
 listener_out_vanished_cb(GDBusConnection *connection,
  gboolean remote_peer_vanished,
@@ -448,7 +448,9 @@ listener_in_vanished_cb(GDBusConnection *connection,
 static gboolean
 dbus_audio_register_listener(AudioState *s,
  GDBusMethodInvocation *invocation,
+#ifdef G_OS_UNIX
  GUnixFDList *fd_list,
+#endif
  GVariant *arg_listener,
  bool out)
 {
@@ -475,6 +477,11 @@ dbus_audio_register_listener(AudioState *s,
 return DBUS_METHOD_INVOCATION_HANDLED;
 }
 
+#ifdef G_OS_WIN32
+if (!dbus_win32_import_socket(invocation, arg_listener, &fd)) {
+return DBUS_METHOD_INVOCATION_HANDLED;
+}
+#else
 fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_listener), &err);
 if (err) {
 g_dbus_method_invocation_return_error(invocation,
@@ -484,6 +491,7 @@ dbus_audio_register_listener(AudioState *s,
   err->message);
 return DBUS_METHOD_INVOCATION_HANDLED;
 }
+#endif
 
 socket = g_socket_new_from_fd(fd, &err);
 if (err) {
@@ -492,15 +500,28 @@ dbus_audio_register_listener(AudioState *s,
   DBUS_DISPLAY_ERROR_FAILED,
   "Couldn't make a socket: %s",
   err->message);
+#ifdef G_OS_WIN32
+closesocket(fd);
+#else
+close(fd);
+#endif
 return DBUS_METHOD_INVOCATION_HANDLED;
 }
 socket_conn = g_socket_connection_factory_create_connection(socket);
 if (out) {
 qemu_dbus_display1_audio_complete_register_out_listener(
-da->iface, invocation, NULL);
+da->iface, invocation
+#ifdef G_OS_UNIX
+, NULL
+#endif
+);
 } else {
 qemu_dbus_display1_audio_complete_register_in_listener(
-da->iface, invocation, NULL);
+da->iface, invocation
+#ifdef G_OS_UNIX
+, NULL
+#endif
+);
 }
 
 listener_conn =
@@ -578,24 +599,33 @@ dbus_audio_register_listener(AudioState *s,
 static gboolean
 dbus_audio_register_out_listener(AudioState *s,
  GDBusMethodInvocation *invocation,
+#ifdef G_OS_UNIX
  GUnixFDList *fd_list,
+#endif
  GVariant *arg_lis

[PATCH 13/21] ui/egl: default to GLES on windows

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

Windows GL drivers are notoriously not very good. Otoh, ANGLE provides
rock solid GLES implementation on top of direct3d. We should recommend
it and default to ES when using EGL (users can easily override this if
necessary)

Signed-off-by: Marc-André Lureau 
---
 ui/egl-helpers.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c
index 4b29dda7ed..1c718b0b98 100644
--- a/ui/egl-helpers.c
+++ b/ui/egl-helpers.c
@@ -537,6 +537,10 @@ int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy, 
DisplayGLMode mode)
 #ifdef WIN32
 int qemu_egl_init_dpy_win32(EGLNativeDisplayType dpy, DisplayGLMode mode)
 {
+/* prefer GL ES, as that's what ANGLE supports */
+if (mode == DISPLAYGL_MODE_ON) {
+mode = DISPLAYGL_MODE_ES;
+}
 return qemu_egl_init_dpy(dpy, 0, mode);
 }
 #endif
-- 
2.40.1




[PATCH 17/21] virtio-gpu-virgl: teach it to get the QEMU EGL display

2023-06-06 Thread marcandre . lureau
From: Marc-André Lureau 

virgl offers a few features that require to have access to the
underlying EGLDisplay. This is the case for the D3D texture sharing support.

The API callback is merged for virgl 1.0:
https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1113

Signed-off-by: Marc-André Lureau 
---
 hw/display/virtio-gpu-virgl.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 1c47603d40..9831c482e5 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -18,9 +18,17 @@
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-gpu.h"
 
+#include "ui/egl-helpers.h"
+
 #include 
 
-static struct virgl_renderer_callbacks virtio_gpu_3d_cbs;
+#if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
+static void *
+virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
+{
+return qemu_egl_display;
+}
+#endif
 
 static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
@@ -608,6 +616,13 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 {
 int ret;
 
+#if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
+if (qemu_egl_display) {
+virtio_gpu_3d_cbs.version = 4;
+virtio_gpu_3d_cbs.get_egl_display = virgl_get_egl_display;
+}
+#endif
+
 ret = virgl_renderer_init(g, 0, &virtio_gpu_3d_cbs);
 if (ret != 0) {
 error_report("virgl could not be initialized: %d", ret);
-- 
2.40.1




  1   2   3   4   >