All of lore.kernel.org
 help / color / mirror / Atom feed
* [PULL 00/21] target-arm queue
@ 2024-01-16 15:12 Peter Maydell
  2024-01-16 15:12 ` [PULL 01/21] docs/devel/docs: Document .hx file syntax Peter Maydell
                   ` (20 more replies)
  0 siblings, 21 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

The following changes since commit 977542ded7e6b28d2bc077bcda24568c716e393c:

  Merge tag 'pull-testing-updates-120124-2' of https://gitlab.com/stsquad/qemu into staging (2024-01-12 14:02:53 +0000)

are available in the Git repository at:

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

for you to fetch changes up to 7ec39730a9cc443c752d4cad2bf1c00467551ef5:

  load_elf: fix iterator's type for elf file processing (2024-01-15 17:14:22 +0000)

----------------------------------------------------------------
target-arm queue:
 * docs/devel/docs: Document .hx file syntax
 * arm_pamax() no longer needs to do feature propagation
 * docs/system/arm/virt.rst: Improve 'highmem' option docs
 * STM32L4x5 Implement SYSCFG and EXTI devices
 * Nuvoton: Implement PCI Mailbox module
 * Nuvoton: Implement GMAC module
 * hw/timer: fix systick trace message
 * hw/arm/virt: Consolidate valid CPU types
 * load_elf: fix iterator's type for elf file processing

----------------------------------------------------------------
Anastasia Belova (1):
      load_elf: fix iterator's type for elf file processing

Gavin Shan (1):
      hw/arm/virt: Consolidate valid CPU types

Hao Wu (3):
      hw/misc: Add Nuvoton's PCI Mailbox Module
      hw/misc: Add qtest for NPCM7xx PCI Mailbox
      hw/arm: Add GMAC devices to NPCM7XX SoC

Inès Varhol (6):
      hw/misc: Implement STM32L4x5 EXTI
      hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC
      tests/qtest: Add STM32L4x5 EXTI QTest testcase
      hw/misc: Implement STM32L4x5 SYSCFG
      hw/arm: Connect STM32L4x5 SYSCFG to STM32L4x5 SoC
      tests/qtest: Add STM32L4x5 SYSCFG QTest testcase

Nabih Estefan Diaz (4):
      tests/qtest: Creating qtest for GMAC Module
      hw/net: GMAC Rx Implementation
      hw/net: GMAC Tx Implementation
      tests/qtest: Adding PCS Module test to GMAC Qtest

Peter Maydell (5):
      docs/devel/docs: Document .hx file syntax
      target/arm: arm_pamax() no longer needs to do feature propagation
      docs/system/arm/virt.rst: Improve 'highmem' option docs
      hw/arm: Add PCI mailbox module to Nuvoton SoC
      hw/net: Add NPCMXXX GMAC device

Samuel Tardieu (1):
      hw/timer: fix systick trace message

 MAINTAINERS                         |   1 +
 docs/devel/docs.rst                 |  60 +++
 docs/devel/index-build.rst          |   1 +
 docs/system/arm/b-l475e-iot01a.rst  |   7 +-
 docs/system/arm/nuvoton.rst         |   2 +
 docs/system/arm/virt.rst            |   8 +-
 include/hw/arm/npcm7xx.h            |   4 +
 include/hw/arm/stm32l4x5_soc.h      |   5 +
 include/hw/elf_ops.h                |   2 +-
 include/hw/misc/npcm7xx_pci_mbox.h  |  81 ++++
 include/hw/misc/stm32l4x5_exti.h    |  51 ++
 include/hw/misc/stm32l4x5_syscfg.h  |  54 +++
 include/hw/net/npcm_gmac.h          | 340 +++++++++++++
 hw/arm/npcm7xx.c                    |  53 +-
 hw/arm/stm32l4x5_soc.c              |  73 ++-
 hw/arm/virt.c                       |   8 +-
 hw/misc/npcm7xx_pci_mbox.c          | 324 +++++++++++++
 hw/misc/stm32l4x5_exti.c            | 290 +++++++++++
 hw/misc/stm32l4x5_syscfg.c          | 266 ++++++++++
 hw/net/npcm_gmac.c                  | 939 ++++++++++++++++++++++++++++++++++++
 target/arm/ptw.c                    |  14 +-
 tests/qtest/npcm7xx_pci_mbox-test.c | 238 +++++++++
 tests/qtest/npcm_gmac-test.c        | 341 +++++++++++++
 tests/qtest/stm32l4x5_exti-test.c   | 524 ++++++++++++++++++++
 tests/qtest/stm32l4x5_syscfg-test.c | 331 +++++++++++++
 hmp-commands-info.hx                |  10 +-
 hmp-commands.hx                     |  10 +-
 hw/arm/Kconfig                      |   2 +
 hw/misc/Kconfig                     |   6 +
 hw/misc/meson.build                 |   3 +
 hw/misc/trace-events                |  16 +
 hw/net/meson.build                  |   2 +-
 hw/net/trace-events                 |  19 +
 hw/timer/trace-events               |   2 +-
 qemu-img-cmds.hx                    |   2 +
 qemu-options.hx                     |   2 +
 tests/qtest/meson.build             |   8 +
 37 files changed, 4066 insertions(+), 33 deletions(-)
 create mode 100644 docs/devel/docs.rst
 create mode 100644 include/hw/misc/npcm7xx_pci_mbox.h
 create mode 100644 include/hw/misc/stm32l4x5_exti.h
 create mode 100644 include/hw/misc/stm32l4x5_syscfg.h
 create mode 100644 include/hw/net/npcm_gmac.h
 create mode 100644 hw/misc/npcm7xx_pci_mbox.c
 create mode 100644 hw/misc/stm32l4x5_exti.c
 create mode 100644 hw/misc/stm32l4x5_syscfg.c
 create mode 100644 hw/net/npcm_gmac.c
 create mode 100644 tests/qtest/npcm7xx_pci_mbox-test.c
 create mode 100644 tests/qtest/npcm_gmac-test.c
 create mode 100644 tests/qtest/stm32l4x5_exti-test.c
 create mode 100644 tests/qtest/stm32l4x5_syscfg-test.c


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 01/21] docs/devel/docs: Document .hx file syntax
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 02/21] target/arm: arm_pamax() no longer needs to do feature propagation Peter Maydell
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

We don't currently document the syntax of .hx files anywhere
except in a few comments at the top of individual .hx files.
We don't even have somewhere in the developer docs where we
could do this.

Add a new files docs/devel/docs.rst which can be a place to
document how our docs build process works. For the moment,
put in only a brief introductory paragraph and the documentation
of the .hx files. We could later add to this file by for
example describing how the QAPI-schema-to-docs process works,
or anything else that developers might need to know about
how to add documentation.

Make the .hx files refer to this doc file, and clean
up their header comments to be more accurate for the
usage in each file and less cut-n-pasted.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Luc Michel <luc.michel@amd.com>
Reviewed-by: David Woodhouse <dwmw@amazon.co.uk>
Message-id: 20231212162313.1742462-1-peter.maydell@linaro.org
---
 MAINTAINERS                |  1 +
 docs/devel/docs.rst        | 60 ++++++++++++++++++++++++++++++++++++++
 docs/devel/index-build.rst |  1 +
 hmp-commands-info.hx       | 10 +++----
 hmp-commands.hx            | 10 +++----
 qemu-img-cmds.hx           |  2 ++
 qemu-options.hx            |  2 ++
 7 files changed, 76 insertions(+), 10 deletions(-)
 create mode 100644 docs/devel/docs.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index b406fb20c05..8e8ca270c4e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4175,6 +4175,7 @@ F: docs/conf.py
 F: docs/*/conf.py
 F: docs/sphinx/
 F: docs/_templates/
+F: docs/devel/docs.rst
 
 Miscellaneous
 -------------
diff --git a/docs/devel/docs.rst b/docs/devel/docs.rst
new file mode 100644
index 00000000000..7da067905b8
--- /dev/null
+++ b/docs/devel/docs.rst
@@ -0,0 +1,60 @@
+
+==================
+QEMU Documentation
+==================
+
+QEMU's documentation is written in reStructuredText format and
+built using the Sphinx documentation generator. We generate both
+the HTML manual and the manpages from the some documentation sources.
+
+hxtool and .hx files
+--------------------
+
+The documentation for QEMU command line options and Human Monitor Protocol
+(HMP) commands is written in files with the ``.hx`` suffix. These
+are processed in two ways:
+
+ * ``scripts/hxtool`` creates C header files from them, which are included
+   in QEMU to do things like handle the ``--help`` option output
+ * a Sphinx extension in ``docs/sphinx/hxtool.py`` generates rST output
+   to be included in the HTML or manpage documentation
+
+The syntax of these ``.hx`` files is simple. It is broadly an
+alternation of C code put into the C output and rST format text
+put into the documention. A few special directives are recognised;
+these are all-caps and must be at the beginning of the line.
+
+``HXCOMM`` is the comment marker. The line, including any arbitrary
+text after the marker, is discarded and appears neither in the C output
+nor the documentation output.
+
+``SRST`` starts a reStructuredText section. Following lines
+are put into the documentation verbatim, and discarded from the C output.
+
+``ERST`` ends the documentation section started with ``SRST``,
+and switches back to a C code section.
+
+``DEFHEADING()`` defines a heading that should appear in both the
+``--help`` output and in the documentation. This directive should
+be in the C code block. If there is a string inside the brackets,
+this is the heading to use. If this string is empty, it produces
+a blank line in the ``--help`` output and is ignored for the rST
+output.
+
+``ARCHHEADING()`` is a variant of ``DEFHEADING()`` which produces
+the heading only if the specified guest architecture was compiled
+into QEMU. This should be avoided in new documentation.
+
+Within C code sections, you should check the comments at the top
+of the file to see what the expected usage is, because this
+varies between files. For instance in ``qemu-options.hx`` we use
+the ``DEF()`` macro to define each option and specify its ``--help``
+text, but in ``hmp-commands.hx`` the C code sections are elements
+of an array of structs of type ``HMPCommand`` which define the
+name, behaviour and help text for each monitor command.
+
+In the file ``qemu-options.hx``, do not try to define a
+reStructuredText label within a documentation section. This file
+is included into two separate Sphinx documents, and some
+versions of Sphinx will complain about the duplicate label
+that results.
diff --git a/docs/devel/index-build.rst b/docs/devel/index-build.rst
index 57e8d39d985..90b406ca0ed 100644
--- a/docs/devel/index-build.rst
+++ b/docs/devel/index-build.rst
@@ -10,6 +10,7 @@ the basics if you are adding new files and targets to the build.
 
    build-system
    kconfig
+   docs
    testing
    acpi-bits
    qtest
diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index f5b37eb74ab..da120f82a32 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -1,8 +1,8 @@
-HXCOMM Use DEFHEADING() to define headings in both help text and rST.
-HXCOMM Text between SRST and ERST is copied to the rST version and
-HXCOMM discarded from C version.
-HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
-HXCOMM monitor info commands
+HXCOMM See docs/devel/docs.rst for the format of this file.
+HXCOMM
+HXCOMM This file defines the contents of an array of HMPCommand structs
+HXCOMM which specify the name, behaviour and help text for HMP commands.
+HXCOMM Text between SRST and ERST is rST format documentation.
 HXCOMM HXCOMM can be used for comments, discarded from both rST and C.
 HXCOMM
 HXCOMM In this file, generally SRST fragments should have two extra
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 765349ed149..2db5701d49c 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1,8 +1,8 @@
-HXCOMM Use DEFHEADING() to define headings in both help text and rST.
-HXCOMM Text between SRST and ERST is copied to the rST version and
-HXCOMM discarded from C version.
-HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
-HXCOMM monitor commands
+HXCOMM See docs/devel/docs.rst for the format of this file.
+HXCOMM
+HXCOMM This file defines the contents of an array of HMPCommand structs
+HXCOMM which specify the name, behaviour and help text for HMP commands.
+HXCOMM Text between SRST and ERST is rST format documentation.
 HXCOMM HXCOMM can be used for comments, discarded from both rST and C.
 
 
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 068692d13eb..c9dd70a8920 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -1,3 +1,5 @@
+HXCOMM See docs/devel/docs.rst for the format of this file.
+HXCOMM
 HXCOMM Keep the list of subcommands sorted by name.
 HXCOMM Use DEFHEADING() to define headings in both help text and rST
 HXCOMM Text between SRST and ERST are copied to rST version and
diff --git a/qemu-options.hx b/qemu-options.hx
index b66570ae006..1912b19cb8f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1,3 +1,5 @@
+HXCOMM See docs/devel/docs.rst for the format of this file.
+HXCOMM
 HXCOMM Use DEFHEADING() to define headings in both help text and rST.
 HXCOMM Text between SRST and ERST is copied to the rST version and
 HXCOMM discarded from C version.
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 02/21] target/arm: arm_pamax() no longer needs to do feature propagation
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
  2024-01-16 15:12 ` [PULL 01/21] docs/devel/docs: Document .hx file syntax Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 03/21] docs/system/arm/virt.rst: Improve 'highmem' option docs Peter Maydell
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

In arm_pamax(), we need to cope with the virt board calling this
function on a CPU object which has been inited but not realize.
We used to do propagation of feature-flag implications (such as
"V7VE implies LPAE") at realize, so we have some code in arm_pamax()
which manually checks for both V7VE and LPAE feature flags.

In commit b8f7959f28c4f36 we moved the feature propagation for
almost all features from realize to post-init. That means that
now when the virt board calls arm_pamax(), the feature propagation
has been done. So we can drop the manual propagation handling
and check only for the feature we actually care about, which
is ARM_FEATURE_LPAE.

Retain the comment that the virt board is calling this function
with a not completely realized CPU object, because that is a
potential beartrap for later changes which is worth calling out.

(Note that b8f7959f28c4f36 actually fixed a bug in the arm_pamax()
handling: arm_pamax() was missing a check for ARM_FEATURE_V8, so it
incorrectly thought that the qemu-system-arm 'max' CPU did not have
LPAE and turned off 'highmem' support in the virt board.  Following
b8f7959f28c4f36 qemu-system-arm 'max' is treated the same as
'cortex-a15' and other v7 LPAE CPUs, because the generic feature
propagation code does correctly propagate V8 -> V7VE -> LPAE.)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20240109143804.1118307-1-peter.maydell@linaro.org
---
 target/arm/ptw.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 2d4fa8dbcaf..5eb3577bcd5 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -95,7 +95,10 @@ static const uint8_t pamax_map[] = {
     [6] = 52,
 };
 
-/* The cpu-specific constant value of PAMax; also used by hw/arm/virt. */
+/*
+ * The cpu-specific constant value of PAMax; also used by hw/arm/virt.
+ * Note that machvirt_init calls this on a CPU that is inited but not realized!
+ */
 unsigned int arm_pamax(ARMCPU *cpu)
 {
     if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
@@ -110,13 +113,8 @@ unsigned int arm_pamax(ARMCPU *cpu)
         return pamax_map[parange];
     }
 
-    /*
-     * In machvirt_init, we call arm_pamax on a cpu that is not fully
-     * initialized, so we can't rely on the propagation done in realize.
-     */
-    if (arm_feature(&cpu->env, ARM_FEATURE_LPAE) ||
-        arm_feature(&cpu->env, ARM_FEATURE_V7VE)) {
-        /* v7 with LPAE */
+    if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
+        /* v7 or v8 with LPAE */
         return 40;
     }
     /* Anything else */
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 03/21] docs/system/arm/virt.rst: Improve 'highmem' option docs
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
  2024-01-16 15:12 ` [PULL 01/21] docs/devel/docs: Document .hx file syntax Peter Maydell
  2024-01-16 15:12 ` [PULL 02/21] target/arm: arm_pamax() no longer needs to do feature propagation Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 04/21] hw/misc: Implement STM32L4x5 EXTI Peter Maydell
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

Improve the 'highmem' option docs to note that by default we assume
that a 32-bit kernel on an LPAE-capable CPU has LPAE enabled, and
what the consequences are.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Message-id: 20240109170834.1387457-1-peter.maydell@linaro.org
---
 docs/system/arm/virt.rst | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
index 7c4c80180c6..c245c52b7ac 100644
--- a/docs/system/arm/virt.rst
+++ b/docs/system/arm/virt.rst
@@ -96,7 +96,13 @@ mte
 highmem
   Set ``on``/``off`` to enable/disable placing devices and RAM in physical
   address space above 32 bits. The default is ``on`` for machine types
-  later than ``virt-2.12``.
+  later than ``virt-2.12`` when the CPU supports an address space
+  bigger than 32 bits (i.e. 64-bit CPUs, and 32-bit CPUs with the
+  Large Physical Address Extension (LPAE) feature). If you want to
+  boot a 32-bit kernel which does not have ``CONFIG_LPAE`` enabled on
+  a CPU type which implements LPAE, you will need to manually set
+  this to ``off``; otherwise some devices, such as the PCI controller,
+  will not be accessible.
 
 compact-highmem
   Set ``on``/``off`` to enable/disable the compact layout for high memory regions.
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 04/21] hw/misc: Implement STM32L4x5 EXTI
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (2 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 03/21] docs/system/arm/virt.rst: Improve 'highmem' option docs Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 05/21] hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC Peter Maydell
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Inès Varhol <ines.varhol@telecom-paris.fr>

Although very similar to the STM32F4xx EXTI, STM32L4x5 EXTI generates
more than 32 event/interrupt requests and thus uses more registers
than STM32F4xx EXTI which generates 23 event/interrupt requests.

Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-id: 20240109160658.311932-2-ines.varhol@telecom-paris.fr
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 docs/system/arm/b-l475e-iot01a.rst |   5 +-
 include/hw/misc/stm32l4x5_exti.h   |  51 +++++
 hw/misc/stm32l4x5_exti.c           | 290 +++++++++++++++++++++++++++++
 hw/misc/Kconfig                    |   3 +
 hw/misc/meson.build                |   1 +
 hw/misc/trace-events               |   5 +
 6 files changed, 352 insertions(+), 3 deletions(-)
 create mode 100644 include/hw/misc/stm32l4x5_exti.h
 create mode 100644 hw/misc/stm32l4x5_exti.c

diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
index 2b128e6b847..72f256ace75 100644
--- a/docs/system/arm/b-l475e-iot01a.rst
+++ b/docs/system/arm/b-l475e-iot01a.rst
@@ -12,17 +12,16 @@ USART, I2C, SPI, CAN and USB OTG, as well as a variety of sensors.
 Supported devices
 """""""""""""""""
 
-Currently, B-L475E-IOT01A machine's implementation is minimal,
-it only supports the following device:
+Currently B-L475E-IOT01A machine's only supports the following devices:
 
 - Cortex-M4F based STM32L4x5 SoC
+- STM32L4x5 EXTI (Extended interrupts and events controller)
 
 Missing devices
 """""""""""""""
 
 The B-L475E-IOT01A does *not* support the following devices:
 
-- Extended interrupts and events controller (EXTI)
 - Reset and clock control (RCC)
 - Serial ports (UART)
 - System configuration controller (SYSCFG)
diff --git a/include/hw/misc/stm32l4x5_exti.h b/include/hw/misc/stm32l4x5_exti.h
new file mode 100644
index 00000000000..be961d2f01f
--- /dev/null
+++ b/include/hw/misc/stm32l4x5_exti.h
@@ -0,0 +1,51 @@
+/*
+ * STM32L4x5 EXTI (Extended interrupts and events controller)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * This work is based on the stm32f4xx_exti by Alistair Francis.
+ * Original code is licensed under the MIT License:
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ */
+
+/*
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#ifndef HW_STM32L4X5_EXTI_H
+#define HW_STM32L4X5_EXTI_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_STM32L4X5_EXTI "stm32l4x5-exti"
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5ExtiState, STM32L4X5_EXTI)
+
+#define EXTI_NUM_INTERRUPT_OUT_LINES 40
+#define EXTI_NUM_REGISTER 2
+
+struct Stm32l4x5ExtiState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+
+    uint32_t imr[EXTI_NUM_REGISTER];
+    uint32_t emr[EXTI_NUM_REGISTER];
+    uint32_t rtsr[EXTI_NUM_REGISTER];
+    uint32_t ftsr[EXTI_NUM_REGISTER];
+    uint32_t swier[EXTI_NUM_REGISTER];
+    uint32_t pr[EXTI_NUM_REGISTER];
+
+    qemu_irq irq[EXTI_NUM_INTERRUPT_OUT_LINES];
+};
+
+#endif
diff --git a/hw/misc/stm32l4x5_exti.c b/hw/misc/stm32l4x5_exti.c
new file mode 100644
index 00000000000..9fd859160d4
--- /dev/null
+++ b/hw/misc/stm32l4x5_exti.c
@@ -0,0 +1,290 @@
+/*
+ * STM32L4x5 EXTI (Extended interrupts and events controller)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Samuel Tardieu <samuel.tardieu@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * This work is based on the stm32f4xx_exti by Alistair Francis.
+ * Original code is licensed under the MIT License:
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ */
+
+/*
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "hw/misc/stm32l4x5_exti.h"
+
+#define EXTI_IMR1   0x00
+#define EXTI_EMR1   0x04
+#define EXTI_RTSR1  0x08
+#define EXTI_FTSR1  0x0C
+#define EXTI_SWIER1 0x10
+#define EXTI_PR1    0x14
+#define EXTI_IMR2   0x20
+#define EXTI_EMR2   0x24
+#define EXTI_RTSR2  0x28
+#define EXTI_FTSR2  0x2C
+#define EXTI_SWIER2 0x30
+#define EXTI_PR2    0x34
+
+#define EXTI_NUM_GPIO_EVENT_IN_LINES 16
+#define EXTI_MAX_IRQ_PER_BANK 32
+#define EXTI_IRQS_BANK0  32
+#define EXTI_IRQS_BANK1  8
+
+static const unsigned irqs_per_bank[EXTI_NUM_REGISTER] = {
+    EXTI_IRQS_BANK0,
+    EXTI_IRQS_BANK1,
+};
+
+static const uint32_t exti_romask[EXTI_NUM_REGISTER] = {
+    0xff820000, /* 0b11111111_10000010_00000000_00000000 */
+    0x00000087, /* 0b00000000_00000000_00000000_10000111 */
+};
+
+static unsigned regbank_index_by_irq(unsigned irq)
+{
+     return irq >= EXTI_MAX_IRQ_PER_BANK ? 1 : 0;
+}
+
+static unsigned regbank_index_by_addr(hwaddr addr)
+{
+     return addr >= EXTI_IMR2 ? 1 : 0;
+}
+
+static unsigned valid_mask(unsigned bank)
+{
+     return MAKE_64BIT_MASK(0, irqs_per_bank[bank]);
+}
+
+static unsigned configurable_mask(unsigned bank)
+{
+     return valid_mask(bank) & ~exti_romask[bank];
+}
+
+static void stm32l4x5_exti_reset_hold(Object *obj)
+{
+    Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
+
+    for (unsigned bank = 0; bank < EXTI_NUM_REGISTER; bank++) {
+        s->imr[bank] = exti_romask[bank];
+        s->emr[bank] = 0x00000000;
+        s->rtsr[bank] = 0x00000000;
+        s->ftsr[bank] = 0x00000000;
+        s->swier[bank] = 0x00000000;
+        s->pr[bank] = 0x00000000;
+    }
+}
+
+static void stm32l4x5_exti_set_irq(void *opaque, int irq, int level)
+{
+    Stm32l4x5ExtiState *s = opaque;
+    const unsigned bank = regbank_index_by_irq(irq);
+    const int oirq = irq;
+
+    trace_stm32l4x5_exti_set_irq(irq, level);
+
+    /* Shift the value to enable access in x2 registers. */
+    irq %= EXTI_MAX_IRQ_PER_BANK;
+
+    /* If the interrupt is masked, pr won't be raised */
+    if (!extract32(s->imr[bank], irq, 1)) {
+        return;
+    }
+
+    if (((1 << irq) & s->rtsr[bank]) && level) {
+        /* Rising Edge */
+        s->pr[bank] |= 1 << irq;
+        qemu_irq_pulse(s->irq[oirq]);
+    } else if (((1 << irq) & s->ftsr[bank]) && !level) {
+        /* Falling Edge */
+        s->pr[bank] |= 1 << irq;
+        qemu_irq_pulse(s->irq[oirq]);
+    }
+    /*
+     * In the following situations :
+     * - falling edge but rising trigger selected
+     * - rising edge but falling trigger selected
+     * - no trigger selected
+     * No action is required
+     */
+}
+
+static uint64_t stm32l4x5_exti_read(void *opaque, hwaddr addr,
+                                    unsigned int size)
+{
+    Stm32l4x5ExtiState *s = opaque;
+    uint32_t r = 0;
+    const unsigned bank = regbank_index_by_addr(addr);
+
+    switch (addr) {
+    case EXTI_IMR1:
+    case EXTI_IMR2:
+        r = s->imr[bank];
+        break;
+    case EXTI_EMR1:
+    case EXTI_EMR2:
+        r = s->emr[bank];
+        break;
+    case EXTI_RTSR1:
+    case EXTI_RTSR2:
+        r = s->rtsr[bank];
+        break;
+    case EXTI_FTSR1:
+    case EXTI_FTSR2:
+        r = s->ftsr[bank];
+        break;
+    case EXTI_SWIER1:
+    case EXTI_SWIER2:
+        r = s->swier[bank];
+        break;
+    case EXTI_PR1:
+    case EXTI_PR2:
+        r = s->pr[bank];
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "STM32L4X5_exti_read: Bad offset 0x%" HWADDR_PRIx "\n",
+                      addr);
+        break;
+    }
+
+    trace_stm32l4x5_exti_read(addr, r);
+
+    return r;
+}
+
+static void stm32l4x5_exti_write(void *opaque, hwaddr addr,
+                                 uint64_t val64, unsigned int size)
+{
+    Stm32l4x5ExtiState *s = opaque;
+    const unsigned bank = regbank_index_by_addr(addr);
+
+    trace_stm32l4x5_exti_write(addr, val64);
+
+    switch (addr) {
+    case EXTI_IMR1:
+    case EXTI_IMR2:
+        s->imr[bank] = val64 & valid_mask(bank);
+        return;
+    case EXTI_EMR1:
+    case EXTI_EMR2:
+        s->emr[bank] = val64 & valid_mask(bank);
+        return;
+    case EXTI_RTSR1:
+    case EXTI_RTSR2:
+        s->rtsr[bank] = val64 & configurable_mask(bank);
+        return;
+    case EXTI_FTSR1:
+    case EXTI_FTSR2:
+        s->ftsr[bank] = val64 & configurable_mask(bank);
+        return;
+    case EXTI_SWIER1:
+    case EXTI_SWIER2: {
+        const uint32_t set = val64 & configurable_mask(bank);
+        const uint32_t pend = set & ~s->swier[bank] & s->imr[bank] &
+                              ~s->pr[bank];
+        s->swier[bank] = set;
+        s->pr[bank] |= pend;
+        for (unsigned i = 0; i < irqs_per_bank[bank]; i++) {
+            if (extract32(pend, i, 1)) {
+                qemu_irq_pulse(s->irq[i + 32 * bank]);
+            }
+        }
+        return;
+    }
+    case EXTI_PR1:
+    case EXTI_PR2: {
+        const uint32_t cleared = s->pr[bank] & val64 & configurable_mask(bank);
+        /* This bit is cleared by writing a 1 to it */
+        s->pr[bank] &= ~cleared;
+        /* Software triggered interrupts are cleared as well */
+        s->swier[bank] &= ~cleared;
+        return;
+    }
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "STM32L4X5_exti_write: Bad offset 0x%" HWADDR_PRIx "\n",
+                      addr);
+    }
+}
+
+static const MemoryRegionOps stm32l4x5_exti_ops = {
+    .read = stm32l4x5_exti_read,
+    .write = stm32l4x5_exti_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .impl.unaligned = false,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .valid.unaligned = false,
+};
+
+static void stm32l4x5_exti_init(Object *obj)
+{
+    Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
+
+    for (size_t i = 0; i < EXTI_NUM_INTERRUPT_OUT_LINES; i++) {
+        sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
+    }
+
+    memory_region_init_io(&s->mmio, obj, &stm32l4x5_exti_ops, s,
+                          TYPE_STM32L4X5_EXTI, 0x400);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+    qdev_init_gpio_in(DEVICE(obj), stm32l4x5_exti_set_irq,
+                      EXTI_NUM_GPIO_EVENT_IN_LINES);
+}
+
+static const VMStateDescription vmstate_stm32l4x5_exti = {
+    .name = TYPE_STM32L4X5_EXTI,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(imr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
+        VMSTATE_UINT32_ARRAY(emr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
+        VMSTATE_UINT32_ARRAY(rtsr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
+        VMSTATE_UINT32_ARRAY(ftsr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
+        VMSTATE_UINT32_ARRAY(swier, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
+        VMSTATE_UINT32_ARRAY(pr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void stm32l4x5_exti_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->vmsd = &vmstate_stm32l4x5_exti;
+    rc->phases.hold = stm32l4x5_exti_reset_hold;
+}
+
+static const TypeInfo stm32l4x5_exti_types[] = {
+    {
+        .name          = TYPE_STM32L4X5_EXTI,
+        .parent        = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(Stm32l4x5ExtiState),
+        .instance_init = stm32l4x5_exti_init,
+        .class_init    = stm32l4x5_exti_class_init,
+    }
+};
+
+DEFINE_TYPES(stm32l4x5_exti_types)
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index cc8a8c1418f..3efe3dc2cc7 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -87,6 +87,9 @@ config STM32F4XX_SYSCFG
 config STM32F4XX_EXTI
     bool
 
+config STM32L4X5_EXTI
+    bool
+
 config MIPS_ITU
     bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 36c20d5637f..16db6e228d7 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -110,6 +110,7 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files(
 system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c'))
 system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
 system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
+system_ss.add(when: 'CONFIG_STM32L4X5_EXTI', if_true: files('stm32l4x5_exti.c'))
 system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c'))
 system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c'))
 
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 85725506bff..fccd3204bf5 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -163,6 +163,11 @@ stm32f4xx_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
 stm32f4xx_exti_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
 stm32f4xx_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
 
+# stm32l4x5_exti.c
+stm32l4x5_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
+stm32l4x5_exti_read(uint64_t addr, uint64_t data) "reg read: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
+stm32l4x5_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
+
 # tz-mpc.c
 tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u"
 tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u"
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 05/21] hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (3 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 04/21] hw/misc: Implement STM32L4x5 EXTI Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 06/21] tests/qtest: Add STM32L4x5 EXTI QTest testcase Peter Maydell
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Inès Varhol <ines.varhol@telecom-paris.fr>

Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Message-id: 20240109160658.311932-3-ines.varhol@telecom-paris.fr
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/arm/stm32l4x5_soc.h |  3 ++
 hw/arm/stm32l4x5_soc.c         | 52 +++++++++++++++++++++++++++++++++-
 hw/arm/Kconfig                 |  1 +
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
index 2fd44a36a9d..f7305568dcc 100644
--- a/include/hw/arm/stm32l4x5_soc.h
+++ b/include/hw/arm/stm32l4x5_soc.h
@@ -26,6 +26,7 @@
 
 #include "exec/memory.h"
 #include "hw/arm/armv7m.h"
+#include "hw/misc/stm32l4x5_exti.h"
 #include "qom/object.h"
 
 #define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
@@ -39,6 +40,8 @@ struct Stm32l4x5SocState {
 
     ARMv7MState armv7m;
 
+    Stm32l4x5ExtiState exti;
+
     MemoryRegion sram1;
     MemoryRegion sram2;
     MemoryRegion flash;
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
index 159d5315c99..756eb694884 100644
--- a/hw/arm/stm32l4x5_soc.c
+++ b/hw/arm/stm32l4x5_soc.c
@@ -36,10 +36,51 @@
 #define SRAM2_BASE_ADDRESS 0x10000000
 #define SRAM2_SIZE (32 * KiB)
 
+#define EXTI_ADDR 0x40010400
+
+#define NUM_EXTI_IRQ 40
+/* Match exti line connections with their CPU IRQ number */
+/* See Vector Table (Reference Manual p.396) */
+static const int exti_irq[NUM_EXTI_IRQ] = {
+    6,                      /* GPIO[0]                 */
+    7,                      /* GPIO[1]                 */
+    8,                      /* GPIO[2]                 */
+    9,                      /* GPIO[3]                 */
+    10,                     /* GPIO[4]                 */
+    23, 23, 23, 23, 23,     /* GPIO[5..9]              */
+    40, 40, 40, 40, 40, 40, /* GPIO[10..15]            */
+    1,                      /* PVD                     */
+    67,                     /* OTG_FS_WKUP, Direct     */
+    41,                     /* RTC_ALARM               */
+    2,                      /* RTC_TAMP_STAMP2/CSS_LSE */
+    3,                      /* RTC wakeup timer        */
+    63,                     /* COMP1                   */
+    63,                     /* COMP2                   */
+    31,                     /* I2C1 wakeup, Direct     */
+    33,                     /* I2C2 wakeup, Direct     */
+    72,                     /* I2C3 wakeup, Direct     */
+    37,                     /* USART1 wakeup, Direct   */
+    38,                     /* USART2 wakeup, Direct   */
+    39,                     /* USART3 wakeup, Direct   */
+    52,                     /* UART4 wakeup, Direct    */
+    53,                     /* UART4 wakeup, Direct    */
+    70,                     /* LPUART1 wakeup, Direct  */
+    65,                     /* LPTIM1, Direct          */
+    66,                     /* LPTIM2, Direct          */
+    76,                     /* SWPMI1 wakeup, Direct   */
+    1,                      /* PVM1 wakeup             */
+    1,                      /* PVM2 wakeup             */
+    1,                      /* PVM3 wakeup             */
+    1,                      /* PVM4 wakeup             */
+    78                      /* LCD wakeup, Direct      */
+};
+
 static void stm32l4x5_soc_initfn(Object *obj)
 {
     Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
 
+    object_initialize_child(obj, "exti", &s->exti, TYPE_STM32L4X5_EXTI);
+
     s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
     s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
 }
@@ -51,6 +92,7 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
     const Stm32l4x5SocClass *sc = STM32L4X5_SOC_GET_CLASS(dev_soc);
     MemoryRegion *system_memory = get_system_memory();
     DeviceState *armv7m;
+    SysBusDevice *busdev;
 
     /*
      * We use s->refclk internally and only define it with qdev_init_clock_in()
@@ -113,6 +155,15 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
         return;
     }
 
+    busdev = SYS_BUS_DEVICE(&s->exti);
+    if (!sysbus_realize(busdev, errp)) {
+        return;
+    }
+    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
+    for (unsigned i = 0; i < NUM_EXTI_IRQ; i++) {
+        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
+    }
+
     /* APB1 BUS */
     create_unimplemented_device("TIM2",      0x40000000, 0x400);
     create_unimplemented_device("TIM3",      0x40000400, 0x400);
@@ -153,7 +204,6 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
     create_unimplemented_device("SYSCFG",    0x40010000, 0x30);
     create_unimplemented_device("VREFBUF",   0x40010030, 0x1D0);
     create_unimplemented_device("COMP",      0x40010200, 0x200);
-    create_unimplemented_device("EXTI",      0x40010400, 0x400);
     /* RESERVED:    0x40010800, 0x1400 */
     create_unimplemented_device("FIREWALL",  0x40011C00, 0x400);
     /* RESERVED:    0x40012000, 0x800 */
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 39d255425b1..da9c6e5064d 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -459,6 +459,7 @@ config STM32L4X5_SOC
     bool
     select ARM_V7M
     select OR_IRQ
+    select STM32L4X5_EXTI
 
 config XLNX_ZYNQMP_ARM
     bool
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 06/21] tests/qtest: Add STM32L4x5 EXTI QTest testcase
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (4 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 05/21] hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 07/21] hw/misc: Implement STM32L4x5 SYSCFG Peter Maydell
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Inès Varhol <ines.varhol@telecom-paris.fr>

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Message-id: 20240109160658.311932-4-ines.varhol@telecom-paris.fr
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 tests/qtest/stm32l4x5_exti-test.c | 524 ++++++++++++++++++++++++++++++
 tests/qtest/meson.build           |   5 +
 2 files changed, 529 insertions(+)
 create mode 100644 tests/qtest/stm32l4x5_exti-test.c

diff --git a/tests/qtest/stm32l4x5_exti-test.c b/tests/qtest/stm32l4x5_exti-test.c
new file mode 100644
index 00000000000..c3900777139
--- /dev/null
+++ b/tests/qtest/stm32l4x5_exti-test.c
@@ -0,0 +1,524 @@
+/*
+ * QTest testcase for STM32L4x5_EXTI
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * 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 "libqtest-single.h"
+
+#define EXTI_BASE_ADDR 0x40010400
+#define EXTI_IMR1 0x00
+#define EXTI_EMR1 0x04
+#define EXTI_RTSR1 0x08
+#define EXTI_FTSR1 0x0C
+#define EXTI_SWIER1 0x10
+#define EXTI_PR1 0x14
+#define EXTI_IMR2 0x20
+#define EXTI_EMR2 0x24
+#define EXTI_RTSR2 0x28
+#define EXTI_FTSR2 0x2C
+#define EXTI_SWIER2 0x30
+#define EXTI_PR2 0x34
+
+#define NVIC_ISER 0xE000E100
+#define NVIC_ISPR 0xE000E200
+#define NVIC_ICPR 0xE000E280
+
+#define EXTI0_IRQ 6
+#define EXTI1_IRQ 7
+#define EXTI35_IRQ 1
+
+static void enable_nvic_irq(unsigned int n)
+{
+    writel(NVIC_ISER, 1 << n);
+}
+
+static void unpend_nvic_irq(unsigned int n)
+{
+    writel(NVIC_ICPR, 1 << n);
+}
+
+static bool check_nvic_pending(unsigned int n)
+{
+    return readl(NVIC_ISPR) & (1 << n);
+}
+
+static void exti_writel(unsigned int offset, uint32_t value)
+{
+    writel(EXTI_BASE_ADDR + offset, value);
+}
+
+static uint32_t exti_readl(unsigned int offset)
+{
+    return readl(EXTI_BASE_ADDR + offset);
+}
+
+static void exti_set_irq(int num, int level)
+{
+   qtest_set_irq_in(global_qtest, "/machine/soc/exti", NULL,
+                    num, level);
+}
+
+static void test_reg_write_read(void)
+{
+    /* Test that non-reserved bits in xMR and xTSR can be set and cleared */
+
+    exti_writel(EXTI_IMR1, 0xFFFFFFFF);
+    g_assert_cmpuint(exti_readl(EXTI_IMR1), ==, 0xFFFFFFFF);
+    exti_writel(EXTI_IMR1, 0x00000000);
+    g_assert_cmpuint(exti_readl(EXTI_IMR1), ==, 0x00000000);
+
+    exti_writel(EXTI_EMR1, 0xFFFFFFFF);
+    g_assert_cmpuint(exti_readl(EXTI_EMR1), ==, 0xFFFFFFFF);
+    exti_writel(EXTI_EMR1, 0x00000000);
+    g_assert_cmpuint(exti_readl(EXTI_EMR1), ==, 0x00000000);
+
+    exti_writel(EXTI_RTSR1, 0xFFFFFFFF);
+    g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x007DFFFF);
+    exti_writel(EXTI_RTSR1, 0x00000000);
+    g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x00000000);
+
+    exti_writel(EXTI_FTSR1, 0xFFFFFFFF);
+    g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x007DFFFF);
+    exti_writel(EXTI_FTSR1, 0x00000000);
+    g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x00000000);
+
+    exti_writel(EXTI_IMR2, 0xFFFFFFFF);
+    g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x000000FF);
+    exti_writel(EXTI_IMR2, 0x00000000);
+    g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x00000000);
+
+    exti_writel(EXTI_EMR2, 0xFFFFFFFF);
+    g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x000000FF);
+    exti_writel(EXTI_EMR2, 0x00000000);
+    g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x00000000);
+
+    exti_writel(EXTI_RTSR2, 0xFFFFFFFF);
+    g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000078);
+    exti_writel(EXTI_RTSR2, 0x00000000);
+    g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
+
+    exti_writel(EXTI_FTSR2, 0xFFFFFFFF);
+    g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000078);
+    exti_writel(EXTI_FTSR2, 0x00000000);
+    g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
+}
+
+static void test_direct_lines_write(void)
+{
+    /* Test that direct lines reserved bits are not written to */
+
+    exti_writel(EXTI_RTSR1, 0xFF820000);
+    g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x00000000);
+
+    exti_writel(EXTI_FTSR1, 0xFF820000);
+    g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x00000000);
+
+    exti_writel(EXTI_SWIER1, 0xFF820000);
+    g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000000);
+
+    exti_writel(EXTI_PR1, 0xFF820000);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+
+    exti_writel(EXTI_RTSR2, 0x00000087);
+    g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
+
+    exti_writel(EXTI_FTSR2, 0x00000087);
+    g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
+
+    exti_writel(EXTI_SWIER2, 0x00000087);
+    g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
+
+    exti_writel(EXTI_PR2, 0x00000087);
+    g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+}
+
+static void test_reserved_bits_write(void)
+{
+    /* Test that reserved bits stay are not written to */
+
+    exti_writel(EXTI_IMR2, 0xFFFFFF00);
+    g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x00000000);
+
+    exti_writel(EXTI_EMR2, 0xFFFFFF00);
+    g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x00000000);
+
+    exti_writel(EXTI_RTSR2, 0xFFFFFF00);
+    g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
+
+    exti_writel(EXTI_FTSR2, 0xFFFFFF00);
+    g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
+
+    exti_writel(EXTI_SWIER2, 0xFFFFFF00);
+    g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
+
+    exti_writel(EXTI_PR2, 0xFFFFFF00);
+    g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+}
+
+static void test_software_interrupt(void)
+{
+    /*
+     * Test that we can launch a software irq by :
+     * - enabling its line in IMR
+     * - and then setting a bit from '0' to '1' in SWIER
+     *
+     * And that the interruption stays pending in NVIC
+     * even after clearing the pending bit in PR.
+     */
+
+    /*
+     * Testing interrupt line EXTI0
+     * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
+     */
+
+    enable_nvic_irq(EXTI0_IRQ);
+    /* Check that there are no interrupts already pending in PR */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that this specific interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    /* Enable interrupt line EXTI0 */
+    exti_writel(EXTI_IMR1, 0x00000001);
+    /* Set the right SWIER bit from '0' to '1' */
+    exti_writel(EXTI_SWIER1, 0x00000000);
+    exti_writel(EXTI_SWIER1, 0x00000001);
+
+    /* Check that the write in SWIER was effective */
+    g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000001);
+    /* Check that the corresponding pending bit in PR is set */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+    /* Check that the corresponding interrupt is pending in the NVIC */
+    g_assert_true(check_nvic_pending(EXTI0_IRQ));
+
+    /* Clear the pending bit in PR */
+    exti_writel(EXTI_PR1, 0x00000001);
+
+    /* Check that the write in PR was effective */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that the corresponding bit in SWIER was cleared */
+    g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000000);
+    /* Check that the interrupt is still pending in the NVIC */
+    g_assert_true(check_nvic_pending(EXTI0_IRQ));
+
+    /*
+     * Testing interrupt line EXTI35
+     * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
+     */
+
+    enable_nvic_irq(EXTI35_IRQ);
+    /* Check that there are no interrupts already pending */
+    g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+    g_assert_false(check_nvic_pending(EXTI35_IRQ));
+
+    /* Enable interrupt line EXTI0 */
+    exti_writel(EXTI_IMR2, 0x00000008);
+    /* Set the right SWIER bit from '0' to '1' */
+    exti_writel(EXTI_SWIER2, 0x00000000);
+    exti_writel(EXTI_SWIER2, 0x00000008);
+
+    /* Check that the write in SWIER was effective */
+    g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000008);
+    /* Check that the corresponding pending bit in PR is set */
+    g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000008);
+    /* Check that the corresponding interrupt is pending in the NVIC */
+    g_assert_true(check_nvic_pending(EXTI35_IRQ));
+
+    /* Clear the pending bit in PR */
+    exti_writel(EXTI_PR2, 0x00000008);
+
+    /* Check that the write in PR was effective */
+    g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+    /* Check that the corresponding bit in SWIER was cleared */
+    g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
+    /* Check that the interrupt is still pending in the NVIC */
+    g_assert_true(check_nvic_pending(EXTI35_IRQ));
+
+    /* Clean NVIC */
+    unpend_nvic_irq(EXTI0_IRQ);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+    unpend_nvic_irq(EXTI35_IRQ);
+    g_assert_false(check_nvic_pending(EXTI35_IRQ));
+}
+
+static void test_edge_selector(void)
+{
+    enable_nvic_irq(EXTI0_IRQ);
+
+    /* Configure EXTI line 0 irq on rising edge */
+    exti_set_irq(0, 1);
+    exti_writel(EXTI_IMR1, 0x00000001);
+    exti_writel(EXTI_RTSR1, 0x00000001);
+    exti_writel(EXTI_FTSR1, 0x00000000);
+
+    /* Test that an irq is raised on rising edge only */
+    exti_set_irq(0, 0);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    exti_set_irq(0, 1);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+    g_assert_true(check_nvic_pending(EXTI0_IRQ));
+
+    /* Clean the test */
+    exti_writel(EXTI_PR1, 0x00000001);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    unpend_nvic_irq(EXTI0_IRQ);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    /* Configure EXTI line 0 irq on falling edge */
+    exti_set_irq(0, 0);
+    exti_writel(EXTI_IMR1, 0x00000001);
+    exti_writel(EXTI_RTSR1, 0x00000000);
+    exti_writel(EXTI_FTSR1, 0x00000001);
+
+    /* Test that an irq is raised on falling edge only */
+    exti_set_irq(0, 1);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    exti_set_irq(0, 0);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+    g_assert_true(check_nvic_pending(EXTI0_IRQ));
+
+    /* Clean the test */
+    exti_writel(EXTI_PR1, 0x00000001);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    unpend_nvic_irq(EXTI0_IRQ);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    /* Configure EXTI line 0 irq on falling and rising edge */
+    exti_writel(EXTI_IMR1, 0x00000001);
+    exti_writel(EXTI_RTSR1, 0x00000001);
+    exti_writel(EXTI_FTSR1, 0x00000001);
+
+    /* Test that an irq is raised on rising edge */
+    exti_set_irq(0, 1);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+    g_assert_true(check_nvic_pending(EXTI0_IRQ));
+
+    /* Clean the test */
+    exti_writel(EXTI_PR1, 0x00000001);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    unpend_nvic_irq(EXTI0_IRQ);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    /* Test that an irq is raised on falling edge */
+    exti_set_irq(0, 0);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+    g_assert_true(check_nvic_pending(EXTI0_IRQ));
+
+    /* Clean the test */
+    exti_writel(EXTI_PR1, 0x00000001);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    unpend_nvic_irq(EXTI0_IRQ);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    /* Configure EXTI line 0 irq without selecting an edge trigger */
+    exti_writel(EXTI_IMR1, 0x00000001);
+    exti_writel(EXTI_RTSR1, 0x00000000);
+    exti_writel(EXTI_FTSR1, 0x00000000);
+
+    /* Test that no irq is raised */
+    exti_set_irq(0, 1);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    exti_set_irq(0, 0);
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+}
+
+static void test_no_software_interrupt(void)
+{
+    /*
+     * Test that software irq doesn't happen when :
+     * - corresponding bit in IMR isn't set
+     * - SWIER is set to 1 before IMR is set to 1
+     */
+
+    /*
+     * Testing interrupt line EXTI0
+     * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
+     */
+
+    enable_nvic_irq(EXTI0_IRQ);
+    /* Check that there are no interrupts already pending in PR */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that this specific interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    /* Mask interrupt line EXTI0 */
+    exti_writel(EXTI_IMR1, 0x00000000);
+    /* Set the corresponding SWIER bit from '0' to '1' */
+    exti_writel(EXTI_SWIER1, 0x00000000);
+    exti_writel(EXTI_SWIER1, 0x00000001);
+
+    /* Check that the write in SWIER was effective */
+    g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000001);
+    /* Check that the pending bit in PR wasn't set */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that the interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    /* Enable interrupt line EXTI0 */
+    exti_writel(EXTI_IMR1, 0x00000001);
+
+    /* Check that the pending bit in PR wasn't set */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that the interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI0_IRQ));
+
+    /*
+     * Testing interrupt line EXTI35
+     * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
+     */
+
+    enable_nvic_irq(EXTI35_IRQ);
+    /* Check that there are no interrupts already pending in PR */
+    g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+    /* Check that this specific interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI35_IRQ));
+
+    /* Mask interrupt line EXTI35 */
+    exti_writel(EXTI_IMR2, 0x00000000);
+    /* Set the corresponding SWIER bit from '0' to '1' */
+    exti_writel(EXTI_SWIER2, 0x00000000);
+    exti_writel(EXTI_SWIER2, 0x00000008);
+
+    /* Check that the write in SWIER was effective */
+    g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000008);
+    /* Check that the pending bit in PR wasn't set */
+    g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+    /* Check that the interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI35_IRQ));
+
+    /* Enable interrupt line EXTI35 */
+    exti_writel(EXTI_IMR2, 0x00000008);
+
+    /* Check that the pending bit in PR wasn't set */
+    g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+    /* Check that the interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI35_IRQ));
+}
+
+static void test_masked_interrupt(void)
+{
+    /*
+     * Test that irq doesn't happen when :
+     * - corresponding bit in IMR isn't set
+     * - SWIER is set to 1 before IMR is set to 1
+     */
+
+    /*
+     * Testing interrupt line EXTI1
+     * with rising edge from GPIOx pin 1
+     */
+
+    enable_nvic_irq(EXTI1_IRQ);
+    /* Check that there are no interrupts already pending in PR */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that this specific interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI1_IRQ));
+
+    /* Mask interrupt line EXTI1 */
+    exti_writel(EXTI_IMR1, 0x00000000);
+
+    /* Configure interrupt on rising edge */
+    exti_writel(EXTI_RTSR1, 0x00000002);
+
+    /* Simulate rising edge from GPIO line 1 */
+    exti_set_irq(1, 1);
+
+    /* Check that the pending bit in PR wasn't set */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that the interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI1_IRQ));
+
+    /* Enable interrupt line EXTI1 */
+    exti_writel(EXTI_IMR1, 0x00000002);
+
+    /* Check that the pending bit in PR wasn't set */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that the interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI1_IRQ));
+}
+
+static void test_interrupt(void)
+{
+    /*
+     * Test that we can launch an irq by :
+     * - enabling its line in IMR
+     * - configuring interrupt on rising edge
+     * - and then setting the input line from '0' to '1'
+     *
+     * And that the interruption stays pending in NVIC
+     * even after clearing the pending bit in PR.
+     */
+
+    /*
+     * Testing interrupt line EXTI1
+     * with rising edge from GPIOx pin 1
+     */
+
+    enable_nvic_irq(EXTI1_IRQ);
+    /* Check that there are no interrupts already pending in PR */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that this specific interrupt isn't pending in NVIC */
+    g_assert_false(check_nvic_pending(EXTI1_IRQ));
+
+    /* Enable interrupt line EXTI1 */
+    exti_writel(EXTI_IMR1, 0x00000002);
+
+    /* Configure interrupt on rising edge */
+    exti_writel(EXTI_RTSR1, 0x00000002);
+
+    /* Simulate rising edge from GPIO line 1 */
+    exti_set_irq(1, 1);
+
+    /* Check that the pending bit in PR was set */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000002);
+    /* Check that the interrupt is pending in NVIC */
+    g_assert_true(check_nvic_pending(EXTI1_IRQ));
+
+    /* Clear the pending bit in PR */
+    exti_writel(EXTI_PR1, 0x00000002);
+
+    /* Check that the write in PR was effective */
+    g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+    /* Check that the interrupt is still pending in the NVIC */
+    g_assert_true(check_nvic_pending(EXTI1_IRQ));
+
+    /* Clean NVIC */
+    unpend_nvic_irq(EXTI1_IRQ);
+    g_assert_false(check_nvic_pending(EXTI1_IRQ));
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_set_nonfatal_assertions();
+    qtest_add_func("stm32l4x5/exti/direct_lines", test_direct_lines_write);
+    qtest_add_func("stm32l4x5/exti/reserved_bits", test_reserved_bits_write);
+    qtest_add_func("stm32l4x5/exti/reg_write_read", test_reg_write_read);
+    qtest_add_func("stm32l4x5/exti/no_software_interrupt",
+                   test_no_software_interrupt);
+    qtest_add_func("stm32l4x5/exti/software_interrupt",
+                   test_software_interrupt);
+    qtest_add_func("stm32l4x5/exti/masked_interrupt", test_masked_interrupt);
+    qtest_add_func("stm32l4x5/exti/interrupt", test_interrupt);
+    qtest_add_func("stm32l4x5/exti/test_edge_selector", test_edge_selector);
+
+    qtest_start("-machine b-l475e-iot01a");
+    ret = g_test_run();
+    qtest_end();
+
+    return ret;
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index fd40136fa9c..07fdd2dc1a5 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -195,6 +195,10 @@ qtests_aspeed = \
   ['aspeed_hace-test',
    'aspeed_smc-test',
    'aspeed_gpio-test']
+
+qtests_stm32l4x5 = \
+  ['stm32l4x5_exti-test']
+
 qtests_arm = \
   (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
   (config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
@@ -208,6 +212,7 @@ qtests_arm = \
   (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
   (config_all_devices.has_key('CONFIG_VEXPRESS') ? ['test-arm-mptimer'] : []) + \
   (config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
+  (config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 : []) + \
   ['arm-cpu-features',
    'boot-serial-test']
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 07/21] hw/misc: Implement STM32L4x5 SYSCFG
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (5 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 06/21] tests/qtest: Add STM32L4x5 EXTI QTest testcase Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 08/21] hw/arm: Connect STM32L4x5 SYSCFG to STM32L4x5 SoC Peter Maydell
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Inès Varhol <ines.varhol@telecom-paris.fr>

Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Message-id: 20240109194438.70934-2-ines.varhol@telecom-paris.fr
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 docs/system/arm/b-l475e-iot01a.rst |   2 +-
 include/hw/misc/stm32l4x5_syscfg.h |  54 ++++++
 hw/misc/stm32l4x5_syscfg.c         | 266 +++++++++++++++++++++++++++++
 hw/misc/Kconfig                    |   3 +
 hw/misc/meson.build                |   1 +
 hw/misc/trace-events               |   6 +
 6 files changed, 331 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/misc/stm32l4x5_syscfg.h
 create mode 100644 hw/misc/stm32l4x5_syscfg.c

diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
index 72f256ace75..1a021b306a6 100644
--- a/docs/system/arm/b-l475e-iot01a.rst
+++ b/docs/system/arm/b-l475e-iot01a.rst
@@ -16,6 +16,7 @@ Currently B-L475E-IOT01A machine's only supports the following devices:
 
 - Cortex-M4F based STM32L4x5 SoC
 - STM32L4x5 EXTI (Extended interrupts and events controller)
+- STM32L4x5 SYSCFG (System configuration controller)
 
 Missing devices
 """""""""""""""
@@ -24,7 +25,6 @@ The B-L475E-IOT01A does *not* support the following devices:
 
 - Reset and clock control (RCC)
 - Serial ports (UART)
-- System configuration controller (SYSCFG)
 - General-purpose I/Os (GPIO)
 - Analog to Digital Converter (ADC)
 - SPI controller
diff --git a/include/hw/misc/stm32l4x5_syscfg.h b/include/hw/misc/stm32l4x5_syscfg.h
new file mode 100644
index 00000000000..29c3522f9dd
--- /dev/null
+++ b/include/hw/misc/stm32l4x5_syscfg.h
@@ -0,0 +1,54 @@
+/*
+ * STM32L4x5 SYSCFG (System Configuration Controller)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * This work is based on the stm32f4xx_syscfg by Alistair Francis.
+ * Original code is licensed under the MIT License:
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ */
+
+/*
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#ifndef HW_STM32L4X5_SYSCFG_H
+#define HW_STM32L4X5_SYSCFG_H
+
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define TYPE_STM32L4X5_SYSCFG "stm32l4x5-syscfg"
+OBJECT_DECLARE_SIMPLE_TYPE(Stm32l4x5SyscfgState, STM32L4X5_SYSCFG)
+
+#define NUM_GPIOS 8
+#define GPIO_NUM_PINS 16
+#define SYSCFG_NUM_EXTICR 4
+
+struct Stm32l4x5SyscfgState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+
+    uint32_t memrmp;
+    uint32_t cfgr1;
+    uint32_t exticr[SYSCFG_NUM_EXTICR];
+    uint32_t scsr;
+    uint32_t cfgr2;
+    uint32_t swpr;
+    uint32_t skr;
+    uint32_t swpr2;
+
+    qemu_irq gpio_out[GPIO_NUM_PINS];
+};
+
+#endif
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
new file mode 100644
index 00000000000..fd68cb800bb
--- /dev/null
+++ b/hw/misc/stm32l4x5_syscfg.c
@@ -0,0 +1,266 @@
+/*
+ * STM32L4x5 SYSCFG (System Configuration Controller)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * This work is based on the stm32f4xx_syscfg by Alistair Francis.
+ * Original code is licensed under the MIT License:
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ */
+
+/*
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "trace.h"
+#include "hw/irq.h"
+#include "migration/vmstate.h"
+#include "hw/misc/stm32l4x5_syscfg.h"
+
+#define SYSCFG_MEMRMP 0x00
+#define SYSCFG_CFGR1 0x04
+#define SYSCFG_EXTICR1 0x08
+#define SYSCFG_EXTICR2 0x0C
+#define SYSCFG_EXTICR3 0x10
+#define SYSCFG_EXTICR4 0x14
+#define SYSCFG_SCSR 0x18
+#define SYSCFG_CFGR2 0x1C
+#define SYSCFG_SWPR 0x20
+#define SYSCFG_SKR 0x24
+#define SYSCFG_SWPR2 0x28
+
+/* 00000000_00000000_00000001_00000111 */
+#define ACTIVABLE_BITS_MEMRP 0x00000107
+
+/* 11111100_11111111_00000001_00000000 */
+#define ACTIVABLE_BITS_CFGR1 0xFCFF0100
+/* 00000000_00000000_00000000_00000001 */
+#define FIREWALL_DISABLE_CFGR1 0x00000001
+
+/* 00000000_00000000_11111111_11111111 */
+#define ACTIVABLE_BITS_EXTICR 0x0000FFFF
+
+/* 00000000_00000000_00000000_00000011 */
+/* #define ACTIVABLE_BITS_SCSR 0x00000003 */
+
+/* 00000000_00000000_00000000_00001111 */
+#define ECC_LOCK_CFGR2 0x0000000F
+/* 00000000_00000000_00000001_00000000 */
+#define SRAM2_PARITY_ERROR_FLAG_CFGR2 0x00000100
+
+/* 00000000_00000000_00000000_11111111 */
+#define ACTIVABLE_BITS_SKR 0x000000FF
+
+#define NUM_LINES_PER_EXTICR_REG 4
+
+static void stm32l4x5_syscfg_hold_reset(Object *obj)
+{
+    Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
+
+    s->memrmp = 0x00000000;
+    s->cfgr1 = 0x7C000001;
+    s->exticr[0] = 0x00000000;
+    s->exticr[1] = 0x00000000;
+    s->exticr[2] = 0x00000000;
+    s->exticr[3] = 0x00000000;
+    s->scsr = 0x00000000;
+    s->cfgr2 = 0x00000000;
+    s->swpr = 0x00000000;
+    s->skr = 0x00000000;
+    s->swpr2 = 0x00000000;
+}
+
+static void stm32l4x5_syscfg_set_irq(void *opaque, int irq, int level)
+{
+    Stm32l4x5SyscfgState *s = opaque;
+    const uint8_t gpio = irq / GPIO_NUM_PINS;
+    const int line = irq % GPIO_NUM_PINS;
+
+    const int exticr_reg = line / NUM_LINES_PER_EXTICR_REG;
+    const int startbit = (line % NUM_LINES_PER_EXTICR_REG) * 4;
+
+    g_assert(gpio < NUM_GPIOS);
+    trace_stm32l4x5_syscfg_set_irq(gpio, line, level);
+
+    if (extract32(s->exticr[exticr_reg], startbit, 4) == gpio) {
+        trace_stm32l4x5_syscfg_forward_exti(line);
+        qemu_set_irq(s->gpio_out[line], level);
+    }
+}
+
+static uint64_t stm32l4x5_syscfg_read(void *opaque, hwaddr addr,
+                                      unsigned int size)
+{
+    Stm32l4x5SyscfgState *s = opaque;
+
+    trace_stm32l4x5_syscfg_read(addr);
+
+    switch (addr) {
+    case SYSCFG_MEMRMP:
+        return s->memrmp;
+    case SYSCFG_CFGR1:
+        return s->cfgr1;
+    case SYSCFG_EXTICR1...SYSCFG_EXTICR4:
+        return s->exticr[(addr - SYSCFG_EXTICR1) / 4];
+    case SYSCFG_SCSR:
+        return s->scsr;
+    case SYSCFG_CFGR2:
+        return s->cfgr2;
+    case SYSCFG_SWPR:
+        return s->swpr;
+    case SYSCFG_SKR:
+        return s->skr;
+    case SYSCFG_SWPR2:
+        return s->swpr2;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
+        return 0;
+    }
+}
+static void stm32l4x5_syscfg_write(void *opaque, hwaddr addr,
+                                   uint64_t value, unsigned int size)
+{
+    Stm32l4x5SyscfgState *s = opaque;
+
+    trace_stm32l4x5_syscfg_write(addr, value);
+
+    switch (addr) {
+    case SYSCFG_MEMRMP:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Changing the memory mapping isn't supported\n",
+                      __func__);
+        s->memrmp = value & ACTIVABLE_BITS_MEMRP;
+        return;
+    case SYSCFG_CFGR1:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Functions in CFGRx aren't supported\n",
+                      __func__);
+        /* bit 0 (firewall dis.) is cleared by software, set only by reset. */
+        s->cfgr1 = (s->cfgr1 & value & FIREWALL_DISABLE_CFGR1) |
+                   (value & ACTIVABLE_BITS_CFGR1);
+        return;
+    case SYSCFG_EXTICR1...SYSCFG_EXTICR4:
+        s->exticr[(addr - SYSCFG_EXTICR1) / 4] =
+                (value & ACTIVABLE_BITS_EXTICR);
+        return;
+    case SYSCFG_SCSR:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Erasing SRAM2 isn't supported\n",
+                      __func__);
+        /*
+         * only non reserved bits are :
+         * bit 0 (write-protected by a passkey), bit 1 (meant to be read)
+         * so it serves no purpose yet to add :
+         * s->scsr = value & 0x3;
+         */
+        return;
+    case SYSCFG_CFGR2:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Functions in CFGRx aren't supported\n",
+                      __func__);
+        /* bit 8 (SRAM2 PEF) is cleared by software by writing a '1'.*/
+        /* bits[3:0] (ECC Lock) are set by software, cleared only by reset.*/
+        s->cfgr2 = (s->cfgr2 | (value & ECC_LOCK_CFGR2)) &
+                   ~(value & SRAM2_PARITY_ERROR_FLAG_CFGR2);
+        return;
+    case SYSCFG_SWPR:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Write protecting SRAM2 isn't supported\n",
+                      __func__);
+        /* These bits are set by software and cleared only by reset.*/
+        s->swpr |= value;
+        return;
+    case SYSCFG_SKR:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Erasing SRAM2 isn't supported\n",
+                      __func__);
+        s->skr = value & ACTIVABLE_BITS_SKR;
+        return;
+    case SYSCFG_SWPR2:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Write protecting SRAM2 isn't supported\n",
+                      __func__);
+        /* These bits are set by software and cleared only by reset.*/
+        s->swpr2 |= value;
+        return;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
+    }
+}
+
+static const MemoryRegionOps stm32l4x5_syscfg_ops = {
+    .read = stm32l4x5_syscfg_read,
+    .write = stm32l4x5_syscfg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
+    .impl.unaligned = false,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .valid.unaligned = false,
+};
+
+static void stm32l4x5_syscfg_init(Object *obj)
+{
+    Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
+
+    memory_region_init_io(&s->mmio, obj, &stm32l4x5_syscfg_ops, s,
+                          TYPE_STM32L4X5_SYSCFG, 0x400);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+    qdev_init_gpio_in(DEVICE(obj), stm32l4x5_syscfg_set_irq,
+                      GPIO_NUM_PINS * NUM_GPIOS);
+    qdev_init_gpio_out(DEVICE(obj), s->gpio_out, GPIO_NUM_PINS);
+}
+
+static const VMStateDescription vmstate_stm32l4x5_syscfg = {
+    .name = TYPE_STM32L4X5_SYSCFG,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(memrmp, Stm32l4x5SyscfgState),
+        VMSTATE_UINT32(cfgr1, Stm32l4x5SyscfgState),
+        VMSTATE_UINT32_ARRAY(exticr, Stm32l4x5SyscfgState,
+                             SYSCFG_NUM_EXTICR),
+        VMSTATE_UINT32(scsr, Stm32l4x5SyscfgState),
+        VMSTATE_UINT32(cfgr2, Stm32l4x5SyscfgState),
+        VMSTATE_UINT32(swpr, Stm32l4x5SyscfgState),
+        VMSTATE_UINT32(skr, Stm32l4x5SyscfgState),
+        VMSTATE_UINT32(swpr2, Stm32l4x5SyscfgState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void stm32l4x5_syscfg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->vmsd = &vmstate_stm32l4x5_syscfg;
+    rc->phases.hold = stm32l4x5_syscfg_hold_reset;
+}
+
+static const TypeInfo stm32l4x5_syscfg_info[] = {
+    {
+        .name          = TYPE_STM32L4X5_SYSCFG,
+        .parent        = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(Stm32l4x5SyscfgState),
+        .instance_init = stm32l4x5_syscfg_init,
+        .class_init    = stm32l4x5_syscfg_class_init,
+    }
+};
+
+DEFINE_TYPES(stm32l4x5_syscfg_info)
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 3efe3dc2cc7..4fc6b29b43d 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -90,6 +90,9 @@ config STM32F4XX_EXTI
 config STM32L4X5_EXTI
     bool
 
+config STM32L4X5_SYSCFG
+    bool
+
 config MIPS_ITU
     bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 16db6e228d7..2ca2ce4b62e 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -111,6 +111,7 @@ system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.
 system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c'))
 system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_exti.c'))
 system_ss.add(when: 'CONFIG_STM32L4X5_EXTI', if_true: files('stm32l4x5_exti.c'))
+system_ss.add(when: 'CONFIG_STM32L4X5_SYSCFG', if_true: files('stm32l4x5_syscfg.c'))
 system_ss.add(when: 'CONFIG_MPS2_FPGAIO', if_true: files('mps2-fpgaio.c'))
 system_ss.add(when: 'CONFIG_MPS2_SCC', if_true: files('mps2-scc.c'))
 
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index fccd3204bf5..5f5bc922223 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -163,6 +163,12 @@ stm32f4xx_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
 stm32f4xx_exti_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
 stm32f4xx_exti_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
 
+# stm32l4x5_syscfg.c
+stm32l4x5_syscfg_set_irq(int gpio, int line, int level) "irq from GPIO: %d, line: %d, level: %d"
+stm32l4x5_syscfg_forward_exti(int irq) "irq %d forwarded to EXTI"
+stm32l4x5_syscfg_read(uint64_t addr) "reg read: addr: 0x%" PRIx64 " "
+stm32l4x5_syscfg_write(uint64_t addr, uint64_t data) "reg write: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
+
 # stm32l4x5_exti.c
 stm32l4x5_exti_set_irq(int irq, int level) "Set EXTI: %d to %d"
 stm32l4x5_exti_read(uint64_t addr, uint64_t data) "reg read: addr: 0x%" PRIx64 " val: 0x%" PRIx64 ""
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 08/21] hw/arm: Connect STM32L4x5 SYSCFG to STM32L4x5 SoC
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (6 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 07/21] hw/misc: Implement STM32L4x5 SYSCFG Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 09/21] tests/qtest: Add STM32L4x5 SYSCFG QTest testcase Peter Maydell
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Inès Varhol <ines.varhol@telecom-paris.fr>

The SYSCFG input GPIOs aren't connected yet. When the STM32L4x5 GPIO
device will be implemented, its output GPIOs will be connected to the
SYSCFG input GPIOs.

Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20240109194438.70934-3-ines.varhol@telecom-paris.fr
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/arm/stm32l4x5_soc.h |  2 ++
 hw/arm/stm32l4x5_soc.c         | 21 ++++++++++++++++++++-
 hw/arm/Kconfig                 |  1 +
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
index f7305568dcc..baf70410b5f 100644
--- a/include/hw/arm/stm32l4x5_soc.h
+++ b/include/hw/arm/stm32l4x5_soc.h
@@ -26,6 +26,7 @@
 
 #include "exec/memory.h"
 #include "hw/arm/armv7m.h"
+#include "hw/misc/stm32l4x5_syscfg.h"
 #include "hw/misc/stm32l4x5_exti.h"
 #include "qom/object.h"
 
@@ -41,6 +42,7 @@ struct Stm32l4x5SocState {
     ARMv7MState armv7m;
 
     Stm32l4x5ExtiState exti;
+    Stm32l4x5SyscfgState syscfg;
 
     MemoryRegion sram1;
     MemoryRegion sram2;
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
index 756eb694884..f470ff74ec7 100644
--- a/hw/arm/stm32l4x5_soc.c
+++ b/hw/arm/stm32l4x5_soc.c
@@ -37,6 +37,7 @@
 #define SRAM2_SIZE (32 * KiB)
 
 #define EXTI_ADDR 0x40010400
+#define SYSCFG_ADDR 0x40010000
 
 #define NUM_EXTI_IRQ 40
 /* Match exti line connections with their CPU IRQ number */
@@ -80,6 +81,7 @@ static void stm32l4x5_soc_initfn(Object *obj)
     Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
 
     object_initialize_child(obj, "exti", &s->exti, TYPE_STM32L4X5_EXTI);
+    object_initialize_child(obj, "syscfg", &s->syscfg, TYPE_STM32L4X5_SYSCFG);
 
     s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
     s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
@@ -155,6 +157,19 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
         return;
     }
 
+    /* System configuration controller */
+    busdev = SYS_BUS_DEVICE(&s->syscfg);
+    if (!sysbus_realize(busdev, errp)) {
+        return;
+    }
+    sysbus_mmio_map(busdev, 0, SYSCFG_ADDR);
+    /*
+     * TODO: when the GPIO device is implemented, connect it
+     * to SYCFG using `qdev_connect_gpio_out`, NUM_GPIOS and
+     * GPIO_NUM_PINS.
+     */
+
+    /* EXTI device */
     busdev = SYS_BUS_DEVICE(&s->exti);
     if (!sysbus_realize(busdev, errp)) {
         return;
@@ -164,6 +179,11 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
         sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
     }
 
+    for (unsigned i = 0; i < 16; i++) {
+        qdev_connect_gpio_out(DEVICE(&s->syscfg), i,
+                              qdev_get_gpio_in(DEVICE(&s->exti), i));
+    }
+
     /* APB1 BUS */
     create_unimplemented_device("TIM2",      0x40000000, 0x400);
     create_unimplemented_device("TIM3",      0x40000400, 0x400);
@@ -201,7 +221,6 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
     /* RESERVED:    0x40009800, 0x6800 */
 
     /* APB2 BUS */
-    create_unimplemented_device("SYSCFG",    0x40010000, 0x30);
     create_unimplemented_device("VREFBUF",   0x40010030, 0x1D0);
     create_unimplemented_device("COMP",      0x40010200, 0x200);
     /* RESERVED:    0x40010800, 0x1400 */
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index da9c6e5064d..218b454e97f 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -459,6 +459,7 @@ config STM32L4X5_SOC
     bool
     select ARM_V7M
     select OR_IRQ
+    select STM32L4X5_SYSCFG
     select STM32L4X5_EXTI
 
 config XLNX_ZYNQMP_ARM
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 09/21] tests/qtest: Add STM32L4x5 SYSCFG QTest testcase
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (7 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 08/21] hw/arm: Connect STM32L4x5 SYSCFG to STM32L4x5 SoC Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 10/21] hw/misc: Add Nuvoton's PCI Mailbox Module Peter Maydell
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Inès Varhol <ines.varhol@telecom-paris.fr>

Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Message-id: 20240109194438.70934-4-ines.varhol@telecom-paris.fr
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 tests/qtest/stm32l4x5_syscfg-test.c | 331 ++++++++++++++++++++++++++++
 tests/qtest/meson.build             |   3 +-
 2 files changed, 333 insertions(+), 1 deletion(-)
 create mode 100644 tests/qtest/stm32l4x5_syscfg-test.c

diff --git a/tests/qtest/stm32l4x5_syscfg-test.c b/tests/qtest/stm32l4x5_syscfg-test.c
new file mode 100644
index 00000000000..ed4801798d4
--- /dev/null
+++ b/tests/qtest/stm32l4x5_syscfg-test.c
@@ -0,0 +1,331 @@
+/*
+ * QTest testcase for STM32L4x5_SYSCFG
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * 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 "libqtest-single.h"
+
+#define SYSCFG_BASE_ADDR 0x40010000
+#define SYSCFG_MEMRMP 0x00
+#define SYSCFG_CFGR1 0x04
+#define SYSCFG_EXTICR1 0x08
+#define SYSCFG_EXTICR2 0x0C
+#define SYSCFG_EXTICR3 0x10
+#define SYSCFG_EXTICR4 0x14
+#define SYSCFG_SCSR 0x18
+#define SYSCFG_CFGR2 0x1C
+#define SYSCFG_SWPR 0x20
+#define SYSCFG_SKR 0x24
+#define SYSCFG_SWPR2 0x28
+#define INVALID_ADDR 0x2C
+
+static void syscfg_writel(unsigned int offset, uint32_t value)
+{
+    writel(SYSCFG_BASE_ADDR + offset, value);
+}
+
+static uint32_t syscfg_readl(unsigned int offset)
+{
+    return readl(SYSCFG_BASE_ADDR + offset);
+}
+
+static void syscfg_set_irq(int num, int level)
+{
+   qtest_set_irq_in(global_qtest, "/machine/soc/syscfg",
+                    NULL, num, level);
+}
+
+static void system_reset(void)
+{
+    QDict *response;
+    response = qtest_qmp(global_qtest, "{'execute': 'system_reset'}");
+    g_assert(qdict_haskey(response, "return"));
+    qobject_unref(response);
+}
+
+static void test_reset(void)
+{
+    /*
+     * Test that registers are initialized at the correct values
+     */
+    g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SCSR), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
+
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR2), ==, 0x00000000);
+}
+
+static void test_reserved_bits(void)
+{
+    /*
+     * Test that reserved bits stay at reset value
+     * (which is 0 for all of them) by writing '1'
+     * in all reserved bits (keeping reset value for
+     * other bits) and checking that the
+     * register is still at reset value
+     */
+    syscfg_writel(SYSCFG_MEMRMP, 0xFFFFFEF8);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_CFGR1, 0x7F00FEFF);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
+
+    syscfg_writel(SYSCFG_EXTICR1, 0xFFFF0000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_EXTICR2, 0xFFFF0000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_EXTICR3, 0xFFFF0000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_EXTICR4, 0xFFFF0000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_SKR, 0xFFFFFF00);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
+}
+
+static void test_set_and_clear(void)
+{
+    /*
+     * Test that regular bits can be set and cleared
+     */
+    syscfg_writel(SYSCFG_MEMRMP, 0x00000107);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000107);
+    syscfg_writel(SYSCFG_MEMRMP, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
+
+    /* cfgr1 bit 0 is clear only so we keep it set */
+    syscfg_writel(SYSCFG_CFGR1, 0xFCFF0101);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0xFCFF0101);
+    syscfg_writel(SYSCFG_CFGR1, 0x00000001);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000001);
+
+    syscfg_writel(SYSCFG_EXTICR1, 0x0000FFFF);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x0000FFFF);
+    syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_EXTICR2, 0x0000FFFF);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x0000FFFF);
+    syscfg_writel(SYSCFG_EXTICR2, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_EXTICR3, 0x0000FFFF);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x0000FFFF);
+    syscfg_writel(SYSCFG_EXTICR3, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_EXTICR4, 0x0000FFFF);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x0000FFFF);
+    syscfg_writel(SYSCFG_EXTICR4, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
+
+    syscfg_writel(SYSCFG_SKR, 0x000000FF);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x000000FF);
+    syscfg_writel(SYSCFG_SKR, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
+}
+
+static void test_clear_by_writing_1(void)
+{
+    /*
+     * Test that writing '1' doesn't set the bit
+     */
+    syscfg_writel(SYSCFG_CFGR2, 0x00000100);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
+}
+
+static void test_set_only_bits(void)
+{
+    /*
+     * Test that set only bits stay can't be cleared
+     */
+    syscfg_writel(SYSCFG_CFGR2, 0x0000000F);
+    syscfg_writel(SYSCFG_CFGR2, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x0000000F);
+
+    syscfg_writel(SYSCFG_SWPR, 0xFFFFFFFF);
+    syscfg_writel(SYSCFG_SWPR, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR), ==, 0xFFFFFFFF);
+
+    syscfg_writel(SYSCFG_SWPR2, 0xFFFFFFFF);
+    syscfg_writel(SYSCFG_SWPR2, 0x00000000);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR2), ==, 0xFFFFFFFF);
+
+    system_reset();
+}
+
+static void test_clear_only_bits(void)
+{
+    /*
+     * Test that clear only bits stay can't be set
+     */
+    syscfg_writel(SYSCFG_CFGR1, 0x00000000);
+    syscfg_writel(SYSCFG_CFGR1, 0x00000001);
+    g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000000);
+
+    system_reset();
+}
+
+static void test_interrupt(void)
+{
+    /*
+     * Test that GPIO rising lines result in an irq
+     * with the right configuration
+     */
+    qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
+
+    /* GPIOA is the default source for EXTI lines 0 to 15 */
+
+    syscfg_set_irq(0, 1);
+
+    g_assert_true(get_irq(0));
+
+
+    syscfg_set_irq(15, 1);
+
+    g_assert_true(get_irq(15));
+
+    /* Configure GPIOB[1] as the source input for EXTI1 */
+    syscfg_writel(SYSCFG_EXTICR1, 0x00000010);
+
+    syscfg_set_irq(17, 1);
+
+    g_assert_true(get_irq(1));
+
+    /* Clean the test */
+    syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
+    syscfg_set_irq(0, 0);
+    syscfg_set_irq(15, 0);
+    syscfg_set_irq(17, 0);
+}
+
+static void test_irq_pin_multiplexer(void)
+{
+    /*
+     * Test that syscfg irq sets the right exti irq
+     */
+
+    qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
+
+    syscfg_set_irq(0, 1);
+
+    /* Check that irq 0 was set and irq 15 wasn't */
+    g_assert_true(get_irq(0));
+    g_assert_false(get_irq(15));
+
+    /* Clean the test */
+    syscfg_set_irq(0, 0);
+
+    syscfg_set_irq(15, 1);
+
+    /* Check that irq 15 was set and irq 0 wasn't */
+    g_assert_true(get_irq(15));
+    g_assert_false(get_irq(0));
+
+    /* Clean the test */
+    syscfg_set_irq(15, 0);
+}
+
+static void test_irq_gpio_multiplexer(void)
+{
+    /*
+     * Test that an irq is generated only by the right GPIO
+     */
+
+    qtest_irq_intercept_in(global_qtest, "/machine/soc/exti");
+
+    /* GPIOA is the default source for EXTI lines 0 to 15 */
+
+    /* Check that setting rising pin GPIOA[0] generates an irq */
+    syscfg_set_irq(0, 1);
+
+    g_assert_true(get_irq(0));
+
+    /* Clean the test */
+    syscfg_set_irq(0, 0);
+
+    /* Check that setting rising pin GPIOB[0] doesn't generate an irq */
+    syscfg_set_irq(16, 1);
+
+    g_assert_false(get_irq(0));
+
+    /* Clean the test */
+    syscfg_set_irq(16, 0);
+
+    /* Configure GPIOB[0] as the source input for EXTI0 */
+    syscfg_writel(SYSCFG_EXTICR1, 0x00000001);
+
+    /* Check that setting rising pin GPIOA[0] doesn't generate an irq */
+    syscfg_set_irq(0, 1);
+
+    g_assert_false(get_irq(0));
+
+    /* Clean the test */
+    syscfg_set_irq(0, 0);
+
+    /* Check that setting rising pin GPIOB[0] generates an irq */
+    syscfg_set_irq(16, 1);
+
+    g_assert_true(get_irq(0));
+
+    /* Clean the test */
+    syscfg_set_irq(16, 0);
+    syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+    g_test_set_nonfatal_assertions();
+
+    qtest_add_func("stm32l4x5/syscfg/test_reset", test_reset);
+    qtest_add_func("stm32l4x5/syscfg/test_reserved_bits",
+                   test_reserved_bits);
+    qtest_add_func("stm32l4x5/syscfg/test_set_and_clear",
+                   test_set_and_clear);
+    qtest_add_func("stm32l4x5/syscfg/test_clear_by_writing_1",
+                   test_clear_by_writing_1);
+    qtest_add_func("stm32l4x5/syscfg/test_set_only_bits",
+                   test_set_only_bits);
+    qtest_add_func("stm32l4x5/syscfg/test_clear_only_bits",
+                   test_clear_only_bits);
+    qtest_add_func("stm32l4x5/syscfg/test_interrupt",
+                   test_interrupt);
+    qtest_add_func("stm32l4x5/syscfg/test_irq_pin_multiplexer",
+                   test_irq_pin_multiplexer);
+    qtest_add_func("stm32l4x5/syscfg/test_irq_gpio_multiplexer",
+                   test_irq_gpio_multiplexer);
+
+    qtest_start("-machine b-l475e-iot01a");
+    ret = g_test_run();
+    qtest_end();
+
+    return ret;
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 07fdd2dc1a5..5e4bc3da85e 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -197,7 +197,8 @@ qtests_aspeed = \
    'aspeed_gpio-test']
 
 qtests_stm32l4x5 = \
-  ['stm32l4x5_exti-test']
+  ['stm32l4x5_exti-test',
+   'stm32l4x5_syscfg-test']
 
 qtests_arm = \
   (config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 10/21] hw/misc: Add Nuvoton's PCI Mailbox Module
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (8 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 09/21] tests/qtest: Add STM32L4x5 SYSCFG QTest testcase Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 11/21] hw/arm: Add PCI mailbox module to Nuvoton SoC Peter Maydell
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Hao Wu <wuhaotsh@google.com>

The PCI Mailbox Module is a high-bandwidth communcation module
between a Nuvoton BMC and CPU. It features 16KB RAM that are both
accessible by the BMC and core CPU. and supports interrupt for
both sides.

This patch implements the BMC side of the PCI mailbox module.
Communication with the core CPU is emulated via a chardev and
will be in a follow-up patch.

Change-Id: Iaca22f81c4526927d437aa367079ed038faf43f2
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-2-nabihestefan@google.com
[PMM: Moved some changes that should have been in the following commit]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/misc/npcm7xx_pci_mbox.h |  81 ++++++++
 hw/misc/npcm7xx_pci_mbox.c         | 324 +++++++++++++++++++++++++++++
 hw/misc/meson.build                |   1 +
 hw/misc/trace-events               |   5 +
 4 files changed, 411 insertions(+)
 create mode 100644 include/hw/misc/npcm7xx_pci_mbox.h
 create mode 100644 hw/misc/npcm7xx_pci_mbox.c

diff --git a/include/hw/misc/npcm7xx_pci_mbox.h b/include/hw/misc/npcm7xx_pci_mbox.h
new file mode 100644
index 00000000000..e595fbcc703
--- /dev/null
+++ b/include/hw/misc/npcm7xx_pci_mbox.h
@@ -0,0 +1,81 @@
+/*
+ * Nuvoton NPCM7xx PCI Mailbox Module
+ *
+ * Copyright 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_PCI_MBOX_H
+#define NPCM7XX_PCI_MBOX_H
+
+#include "chardev/char-fe.h"
+#include "exec/memory.h"
+#include "hw/clock.h"
+#include "hw/irq.h"
+#include "hw/pci/pci.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define NPCM7XX_PCI_MBOX_RAM_SIZE 0x4000
+
+#define NPCM7XX_PCI_VENDOR_ID   0x1050
+#define NPCM7XX_PCI_DEVICE_ID   0x0750
+#define NPCM7XX_PCI_REVISION    0
+#define NPCM7XX_PCI_CLASS_CODE  0xff
+
+typedef enum NPCM7xxPCIMBoxHostState {
+    NPCM7XX_PCI_MBOX_STATE_IDLE,
+    NPCM7XX_PCI_MBOX_STATE_OFFSET,
+    NPCM7XX_PCI_MBOX_STATE_SIZE,
+    NPCM7XX_PCI_MBOX_STATE_DATA,
+} NPCM7xxPCIMBoxHostState ;
+
+/*
+ * Maximum amount of control registers in PCI Mailbox module. Do not increase
+ * this value without bumping vm version.
+ */
+#define NPCM7XX_PCI_MBOX_NR_REGS 3
+
+/**
+ * struct NPCM7xxPciMboxState - PCI Mailbox Device
+ * @parent: System bus device.
+ * @ram: the mailbox RAM memory space
+ * @iomem: Memory region through which registers are accessed.
+ * @content: The content of the PCI mailbox, initialized to 0.
+ * @regs: The MMIO registers.
+ * @chr: The chardev backend used to communicate with core CPU.
+ * @offset: The offset to start transfer.
+ */
+typedef struct NPCM7xxPCIMBoxState {
+    SysBusDevice parent;
+
+    MemoryRegion ram;
+    MemoryRegion iomem;
+
+    qemu_irq irq;
+    uint8_t content[NPCM7XX_PCI_MBOX_RAM_SIZE];
+    uint32_t regs[NPCM7XX_PCI_MBOX_NR_REGS];
+    CharBackend chr;
+
+    /* aux data for receiving host commands. */
+    NPCM7xxPCIMBoxHostState state;
+    uint8_t op;
+    hwaddr offset;
+    uint8_t size;
+    uint64_t data;
+    int receive_count;
+} NPCM7xxPCIMBoxState;
+
+#define TYPE_NPCM7XX_PCI_MBOX "npcm7xx-pci-mbox"
+#define NPCM7XX_PCI_MBOX(obj) \
+    OBJECT_CHECK(NPCM7xxPCIMBoxState, (obj), TYPE_NPCM7XX_PCI_MBOX)
+
+#endif /* NPCM7XX_PCI_MBOX_H */
diff --git a/hw/misc/npcm7xx_pci_mbox.c b/hw/misc/npcm7xx_pci_mbox.c
new file mode 100644
index 00000000000..c770ad6fcfe
--- /dev/null
+++ b/hw/misc/npcm7xx_pci_mbox.c
@@ -0,0 +1,324 @@
+/*
+ * Nuvoton NPCM7xx PCI Mailbox Module
+ *
+ * Copyright 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "chardev/char-fe.h"
+#include "hw/irq.h"
+#include "hw/qdev-clock.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/misc/npcm7xx_pci_mbox.h"
+#include "hw/registerfields.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qemu/bitops.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qemu/units.h"
+#include "trace.h"
+
+REG32(NPCM7XX_PCI_MBOX_BMBXSTAT, 0x00);
+REG32(NPCM7XX_PCI_MBOX_BMBXCTL, 0x04);
+REG32(NPCM7XX_PCI_MBOX_BMBXCMD, 0x08);
+
+enum NPCM7xxPCIMBoxOperation {
+    NPCM7XX_PCI_MBOX_OP_READ = 1,
+    NPCM7XX_PCI_MBOX_OP_WRITE,
+};
+
+#define NPCM7XX_PCI_MBOX_OFFSET_BYTES 8
+
+/* Response code */
+#define NPCM7XX_PCI_MBOX_OK 0
+#define NPCM7XX_PCI_MBOX_INVALID_OP 0xa0
+#define NPCM7XX_PCI_MBOX_INVALID_SIZE 0xa1
+#define NPCM7XX_PCI_MBOX_UNSPECIFIED_ERROR 0xff
+
+#define NPCM7XX_PCI_MBOX_NR_CI 8
+#define NPCM7XX_PCI_MBOX_CI_MASK MAKE_64BIT_MASK(0, NPCM7XX_PCI_MBOX_NR_CI)
+
+static void npcm7xx_pci_mbox_update_irq(NPCM7xxPCIMBoxState *s)
+{
+    /* We should send an interrupt when one of the CIE and CIF are both 1. */
+    if (s->regs[R_NPCM7XX_PCI_MBOX_BMBXSTAT] &
+        s->regs[R_NPCM7XX_PCI_MBOX_BMBXCTL] &
+        NPCM7XX_PCI_MBOX_CI_MASK) {
+        qemu_irq_raise(s->irq);
+        trace_npcm7xx_pci_mbox_irq(1);
+    } else {
+        qemu_irq_lower(s->irq);
+        trace_npcm7xx_pci_mbox_irq(0);
+    }
+}
+
+static void npcm7xx_pci_mbox_send_response(NPCM7xxPCIMBoxState *s, uint8_t code)
+{
+    qemu_chr_fe_write(&s->chr, &code, 1);
+    if (code == NPCM7XX_PCI_MBOX_OK && s->op == NPCM7XX_PCI_MBOX_OP_READ) {
+        qemu_chr_fe_write(&s->chr, (uint8_t *)(&s->data), s->size);
+    }
+}
+
+static void npcm7xx_pci_mbox_handle_read(NPCM7xxPCIMBoxState *s)
+{
+    MemTxResult r = memory_region_dispatch_read(
+        &s->ram, s->offset, &s->data, MO_LE | size_memop(s->size),
+        MEMTXATTRS_UNSPECIFIED);
+
+    npcm7xx_pci_mbox_send_response(s, (uint8_t)r);
+}
+
+static void npcm7xx_pci_mbox_handle_write(NPCM7xxPCIMBoxState *s)
+{
+    MemTxResult r = memory_region_dispatch_write(
+        &s->ram, s->offset, s->data, MO_LE | size_memop(s->size),
+        MEMTXATTRS_UNSPECIFIED);
+
+    npcm7xx_pci_mbox_send_response(s, (uint8_t)r);
+}
+
+static void npcm7xx_pci_mbox_receive_char(NPCM7xxPCIMBoxState *s, uint8_t byte)
+{
+    switch (s->state) {
+    case NPCM7XX_PCI_MBOX_STATE_IDLE:
+        switch (byte) {
+        case NPCM7XX_PCI_MBOX_OP_READ:
+        case NPCM7XX_PCI_MBOX_OP_WRITE:
+            s->op = byte;
+            s->state = NPCM7XX_PCI_MBOX_STATE_OFFSET;
+            s->offset = 0;
+            s->receive_count = 0;
+            break;
+
+        default:
+            qemu_log_mask(LOG_GUEST_ERROR,
+                "received invalid op type: 0x%" PRIx8, byte);
+            npcm7xx_pci_mbox_send_response(s, NPCM7XX_PCI_MBOX_INVALID_OP);
+            break;
+        }
+        break;
+
+    case NPCM7XX_PCI_MBOX_STATE_OFFSET:
+        s->offset += (uint64_t)byte << (s->receive_count * BITS_PER_BYTE);
+        if (++s->receive_count >= NPCM7XX_PCI_MBOX_OFFSET_BYTES) {
+            s->state = NPCM7XX_PCI_MBOX_STATE_SIZE;
+        }
+        break;
+
+    case NPCM7XX_PCI_MBOX_STATE_SIZE:
+        s->size = byte;
+        if (s->size < 1 || s->size > sizeof(uint64_t)) {
+            qemu_log_mask(LOG_GUEST_ERROR, "received invalid size: %u", byte);
+            npcm7xx_pci_mbox_send_response(s, NPCM7XX_PCI_MBOX_INVALID_SIZE);
+            s->state = NPCM7XX_PCI_MBOX_STATE_IDLE;
+            break;
+        }
+        if (s->op == NPCM7XX_PCI_MBOX_OP_READ) {
+            npcm7xx_pci_mbox_handle_read(s);
+            s->state = NPCM7XX_PCI_MBOX_STATE_IDLE;
+        } else {
+            s->receive_count = 0;
+            s->data = 0;
+            s->state = NPCM7XX_PCI_MBOX_STATE_DATA;
+        }
+        break;
+
+    case NPCM7XX_PCI_MBOX_STATE_DATA:
+        g_assert(s->op == NPCM7XX_PCI_MBOX_OP_WRITE);
+        s->data += (uint64_t)byte << (s->receive_count * BITS_PER_BYTE);
+        if (++s->receive_count >= s->size) {
+            npcm7xx_pci_mbox_handle_write(s);
+            s->state = NPCM7XX_PCI_MBOX_STATE_IDLE;
+        }
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static uint64_t npcm7xx_pci_mbox_read(void *opaque, hwaddr offset,
+                                      unsigned size)
+{
+    NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(opaque);
+    uint16_t value = 0;
+
+    if (offset / sizeof(uint32_t) >= NPCM7XX_PCI_MBOX_NR_REGS) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
+                      __func__, offset);
+        return 0;
+    }
+
+    value = s->regs[offset / sizeof(uint32_t)];
+    trace_npcm7xx_pci_mbox_read(DEVICE(s)->canonical_path, offset, value, size);
+    return value;
+}
+
+static void npcm7xx_pci_mbox_write(void *opaque, hwaddr offset,
+                              uint64_t v, unsigned size)
+{
+    NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(opaque);
+
+    trace_npcm7xx_pci_mbox_write(DEVICE(s)->canonical_path, offset, v, size);
+    switch (offset) {
+    case A_NPCM7XX_PCI_MBOX_BMBXSTAT:
+        /* Clear bits that are 1. */
+        s->regs[R_NPCM7XX_PCI_MBOX_BMBXSTAT] &= ~v;
+        break;
+
+    case A_NPCM7XX_PCI_MBOX_BMBXCTL:
+        s->regs[R_NPCM7XX_PCI_MBOX_BMBXCTL] = v;
+        break;
+
+    case A_NPCM7XX_PCI_MBOX_BMBXCMD:
+        /* Set the bits that are 1. */
+        s->regs[R_NPCM7XX_PCI_MBOX_BMBXCMD] |= v;
+        /* TODO: Set interrupt to host. */
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: offset 0x%04" HWADDR_PRIx " out of range\n",
+                      __func__, offset);
+    }
+    npcm7xx_pci_mbox_update_irq(s);
+}
+
+static const struct MemoryRegionOps npcm7xx_pci_mbox_ops = {
+    .read       = npcm7xx_pci_mbox_read,
+    .write      = npcm7xx_pci_mbox_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid      = {
+        .min_access_size        = 4,
+        .max_access_size        = 4,
+        .unaligned              = false,
+    },
+};
+
+static void npcm7xx_pci_mbox_enter_reset(Object *obj, ResetType type)
+{
+    NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(obj);
+
+    memset(s->regs, 0, 4 * NPCM7XX_PCI_MBOX_NR_REGS);
+    s->state = NPCM7XX_PCI_MBOX_STATE_IDLE;
+    s->receive_count = 0;
+}
+
+static void npcm7xx_pci_mbox_hold_reset(Object *obj)
+{
+    NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(obj);
+
+    qemu_irq_lower(s->irq);
+}
+
+static int can_receive(void *opaque)
+{
+    return 1;
+}
+
+static void receive(void *opaque, const uint8_t *buf, int size)
+{
+    NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(opaque);
+    int i;
+
+    for (i = 0; i < size; ++i) {
+        npcm7xx_pci_mbox_receive_char(s, buf[i]);
+    }
+}
+
+static void chr_event(void *opaque, QEMUChrEvent event)
+{
+    switch (event) {
+    case CHR_EVENT_OPENED:
+    case CHR_EVENT_CLOSED:
+    case CHR_EVENT_BREAK:
+    case CHR_EVENT_MUX_IN:
+    case CHR_EVENT_MUX_OUT:
+        /* Ignore */
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static void npcm7xx_pci_mbox_init(Object *obj)
+{
+    NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+    memory_region_init_ram_device_ptr(&s->ram, obj, "pci-mbox-ram",
+                                      NPCM7XX_PCI_MBOX_RAM_SIZE, s->content);
+    memory_region_init_io(&s->iomem, obj, &npcm7xx_pci_mbox_ops, s,
+                          "pci-mbox-iomem", 4 * KiB);
+    sysbus_init_mmio(sbd, &s->ram);
+    sysbus_init_mmio(sbd, &s->iomem);
+    sysbus_init_irq(sbd, &s->irq);
+}
+
+static void npcm7xx_pci_mbox_realize(DeviceState *dev, Error **errp)
+{
+    NPCM7xxPCIMBoxState *s = NPCM7XX_PCI_MBOX(dev);
+
+    qemu_chr_fe_set_handlers(&s->chr, can_receive, receive,
+                             chr_event, NULL, OBJECT(dev), NULL, true);
+}
+
+static const VMStateDescription vmstate_npcm7xx_pci_mbox = {
+    .name = "npcm7xx-pci-mbox-module",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, NPCM7xxPCIMBoxState,
+                             NPCM7XX_PCI_MBOX_NR_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static Property npcm7xx_pci_mbox_properties[] = {
+    DEFINE_PROP_CHR("chardev", NPCM7xxPCIMBoxState, chr),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void npcm7xx_pci_mbox_class_init(ObjectClass *klass, void *data)
+{
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->desc = "NPCM7xx PCI Mailbox Controller";
+    dc->vmsd = &vmstate_npcm7xx_pci_mbox;
+    dc->realize = npcm7xx_pci_mbox_realize;
+    rc->phases.enter = npcm7xx_pci_mbox_enter_reset;
+    rc->phases.hold = npcm7xx_pci_mbox_hold_reset;
+    device_class_set_props(dc, npcm7xx_pci_mbox_properties);
+}
+
+static const TypeInfo npcm7xx_pci_mbox_info = {
+    .name               = TYPE_NPCM7XX_PCI_MBOX,
+    .parent             = TYPE_SYS_BUS_DEVICE,
+    .instance_size      = sizeof(NPCM7xxPCIMBoxState),
+    .class_init         = npcm7xx_pci_mbox_class_init,
+    .instance_init      = npcm7xx_pci_mbox_init,
+};
+
+static void npcm7xx_pci_mbox_register_type(void)
+{
+    type_register_static(&npcm7xx_pci_mbox_info);
+}
+type_init(npcm7xx_pci_mbox_register_type);
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 2ca2ce4b62e..4e7a8f8f1bb 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -73,6 +73,7 @@ system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files(
   'npcm7xx_clk.c',
   'npcm7xx_gcr.c',
   'npcm7xx_mft.c',
+  'npcm7xx_pci_mbox.c',
   'npcm7xx_pwm.c',
   'npcm7xx_rng.c',
 ))
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 5f5bc922223..d9fd316602d 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -152,6 +152,11 @@ npcm7xx_pwm_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0
 npcm7xx_pwm_update_freq(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Freq: old_freq: %u, new_freq: %u"
 npcm7xx_pwm_update_duty(const char *id, uint8_t index, uint32_t old_value, uint32_t new_value) "%s pwm[%u] Update Duty: old_duty: %u, new_duty: %u"
 
+# npcm7xx_pci_mbox.c
+npcm7xx_pci_mbox_read(const char *id, uint64_t offset, uint64_t value, unsigned size) "%s offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
+npcm7xx_pci_mbox_write(const char *id, uint64_t offset, uint64_t value, unsigned size) "%s offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
+npcm7xx_pci_mbox_irq(int irq_level) "irq level: %d"
+
 # stm32f4xx_syscfg.c
 stm32f4xx_syscfg_set_irq(int gpio, int line, int level) "Interrupt: GPIO: %d, Line: %d; Level: %d"
 stm32f4xx_pulse_exti(int irq) "Pulse EXTI: %d"
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 11/21] hw/arm: Add PCI mailbox module to Nuvoton SoC
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (9 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 10/21] hw/misc: Add Nuvoton's PCI Mailbox Module Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 12/21] hw/misc: Add qtest for NPCM7xx PCI Mailbox Peter Maydell
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

This patch wires the PCI mailbox module to Nuvoton SoC.

Change-Id: I14c42c628258804030f0583889882842bde0d972
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-3-nabihestefan@google.com
[PMM: moved some changes incorrectly in previous patch into this one]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 docs/system/arm/nuvoton.rst |  2 ++
 include/hw/arm/npcm7xx.h    |  2 ++
 hw/arm/npcm7xx.c            | 17 ++++++++++++++++-
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
index 0424cae4b01..e6110995455 100644
--- a/docs/system/arm/nuvoton.rst
+++ b/docs/system/arm/nuvoton.rst
@@ -50,6 +50,8 @@ Supported devices
  * Ethernet controller (EMC)
  * Tachometer
  * Peripheral SPI controller (PSPI)
+ * BIOS POST code FIFO
+ * PCI Mailbox
 
 Missing devices
 ---------------
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index 72c77220964..cec3792a2e8 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -26,6 +26,7 @@
 #include "hw/misc/npcm7xx_clk.h"
 #include "hw/misc/npcm7xx_gcr.h"
 #include "hw/misc/npcm7xx_mft.h"
+#include "hw/misc/npcm7xx_pci_mbox.h"
 #include "hw/misc/npcm7xx_pwm.h"
 #include "hw/misc/npcm7xx_rng.h"
 #include "hw/net/npcm7xx_emc.h"
@@ -104,6 +105,7 @@ struct NPCM7xxState {
     OHCISysBusState     ohci;
     NPCM7xxFIUState     fiu[2];
     NPCM7xxEMCState     emc[2];
+    NPCM7xxPCIMBoxState pci_mbox;
     NPCM7xxSDHCIState   mmc;
     NPCMPSPIState       pspi[2];
 };
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 15ff21d0472..c9e87162cbe 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -53,6 +53,9 @@
 /* ADC Module */
 #define NPCM7XX_ADC_BA          (0xf000c000)
 
+/* PCI Mailbox Module */
+#define NPCM7XX_PCI_MBOX_BA     (0xf0848000)
+
 /* Internal AHB SRAM */
 #define NPCM7XX_RAM3_BA         (0xc0008000)
 #define NPCM7XX_RAM3_SZ         (4 * KiB)
@@ -83,6 +86,9 @@ enum NPCM7xxInterrupt {
     NPCM7XX_UART1_IRQ,
     NPCM7XX_UART2_IRQ,
     NPCM7XX_UART3_IRQ,
+    NPCM7XX_PCI_MBOX_IRQ        = 8,
+    NPCM7XX_KCS_HIB_IRQ         = 9,
+    NPCM7XX_GMAC1_IRQ           = 14,
     NPCM7XX_EMC1RX_IRQ          = 15,
     NPCM7XX_EMC1TX_IRQ,
     NPCM7XX_MMC_IRQ             = 26,
@@ -456,6 +462,8 @@ static void npcm7xx_init(Object *obj)
         object_initialize_child(obj, "pspi[*]", &s->pspi[i], TYPE_NPCM_PSPI);
     }
 
+    object_initialize_child(obj, "pci-mbox", &s->pci_mbox,
+                            TYPE_NPCM7XX_PCI_MBOX);
     object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
 }
 
@@ -706,6 +714,14 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
         }
     }
 
+    /* PCI Mailbox. Cannot fail */
+    sysbus_realize(SYS_BUS_DEVICE(&s->pci_mbox), &error_abort);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->pci_mbox), 0, NPCM7XX_PCI_MBOX_BA);
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->pci_mbox), 1,
+        NPCM7XX_PCI_MBOX_BA + NPCM7XX_PCI_MBOX_RAM_SIZE);
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->pci_mbox), 0,
+                       npcm7xx_irq(s, NPCM7XX_PCI_MBOX_IRQ));
+
     /* RAM2 (SRAM) */
     memory_region_init_ram(&s->sram, OBJECT(dev), "ram2",
                            NPCM7XX_RAM2_SZ, &error_abort);
@@ -765,7 +781,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
     create_unimplemented_device("npcm7xx.usbd[8]",      0xf0838000,   4 * KiB);
     create_unimplemented_device("npcm7xx.usbd[9]",      0xf0839000,   4 * KiB);
     create_unimplemented_device("npcm7xx.sd",           0xf0840000,   8 * KiB);
-    create_unimplemented_device("npcm7xx.pcimbx",       0xf0848000, 512 * KiB);
     create_unimplemented_device("npcm7xx.aes",          0xf0858000,   4 * KiB);
     create_unimplemented_device("npcm7xx.des",          0xf0859000,   4 * KiB);
     create_unimplemented_device("npcm7xx.sha",          0xf085a000,   4 * KiB);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 12/21] hw/misc: Add qtest for NPCM7xx PCI Mailbox
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (10 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 11/21] hw/arm: Add PCI mailbox module to Nuvoton SoC Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 13/21] hw/net: Add NPCMXXX GMAC device Peter Maydell
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Hao Wu <wuhaotsh@google.com>

This patches adds a qtest for NPCM7XX PCI Mailbox module.
It sends read and write requests to the module, and verifies that
the module contains the correct data after the requests.

Change-Id: I2e1dbaecf8be9ec7eab55cb54f7fdeb0715b8275
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-4-nabihestefan@google.com
[PMM: avoid in_port_t type as it is not present on Windows]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 tests/qtest/npcm7xx_pci_mbox-test.c | 238 ++++++++++++++++++++++++++++
 tests/qtest/meson.build             |   1 +
 2 files changed, 239 insertions(+)
 create mode 100644 tests/qtest/npcm7xx_pci_mbox-test.c

diff --git a/tests/qtest/npcm7xx_pci_mbox-test.c b/tests/qtest/npcm7xx_pci_mbox-test.c
new file mode 100644
index 00000000000..341642e6371
--- /dev/null
+++ b/tests/qtest/npcm7xx_pci_mbox-test.c
@@ -0,0 +1,238 @@
+/*
+ * QTests for Nuvoton NPCM7xx PCI Mailbox Modules.
+ *
+ * Copyright 2021 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qnum.h"
+#include "libqtest-single.h"
+
+#define PCI_MBOX_BA         0xf0848000
+#define PCI_MBOX_IRQ        8
+
+/* register offset */
+#define PCI_MBOX_STAT       0x00
+#define PCI_MBOX_CTL        0x04
+#define PCI_MBOX_CMD        0x08
+
+#define CODE_OK             0x00
+#define CODE_INVALID_OP     0xa0
+#define CODE_INVALID_SIZE   0xa1
+#define CODE_ERROR          0xff
+
+#define OP_READ             0x01
+#define OP_WRITE            0x02
+#define OP_INVALID          0x41
+
+
+static int sock;
+static int fd;
+
+/*
+ * Create a local TCP socket with any port, then save off the port we got.
+ */
+static int open_socket(void)
+{
+    struct sockaddr_in myaddr;
+    socklen_t addrlen;
+
+    myaddr.sin_family = AF_INET;
+    myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    myaddr.sin_port = 0;
+    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    g_assert(sock != -1);
+    g_assert(bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) != -1);
+    addrlen = sizeof(myaddr);
+    g_assert(getsockname(sock, (struct sockaddr *) &myaddr , &addrlen) != -1);
+    g_assert(listen(sock, 1) != -1);
+    return ntohs(myaddr.sin_port);
+}
+
+static void setup_fd(void)
+{
+    fd_set readfds;
+
+    FD_ZERO(&readfds);
+    FD_SET(sock, &readfds);
+    g_assert(select(sock + 1, &readfds, NULL, NULL, NULL) == 1);
+
+    fd = accept(sock, NULL, 0);
+    g_assert(fd >= 0);
+}
+
+static uint8_t read_response(uint8_t *buf, size_t len)
+{
+    uint8_t code;
+    ssize_t ret = read(fd, &code, 1);
+
+    if (ret == -1) {
+        return CODE_ERROR;
+    }
+    if (code != CODE_OK) {
+        return code;
+    }
+    g_test_message("response code: %x", code);
+    if (len > 0) {
+        ret = read(fd, buf, len);
+        if (ret < len) {
+            return CODE_ERROR;
+        }
+    }
+    return CODE_OK;
+}
+
+static void receive_data(uint64_t offset, uint8_t *buf, size_t len)
+{
+    uint8_t op = OP_READ;
+    uint8_t code;
+    ssize_t rv;
+
+    while (len > 0) {
+        uint8_t size;
+
+        if (len >= 8) {
+            size = 8;
+        } else if (len >= 4) {
+            size = 4;
+        } else if (len >= 2) {
+            size = 2;
+        } else {
+            size = 1;
+        }
+
+        g_test_message("receiving %u bytes", size);
+        /* Write op */
+        rv = write(fd, &op, 1);
+        g_assert_cmpint(rv, ==, 1);
+        /* Write offset */
+        rv = write(fd, (uint8_t *)&offset, sizeof(uint64_t));
+        g_assert_cmpint(rv, ==, sizeof(uint64_t));
+        /* Write size */
+        g_assert_cmpint(write(fd, &size, 1), ==, 1);
+
+        /* Read data and Expect response */
+        code = read_response(buf, size);
+        g_assert_cmphex(code, ==, CODE_OK);
+
+        buf += size;
+        offset += size;
+        len -= size;
+    }
+}
+
+static void send_data(uint64_t offset, const uint8_t *buf, size_t len)
+{
+    uint8_t op = OP_WRITE;
+    uint8_t code;
+    ssize_t rv;
+
+    while (len > 0) {
+        uint8_t size;
+
+        if (len >= 8) {
+            size = 8;
+        } else if (len >= 4) {
+            size = 4;
+        } else if (len >= 2) {
+            size = 2;
+        } else {
+            size = 1;
+        }
+
+        g_test_message("sending %u bytes", size);
+        /* Write op */
+        rv = write(fd, &op, 1);
+        g_assert_cmpint(rv, ==, 1);
+        /* Write offset */
+        rv = write(fd, (uint8_t *)&offset, sizeof(uint64_t));
+        g_assert_cmpint(rv, ==, sizeof(uint64_t));
+        /* Write size */
+        g_assert_cmpint(write(fd, &size, 1), ==, 1);
+        /* Write data */
+        g_assert_cmpint(write(fd, buf, size), ==, size);
+
+        /* Expect response */
+        code = read_response(NULL, 0);
+        g_assert_cmphex(code, ==, CODE_OK);
+
+        buf += size;
+        offset += size;
+        len -= size;
+    }
+}
+
+static void test_invalid_op(void)
+{
+    uint8_t op = OP_INVALID;
+    uint8_t code;
+    uint8_t buf[1];
+
+    g_assert_cmpint(write(fd, &op, 1), ==, 1);
+    code = read_response(buf, 1);
+    g_assert_cmphex(code, ==, CODE_INVALID_OP);
+}
+
+/* Send data via chardev and read them in guest. */
+static void test_guest_read(void)
+{
+    const char *data = "Hello World!";
+    uint64_t offset = 0xa0;
+    char buf[100];
+    size_t len = strlen(data);
+
+    send_data(offset, (uint8_t *)data, len);
+    memread(PCI_MBOX_BA + offset, buf, len);
+    g_assert_cmpint(strncmp(data, buf, len), ==, 0);
+}
+
+/* Write data in guest and read out via chardev. */
+static void test_guest_write(void)
+{
+    const char *data = "Hello World!";
+    uint64_t offset = 0xa0;
+    char buf[100];
+    size_t len = strlen(data);
+
+    memwrite(PCI_MBOX_BA + offset, data, len);
+    receive_data(offset, (uint8_t *)buf, len);
+    g_assert_cmpint(strncmp(data, buf, len), ==, 0);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+    int port;
+
+    g_test_init(&argc, &argv, NULL);
+    port = open_socket();
+    g_test_message("port=%d", port);
+    global_qtest = qtest_initf("-machine npcm750-evb "
+        "-chardev socket,id=npcm7xx-pcimbox-chr,host=localhost,"
+        "port=%d,reconnect=10 "
+        "-global driver=npcm7xx-pci-mbox,property=chardev,"
+        "value=npcm7xx-pcimbox-chr",
+        port);
+    setup_fd();
+    qtest_irq_intercept_in(global_qtest, "/machine/soc/a9mpcore/gic");
+
+    qtest_add_func("/npcm7xx_pci_mbox/invalid_op", test_invalid_op);
+    qtest_add_func("/npcm7xx_pci_mbox/read", test_guest_read);
+    qtest_add_func("/npcm7xx_pci_mbox/write", test_guest_write);
+    ret = g_test_run();
+    qtest_quit(global_qtest);
+
+    return ret;
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 5e4bc3da85e..464eb4c6845 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -184,6 +184,7 @@ qtests_sparc64 = \
 qtests_npcm7xx = \
   ['npcm7xx_adc-test',
    'npcm7xx_gpio-test',
+   'npcm7xx_pci_mbox-test',
    'npcm7xx_pwm-test',
    'npcm7xx_rng-test',
    'npcm7xx_sdhci-test',
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 13/21] hw/net: Add NPCMXXX GMAC device
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (11 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 12/21] hw/misc: Add qtest for NPCM7xx PCI Mailbox Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 14/21] hw/arm: Add GMAC devices to NPCM7XX SoC Peter Maydell
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

This patch implements the basic registers of GMAC device and sets
registers for networking functionalities.

Tested:
The following message shows up with the change:
Broadcom BCM54612E stmmac-0:00: attached PHY driver [Broadcom BCM54612E] (mii_bus:phy_addr=stmmac-0:00, irq=POLL)
stmmaceth f0802000.eth eth0: Link is Up - 1Gbps/Full - flow control rx/tx

Change-Id: If71c6d486b95edcccba109ba454870714d7e0940
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Signed-off-by: Nabih Estefan Diaz <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-5-nabihestefan@google.com
[PMM: Squashed another patch into this one to avoid compilation failure]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/net/npcm_gmac.h | 340 +++++++++++++++++++++++++++
 hw/net/npcm_gmac.c         | 464 +++++++++++++++++++++++++++++++++++++
 hw/net/meson.build         |   2 +-
 hw/net/trace-events        |  12 +
 4 files changed, 817 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/net/npcm_gmac.h
 create mode 100644 hw/net/npcm_gmac.c

diff --git a/include/hw/net/npcm_gmac.h b/include/hw/net/npcm_gmac.h
new file mode 100644
index 00000000000..d0a37e69884
--- /dev/null
+++ b/include/hw/net/npcm_gmac.h
@@ -0,0 +1,340 @@
+/*
+ * Nuvoton NPCM7xx/8xx GMAC Module
+ *
+ * Copyright 2022 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef NPCM_GMAC_H
+#define NPCM_GMAC_H
+
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "net/net.h"
+
+#define NPCM_GMAC_NR_REGS (0x1060 / sizeof(uint32_t))
+
+#define NPCM_GMAC_MAX_PHYS 32
+#define NPCM_GMAC_MAX_PHY_REGS 32
+
+struct NPCMGMACRxDesc {
+    uint32_t rdes0;
+    uint32_t rdes1;
+    uint32_t rdes2;
+    uint32_t rdes3;
+};
+
+/* NPCMGMACRxDesc.flags values */
+/* RDES2 and RDES3 are buffer addresses */
+/* Owner: 0 = software, 1 = dma */
+#define RX_DESC_RDES0_OWN BIT(31)
+/* Destination Address Filter Fail */
+#define RX_DESC_RDES0_DEST_ADDR_FILT_FAIL BIT(30)
+/* Frame length */
+#define RX_DESC_RDES0_FRAME_LEN_MASK(word) extract32(word, 16, 14)
+/* Frame length Shift*/
+#define RX_DESC_RDES0_FRAME_LEN_SHIFT 16
+/* Error Summary */
+#define RX_DESC_RDES0_ERR_SUMM_MASK BIT(15)
+/* Descriptor Error */
+#define RX_DESC_RDES0_DESC_ERR_MASK BIT(14)
+/* Source Address Filter Fail */
+#define RX_DESC_RDES0_SRC_ADDR_FILT_FAIL_MASK BIT(13)
+/* Length Error */
+#define RX_DESC_RDES0_LEN_ERR_MASK BIT(12)
+/* Overflow Error */
+#define RX_DESC_RDES0_OVRFLW_ERR_MASK BIT(11)
+/* VLAN Tag */
+#define RX_DESC_RDES0_VLAN_TAG_MASK BIT(10)
+/* First Descriptor */
+#define RX_DESC_RDES0_FIRST_DESC_MASK BIT(9)
+/* Last Descriptor */
+#define RX_DESC_RDES0_LAST_DESC_MASK BIT(8)
+/* IPC Checksum Error/Giant Frame */
+#define RX_DESC_RDES0_IPC_CHKSM_ERR_GNT_FRM_MASK BIT(7)
+/* Late Collision */
+#define RX_DESC_RDES0_LT_COLL_MASK BIT(6)
+/* Frame Type */
+#define RX_DESC_RDES0_FRM_TYPE_MASK BIT(5)
+/* Receive Watchdog Timeout */
+#define RX_DESC_RDES0_REC_WTCHDG_TMT_MASK BIT(4)
+/* Receive Error */
+#define RX_DESC_RDES0_RCV_ERR_MASK BIT(3)
+/* Dribble Bit Error */
+#define RX_DESC_RDES0_DRBL_BIT_ERR_MASK BIT(2)
+/* Cyclcic Redundancy Check Error */
+#define RX_DESC_RDES0_CRC_ERR_MASK BIT(1)
+/* Rx MAC Address/Payload Checksum Error */
+#define RC_DESC_RDES0_RCE_MASK BIT(0)
+
+/* Disable Interrupt on Completion */
+#define RX_DESC_RDES1_DIS_INTR_COMP_MASK BIT(31)
+/* Recieve end of ring */
+#define RX_DESC_RDES1_RC_END_RING_MASK BIT(25)
+/* Second Address Chained */
+#define RX_DESC_RDES1_SEC_ADDR_CHND_MASK BIT(24)
+/* Receive Buffer 2 Size */
+#define RX_DESC_RDES1_BFFR2_SZ_SHIFT 11
+#define RX_DESC_RDES1_BFFR2_SZ_MASK(word) extract32(word, \
+    RX_DESC_RDES1_BFFR2_SZ_SHIFT, 11)
+/* Receive Buffer 1 Size */
+#define RX_DESC_RDES1_BFFR1_SZ_MASK(word) extract32(word, 0, 11)
+
+
+struct NPCMGMACTxDesc {
+    uint32_t tdes0;
+    uint32_t tdes1;
+    uint32_t tdes2;
+    uint32_t tdes3;
+};
+
+/* NPCMGMACTxDesc.flags values */
+/* TDES2 and TDES3 are buffer addresses */
+/* Owner: 0 = software, 1 = gmac */
+#define TX_DESC_TDES0_OWN BIT(31)
+/* Tx Time Stamp Status */
+#define TX_DESC_TDES0_TTSS_MASK BIT(17)
+/* IP Header Error */
+#define TX_DESC_TDES0_IP_HEAD_ERR_MASK BIT(16)
+/* Error Summary */
+#define TX_DESC_TDES0_ERR_SUMM_MASK BIT(15)
+/* Jabber Timeout */
+#define TX_DESC_TDES0_JBBR_TMT_MASK BIT(14)
+/* Frame Flushed */
+#define TX_DESC_TDES0_FRM_FLSHD_MASK BIT(13)
+/* Payload Checksum Error */
+#define TX_DESC_TDES0_PYLD_CHKSM_ERR_MASK BIT(12)
+/* Loss of Carrier */
+#define TX_DESC_TDES0_LSS_CARR_MASK BIT(11)
+/* No Carrier */
+#define TX_DESC_TDES0_NO_CARR_MASK BIT(10)
+/* Late Collision */
+#define TX_DESC_TDES0_LATE_COLL_MASK BIT(9)
+/* Excessive Collision */
+#define TX_DESC_TDES0_EXCS_COLL_MASK BIT(8)
+/* VLAN Frame */
+#define TX_DESC_TDES0_VLAN_FRM_MASK BIT(7)
+/* Collision Count */
+#define TX_DESC_TDES0_COLL_CNT_MASK(word) extract32(word, 3, 4)
+/* Excessive Deferral */
+#define TX_DESC_TDES0_EXCS_DEF_MASK BIT(2)
+/* Underflow Error */
+#define TX_DESC_TDES0_UNDRFLW_ERR_MASK BIT(1)
+/* Deferred Bit */
+#define TX_DESC_TDES0_DFRD_BIT_MASK BIT(0)
+
+/* Interrupt of Completion */
+#define TX_DESC_TDES1_INTERR_COMP_MASK BIT(31)
+/* Last Segment */
+#define TX_DESC_TDES1_LAST_SEG_MASK BIT(30)
+/* First Segment */
+#define TX_DESC_TDES1_FIRST_SEG_MASK BIT(29)
+/* Checksum Insertion Control */
+#define TX_DESC_TDES1_CHKSM_INS_CTRL_MASK(word) extract32(word, 27, 2)
+/* Disable Cyclic Redundancy Check */
+#define TX_DESC_TDES1_DIS_CDC_MASK BIT(26)
+/* Transmit End of Ring */
+#define TX_DESC_TDES1_TX_END_RING_MASK BIT(25)
+/* Secondary Address Chained */
+#define TX_DESC_TDES1_SEC_ADDR_CHND_MASK BIT(24)
+/* Transmit Buffer 2 Size */
+#define TX_DESC_TDES1_BFFR2_SZ_MASK(word) extract32(word, 11, 11)
+/* Transmit Buffer 1 Size */
+#define TX_DESC_TDES1_BFFR1_SZ_MASK(word) extract32(word, 0, 11)
+
+typedef struct NPCMGMACState {
+    SysBusDevice parent;
+
+    MemoryRegion iomem;
+    qemu_irq irq;
+
+    NICState *nic;
+    NICConf conf;
+
+    uint32_t regs[NPCM_GMAC_NR_REGS];
+    uint16_t phy_regs[NPCM_GMAC_MAX_PHYS][NPCM_GMAC_MAX_PHY_REGS];
+} NPCMGMACState;
+
+#define TYPE_NPCM_GMAC "npcm-gmac"
+OBJECT_DECLARE_SIMPLE_TYPE(NPCMGMACState, NPCM_GMAC)
+
+/* Mask for RO bits in Status */
+#define NPCM_DMA_STATUS_RO_MASK(word) (word & 0xfffe0000)
+/* Mask for RO bits in Status */
+#define NPCM_DMA_STATUS_W1C_MASK(word) (word & 0x1e7ff)
+
+/* Transmit Process State */
+#define NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT 20
+/* Transmit States */
+#define NPCM_DMA_STATUS_TX_STOPPED_STATE \
+    (0b000)
+#define NPCM_DMA_STATUS_TX_RUNNING_FETCHING_STATE \
+    (0b001)
+#define NPCM_DMA_STATUS_TX_RUNNING_WAITING_STATE \
+    (0b010)
+#define NPCM_DMA_STATUS_TX_RUNNING_READ_STATE \
+    (0b011)
+#define NPCM_DMA_STATUS_TX_SUSPENDED_STATE \
+    (0b110)
+#define NPCM_DMA_STATUS_TX_RUNNING_CLOSING_STATE \
+    (0b111)
+/* Transmit Process State */
+#define NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT 17
+/* Receive States */
+#define NPCM_DMA_STATUS_RX_STOPPED_STATE \
+    (0b000)
+#define NPCM_DMA_STATUS_RX_RUNNING_FETCHING_STATE \
+    (0b001)
+#define NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE \
+    (0b011)
+#define NPCM_DMA_STATUS_RX_SUSPENDED_STATE \
+    (0b100)
+#define NPCM_DMA_STATUS_RX_RUNNING_CLOSING_STATE \
+    (0b101)
+#define NPCM_DMA_STATUS_RX_RUNNING_TRANSFERRING_STATE \
+    (0b111)
+
+
+/* Early Receive Interrupt */
+#define NPCM_DMA_STATUS_ERI BIT(14)
+/* Fatal Bus Error Interrupt */
+#define NPCM_DMA_STATUS_FBI BIT(13)
+/* Early transmit Interrupt */
+#define NPCM_DMA_STATUS_ETI BIT(10)
+/* Receive Watchdog Timout */
+#define NPCM_DMA_STATUS_RWT BIT(9)
+/* Receive Process Stopped */
+#define NPCM_DMA_STATUS_RPS BIT(8)
+/* Receive Buffer Unavailable */
+#define NPCM_DMA_STATUS_RU BIT(7)
+/* Receive Interrupt */
+#define NPCM_DMA_STATUS_RI BIT(6)
+/* Transmit Underflow */
+#define NPCM_DMA_STATUS_UNF BIT(5)
+/* Receive Overflow */
+#define NPCM_DMA_STATUS_OVF BIT(4)
+/* Transmit Jabber Timeout */
+#define NPCM_DMA_STATUS_TJT BIT(3)
+/* Transmit Buffer Unavailable */
+#define NPCM_DMA_STATUS_TU BIT(2)
+/* Transmit Process Stopped */
+#define NPCM_DMA_STATUS_TPS BIT(1)
+/* Transmit Interrupt */
+#define NPCM_DMA_STATUS_TI BIT(0)
+
+/* Normal Interrupt Summary */
+#define NPCM_DMA_STATUS_NIS BIT(16)
+/* Interrupts enabled by NIE */
+#define NPCM_DMA_STATUS_NIS_BITS (NPCM_DMA_STATUS_TI | \
+                                  NPCM_DMA_STATUS_TU | \
+                                  NPCM_DMA_STATUS_RI | \
+                                  NPCM_DMA_STATUS_ERI)
+/* Abnormal Interrupt Summary */
+#define NPCM_DMA_STATUS_AIS BIT(15)
+/* Interrupts enabled by AIE */
+#define NPCM_DMA_STATUS_AIS_BITS (NPCM_DMA_STATUS_TPS | \
+                                  NPCM_DMA_STATUS_TJT | \
+                                  NPCM_DMA_STATUS_OVF | \
+                                  NPCM_DMA_STATUS_UNF | \
+                                  NPCM_DMA_STATUS_RU  | \
+                                  NPCM_DMA_STATUS_RPS | \
+                                  NPCM_DMA_STATUS_RWT | \
+                                  NPCM_DMA_STATUS_ETI | \
+                                  NPCM_DMA_STATUS_FBI)
+
+/* Early Receive Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_ERE BIT(14)
+/* Fatal Bus Error Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_FBE BIT(13)
+/* Early transmit Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_ETE BIT(10)
+/* Receive Watchdog Timout Enable */
+#define NPCM_DMA_INTR_ENAB_RWE BIT(9)
+/* Receive Process Stopped Enable */
+#define NPCM_DMA_INTR_ENAB_RSE BIT(8)
+/* Receive Buffer Unavailable Enable */
+#define NPCM_DMA_INTR_ENAB_RUE BIT(7)
+/* Receive Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_RIE BIT(6)
+/* Transmit Underflow Enable */
+#define NPCM_DMA_INTR_ENAB_UNE BIT(5)
+/* Receive Overflow Enable */
+#define NPCM_DMA_INTR_ENAB_OVE BIT(4)
+/* Transmit Jabber Timeout Enable */
+#define NPCM_DMA_INTR_ENAB_TJE BIT(3)
+/* Transmit Buffer Unavailable Enable */
+#define NPCM_DMA_INTR_ENAB_TUE BIT(2)
+/* Transmit Process Stopped Enable */
+#define NPCM_DMA_INTR_ENAB_TSE BIT(1)
+/* Transmit Interrupt Enable */
+#define NPCM_DMA_INTR_ENAB_TIE BIT(0)
+
+/* Normal Interrupt Summary Enable */
+#define NPCM_DMA_INTR_ENAB_NIE BIT(16)
+/* Interrupts enabled by NIE Enable */
+#define NPCM_DMA_INTR_ENAB_NIE_BITS (NPCM_DMA_INTR_ENAB_TIE | \
+                                     NPCM_DMA_INTR_ENAB_TUE | \
+                                     NPCM_DMA_INTR_ENAB_RIE | \
+                                     NPCM_DMA_INTR_ENAB_ERE)
+/* Abnormal Interrupt Summary Enable */
+#define NPCM_DMA_INTR_ENAB_AIE BIT(15)
+/* Interrupts enabled by AIE Enable */
+#define NPCM_DMA_INTR_ENAB_AIE_BITS (NPCM_DMA_INTR_ENAB_TSE | \
+                                     NPCM_DMA_INTR_ENAB_TJE | \
+                                     NPCM_DMA_INTR_ENAB_OVE | \
+                                     NPCM_DMA_INTR_ENAB_UNE | \
+                                     NPCM_DMA_INTR_ENAB_RUE | \
+                                     NPCM_DMA_INTR_ENAB_RSE | \
+                                     NPCM_DMA_INTR_ENAB_RWE | \
+                                     NPCM_DMA_INTR_ENAB_ETE | \
+                                     NPCM_DMA_INTR_ENAB_FBE)
+
+/* Flushing Disabled */
+#define NPCM_DMA_CONTROL_FLUSH_MASK BIT(24)
+/* Start/stop Transmit */
+#define NPCM_DMA_CONTROL_START_STOP_TX BIT(13)
+/* Start/stop Receive */
+#define NPCM_DMA_CONTROL_START_STOP_RX BIT(1)
+/* Next receive descriptor start address */
+#define NPCM_DMA_HOST_RX_DESC_MASK(word) ((uint32_t) (word) & ~3u)
+/* Next transmit descriptor start address */
+#define NPCM_DMA_HOST_TX_DESC_MASK(word) ((uint32_t) (word) & ~3u)
+
+/* Receive enable */
+#define NPCM_GMAC_MAC_CONFIG_RX_EN BIT(2)
+/* Transmit enable */
+#define NPCM_GMAC_MAC_CONFIG_TX_EN BIT(3)
+
+/* Frame Receive All */
+#define NPCM_GMAC_FRAME_FILTER_REC_ALL_MASK BIT(31)
+/* Frame HPF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_HPF_MASK BIT(10)
+/* Frame SAF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_SAF_MASK BIT(9)
+/* Frame SAIF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_SAIF_MASK BIT(8)
+/* Frame PCF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_PCF_MASK BIT(word) extract32((word), 6, 2)
+/* Frame DBF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_DBF_MASK BIT(5)
+/* Frame PM Filter*/
+#define NPCM_GMAC_FRAME_FILTER_PM_MASK BIT(4)
+/* Frame DAIF Filter*/
+#define NPCM_GMAC_FRAME_FILTER_DAIF_MASK BIT(3)
+/* Frame HMC Filter*/
+#define NPCM_GMAC_FRAME_FILTER_HMC_MASK BIT(2)
+/* Frame HUC Filter*/
+#define NPCM_GMAC_FRAME_FILTER_HUC_MASK BIT(1)
+/* Frame PR Filter*/
+#define NPCM_GMAC_FRAME_FILTER_PR_MASK BIT(0)
+
+#endif /* NPCM_GMAC_H */
diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c
new file mode 100644
index 00000000000..44c4ffaff42
--- /dev/null
+++ b/hw/net/npcm_gmac.c
@@ -0,0 +1,464 @@
+/*
+ * Nuvoton NPCM7xx/8xx GMAC Module
+ *
+ * Copyright 2022 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * Unsupported/unimplemented features:
+ * - MII is not implemented, MII_ADDR.BUSY and MII_DATA always return zero
+ * - Precision timestamp (PTP) is not implemented.
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/registerfields.h"
+#include "hw/net/mii.h"
+#include "hw/net/npcm_gmac.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qemu/units.h"
+#include "sysemu/dma.h"
+#include "trace.h"
+
+REG32(NPCM_DMA_BUS_MODE, 0x1000)
+REG32(NPCM_DMA_XMT_POLL_DEMAND, 0x1004)
+REG32(NPCM_DMA_RCV_POLL_DEMAND, 0x1008)
+REG32(NPCM_DMA_RX_BASE_ADDR, 0x100c)
+REG32(NPCM_DMA_TX_BASE_ADDR, 0x1010)
+REG32(NPCM_DMA_STATUS, 0x1014)
+REG32(NPCM_DMA_CONTROL, 0x1018)
+REG32(NPCM_DMA_INTR_ENA, 0x101c)
+REG32(NPCM_DMA_MISSED_FRAME_CTR, 0x1020)
+REG32(NPCM_DMA_HOST_TX_DESC, 0x1048)
+REG32(NPCM_DMA_HOST_RX_DESC, 0x104c)
+REG32(NPCM_DMA_CUR_TX_BUF_ADDR, 0x1050)
+REG32(NPCM_DMA_CUR_RX_BUF_ADDR, 0x1054)
+REG32(NPCM_DMA_HW_FEATURE, 0x1058)
+
+REG32(NPCM_GMAC_MAC_CONFIG, 0x0)
+REG32(NPCM_GMAC_FRAME_FILTER, 0x4)
+REG32(NPCM_GMAC_HASH_HIGH, 0x8)
+REG32(NPCM_GMAC_HASH_LOW, 0xc)
+REG32(NPCM_GMAC_MII_ADDR, 0x10)
+REG32(NPCM_GMAC_MII_DATA, 0x14)
+REG32(NPCM_GMAC_FLOW_CTRL, 0x18)
+REG32(NPCM_GMAC_VLAN_FLAG, 0x1c)
+REG32(NPCM_GMAC_VERSION, 0x20)
+REG32(NPCM_GMAC_WAKEUP_FILTER, 0x28)
+REG32(NPCM_GMAC_PMT, 0x2c)
+REG32(NPCM_GMAC_LPI_CTRL, 0x30)
+REG32(NPCM_GMAC_TIMER_CTRL, 0x34)
+REG32(NPCM_GMAC_INT_STATUS, 0x38)
+REG32(NPCM_GMAC_INT_MASK, 0x3c)
+REG32(NPCM_GMAC_MAC0_ADDR_HI, 0x40)
+REG32(NPCM_GMAC_MAC0_ADDR_LO, 0x44)
+REG32(NPCM_GMAC_MAC1_ADDR_HI, 0x48)
+REG32(NPCM_GMAC_MAC1_ADDR_LO, 0x4c)
+REG32(NPCM_GMAC_MAC2_ADDR_HI, 0x50)
+REG32(NPCM_GMAC_MAC2_ADDR_LO, 0x54)
+REG32(NPCM_GMAC_MAC3_ADDR_HI, 0x58)
+REG32(NPCM_GMAC_MAC3_ADDR_LO, 0x5c)
+REG32(NPCM_GMAC_RGMII_STATUS, 0xd8)
+REG32(NPCM_GMAC_WATCHDOG, 0xdc)
+REG32(NPCM_GMAC_PTP_TCR, 0x700)
+REG32(NPCM_GMAC_PTP_SSIR, 0x704)
+REG32(NPCM_GMAC_PTP_STSR, 0x708)
+REG32(NPCM_GMAC_PTP_STNSR, 0x70c)
+REG32(NPCM_GMAC_PTP_STSUR, 0x710)
+REG32(NPCM_GMAC_PTP_STNSUR, 0x714)
+REG32(NPCM_GMAC_PTP_TAR, 0x718)
+REG32(NPCM_GMAC_PTP_TTSR, 0x71c)
+
+/* Register Fields */
+#define NPCM_GMAC_MII_ADDR_BUSY             BIT(0)
+#define NPCM_GMAC_MII_ADDR_WRITE            BIT(1)
+#define NPCM_GMAC_MII_ADDR_GR(rv)           extract16((rv), 6, 5)
+#define NPCM_GMAC_MII_ADDR_PA(rv)           extract16((rv), 11, 5)
+
+#define NPCM_GMAC_INT_MASK_LPIIM            BIT(10)
+#define NPCM_GMAC_INT_MASK_PMTM             BIT(3)
+#define NPCM_GMAC_INT_MASK_RGIM             BIT(0)
+
+#define NPCM_DMA_BUS_MODE_SWR               BIT(0)
+
+static const uint32_t npcm_gmac_cold_reset_values[NPCM_GMAC_NR_REGS] = {
+    /* Reduce version to 3.2 so that the kernel can enable interrupt. */
+    [R_NPCM_GMAC_VERSION]         = 0x00001032,
+    [R_NPCM_GMAC_TIMER_CTRL]      = 0x03e80000,
+    [R_NPCM_GMAC_MAC0_ADDR_HI]    = 0x8000ffff,
+    [R_NPCM_GMAC_MAC0_ADDR_LO]    = 0xffffffff,
+    [R_NPCM_GMAC_MAC1_ADDR_HI]    = 0x0000ffff,
+    [R_NPCM_GMAC_MAC1_ADDR_LO]    = 0xffffffff,
+    [R_NPCM_GMAC_MAC2_ADDR_HI]    = 0x0000ffff,
+    [R_NPCM_GMAC_MAC2_ADDR_LO]    = 0xffffffff,
+    [R_NPCM_GMAC_MAC3_ADDR_HI]    = 0x0000ffff,
+    [R_NPCM_GMAC_MAC3_ADDR_LO]    = 0xffffffff,
+    [R_NPCM_GMAC_PTP_TCR]         = 0x00002000,
+    [R_NPCM_DMA_BUS_MODE]         = 0x00020101,
+    [R_NPCM_DMA_HW_FEATURE]       = 0x100d4f37,
+};
+
+static const uint16_t phy_reg_init[] = {
+    [MII_BMCR]      = MII_BMCR_AUTOEN | MII_BMCR_FD | MII_BMCR_SPEED1000,
+    [MII_BMSR]      = MII_BMSR_100TX_FD | MII_BMSR_100TX_HD | MII_BMSR_10T_FD |
+                      MII_BMSR_10T_HD | MII_BMSR_EXTSTAT | MII_BMSR_AUTONEG |
+                      MII_BMSR_LINK_ST | MII_BMSR_EXTCAP,
+    [MII_PHYID1]    = 0x0362,
+    [MII_PHYID2]    = 0x5e6a,
+    [MII_ANAR]      = MII_ANAR_TXFD | MII_ANAR_TX | MII_ANAR_10FD |
+                      MII_ANAR_10 | MII_ANAR_CSMACD,
+    [MII_ANLPAR]    = MII_ANLPAR_ACK | MII_ANLPAR_PAUSE |
+                      MII_ANLPAR_TXFD | MII_ANLPAR_TX | MII_ANLPAR_10FD |
+                      MII_ANLPAR_10 | MII_ANLPAR_CSMACD,
+    [MII_ANER]      = 0x64 | MII_ANER_NWAY,
+    [MII_ANNP]      = 0x2001,
+    [MII_CTRL1000]  = MII_CTRL1000_FULL,
+    [MII_STAT1000]  = MII_STAT1000_FULL,
+    [MII_EXTSTAT]   = 0x3000, /* 1000BASTE_T full-duplex capable */
+};
+
+static void npcm_gmac_soft_reset(NPCMGMACState *gmac)
+{
+    memcpy(gmac->regs, npcm_gmac_cold_reset_values,
+           NPCM_GMAC_NR_REGS * sizeof(uint32_t));
+    /* Clear reset bits */
+    gmac->regs[R_NPCM_DMA_BUS_MODE] &= ~NPCM_DMA_BUS_MODE_SWR;
+}
+
+static void gmac_phy_set_link(NPCMGMACState *gmac, bool active)
+{
+    /* Autonegotiation status mirrors link status.  */
+    if (active) {
+        gmac->phy_regs[0][MII_BMSR] |= (MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
+    } else {
+        gmac->phy_regs[0][MII_BMSR] &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP);
+    }
+}
+
+static bool gmac_can_receive(NetClientState *nc)
+{
+    return true;
+}
+
+/*
+ * Function that updates the GMAC IRQ
+ * It find the logical OR of the enabled bits for NIS (if enabled)
+ * It find the logical OR of the enabled bits for AIS (if enabled)
+ */
+static void gmac_update_irq(NPCMGMACState *gmac)
+{
+    /*
+     * Check if the normal interrupts summary is enabled
+     * if so, add the bits for the summary that are enabled
+     */
+    if (gmac->regs[R_NPCM_DMA_INTR_ENA] & gmac->regs[R_NPCM_DMA_STATUS] &
+        (NPCM_DMA_INTR_ENAB_NIE_BITS)) {
+        gmac->regs[R_NPCM_DMA_STATUS] |=  NPCM_DMA_STATUS_NIS;
+    }
+    /*
+     * Check if the abnormal interrupts summary is enabled
+     * if so, add the bits for the summary that are enabled
+     */
+    if (gmac->regs[R_NPCM_DMA_INTR_ENA] & gmac->regs[R_NPCM_DMA_STATUS] &
+        (NPCM_DMA_INTR_ENAB_AIE_BITS)) {
+        gmac->regs[R_NPCM_DMA_STATUS] |=  NPCM_DMA_STATUS_AIS;
+    }
+
+    /* Get the logical OR of both normal and abnormal interrupts */
+    int level = !!((gmac->regs[R_NPCM_DMA_STATUS] &
+                    gmac->regs[R_NPCM_DMA_INTR_ENA] &
+                    NPCM_DMA_STATUS_NIS) |
+                   (gmac->regs[R_NPCM_DMA_STATUS] &
+                   gmac->regs[R_NPCM_DMA_INTR_ENA] &
+                   NPCM_DMA_STATUS_AIS));
+
+    /* Set the IRQ */
+    trace_npcm_gmac_update_irq(DEVICE(gmac)->canonical_path,
+                               gmac->regs[R_NPCM_DMA_STATUS],
+                               gmac->regs[R_NPCM_DMA_INTR_ENA],
+                               level);
+    qemu_set_irq(gmac->irq, level);
+}
+
+static ssize_t gmac_receive(NetClientState *nc, const uint8_t *buf, size_t len)
+{
+    /* Placeholder. Function will be filled in following patches */
+    return 0;
+}
+
+static void gmac_cleanup(NetClientState *nc)
+{
+    /* Nothing to do yet. */
+}
+
+static void gmac_set_link(NetClientState *nc)
+{
+    NPCMGMACState *gmac = qemu_get_nic_opaque(nc);
+
+    trace_npcm_gmac_set_link(!nc->link_down);
+    gmac_phy_set_link(gmac, !nc->link_down);
+}
+
+static void npcm_gmac_mdio_access(NPCMGMACState *gmac, uint16_t v)
+{
+    bool busy = v & NPCM_GMAC_MII_ADDR_BUSY;
+    uint8_t is_write;
+    uint8_t pa, gr;
+    uint16_t data;
+
+    if (busy) {
+        is_write = v & NPCM_GMAC_MII_ADDR_WRITE;
+        pa = NPCM_GMAC_MII_ADDR_PA(v);
+        gr = NPCM_GMAC_MII_ADDR_GR(v);
+        /* Both pa and gr are 5 bits, so they are less than 32. */
+        g_assert(pa < NPCM_GMAC_MAX_PHYS);
+        g_assert(gr < NPCM_GMAC_MAX_PHY_REGS);
+
+
+        if (v & NPCM_GMAC_MII_ADDR_WRITE) {
+            data = gmac->regs[R_NPCM_GMAC_MII_DATA];
+            /* Clear reset bit for BMCR register */
+            switch (gr) {
+            case MII_BMCR:
+                data &= ~MII_BMCR_RESET;
+                /* Autonegotiation is a W1C bit*/
+                if (data & MII_BMCR_ANRESTART) {
+                    /* Tells autonegotiation to not restart again */
+                    data &= ~MII_BMCR_ANRESTART;
+                }
+                if ((data & MII_BMCR_AUTOEN) &&
+                    !(gmac->phy_regs[pa][MII_BMSR] & MII_BMSR_AN_COMP)) {
+                    /* sets autonegotiation as complete */
+                    gmac->phy_regs[pa][MII_BMSR] |= MII_BMSR_AN_COMP;
+                    /* Resolve AN automatically->need to set this */
+                    gmac->phy_regs[0][MII_ANLPAR] = 0x0000;
+                }
+            }
+            gmac->phy_regs[pa][gr] = data;
+        } else {
+            data = gmac->phy_regs[pa][gr];
+            gmac->regs[R_NPCM_GMAC_MII_DATA] = data;
+        }
+        trace_npcm_gmac_mdio_access(DEVICE(gmac)->canonical_path, is_write, pa,
+                                        gr, data);
+    }
+    gmac->regs[R_NPCM_GMAC_MII_ADDR] = v & ~NPCM_GMAC_MII_ADDR_BUSY;
+}
+
+static uint64_t npcm_gmac_read(void *opaque, hwaddr offset, unsigned size)
+{
+    NPCMGMACState *gmac = opaque;
+    uint32_t v = 0;
+
+    switch (offset) {
+    /* Write only registers */
+    case A_NPCM_DMA_XMT_POLL_DEMAND:
+    case A_NPCM_DMA_RCV_POLL_DEMAND:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Read of write-only reg: offset: 0x%04" HWADDR_PRIx
+                      "\n", DEVICE(gmac)->canonical_path, offset);
+        break;
+
+    default:
+        v = gmac->regs[offset / sizeof(uint32_t)];
+    }
+
+    trace_npcm_gmac_reg_read(DEVICE(gmac)->canonical_path, offset, v);
+    return v;
+}
+
+static void npcm_gmac_write(void *opaque, hwaddr offset,
+                              uint64_t v, unsigned size)
+{
+    NPCMGMACState *gmac = opaque;
+
+    trace_npcm_gmac_reg_write(DEVICE(gmac)->canonical_path, offset, v);
+
+    switch (offset) {
+    /* Read only registers */
+    case A_NPCM_GMAC_VERSION:
+    case A_NPCM_GMAC_INT_STATUS:
+    case A_NPCM_GMAC_RGMII_STATUS:
+    case A_NPCM_GMAC_PTP_STSR:
+    case A_NPCM_GMAC_PTP_STNSR:
+    case A_NPCM_DMA_MISSED_FRAME_CTR:
+    case A_NPCM_DMA_HOST_TX_DESC:
+    case A_NPCM_DMA_HOST_RX_DESC:
+    case A_NPCM_DMA_CUR_TX_BUF_ADDR:
+    case A_NPCM_DMA_CUR_RX_BUF_ADDR:
+    case A_NPCM_DMA_HW_FEATURE:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Write of read-only reg: offset: 0x%04" HWADDR_PRIx
+                      ", value: 0x%04" PRIx64 "\n",
+                      DEVICE(gmac)->canonical_path, offset, v);
+        break;
+
+    case A_NPCM_GMAC_MAC_CONFIG:
+        break;
+
+    case A_NPCM_GMAC_MII_ADDR:
+        npcm_gmac_mdio_access(gmac, v);
+        break;
+
+    case A_NPCM_GMAC_MAC0_ADDR_HI:
+        gmac->regs[offset / sizeof(uint32_t)] = v;
+        gmac->conf.macaddr.a[0] = v >> 8;
+        gmac->conf.macaddr.a[1] = v >> 0;
+        break;
+
+    case A_NPCM_GMAC_MAC0_ADDR_LO:
+        gmac->regs[offset / sizeof(uint32_t)] = v;
+        gmac->conf.macaddr.a[2] = v >> 24;
+        gmac->conf.macaddr.a[3] = v >> 16;
+        gmac->conf.macaddr.a[4] = v >> 8;
+        gmac->conf.macaddr.a[5] = v >> 0;
+        break;
+
+    case A_NPCM_GMAC_MAC1_ADDR_HI:
+    case A_NPCM_GMAC_MAC1_ADDR_LO:
+    case A_NPCM_GMAC_MAC2_ADDR_HI:
+    case A_NPCM_GMAC_MAC2_ADDR_LO:
+    case A_NPCM_GMAC_MAC3_ADDR_HI:
+    case A_NPCM_GMAC_MAC3_ADDR_LO:
+        gmac->regs[offset / sizeof(uint32_t)] = v;
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Only MAC Address 0 is supported. This request "
+                      "is ignored.\n", DEVICE(gmac)->canonical_path);
+        break;
+
+    case A_NPCM_DMA_BUS_MODE:
+        gmac->regs[offset / sizeof(uint32_t)] = v;
+        if (v & NPCM_DMA_BUS_MODE_SWR) {
+            npcm_gmac_soft_reset(gmac);
+        }
+        break;
+
+    case A_NPCM_DMA_RCV_POLL_DEMAND:
+        /* We dont actually care about the value */
+        break;
+
+    case A_NPCM_DMA_STATUS:
+        /* Check that RO bits are not written to */
+        if (NPCM_DMA_STATUS_RO_MASK(v)) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Write of read-only bits of reg: offset: 0x%04"
+                           HWADDR_PRIx ", value: 0x%04" PRIx64 "\n",
+                           DEVICE(gmac)->canonical_path, offset, v);
+        }
+        break;
+
+    default:
+        gmac->regs[offset / sizeof(uint32_t)] = v;
+        break;
+    }
+
+    gmac_update_irq(gmac);
+}
+
+static void npcm_gmac_reset(DeviceState *dev)
+{
+    NPCMGMACState *gmac = NPCM_GMAC(dev);
+
+    npcm_gmac_soft_reset(gmac);
+    memcpy(gmac->phy_regs[0], phy_reg_init, sizeof(phy_reg_init));
+
+    trace_npcm_gmac_reset(DEVICE(gmac)->canonical_path,
+                          gmac->phy_regs[0][MII_BMSR]);
+}
+
+static NetClientInfo net_npcm_gmac_info = {
+    .type = NET_CLIENT_DRIVER_NIC,
+    .size = sizeof(NICState),
+    .can_receive = gmac_can_receive,
+    .receive = gmac_receive,
+    .cleanup = gmac_cleanup,
+    .link_status_changed = gmac_set_link,
+};
+
+static const struct MemoryRegionOps npcm_gmac_ops = {
+    .read = npcm_gmac_read,
+    .write = npcm_gmac_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+        .unaligned = false,
+    },
+};
+
+static void npcm_gmac_realize(DeviceState *dev, Error **errp)
+{
+    NPCMGMACState *gmac = NPCM_GMAC(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    memory_region_init_io(&gmac->iomem, OBJECT(gmac), &npcm_gmac_ops, gmac,
+                          TYPE_NPCM_GMAC, 8 * KiB);
+    sysbus_init_mmio(sbd, &gmac->iomem);
+    sysbus_init_irq(sbd, &gmac->irq);
+
+    qemu_macaddr_default_if_unset(&gmac->conf.macaddr);
+
+    gmac->nic = qemu_new_nic(&net_npcm_gmac_info, &gmac->conf, TYPE_NPCM_GMAC,
+                             dev->id, &dev->mem_reentrancy_guard, gmac);
+    qemu_format_nic_info_str(qemu_get_queue(gmac->nic), gmac->conf.macaddr.a);
+    gmac->regs[R_NPCM_GMAC_MAC0_ADDR_HI] = (gmac->conf.macaddr.a[0] << 8) + \
+                                            gmac->conf.macaddr.a[1];
+    gmac->regs[R_NPCM_GMAC_MAC0_ADDR_LO] = (gmac->conf.macaddr.a[2] << 24) + \
+                                           (gmac->conf.macaddr.a[3] << 16) + \
+                                           (gmac->conf.macaddr.a[4] << 8) + \
+                                            gmac->conf.macaddr.a[5];
+}
+
+static void npcm_gmac_unrealize(DeviceState *dev)
+{
+    NPCMGMACState *gmac = NPCM_GMAC(dev);
+
+    qemu_del_nic(gmac->nic);
+}
+
+static const VMStateDescription vmstate_npcm_gmac = {
+    .name = TYPE_NPCM_GMAC,
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, NPCMGMACState, NPCM_GMAC_NR_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static Property npcm_gmac_properties[] = {
+    DEFINE_NIC_PROPERTIES(NPCMGMACState, conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void npcm_gmac_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
+    dc->desc = "NPCM GMAC Controller";
+    dc->realize = npcm_gmac_realize;
+    dc->unrealize = npcm_gmac_unrealize;
+    dc->reset = npcm_gmac_reset;
+    dc->vmsd = &vmstate_npcm_gmac;
+    device_class_set_props(dc, npcm_gmac_properties);
+}
+
+static const TypeInfo npcm_gmac_types[] = {
+    {
+        .name = TYPE_NPCM_GMAC,
+        .parent = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(NPCMGMACState),
+        .class_init = npcm_gmac_class_init,
+    },
+};
+DEFINE_TYPES(npcm_gmac_types)
diff --git a/hw/net/meson.build b/hw/net/meson.build
index 9afceb06191..d4e1dc98389 100644
--- a/hw/net/meson.build
+++ b/hw/net/meson.build
@@ -38,7 +38,7 @@ system_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
 system_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
 system_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
 system_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
-system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
+system_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c', 'npcm_gmac.c'))
 
 system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
 system_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 387e32e1533..56057de47f3 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -467,6 +467,18 @@ npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
 npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
 npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
 
+# npcm_gmac.c
+npcm_gmac_reg_read(const char *name, uint64_t offset, uint32_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx32
+npcm_gmac_reg_write(const char *name, uint64_t offset, uint32_t value) "%s: offset: 0x%04" PRIx64 " value: 0x%04" PRIx32
+npcm_gmac_mdio_access(const char *name, uint8_t is_write, uint8_t pa, uint8_t gr, uint16_t val) "%s: is_write: %" PRIu8 " pa: %" PRIu8 " gr: %" PRIu8 " val: 0x%04" PRIx16
+npcm_gmac_reset(const char *name, uint16_t value) "%s: phy_regs[0][1]: 0x%04" PRIx16
+npcm_gmac_set_link(bool active) "Set link: active=%u"
+npcm_gmac_update_irq(const char *name, uint32_t status, uint32_t intr_en, int level) "%s: Status Reg: 0x%04" PRIX32 " Interrupt Enable Reg: 0x%04" PRIX32 " IRQ Set: %d"
+
+# npcm_pcs.c
+npcm_pcs_reg_read(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
+npcm_pcs_reg_write(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
+
 # dp8398x.c
 dp8393x_raise_irq(int isr) "raise irq, isr is 0x%04x"
 dp8393x_lower_irq(void) "lower irq"
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 14/21] hw/arm: Add GMAC devices to NPCM7XX SoC
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (12 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 13/21] hw/net: Add NPCMXXX GMAC device Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 15/21] tests/qtest: Creating qtest for GMAC Module Peter Maydell
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Hao Wu <wuhaotsh@google.com>

Change-Id: Id8a3461fb5042adc4c3fd6f4fbd1ca0d33e22565
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-6-nabihestefan@google.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/arm/npcm7xx.h |  2 ++
 hw/arm/npcm7xx.c         | 36 ++++++++++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
index cec3792a2e8..9e5cf639a2d 100644
--- a/include/hw/arm/npcm7xx.h
+++ b/include/hw/arm/npcm7xx.h
@@ -30,6 +30,7 @@
 #include "hw/misc/npcm7xx_pwm.h"
 #include "hw/misc/npcm7xx_rng.h"
 #include "hw/net/npcm7xx_emc.h"
+#include "hw/net/npcm_gmac.h"
 #include "hw/nvram/npcm7xx_otp.h"
 #include "hw/timer/npcm7xx_timer.h"
 #include "hw/ssi/npcm7xx_fiu.h"
@@ -105,6 +106,7 @@ struct NPCM7xxState {
     OHCISysBusState     ohci;
     NPCM7xxFIUState     fiu[2];
     NPCM7xxEMCState     emc[2];
+    NPCMGMACState       gmac[2];
     NPCM7xxPCIMBoxState pci_mbox;
     NPCM7xxSDHCIState   mmc;
     NPCMPSPIState       pspi[2];
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index c9e87162cbe..12e11250e1e 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -91,6 +91,7 @@ enum NPCM7xxInterrupt {
     NPCM7XX_GMAC1_IRQ           = 14,
     NPCM7XX_EMC1RX_IRQ          = 15,
     NPCM7XX_EMC1TX_IRQ,
+    NPCM7XX_GMAC2_IRQ,
     NPCM7XX_MMC_IRQ             = 26,
     NPCM7XX_PSPI2_IRQ           = 28,
     NPCM7XX_PSPI1_IRQ           = 31,
@@ -234,6 +235,12 @@ static const hwaddr npcm7xx_pspi_addr[] = {
     0xf0201000,
 };
 
+/* Register base address for each GMAC Module */
+static const hwaddr npcm7xx_gmac_addr[] = {
+    0xf0802000,
+    0xf0804000,
+};
+
 static const struct {
     hwaddr regs_addr;
     uint32_t unconnected_pins;
@@ -462,6 +469,10 @@ static void npcm7xx_init(Object *obj)
         object_initialize_child(obj, "pspi[*]", &s->pspi[i], TYPE_NPCM_PSPI);
     }
 
+    for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
+        object_initialize_child(obj, "gmac[*]", &s->gmac[i], TYPE_NPCM_GMAC);
+    }
+
     object_initialize_child(obj, "pci-mbox", &s->pci_mbox,
                             TYPE_NPCM7XX_PCI_MBOX);
     object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
@@ -695,6 +706,29 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
         sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
     }
 
+    /*
+     * GMAC Modules. Cannot fail.
+     */
+    QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_gmac_addr) != ARRAY_SIZE(s->gmac));
+    QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->gmac) != 2);
+    for (i = 0; i < ARRAY_SIZE(s->gmac); i++) {
+        SysBusDevice *sbd = SYS_BUS_DEVICE(&s->gmac[i]);
+
+        /*
+         * The device exists regardless of whether it's connected to a QEMU
+         * netdev backend. So always instantiate it even if there is no
+         * backend.
+         */
+        sysbus_realize(sbd, &error_abort);
+        sysbus_mmio_map(sbd, 0, npcm7xx_gmac_addr[i]);
+        int irq = i == 0 ? NPCM7XX_GMAC1_IRQ : NPCM7XX_GMAC2_IRQ;
+        /*
+         * N.B. The values for the second argument sysbus_connect_irq are
+         * chosen to match the registration order in npcm7xx_emc_realize.
+         */
+        sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, irq));
+    }
+
     /*
      * Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
      * specified, but this is a programming error.
@@ -765,8 +799,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
     create_unimplemented_device("npcm7xx.siox[2]",      0xf0102000,   4 * KiB);
     create_unimplemented_device("npcm7xx.ahbpci",       0xf0400000,   1 * MiB);
     create_unimplemented_device("npcm7xx.mcphy",        0xf05f0000,  64 * KiB);
-    create_unimplemented_device("npcm7xx.gmac1",        0xf0802000,   8 * KiB);
-    create_unimplemented_device("npcm7xx.gmac2",        0xf0804000,   8 * KiB);
     create_unimplemented_device("npcm7xx.vcd",          0xf0810000,  64 * KiB);
     create_unimplemented_device("npcm7xx.ece",          0xf0820000,   8 * KiB);
     create_unimplemented_device("npcm7xx.vdma",         0xf0822000,   8 * KiB);
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 15/21] tests/qtest: Creating qtest for GMAC Module
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (13 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 14/21] hw/arm: Add GMAC devices to NPCM7XX SoC Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 16/21] hw/net: GMAC Rx Implementation Peter Maydell
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Nabih Estefan Diaz <nabihestefan@google.com>

 - Created qtest to check initialization of registers in GMAC Module.
 - Implemented test into Build File.

Change-Id: I8b2fe152d3987a7eec4cf6a1d25ba92e75a5391d
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-7-nabihestefan@google.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 tests/qtest/npcm_gmac-test.c | 209 +++++++++++++++++++++++++++++++++++
 tests/qtest/meson.build      |   1 +
 2 files changed, 210 insertions(+)
 create mode 100644 tests/qtest/npcm_gmac-test.c

diff --git a/tests/qtest/npcm_gmac-test.c b/tests/qtest/npcm_gmac-test.c
new file mode 100644
index 00000000000..130a1599a84
--- /dev/null
+++ b/tests/qtest/npcm_gmac-test.c
@@ -0,0 +1,209 @@
+/*
+ * QTests for Nuvoton NPCM7xx/8xx GMAC Modules.
+ *
+ * Copyright 2023 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "qemu/osdep.h"
+#include "libqos/libqos.h"
+
+/* Name of the GMAC Device */
+#define TYPE_NPCM_GMAC "npcm-gmac"
+
+typedef struct GMACModule {
+    int irq;
+    uint64_t base_addr;
+} GMACModule;
+
+typedef struct TestData {
+    const GMACModule *module;
+} TestData;
+
+/* Values extracted from hw/arm/npcm8xx.c */
+static const GMACModule gmac_module_list[] = {
+    {
+        .irq        = 14,
+        .base_addr  = 0xf0802000
+    },
+    {
+        .irq        = 15,
+        .base_addr  = 0xf0804000
+    },
+    {
+        .irq        = 16,
+        .base_addr  = 0xf0806000
+    },
+    {
+        .irq        = 17,
+        .base_addr  = 0xf0808000
+    }
+};
+
+/* Returns the index of the GMAC module. */
+static int gmac_module_index(const GMACModule *mod)
+{
+    ptrdiff_t diff = mod - gmac_module_list;
+
+    g_assert_true(diff >= 0 && diff < ARRAY_SIZE(gmac_module_list));
+
+    return diff;
+}
+
+/* 32-bit register indices. Taken from npcm_gmac.c */
+typedef enum NPCMRegister {
+    /* DMA Registers */
+    NPCM_DMA_BUS_MODE = 0x1000,
+    NPCM_DMA_XMT_POLL_DEMAND = 0x1004,
+    NPCM_DMA_RCV_POLL_DEMAND = 0x1008,
+    NPCM_DMA_RCV_BASE_ADDR = 0x100c,
+    NPCM_DMA_TX_BASE_ADDR = 0x1010,
+    NPCM_DMA_STATUS = 0x1014,
+    NPCM_DMA_CONTROL = 0x1018,
+    NPCM_DMA_INTR_ENA = 0x101c,
+    NPCM_DMA_MISSED_FRAME_CTR = 0x1020,
+    NPCM_DMA_HOST_TX_DESC = 0x1048,
+    NPCM_DMA_HOST_RX_DESC = 0x104c,
+    NPCM_DMA_CUR_TX_BUF_ADDR = 0x1050,
+    NPCM_DMA_CUR_RX_BUF_ADDR = 0x1054,
+    NPCM_DMA_HW_FEATURE = 0x1058,
+
+    /* GMAC Registers */
+    NPCM_GMAC_MAC_CONFIG = 0x0,
+    NPCM_GMAC_FRAME_FILTER = 0x4,
+    NPCM_GMAC_HASH_HIGH = 0x8,
+    NPCM_GMAC_HASH_LOW = 0xc,
+    NPCM_GMAC_MII_ADDR = 0x10,
+    NPCM_GMAC_MII_DATA = 0x14,
+    NPCM_GMAC_FLOW_CTRL = 0x18,
+    NPCM_GMAC_VLAN_FLAG = 0x1c,
+    NPCM_GMAC_VERSION = 0x20,
+    NPCM_GMAC_WAKEUP_FILTER = 0x28,
+    NPCM_GMAC_PMT = 0x2c,
+    NPCM_GMAC_LPI_CTRL = 0x30,
+    NPCM_GMAC_TIMER_CTRL = 0x34,
+    NPCM_GMAC_INT_STATUS = 0x38,
+    NPCM_GMAC_INT_MASK = 0x3c,
+    NPCM_GMAC_MAC0_ADDR_HI = 0x40,
+    NPCM_GMAC_MAC0_ADDR_LO = 0x44,
+    NPCM_GMAC_MAC1_ADDR_HI = 0x48,
+    NPCM_GMAC_MAC1_ADDR_LO = 0x4c,
+    NPCM_GMAC_MAC2_ADDR_HI = 0x50,
+    NPCM_GMAC_MAC2_ADDR_LO = 0x54,
+    NPCM_GMAC_MAC3_ADDR_HI = 0x58,
+    NPCM_GMAC_MAC3_ADDR_LO = 0x5c,
+    NPCM_GMAC_RGMII_STATUS = 0xd8,
+    NPCM_GMAC_WATCHDOG = 0xdc,
+    NPCM_GMAC_PTP_TCR = 0x700,
+    NPCM_GMAC_PTP_SSIR = 0x704,
+    NPCM_GMAC_PTP_STSR = 0x708,
+    NPCM_GMAC_PTP_STNSR = 0x70c,
+    NPCM_GMAC_PTP_STSUR = 0x710,
+    NPCM_GMAC_PTP_STNSUR = 0x714,
+    NPCM_GMAC_PTP_TAR = 0x718,
+    NPCM_GMAC_PTP_TTSR = 0x71c,
+} NPCMRegister;
+
+static uint32_t gmac_read(QTestState *qts, const GMACModule *mod,
+                          NPCMRegister regno)
+{
+    return qtest_readl(qts, mod->base_addr + regno);
+}
+
+/* Check that GMAC registers are reset to default value */
+static void test_init(gconstpointer test_data)
+{
+    const TestData *td = test_data;
+    const GMACModule *mod = td->module;
+    QTestState *qts = qtest_init("-machine npcm845-evb");
+
+#define CHECK_REG32(regno, value) \
+    do { \
+        g_assert_cmphex(gmac_read(qts, mod, (regno)), ==, (value)); \
+    } while (0)
+
+    CHECK_REG32(NPCM_DMA_BUS_MODE, 0x00020100);
+    CHECK_REG32(NPCM_DMA_XMT_POLL_DEMAND, 0);
+    CHECK_REG32(NPCM_DMA_RCV_POLL_DEMAND, 0);
+    CHECK_REG32(NPCM_DMA_RCV_BASE_ADDR, 0);
+    CHECK_REG32(NPCM_DMA_TX_BASE_ADDR, 0);
+    CHECK_REG32(NPCM_DMA_STATUS, 0);
+    CHECK_REG32(NPCM_DMA_CONTROL, 0);
+    CHECK_REG32(NPCM_DMA_INTR_ENA, 0);
+    CHECK_REG32(NPCM_DMA_MISSED_FRAME_CTR, 0);
+    CHECK_REG32(NPCM_DMA_HOST_TX_DESC, 0);
+    CHECK_REG32(NPCM_DMA_HOST_RX_DESC, 0);
+    CHECK_REG32(NPCM_DMA_CUR_TX_BUF_ADDR, 0);
+    CHECK_REG32(NPCM_DMA_CUR_RX_BUF_ADDR, 0);
+    CHECK_REG32(NPCM_DMA_HW_FEATURE, 0x100d4f37);
+
+    CHECK_REG32(NPCM_GMAC_MAC_CONFIG, 0);
+    CHECK_REG32(NPCM_GMAC_FRAME_FILTER, 0);
+    CHECK_REG32(NPCM_GMAC_HASH_HIGH, 0);
+    CHECK_REG32(NPCM_GMAC_HASH_LOW, 0);
+    CHECK_REG32(NPCM_GMAC_MII_ADDR, 0);
+    CHECK_REG32(NPCM_GMAC_MII_DATA, 0);
+    CHECK_REG32(NPCM_GMAC_FLOW_CTRL, 0);
+    CHECK_REG32(NPCM_GMAC_VLAN_FLAG, 0);
+    CHECK_REG32(NPCM_GMAC_VERSION, 0x00001032);
+    CHECK_REG32(NPCM_GMAC_WAKEUP_FILTER, 0);
+    CHECK_REG32(NPCM_GMAC_PMT, 0);
+    CHECK_REG32(NPCM_GMAC_LPI_CTRL, 0);
+    CHECK_REG32(NPCM_GMAC_TIMER_CTRL, 0x03e80000);
+    CHECK_REG32(NPCM_GMAC_INT_STATUS, 0);
+    CHECK_REG32(NPCM_GMAC_INT_MASK, 0);
+    CHECK_REG32(NPCM_GMAC_MAC0_ADDR_HI, 0x8000ffff);
+    CHECK_REG32(NPCM_GMAC_MAC0_ADDR_LO, 0xffffffff);
+    CHECK_REG32(NPCM_GMAC_MAC1_ADDR_HI, 0x0000ffff);
+    CHECK_REG32(NPCM_GMAC_MAC1_ADDR_LO, 0xffffffff);
+    CHECK_REG32(NPCM_GMAC_MAC2_ADDR_HI, 0x0000ffff);
+    CHECK_REG32(NPCM_GMAC_MAC2_ADDR_LO, 0xffffffff);
+    CHECK_REG32(NPCM_GMAC_MAC3_ADDR_HI, 0x0000ffff);
+    CHECK_REG32(NPCM_GMAC_MAC3_ADDR_LO, 0xffffffff);
+    CHECK_REG32(NPCM_GMAC_RGMII_STATUS, 0);
+    CHECK_REG32(NPCM_GMAC_WATCHDOG, 0);
+    CHECK_REG32(NPCM_GMAC_PTP_TCR, 0x00002000);
+    CHECK_REG32(NPCM_GMAC_PTP_SSIR, 0);
+    CHECK_REG32(NPCM_GMAC_PTP_STSR, 0);
+    CHECK_REG32(NPCM_GMAC_PTP_STNSR, 0);
+    CHECK_REG32(NPCM_GMAC_PTP_STSUR, 0);
+    CHECK_REG32(NPCM_GMAC_PTP_STNSUR, 0);
+    CHECK_REG32(NPCM_GMAC_PTP_TAR, 0);
+    CHECK_REG32(NPCM_GMAC_PTP_TTSR, 0);
+
+    qtest_quit(qts);
+}
+
+static void gmac_add_test(const char *name, const TestData* td,
+                          GTestDataFunc fn)
+{
+    g_autofree char *full_name = g_strdup_printf(
+            "npcm7xx_gmac/gmac[%d]/%s", gmac_module_index(td->module), name);
+    qtest_add_data_func(full_name, td, fn);
+}
+
+int main(int argc, char **argv)
+{
+    TestData test_data_list[ARRAY_SIZE(gmac_module_list)];
+
+    g_test_init(&argc, &argv, NULL);
+
+    for (int i = 0; i < ARRAY_SIZE(gmac_module_list); ++i) {
+        TestData *td = &test_data_list[i];
+
+        td->module = &gmac_module_list[i];
+
+        gmac_add_test("init", td, test_init);
+    }
+
+    return g_test_run();
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 464eb4c6845..2d085590d52 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -228,6 +228,7 @@ qtests_aarch64 = \
   (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) +  \
   (config_all_accel.has_key('CONFIG_TCG') and                                            \
    config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
+  (config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
   ['arm-cpu-features',
    'numa-test',
    'boot-serial-test',
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 16/21] hw/net: GMAC Rx Implementation
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (14 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 15/21] tests/qtest: Creating qtest for GMAC Module Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 17/21] hw/net: GMAC Tx Implementation Peter Maydell
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Nabih Estefan Diaz <nabihestefan@google.com>

- Implementation of Receive function for packets
- Implementation for reading and writing from and to descriptors in
  memory for Rx

When RX starts, we need to flush the queued packets so that they
can be received by the GMAC device. Without this it won't work
with TAP NIC device.

When RX descriptor list is full, it returns a DMA_STATUS for software
to handle it. But there's no way to indicate the software has
handled all RX descriptors and the whole pipeline stalls.

We do something similar to NPCM7XX EMC to handle this case.

1. Return packet size when RX descriptor is full, effectively
dropping these packets in such a case.
2. When software clears RX descriptor full bit, continue receiving
further packets by flushing QEMU packet queue.

Added relevant trace-events

Change-Id: I132aa254a94cda1a586aba2ea33bbfc74ecdb831
Signed-off-by: Hao Wu <wuhaotsh@google.com>
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-9-nabihestefan@google.com
[PMM: moved a couple of functions into the following patch]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/net/npcm_gmac.c  | 276 +++++++++++++++++++++++++++++++++++++++++++-
 hw/net/trace-events |   5 +
 2 files changed, 279 insertions(+), 2 deletions(-)

diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c
index 44c4ffaff42..8dfd370f54c 100644
--- a/hw/net/npcm_gmac.c
+++ b/hw/net/npcm_gmac.c
@@ -24,6 +24,10 @@
 #include "hw/net/mii.h"
 #include "hw/net/npcm_gmac.h"
 #include "migration/vmstate.h"
+#include "net/checksum.h"
+#include "net/eth.h"
+#include "net/net.h"
+#include "qemu/cutils.h"
 #include "qemu/log.h"
 #include "qemu/units.h"
 #include "sysemu/dma.h"
@@ -146,6 +150,17 @@ static void gmac_phy_set_link(NPCMGMACState *gmac, bool active)
 
 static bool gmac_can_receive(NetClientState *nc)
 {
+    NPCMGMACState *gmac = NPCM_GMAC(qemu_get_nic_opaque(nc));
+
+    /* If GMAC receive is disabled. */
+    if (!(gmac->regs[R_NPCM_GMAC_MAC_CONFIG] & NPCM_GMAC_MAC_CONFIG_RX_EN)) {
+        return false;
+    }
+
+    /* If GMAC DMA RX is stopped. */
+    if (!(gmac->regs[R_NPCM_DMA_CONTROL] & NPCM_DMA_CONTROL_START_STOP_RX)) {
+        return false;
+    }
     return true;
 }
 
@@ -189,10 +204,256 @@ static void gmac_update_irq(NPCMGMACState *gmac)
     qemu_set_irq(gmac->irq, level);
 }
 
+static int gmac_read_rx_desc(dma_addr_t addr, struct NPCMGMACRxDesc *desc)
+{
+    if (dma_memory_read(&address_space_memory, addr, desc,
+                        sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
+                      HWADDR_PRIx "\n", __func__, addr);
+        return -1;
+    }
+    desc->rdes0 = le32_to_cpu(desc->rdes0);
+    desc->rdes1 = le32_to_cpu(desc->rdes1);
+    desc->rdes2 = le32_to_cpu(desc->rdes2);
+    desc->rdes3 = le32_to_cpu(desc->rdes3);
+    return 0;
+}
+
+static int gmac_write_rx_desc(dma_addr_t addr, struct NPCMGMACRxDesc *desc)
+{
+    struct NPCMGMACRxDesc le_desc;
+    le_desc.rdes0 = cpu_to_le32(desc->rdes0);
+    le_desc.rdes1 = cpu_to_le32(desc->rdes1);
+    le_desc.rdes2 = cpu_to_le32(desc->rdes2);
+    le_desc.rdes3 = cpu_to_le32(desc->rdes3);
+    if (dma_memory_write(&address_space_memory, addr, &le_desc,
+                        sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
+                      HWADDR_PRIx "\n", __func__, addr);
+        return -1;
+    }
+    return 0;
+}
+
+static int gmac_rx_transfer_frame_to_buffer(uint32_t rx_buf_len,
+                                            uint32_t *left_frame,
+                                            uint32_t rx_buf_addr,
+                                            bool *eof_transferred,
+                                            const uint8_t **frame_ptr,
+                                            uint16_t *transferred)
+{
+    uint32_t to_transfer;
+    /*
+     * Check that buffer is bigger than the frame being transfered
+     * If bigger then transfer only whats left of frame
+     * Else, fill frame with all the content possible
+     */
+    if (rx_buf_len >= *left_frame) {
+        to_transfer = *left_frame;
+        *eof_transferred = true;
+    } else {
+        to_transfer = rx_buf_len;
+    }
+
+    /* write frame part to memory */
+    if (dma_memory_write(&address_space_memory, (uint64_t) rx_buf_addr,
+                         *frame_ptr, to_transfer, MEMTXATTRS_UNSPECIFIED)) {
+        return -1;
+    }
+
+    /* update frame pointer and size of whats left of frame */
+    *frame_ptr += to_transfer;
+    *left_frame -= to_transfer;
+    *transferred += to_transfer;
+
+    return 0;
+}
+
+static void gmac_dma_set_state(NPCMGMACState *gmac, int shift, uint32_t state)
+{
+    gmac->regs[R_NPCM_DMA_STATUS] = deposit32(gmac->regs[R_NPCM_DMA_STATUS],
+        shift, 3, state);
+}
+
 static ssize_t gmac_receive(NetClientState *nc, const uint8_t *buf, size_t len)
 {
-    /* Placeholder. Function will be filled in following patches */
-    return 0;
+    /*
+     * Comments have steps that relate to the
+     * receiving process steps in pg 386
+     */
+    NPCMGMACState *gmac = NPCM_GMAC(qemu_get_nic_opaque(nc));
+    uint32_t left_frame = len;
+    const uint8_t *frame_ptr = buf;
+    uint32_t desc_addr;
+    uint32_t rx_buf_len, rx_buf_addr;
+    struct NPCMGMACRxDesc rx_desc;
+    uint16_t transferred = 0;
+    bool eof_transferred = false;
+
+    trace_npcm_gmac_packet_receive(DEVICE(gmac)->canonical_path, len);
+    if (!gmac_can_receive(nc)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "GMAC Currently is not able for Rx");
+        return -1;
+    }
+    if (!gmac->regs[R_NPCM_DMA_HOST_RX_DESC]) {
+        gmac->regs[R_NPCM_DMA_HOST_RX_DESC] =
+            NPCM_DMA_HOST_RX_DESC_MASK(gmac->regs[R_NPCM_DMA_RX_BASE_ADDR]);
+    }
+    desc_addr = NPCM_DMA_HOST_RX_DESC_MASK(gmac->regs[R_NPCM_DMA_HOST_RX_DESC]);
+
+    /* step 1 */
+    gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+        NPCM_DMA_STATUS_RX_RUNNING_FETCHING_STATE);
+    trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path, desc_addr);
+    if (gmac_read_rx_desc(desc_addr, &rx_desc)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "RX Descriptor @ 0x%x cant be read\n",
+                      desc_addr);
+        gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+            NPCM_DMA_STATUS_RX_SUSPENDED_STATE);
+        return -1;
+    }
+
+    /* step 2 */
+    if (!(rx_desc.rdes0 & RX_DESC_RDES0_OWN)) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "RX Descriptor @ 0x%x is owned by software\n",
+                      desc_addr);
+        gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RU;
+        gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RI;
+        gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+            NPCM_DMA_STATUS_RX_SUSPENDED_STATE);
+        gmac_update_irq(gmac);
+        return len;
+    }
+    /* step 3 */
+    /*
+     * TODO --
+     * Implement all frame filtering and processing (with its own interrupts)
+     */
+    trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
+                                    rx_desc.rdes0, rx_desc.rdes1, rx_desc.rdes2,
+                                    rx_desc.rdes3);
+    /* Clear rdes0 for the incoming descriptor and set FS in first descriptor.*/
+    rx_desc.rdes0 = RX_DESC_RDES0_FIRST_DESC_MASK;
+
+    gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+        NPCM_DMA_STATUS_RX_RUNNING_TRANSFERRING_STATE);
+
+    /* Pad the frame with FCS as the kernel driver will strip it away. */
+    left_frame += ETH_FCS_LEN;
+
+    /* repeat while we still have frame to transfer to memory */
+    while (!eof_transferred) {
+        /* Return descriptor no matter what happens */
+        rx_desc.rdes0 &= ~RX_DESC_RDES0_OWN;
+        /* Set the frame to be an IPv4/IPv6 frame. */
+        rx_desc.rdes0 |= RX_DESC_RDES0_FRM_TYPE_MASK;
+
+        /* step 4 */
+        rx_buf_len = RX_DESC_RDES1_BFFR1_SZ_MASK(rx_desc.rdes1);
+        rx_buf_addr = rx_desc.rdes2;
+        gmac->regs[R_NPCM_DMA_CUR_RX_BUF_ADDR] = rx_buf_addr;
+        gmac_rx_transfer_frame_to_buffer(rx_buf_len, &left_frame, rx_buf_addr,
+                                         &eof_transferred, &frame_ptr,
+                                         &transferred);
+
+        trace_npcm_gmac_packet_receiving_buffer(DEVICE(gmac)->canonical_path,
+                                                rx_buf_len, rx_buf_addr);
+        /* if we still have frame left and the second buffer is not chained */
+         if (!(rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) && \
+              !eof_transferred) {
+            /* repeat process from above on buffer 2 */
+            rx_buf_len = RX_DESC_RDES1_BFFR2_SZ_MASK(rx_desc.rdes1);
+            rx_buf_addr = rx_desc.rdes3;
+            gmac->regs[R_NPCM_DMA_CUR_RX_BUF_ADDR] = rx_buf_addr;
+            gmac_rx_transfer_frame_to_buffer(rx_buf_len, &left_frame,
+                                             rx_buf_addr, &eof_transferred,
+                                             &frame_ptr, &transferred);
+            trace_npcm_gmac_packet_receiving_buffer( \
+                                                DEVICE(gmac)->canonical_path,
+                                                rx_buf_len, rx_buf_addr);
+        }
+        /* update address for descriptor */
+        gmac->regs[R_NPCM_DMA_HOST_RX_DESC] = rx_buf_addr;
+        /* Return descriptor */
+        rx_desc.rdes0 &= ~RX_DESC_RDES0_OWN;
+        /* Update frame length transferred */
+        rx_desc.rdes0 |= ((uint32_t)transferred)
+            << RX_DESC_RDES0_FRAME_LEN_SHIFT;
+        trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
+                                        rx_desc.rdes0, rx_desc.rdes1,
+                                        rx_desc.rdes2, rx_desc.rdes3);
+
+        /* step 5 */
+        gmac_write_rx_desc(desc_addr, &rx_desc);
+        trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path,
+                                        &rx_desc, rx_desc.rdes0,
+                                        rx_desc.rdes1, rx_desc.rdes2,
+                                        rx_desc.rdes3);
+        /* read new descriptor into rx_desc if needed*/
+        if (!eof_transferred) {
+            /* Get next descriptor address (chained or sequential) */
+            if (rx_desc.rdes1 & RX_DESC_RDES1_RC_END_RING_MASK) {
+                desc_addr = gmac->regs[R_NPCM_DMA_RX_BASE_ADDR];
+            } else if (rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) {
+                desc_addr = rx_desc.rdes3;
+            } else {
+                desc_addr += sizeof(rx_desc);
+            }
+            trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path,
+                                             desc_addr);
+            if (gmac_read_rx_desc(desc_addr, &rx_desc)) {
+                qemu_log_mask(LOG_GUEST_ERROR,
+                              "RX Descriptor @ 0x%x cant be read\n",
+                              desc_addr);
+                gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RU;
+                gmac_update_irq(gmac);
+                return len;
+            }
+
+            /* step 6 */
+            if (!(rx_desc.rdes0 & RX_DESC_RDES0_OWN)) {
+                if (!(gmac->regs[R_NPCM_DMA_CONTROL] & \
+                     NPCM_DMA_CONTROL_FLUSH_MASK)) {
+                    rx_desc.rdes0 |= RX_DESC_RDES0_DESC_ERR_MASK;
+                }
+                eof_transferred = true;
+            }
+            /* Clear rdes0 for the incoming descriptor */
+            rx_desc.rdes0 = 0;
+        }
+    }
+    gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+        NPCM_DMA_STATUS_RX_RUNNING_CLOSING_STATE);
+
+    rx_desc.rdes0 |= RX_DESC_RDES0_LAST_DESC_MASK;
+    if (!(rx_desc.rdes1 & RX_DESC_RDES1_DIS_INTR_COMP_MASK)) {
+        gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_RI;
+        gmac_update_irq(gmac);
+    }
+    trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &rx_desc,
+                                    rx_desc.rdes0, rx_desc.rdes1, rx_desc.rdes2,
+                                    rx_desc.rdes3);
+
+    /* step 8 */
+    gmac->regs[R_NPCM_DMA_CONTROL] |= NPCM_DMA_CONTROL_FLUSH_MASK;
+
+    /* step 9 */
+    trace_npcm_gmac_packet_received(DEVICE(gmac)->canonical_path, left_frame);
+    gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+        NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
+    gmac_write_rx_desc(desc_addr, &rx_desc);
+
+    /* Get next descriptor address (chained or sequential) */
+    if (rx_desc.rdes1 & RX_DESC_RDES1_RC_END_RING_MASK) {
+        desc_addr = gmac->regs[R_NPCM_DMA_RX_BASE_ADDR];
+    } else if (rx_desc.rdes1 & RX_DESC_RDES1_SEC_ADDR_CHND_MASK) {
+        desc_addr = rx_desc.rdes3;
+    } else {
+        desc_addr += sizeof(rx_desc);
+    }
+    gmac->regs[R_NPCM_DMA_HOST_RX_DESC] = desc_addr;
+    return len;
 }
 
 static void gmac_cleanup(NetClientState *nc)
@@ -303,6 +564,7 @@ static void npcm_gmac_write(void *opaque, hwaddr offset,
         break;
 
     case A_NPCM_GMAC_MAC_CONFIG:
+        gmac->regs[offset / sizeof(uint32_t)] = v;
         break;
 
     case A_NPCM_GMAC_MII_ADDR:
@@ -344,6 +606,8 @@ static void npcm_gmac_write(void *opaque, hwaddr offset,
 
     case A_NPCM_DMA_RCV_POLL_DEMAND:
         /* We dont actually care about the value */
+        gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+            NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
         break;
 
     case A_NPCM_DMA_STATUS:
@@ -354,6 +618,14 @@ static void npcm_gmac_write(void *opaque, hwaddr offset,
                            HWADDR_PRIx ", value: 0x%04" PRIx64 "\n",
                            DEVICE(gmac)->canonical_path, offset, v);
         }
+        /* for W1C bits, implement W1C */
+        gmac->regs[offset / sizeof(uint32_t)] &= ~NPCM_DMA_STATUS_W1C_MASK(v);
+        if (v & NPCM_DMA_STATUS_RU) {
+            /* Clearing RU bit indicates descriptor is owned by DMA again. */
+            gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+                NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
+            qemu_flush_queued_packets(qemu_get_queue(gmac->nic));
+        }
         break;
 
     default:
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 56057de47f3..f91b1a4a3de 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -474,6 +474,11 @@ npcm_gmac_mdio_access(const char *name, uint8_t is_write, uint8_t pa, uint8_t gr
 npcm_gmac_reset(const char *name, uint16_t value) "%s: phy_regs[0][1]: 0x%04" PRIx16
 npcm_gmac_set_link(bool active) "Set link: active=%u"
 npcm_gmac_update_irq(const char *name, uint32_t status, uint32_t intr_en, int level) "%s: Status Reg: 0x%04" PRIX32 " Interrupt Enable Reg: 0x%04" PRIX32 " IRQ Set: %d"
+npcm_gmac_packet_desc_read(const char* name, uint32_t desc_addr) "%s: attempting to read descriptor @0x%04" PRIX32
+npcm_gmac_packet_receive(const char* name, uint32_t len) "%s: RX packet length: 0x%04" PRIX32
+npcm_gmac_packet_receiving_buffer(const char* name, uint32_t buf_len, uint32_t rx_buf_addr) "%s: Receiving into Buffer size: 0x%04" PRIX32 " at address 0x%04" PRIX32
+npcm_gmac_packet_received(const char* name, uint32_t len) "%s: Reception finished, packet left: 0x%04" PRIX32
+npcm_gmac_debug_desc_data(const char* name, void* addr, uint32_t des0, uint32_t des1, uint32_t des2, uint32_t des3)"%s: Address: %p Descriptor 0: 0x%04" PRIX32 " Descriptor 1: 0x%04" PRIX32 "Descriptor 2: 0x%04" PRIX32 " Descriptor 3: 0x%04" PRIX32
 
 # npcm_pcs.c
 npcm_pcs_reg_read(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 17/21] hw/net: GMAC Tx Implementation
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (15 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 16/21] hw/net: GMAC Rx Implementation Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 18/21] tests/qtest: Adding PCS Module test to GMAC Qtest Peter Maydell
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Nabih Estefan Diaz <nabihestefan@google.com>

- Implementation of Transmit function for packets
- Implementation for reading and writing from and to descriptors in
  memory for Tx

NOTE: This function implements the steps detailed in the datasheet for
transmitting messages from the GMAC.

Added relevant trace-events

Change-Id: Icf14f9fcc6cc7808a41acd872bca67c9832087e6
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-10-nabihestefan@google.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/net/npcm_gmac.c  | 203 ++++++++++++++++++++++++++++++++++++++++++++
 hw/net/trace-events |   2 +
 2 files changed, 205 insertions(+)

diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c
index 8dfd370f54c..c107e835b18 100644
--- a/hw/net/npcm_gmac.c
+++ b/hw/net/npcm_gmac.c
@@ -235,6 +235,37 @@ static int gmac_write_rx_desc(dma_addr_t addr, struct NPCMGMACRxDesc *desc)
     return 0;
 }
 
+static int gmac_read_tx_desc(dma_addr_t addr, struct NPCMGMACTxDesc *desc)
+{
+    if (dma_memory_read(&address_space_memory, addr, desc,
+                        sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
+                      HWADDR_PRIx "\n", __func__, addr);
+        return -1;
+    }
+    desc->tdes0 = le32_to_cpu(desc->tdes0);
+    desc->tdes1 = le32_to_cpu(desc->tdes1);
+    desc->tdes2 = le32_to_cpu(desc->tdes2);
+    desc->tdes3 = le32_to_cpu(desc->tdes3);
+    return 0;
+}
+
+static int gmac_write_tx_desc(dma_addr_t addr, struct NPCMGMACTxDesc *desc)
+{
+    struct NPCMGMACTxDesc le_desc;
+    le_desc.tdes0 = cpu_to_le32(desc->tdes0);
+    le_desc.tdes1 = cpu_to_le32(desc->tdes1);
+    le_desc.tdes2 = cpu_to_le32(desc->tdes2);
+    le_desc.tdes3 = cpu_to_le32(desc->tdes3);
+    if (dma_memory_write(&address_space_memory, addr, &le_desc,
+                        sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
+                      HWADDR_PRIx "\n", __func__, addr);
+        return -1;
+    }
+    return 0;
+}
+
 static int gmac_rx_transfer_frame_to_buffer(uint32_t rx_buf_len,
                                             uint32_t *left_frame,
                                             uint32_t rx_buf_addr,
@@ -456,6 +487,155 @@ static ssize_t gmac_receive(NetClientState *nc, const uint8_t *buf, size_t len)
     return len;
 }
 
+static int gmac_tx_get_csum(uint32_t tdes1)
+{
+    uint32_t mask = TX_DESC_TDES1_CHKSM_INS_CTRL_MASK(tdes1);
+    int csum = 0;
+
+    if (likely(mask > 0)) {
+        csum |= CSUM_IP;
+    }
+    if (likely(mask > 1)) {
+        csum |= CSUM_TCP | CSUM_UDP;
+    }
+
+    return csum;
+}
+
+static void gmac_try_send_next_packet(NPCMGMACState *gmac)
+{
+    /*
+     * Comments about steps refer to steps for
+     * transmitting in page 384 of datasheet
+     */
+    uint16_t tx_buffer_size = 2048;
+    g_autofree uint8_t *tx_send_buffer = g_malloc(tx_buffer_size);
+    uint32_t desc_addr;
+    struct NPCMGMACTxDesc tx_desc;
+    uint32_t tx_buf_addr, tx_buf_len;
+    uint16_t length = 0;
+    uint8_t *buf = tx_send_buffer;
+    uint32_t prev_buf_size = 0;
+    int csum = 0;
+
+    /* steps 1&2 */
+    if (!gmac->regs[R_NPCM_DMA_HOST_TX_DESC]) {
+        gmac->regs[R_NPCM_DMA_HOST_TX_DESC] =
+            NPCM_DMA_HOST_TX_DESC_MASK(gmac->regs[R_NPCM_DMA_TX_BASE_ADDR]);
+    }
+    desc_addr = gmac->regs[R_NPCM_DMA_HOST_TX_DESC];
+
+    while (true) {
+        gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+            NPCM_DMA_STATUS_TX_RUNNING_FETCHING_STATE);
+        if (gmac_read_tx_desc(desc_addr, &tx_desc)) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "TX Descriptor @ 0x%x can't be read\n",
+                          desc_addr);
+            return;
+        }
+        /* step 3 */
+
+        trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path,
+            desc_addr);
+        trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &tx_desc,
+            tx_desc.tdes0, tx_desc.tdes1, tx_desc.tdes2, tx_desc.tdes3);
+
+        /* 1 = DMA Owned, 0 = Software Owned */
+        if (!(tx_desc.tdes0 & TX_DESC_TDES0_OWN)) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "TX Descriptor @ 0x%x is owned by software\n",
+                          desc_addr);
+            gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TU;
+            gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+                NPCM_DMA_STATUS_TX_SUSPENDED_STATE);
+            gmac_update_irq(gmac);
+            return;
+        }
+
+        gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+            NPCM_DMA_STATUS_TX_RUNNING_READ_STATE);
+        /* Give the descriptor back regardless of what happens. */
+        tx_desc.tdes0 &= ~TX_DESC_TDES0_OWN;
+
+        if (tx_desc.tdes1 & TX_DESC_TDES1_FIRST_SEG_MASK) {
+            csum = gmac_tx_get_csum(tx_desc.tdes1);
+        }
+
+        /* step 4 */
+        tx_buf_addr = tx_desc.tdes2;
+        gmac->regs[R_NPCM_DMA_CUR_TX_BUF_ADDR] = tx_buf_addr;
+        tx_buf_len = TX_DESC_TDES1_BFFR1_SZ_MASK(tx_desc.tdes1);
+        buf = &tx_send_buffer[prev_buf_size];
+
+        if ((prev_buf_size + tx_buf_len) > sizeof(buf)) {
+            tx_buffer_size = prev_buf_size + tx_buf_len;
+            tx_send_buffer = g_realloc(tx_send_buffer, tx_buffer_size);
+            buf = &tx_send_buffer[prev_buf_size];
+        }
+
+        /* step 5 */
+        if (dma_memory_read(&address_space_memory, tx_buf_addr, buf,
+                            tx_buf_len, MEMTXATTRS_UNSPECIFIED)) {
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n",
+                        __func__, tx_buf_addr);
+            return;
+        }
+        length += tx_buf_len;
+        prev_buf_size += tx_buf_len;
+
+        /* If not chained we'll have a second buffer. */
+        if (!(tx_desc.tdes1 & TX_DESC_TDES1_SEC_ADDR_CHND_MASK)) {
+            tx_buf_addr = tx_desc.tdes3;
+            gmac->regs[R_NPCM_DMA_CUR_TX_BUF_ADDR] = tx_buf_addr;
+            tx_buf_len = TX_DESC_TDES1_BFFR2_SZ_MASK(tx_desc.tdes1);
+            buf = &tx_send_buffer[prev_buf_size];
+
+            if ((prev_buf_size + tx_buf_len) > sizeof(buf)) {
+                tx_buffer_size = prev_buf_size + tx_buf_len;
+                tx_send_buffer = g_realloc(tx_send_buffer, tx_buffer_size);
+                buf = &tx_send_buffer[prev_buf_size];
+            }
+
+            if (dma_memory_read(&address_space_memory, tx_buf_addr, buf,
+                                tx_buf_len, MEMTXATTRS_UNSPECIFIED)) {
+                qemu_log_mask(LOG_GUEST_ERROR,
+                              "%s: Failed to read packet @ 0x%x\n",
+                              __func__, tx_buf_addr);
+                return;
+            }
+            length += tx_buf_len;
+            prev_buf_size += tx_buf_len;
+        }
+        if (tx_desc.tdes1 & TX_DESC_TDES1_LAST_SEG_MASK) {
+            net_checksum_calculate(tx_send_buffer, length, csum);
+            qemu_send_packet(qemu_get_queue(gmac->nic), tx_send_buffer, length);
+            trace_npcm_gmac_packet_sent(DEVICE(gmac)->canonical_path, length);
+            buf = tx_send_buffer;
+            length = 0;
+        }
+
+        /* step 6 */
+        gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+            NPCM_DMA_STATUS_TX_RUNNING_CLOSING_STATE);
+        gmac_write_tx_desc(desc_addr, &tx_desc);
+        if (tx_desc.tdes1 & TX_DESC_TDES1_TX_END_RING_MASK) {
+            desc_addr = gmac->regs[R_NPCM_DMA_TX_BASE_ADDR];
+        } else if (tx_desc.tdes1 & TX_DESC_TDES1_SEC_ADDR_CHND_MASK) {
+            desc_addr = tx_desc.tdes3;
+        } else {
+            desc_addr += sizeof(tx_desc);
+        }
+        gmac->regs[R_NPCM_DMA_HOST_TX_DESC] = desc_addr;
+
+        /* step 7 */
+        if (tx_desc.tdes1 & TX_DESC_TDES1_INTERR_COMP_MASK) {
+            gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TI;
+            gmac_update_irq(gmac);
+        }
+    }
+}
+
 static void gmac_cleanup(NetClientState *nc)
 {
     /* Nothing to do yet. */
@@ -610,6 +790,29 @@ static void npcm_gmac_write(void *opaque, hwaddr offset,
             NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
         break;
 
+    case A_NPCM_DMA_XMT_POLL_DEMAND:
+        /* We dont actually care about the value */
+        gmac_try_send_next_packet(gmac);
+        break;
+
+    case A_NPCM_DMA_CONTROL:
+        gmac->regs[offset / sizeof(uint32_t)] = v;
+        if (v & NPCM_DMA_CONTROL_START_STOP_TX) {
+            gmac_try_send_next_packet(gmac);
+        } else {
+            gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+                NPCM_DMA_STATUS_TX_STOPPED_STATE);
+        }
+        if (v & NPCM_DMA_CONTROL_START_STOP_RX) {
+            gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+                NPCM_DMA_STATUS_RX_RUNNING_WAITING_STATE);
+            qemu_flush_queued_packets(qemu_get_queue(gmac->nic));
+        } else {
+            gmac_dma_set_state(gmac, NPCM_DMA_STATUS_RX_PROCESS_STATE_SHIFT,
+                NPCM_DMA_STATUS_RX_STOPPED_STATE);
+        }
+        break;
+
     case A_NPCM_DMA_STATUS:
         /* Check that RO bits are not written to */
         if (NPCM_DMA_STATUS_RO_MASK(v)) {
diff --git a/hw/net/trace-events b/hw/net/trace-events
index f91b1a4a3de..78efa2ec2cc 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -478,7 +478,9 @@ npcm_gmac_packet_desc_read(const char* name, uint32_t desc_addr) "%s: attempting
 npcm_gmac_packet_receive(const char* name, uint32_t len) "%s: RX packet length: 0x%04" PRIX32
 npcm_gmac_packet_receiving_buffer(const char* name, uint32_t buf_len, uint32_t rx_buf_addr) "%s: Receiving into Buffer size: 0x%04" PRIX32 " at address 0x%04" PRIX32
 npcm_gmac_packet_received(const char* name, uint32_t len) "%s: Reception finished, packet left: 0x%04" PRIX32
+npcm_gmac_packet_sent(const char* name, uint16_t len) "%s: TX packet sent!, length: 0x%04" PRIX16
 npcm_gmac_debug_desc_data(const char* name, void* addr, uint32_t des0, uint32_t des1, uint32_t des2, uint32_t des3)"%s: Address: %p Descriptor 0: 0x%04" PRIX32 " Descriptor 1: 0x%04" PRIX32 "Descriptor 2: 0x%04" PRIX32 " Descriptor 3: 0x%04" PRIX32
+npcm_gmac_packet_tx_desc_data(const char* name, uint32_t tdes0, uint32_t tdes1) "%s: Tdes0: 0x%04" PRIX32 " Tdes1: 0x%04" PRIX32
 
 # npcm_pcs.c
 npcm_pcs_reg_read(const char *name, uint16_t indirect_access_baes, uint64_t offset, uint16_t value) "%s: IND: 0x%02" PRIx16 " offset: 0x%04" PRIx64 " value: 0x%04" PRIx16
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 18/21] tests/qtest: Adding PCS Module test to GMAC Qtest
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (16 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 17/21] hw/net: GMAC Tx Implementation Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 19/21] hw/timer: fix systick trace message Peter Maydell
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Nabih Estefan Diaz <nabihestefan@google.com>

 - Add PCS Register check to npcm_gmac-test

Change-Id: I34821beb5e0b1e89e2be576ab58eabe41545af12
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
Message-id: 20240110234232.4116804-11-nabihestefan@google.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
 tests/qtest/npcm_gmac-test.c | 132 +++++++++++++++++++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git a/tests/qtest/npcm_gmac-test.c b/tests/qtest/npcm_gmac-test.c
index 130a1599a84..b64515794bd 100644
--- a/tests/qtest/npcm_gmac-test.c
+++ b/tests/qtest/npcm_gmac-test.c
@@ -20,6 +20,10 @@
 /* Name of the GMAC Device */
 #define TYPE_NPCM_GMAC "npcm-gmac"
 
+/* Address of the PCS Module */
+#define PCS_BASE_ADDRESS 0xf0780000
+#define NPCM_PCS_IND_AC_BA 0x1fe
+
 typedef struct GMACModule {
     int irq;
     uint64_t base_addr;
@@ -111,6 +115,62 @@ typedef enum NPCMRegister {
     NPCM_GMAC_PTP_STNSUR = 0x714,
     NPCM_GMAC_PTP_TAR = 0x718,
     NPCM_GMAC_PTP_TTSR = 0x71c,
+
+    /* PCS Registers */
+    NPCM_PCS_SR_CTL_ID1 = 0x3c0008,
+    NPCM_PCS_SR_CTL_ID2 = 0x3c000a,
+    NPCM_PCS_SR_CTL_STS = 0x3c0010,
+
+    NPCM_PCS_SR_MII_CTRL = 0x3e0000,
+    NPCM_PCS_SR_MII_STS = 0x3e0002,
+    NPCM_PCS_SR_MII_DEV_ID1 = 0x3e0004,
+    NPCM_PCS_SR_MII_DEV_ID2 = 0x3e0006,
+    NPCM_PCS_SR_MII_AN_ADV = 0x3e0008,
+    NPCM_PCS_SR_MII_LP_BABL = 0x3e000a,
+    NPCM_PCS_SR_MII_AN_EXPN = 0x3e000c,
+    NPCM_PCS_SR_MII_EXT_STS = 0x3e001e,
+
+    NPCM_PCS_SR_TIM_SYNC_ABL = 0x3e0e10,
+    NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_LWR = 0x3e0e12,
+    NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_UPR = 0x3e0e14,
+    NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_LWR = 0x3e0e16,
+    NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_UPR = 0x3e0e18,
+    NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_LWR = 0x3e0e1a,
+    NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_UPR = 0x3e0e1c,
+    NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_LWR = 0x3e0e1e,
+    NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_UPR = 0x3e0e20,
+
+    NPCM_PCS_VR_MII_MMD_DIG_CTRL1 = 0x3f0000,
+    NPCM_PCS_VR_MII_AN_CTRL = 0x3f0002,
+    NPCM_PCS_VR_MII_AN_INTR_STS = 0x3f0004,
+    NPCM_PCS_VR_MII_TC = 0x3f0006,
+    NPCM_PCS_VR_MII_DBG_CTRL = 0x3f000a,
+    NPCM_PCS_VR_MII_EEE_MCTRL0 = 0x3f000c,
+    NPCM_PCS_VR_MII_EEE_TXTIMER = 0x3f0010,
+    NPCM_PCS_VR_MII_EEE_RXTIMER = 0x3f0012,
+    NPCM_PCS_VR_MII_LINK_TIMER_CTRL = 0x3f0014,
+    NPCM_PCS_VR_MII_EEE_MCTRL1 = 0x3f0016,
+    NPCM_PCS_VR_MII_DIG_STS = 0x3f0020,
+    NPCM_PCS_VR_MII_ICG_ERRCNT1 = 0x3f0022,
+    NPCM_PCS_VR_MII_MISC_STS = 0x3f0030,
+    NPCM_PCS_VR_MII_RX_LSTS = 0x3f0040,
+    NPCM_PCS_VR_MII_MP_TX_BSTCTRL0 = 0x3f0070,
+    NPCM_PCS_VR_MII_MP_TX_LVLCTRL0 = 0x3f0074,
+    NPCM_PCS_VR_MII_MP_TX_GENCTRL0 = 0x3f007a,
+    NPCM_PCS_VR_MII_MP_TX_GENCTRL1 = 0x3f007c,
+    NPCM_PCS_VR_MII_MP_TX_STS = 0x3f0090,
+    NPCM_PCS_VR_MII_MP_RX_GENCTRL0 = 0x3f00b0,
+    NPCM_PCS_VR_MII_MP_RX_GENCTRL1 = 0x3f00b2,
+    NPCM_PCS_VR_MII_MP_RX_LOS_CTRL0 = 0x3f00ba,
+    NPCM_PCS_VR_MII_MP_MPLL_CTRL0 = 0x3f00f0,
+    NPCM_PCS_VR_MII_MP_MPLL_CTRL1 = 0x3f00f2,
+    NPCM_PCS_VR_MII_MP_MPLL_STS = 0x3f0110,
+    NPCM_PCS_VR_MII_MP_MISC_CTRL2 = 0x3f0126,
+    NPCM_PCS_VR_MII_MP_LVL_CTRL = 0x3f0130,
+    NPCM_PCS_VR_MII_MP_MISC_CTRL0 = 0x3f0132,
+    NPCM_PCS_VR_MII_MP_MISC_CTRL1 = 0x3f0134,
+    NPCM_PCS_VR_MII_DIG_CTRL2 = 0x3f01c2,
+    NPCM_PCS_VR_MII_DIG_ERRCNT_SEL = 0x3f01c4,
 } NPCMRegister;
 
 static uint32_t gmac_read(QTestState *qts, const GMACModule *mod,
@@ -119,6 +179,15 @@ static uint32_t gmac_read(QTestState *qts, const GMACModule *mod,
     return qtest_readl(qts, mod->base_addr + regno);
 }
 
+static uint16_t pcs_read(QTestState *qts, const GMACModule *mod,
+                          NPCMRegister regno)
+{
+    uint32_t write_value = (regno & 0x3ffe00) >> 9;
+    qtest_writel(qts, PCS_BASE_ADDRESS + NPCM_PCS_IND_AC_BA, write_value);
+    uint32_t read_offset = regno & 0x1ff;
+    return qtest_readl(qts, PCS_BASE_ADDRESS + read_offset);
+}
+
 /* Check that GMAC registers are reset to default value */
 static void test_init(gconstpointer test_data)
 {
@@ -131,6 +200,11 @@ static void test_init(gconstpointer test_data)
         g_assert_cmphex(gmac_read(qts, mod, (regno)), ==, (value)); \
     } while (0)
 
+#define CHECK_REG_PCS(regno, value) \
+    do { \
+        g_assert_cmphex(pcs_read(qts, mod, (regno)), ==, (value)); \
+    } while (0)
+
     CHECK_REG32(NPCM_DMA_BUS_MODE, 0x00020100);
     CHECK_REG32(NPCM_DMA_XMT_POLL_DEMAND, 0);
     CHECK_REG32(NPCM_DMA_RCV_POLL_DEMAND, 0);
@@ -180,6 +254,64 @@ static void test_init(gconstpointer test_data)
     CHECK_REG32(NPCM_GMAC_PTP_TAR, 0);
     CHECK_REG32(NPCM_GMAC_PTP_TTSR, 0);
 
+    /* TODO Add registers PCS */
+    if (mod->base_addr == 0xf0802000) {
+        CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID1, 0x699e);
+        CHECK_REG_PCS(NPCM_PCS_SR_CTL_ID2, 0);
+        CHECK_REG_PCS(NPCM_PCS_SR_CTL_STS, 0x8000);
+
+        CHECK_REG_PCS(NPCM_PCS_SR_MII_CTRL, 0x1140);
+        CHECK_REG_PCS(NPCM_PCS_SR_MII_STS, 0x0109);
+        CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID1, 0x699e);
+        CHECK_REG_PCS(NPCM_PCS_SR_MII_DEV_ID2, 0x0ced0);
+        CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_ADV, 0x0020);
+        CHECK_REG_PCS(NPCM_PCS_SR_MII_LP_BABL, 0);
+        CHECK_REG_PCS(NPCM_PCS_SR_MII_AN_EXPN, 0);
+        CHECK_REG_PCS(NPCM_PCS_SR_MII_EXT_STS, 0xc000);
+
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_ABL, 0x0003);
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_LWR, 0x0038);
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MAX_DLY_UPR, 0);
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_LWR, 0x0038);
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_TX_MIN_DLY_UPR, 0);
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_LWR, 0x0058);
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MAX_DLY_UPR, 0);
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_LWR, 0x0048);
+        CHECK_REG_PCS(NPCM_PCS_SR_TIM_SYNC_RX_MIN_DLY_UPR, 0);
+
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MMD_DIG_CTRL1, 0x2400);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_CTRL, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_AN_INTR_STS, 0x000a);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_TC, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_DBG_CTRL, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL0, 0x899c);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_TXTIMER, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_RXTIMER, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_LINK_TIMER_CTRL, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_EEE_MCTRL1, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_STS, 0x0010);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_ICG_ERRCNT1, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MISC_STS, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_RX_LSTS, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_BSTCTRL0, 0x00a);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_LVLCTRL0, 0x007f);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_GENCTRL0, 0x0001);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_GENCTRL1, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_TX_STS, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_GENCTRL0, 0x0100);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_GENCTRL1, 0x1100);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_RX_LOS_CTRL0, 0x000e);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_CTRL0, 0x0100);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_CTRL1, 0x0032);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MPLL_STS, 0x0001);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL2, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_LVL_CTRL, 0x0019);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL0, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_MP_MISC_CTRL1, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_CTRL2, 0);
+        CHECK_REG_PCS(NPCM_PCS_VR_MII_DIG_ERRCNT_SEL, 0);
+    }
+
     qtest_quit(qts);
 }
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 19/21] hw/timer: fix systick trace message
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (17 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 18/21] tests/qtest: Adding PCS Module test to GMAC Qtest Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 20/21] hw/arm/virt: Consolidate valid CPU types Peter Maydell
  2024-01-16 15:12 ` [PULL 21/21] load_elf: fix iterator's type for elf file processing Peter Maydell
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Samuel Tardieu <sam@rfc1149.net>

Signed-off-by: Samuel Tardieu <sam@rfc1149.net>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-id: 20240109184508.3189599-1-sam@rfc1149.net
Fixes: ff68dacbc786 ("armv7m: Split systick out from NVIC")
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/timer/trace-events | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 3eccef83858..8145e18e3da 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -35,7 +35,7 @@ aspeed_timer_read(uint64_t offset, unsigned size, uint64_t value) "From 0x%" PRI
 
 # armv7m_systick.c
 systick_reload(void) "systick reload"
-systick_timer_tick(void) "systick reload"
+systick_timer_tick(void) "systick tick"
 systick_read(uint64_t addr, uint32_t value, unsigned size) "systick read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
 systick_write(uint64_t addr, uint32_t value, unsigned size) "systick write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
 
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 20/21] hw/arm/virt: Consolidate valid CPU types
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (18 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 19/21] hw/timer: fix systick trace message Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  2024-01-16 15:12 ` [PULL 21/21] load_elf: fix iterator's type for elf file processing Peter Maydell
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Gavin Shan <gshan@redhat.com>

It's found that some of the CPU type names in the array of valid
CPU types are invalid because their corresponding classes aren't
registered, as reported by Peter Maydell.

[gshan@gshan build]$ ./qemu-system-arm -machine virt -cpu cortex-a9
qemu-system-arm: Invalid CPU model: cortex-a9
The valid models are: cortex-a7, cortex-a15, (null), (null), (null),
(null), (null), (null), (null), (null), (null), (null), (null), max

Fix it by consolidating the array of valid CPU types. After it's
applied, we have the following output when TCG is enabled.

[gshan@gshan build]$ ./qemu-system-arm -machine virt -cpu cortex-a9
qemu-system-arm: Invalid CPU model: cortex-a9
The valid models are: cortex-a7, cortex-a15, max

[gshan@gshan build]$ ./qemu-system-aarch64 -machine virt -cpu cortex-a9
qemu-system-aarch64: Invalid CPU model: cortex-a9
The valid models are: cortex-a7, cortex-a15, cortex-a35, cortex-a55,
cortex-a72, cortex-a76, cortex-a710, a64fx, neoverse-n1, neoverse-v1,
neoverse-n2, cortex-a53, cortex-a57, max

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2084
Reported-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-id: 20240111051054.83304-1-gshan@redhat.com
Fixes: fa8c617791 ("hw/arm/virt: Check CPU type in machine_run_board_init()")
Signed-off-by: Gavin Shan <gshan@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/virt.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 2793121cb41..5cbc69dff83 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2905,6 +2905,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
 #ifdef CONFIG_TCG
         ARM_CPU_TYPE_NAME("cortex-a7"),
         ARM_CPU_TYPE_NAME("cortex-a15"),
+#ifdef TARGET_AARCH64
         ARM_CPU_TYPE_NAME("cortex-a35"),
         ARM_CPU_TYPE_NAME("cortex-a55"),
         ARM_CPU_TYPE_NAME("cortex-a72"),
@@ -2914,12 +2915,15 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
         ARM_CPU_TYPE_NAME("neoverse-n1"),
         ARM_CPU_TYPE_NAME("neoverse-v1"),
         ARM_CPU_TYPE_NAME("neoverse-n2"),
-#endif
+#endif /* TARGET_AARCH64 */
+#endif /* CONFIG_TCG */
+#ifdef TARGET_AARCH64
         ARM_CPU_TYPE_NAME("cortex-a53"),
         ARM_CPU_TYPE_NAME("cortex-a57"),
 #if defined(CONFIG_KVM) || defined(CONFIG_HVF)
         ARM_CPU_TYPE_NAME("host"),
-#endif
+#endif /* CONFIG_KVM || CONFIG_HVF */
+#endif /* TARGET_AARCH64 */
         ARM_CPU_TYPE_NAME("max"),
         NULL
     };
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PULL 21/21] load_elf: fix iterator's type for elf file processing
  2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
                   ` (19 preceding siblings ...)
  2024-01-16 15:12 ` [PULL 20/21] hw/arm/virt: Consolidate valid CPU types Peter Maydell
@ 2024-01-16 15:12 ` Peter Maydell
  20 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2024-01-16 15:12 UTC (permalink / raw)
  To: qemu-devel

From: Anastasia Belova <abelova@astralinux.ru>

j is used while loading an ELF file to byteswap segments'
data. If data is larger than 2GB an overflow may happen.
So j should be elf_word.

This commit fixes a minor bug: it's unlikely anybody is trying to
load ELF files with 2GB+ segments for wrong-endianness targets,
but if they did, it wouldn't work correctly.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Cc: qemu-stable@nongnu.org
Fixes: 7ef295ea5b ("loader: Add data swap option to load-elf")
Signed-off-by: Anastasia Belova <abelova@astralinux.ru>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 include/hw/elf_ops.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index 0a5c258fe68..9c35d1b9da6 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -500,7 +500,7 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
             }
 
             if (data_swab) {
-                int j;
+                elf_word j;
                 for (j = 0; j < file_size; j += (1 << data_swab)) {
                     uint8_t *dp = data + j;
                     switch (data_swab) {
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2024-04-30 16:48 [PULL 00/21] target-arm queue Peter Maydell
@ 2024-04-30 23:01 ` Richard Henderson
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2024-04-30 23:01 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel

On 4/30/24 09:48, Peter Maydell wrote:
> Here's another arm pullreq; nothing too exciting in here I think.
> 
> thanks
> -- PMM
> 
> The following changes since commit 5fee33d97a7f2e95716417bd164f2f5264acd976:
> 
>    Merge tag 'samuel-thibault' ofhttps://people.debian.org/~sthibault/qemu  into staging (2024-04-29 14:34:25 -0700)
> 
> are available in the Git repository at:
> 
>    https://git.linaro.org/people/pmaydell/qemu-arm.git  tags/pull-target-arm-20240430
> 
> for you to fetch changes up to a0c325c4b05cf7815739d6a84e567b95c8c5be7e:
> 
>    tests/qtest : Add testcase for DM163 (2024-04-30 16:05:08 +0100)
> 
> ----------------------------------------------------------------
> target-arm queue:
>   * hw/core/clock: allow clock_propagate on child clocks
>   * hvf: arm: Remove unused PL1_WRITE_MASK define
>   * target/arm: Restrict translation disabled alignment check to VMSA
>   * docs/system/arm/emulation.rst: Add missing implemented features
>   * target/arm: Enable FEAT_CSV2_3, FEAT_ETS2, FEAT_Spec_FPACC for 'max'
>   * tests/avocado: update sunxi kernel from armbian to 6.6.16
>   * target/arm: Make new CPUs default to 1GHz generic timer
>   * hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields
>   * hw/char/stm32l4x5_usart: Fix memory corruption by adding correct class_size
>   * hw/arm/npcm7xx: Store derivative OTP fuse key in little endian
>   * hw/arm: Add DM163 display to B-L475E-IOT01A board

Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/9.1 as appropriate.


r~



^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 00/21] target-arm queue
@ 2024-04-30 16:48 Peter Maydell
  2024-04-30 23:01 ` Richard Henderson
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2024-04-30 16:48 UTC (permalink / raw)
  To: qemu-devel

Here's another arm pullreq; nothing too exciting in here I think.

thanks
-- PMM

The following changes since commit 5fee33d97a7f2e95716417bd164f2f5264acd976:

  Merge tag 'samuel-thibault' of https://people.debian.org/~sthibault/qemu into staging (2024-04-29 14:34:25 -0700)

are available in the Git repository at:

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

for you to fetch changes up to a0c325c4b05cf7815739d6a84e567b95c8c5be7e:

  tests/qtest : Add testcase for DM163 (2024-04-30 16:05:08 +0100)

----------------------------------------------------------------
target-arm queue:
 * hw/core/clock: allow clock_propagate on child clocks
 * hvf: arm: Remove unused PL1_WRITE_MASK define
 * target/arm: Restrict translation disabled alignment check to VMSA
 * docs/system/arm/emulation.rst: Add missing implemented features
 * target/arm: Enable FEAT_CSV2_3, FEAT_ETS2, FEAT_Spec_FPACC for 'max'
 * tests/avocado: update sunxi kernel from armbian to 6.6.16
 * target/arm: Make new CPUs default to 1GHz generic timer
 * hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields
 * hw/char/stm32l4x5_usart: Fix memory corruption by adding correct class_size
 * hw/arm/npcm7xx: Store derivative OTP fuse key in little endian
 * hw/arm: Add DM163 display to B-L475E-IOT01A board

----------------------------------------------------------------
Alexandra Diupina (1):
      hw/dmax/xlnx_dpdma: fix handling of address_extension descriptor fields

Inès Varhol (5):
      hw/display : Add device DM163
      hw/arm : Pass STM32L4x5 SYSCFG gpios to STM32L4x5 SoC
      hw/arm : Create Bl475eMachineState
      hw/arm : Connect DM163 to B-L475E-IOT01A
      tests/qtest : Add testcase for DM163

Peter Maydell (10):
      docs/system/arm/emulation.rst: Add missing implemented features
      target/arm: Enable FEAT_CSV2_3 for -cpu max
      target/arm: Enable FEAT_ETS2 for -cpu max
      target/arm: Implement ID_AA64MMFR3_EL1
      target/arm: Enable FEAT_Spec_FPACC for -cpu max
      tests/avocado: update sunxi kernel from armbian to 6.6.16
      target/arm: Refactor default generic timer frequency handling
      hw/arm/sbsa-ref: Force CPU generic timer to 62.5MHz
      hw/watchdog/sbsa_gwdt: Make watchdog timer frequency a QOM property
      target/arm: Default to 1GHz cntfrq for 'max' and new CPUs

Philippe Mathieu-Daudé (1):
      hw/arm/npcm7xx: Store derivative OTP fuse key in little endian

Raphael Poggi (1):
      hw/core/clock: allow clock_propagate on child clocks

Richard Henderson (1):
      target/arm: Restrict translation disabled alignment check to VMSA

Thomas Huth (1):
      hw/char/stm32l4x5_usart: Fix memory corruption by adding correct class_size

Zenghui Yu (1):
      hvf: arm: Remove PL1_WRITE_MASK

 docs/system/arm/b-l475e-iot01a.rst  |   3 +-
 docs/system/arm/emulation.rst       |  42 ++++-
 include/hw/display/dm163.h          |  59 ++++++
 include/hw/watchdog/sbsa_gwdt.h     |   3 +-
 target/arm/cpu.h                    |  28 +++
 target/arm/internals.h              |  15 +-
 hw/arm/b-l475e-iot01a.c             | 105 +++++++++--
 hw/arm/npcm7xx.c                    |   3 +-
 hw/arm/sbsa-ref.c                   |  16 ++
 hw/arm/stm32l4x5_soc.c              |   6 +-
 hw/char/stm32l4x5_usart.c           |   1 +
 hw/core/clock.c                     |   1 -
 hw/core/machine.c                   |   4 +-
 hw/display/dm163.c                  | 349 ++++++++++++++++++++++++++++++++++++
 hw/dma/xlnx_dpdma.c                 |  20 +--
 hw/watchdog/sbsa_gwdt.c             |  15 +-
 target/arm/cpu.c                    |  42 +++--
 target/arm/cpu64.c                  |   2 +
 target/arm/helper.c                 |  22 +--
 target/arm/hvf/hvf.c                |   3 +-
 target/arm/kvm.c                    |   2 +
 target/arm/tcg/cpu32.c              |   6 +-
 target/arm/tcg/cpu64.c              |  28 ++-
 target/arm/tcg/hflags.c             |  12 +-
 tests/qtest/dm163-test.c            | 194 ++++++++++++++++++++
 tests/qtest/stm32l4x5_gpio-test.c   |  13 +-
 tests/qtest/stm32l4x5_syscfg-test.c |  17 +-
 hw/arm/Kconfig                      |   1 +
 hw/display/Kconfig                  |   3 +
 hw/display/meson.build              |   1 +
 hw/display/trace-events             |  14 ++
 tests/avocado/boot_linux_console.py |  70 ++++----
 tests/avocado/replay_kernel.py      |   8 +-
 tests/qtest/meson.build             |   2 +
 34 files changed, 987 insertions(+), 123 deletions(-)
 create mode 100644 include/hw/display/dm163.h
 create mode 100644 hw/display/dm163.c
 create mode 100644 tests/qtest/dm163-test.c


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2023-05-30 13:25 Peter Maydell
@ 2023-05-30 14:13 ` Richard Henderson
  0 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2023-05-30 14:13 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel

On 5/30/23 06:25, Peter Maydell wrote:
> Hi; here's the latest batch of arm changes. The big thing
> in here is the SMMUv3 changes to add stage-2 translation support.
> 
> thanks
> -- PMM
> 
> The following changes since commit aa9bbd865502ed517624ab6fe7d4b5d89ca95e43:
> 
>    Merge tag 'pull-ppc-20230528' of https://gitlab.com/danielhb/qemu into staging (2023-05-29 14:31:52 -0700)
> 
> are available in the Git repository at:
> 
>    https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230530
> 
> for you to fetch changes up to b03d0d4f531a8b867e0aac1fab0b876903015680:
> 
>    docs: sbsa: correct graphics card name (2023-05-30 13:32:46 +0100)
> 
> ----------------------------------------------------------------
> target-arm queue:
>   * fsl-imx6: Add SNVS support for i.MX6 boards
>   * smmuv3: Add support for stage 2 translations
>   * hw/dma/xilinx_axidma: Check DMASR.HALTED to prevent infinite loop
>   * hw/arm/xlnx-zynqmp: fix unsigned error when checking the RPUs number
>   * cleanups for recent Kconfig changes
>   * target/arm: Explicitly select short-format FSR for M-profile
>   * tests/qtest: Run arm-specific tests only if the required machine is available
>   * hw/arm/sbsa-ref: add GIC node into DT
>   * docs: sbsa: correct graphics card name
>   * Update copyright dates to 2023

Printf failure on aarch64-macos and cross-mipsel:

https://gitlab.com/qemu-project/qemu/-/jobs/4374716505#L3662
https://gitlab.com/qemu-project/qemu/-/jobs/4374716612#L4963

../hw/arm/smmuv3.c:423:23: error: format specifies type 'unsigned long' but the argument 
has type 'uint64_t' (aka 'unsigned long long') [-Werror,-Wformat]
                       cfg->s2cfg.vttb,  cfg->s2cfg.eff_ps);
                       ^~~~~~~~~~~~~~~
/private/var/folders/76/zy5ktkns50v6gt5g8r0sf6sc0000gn/T/cirrus-ci-build/include/qemu/log.h:54:30: 
note: expanded from macro 'qemu_log_mask'
             qemu_log(FMT, ## __VA_ARGS__);              \
                      ~~~     ^~~~~~~~~~~


r~


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 00/21] target-arm queue
@ 2023-05-30 13:25 Peter Maydell
  2023-05-30 14:13 ` Richard Henderson
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2023-05-30 13:25 UTC (permalink / raw)
  To: qemu-devel

Hi; here's the latest batch of arm changes. The big thing
in here is the SMMUv3 changes to add stage-2 translation support.

thanks
-- PMM

The following changes since commit aa9bbd865502ed517624ab6fe7d4b5d89ca95e43:

  Merge tag 'pull-ppc-20230528' of https://gitlab.com/danielhb/qemu into staging (2023-05-29 14:31:52 -0700)

are available in the Git repository at:

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

for you to fetch changes up to b03d0d4f531a8b867e0aac1fab0b876903015680:

  docs: sbsa: correct graphics card name (2023-05-30 13:32:46 +0100)

----------------------------------------------------------------
target-arm queue:
 * fsl-imx6: Add SNVS support for i.MX6 boards
 * smmuv3: Add support for stage 2 translations
 * hw/dma/xilinx_axidma: Check DMASR.HALTED to prevent infinite loop
 * hw/arm/xlnx-zynqmp: fix unsigned error when checking the RPUs number
 * cleanups for recent Kconfig changes
 * target/arm: Explicitly select short-format FSR for M-profile
 * tests/qtest: Run arm-specific tests only if the required machine is available
 * hw/arm/sbsa-ref: add GIC node into DT
 * docs: sbsa: correct graphics card name
 * Update copyright dates to 2023

----------------------------------------------------------------
Clément Chigot (1):
      hw/arm/xlnx-zynqmp: fix unsigned error when checking the RPUs number

Enze Li (1):
      Update copyright dates to 2023

Fabiano Rosas (3):
      target/arm: Explain why we need to select ARM_V7M
      arm/Kconfig: Keep Kconfig default entries in default.mak as documentation
      arm/Kconfig: Make TCG dependence explicit

Marcin Juszkiewicz (2):
      hw/arm/sbsa-ref: add GIC node into DT
      docs: sbsa: correct graphics card name

Mostafa Saleh (10):
      hw/arm/smmuv3: Add missing fields for IDR0
      hw/arm/smmuv3: Update translation config to hold stage-2
      hw/arm/smmuv3: Refactor stage-1 PTW
      hw/arm/smmuv3: Add page table walk for stage-2
      hw/arm/smmuv3: Parse STE config for stage-2
      hw/arm/smmuv3: Make TLB lookup work for stage-2
      hw/arm/smmuv3: Add VMID to TLB tagging
      hw/arm/smmuv3: Add CMDs related to stage-2
      hw/arm/smmuv3: Add stage-2 support in iova notifier
      hw/arm/smmuv3: Add knob to choose translation stage and enable stage-2

Peter Maydell (1):
      target/arm: Explicitly select short-format FSR for M-profile

Thomas Huth (1):
      tests/qtest: Run arm-specific tests only if the required machine is available

Tommy Wu (1):
      hw/dma/xilinx_axidma: Check DMASR.HALTED to prevent infinite loop.

Vitaly Cheptsov (1):
      fsl-imx6: Add SNVS support for i.MX6 boards

 docs/conf.py                                |   2 +-
 docs/system/arm/sbsa.rst                    |   2 +-
 configs/devices/aarch64-softmmu/default.mak |   6 +
 configs/devices/arm-softmmu/default.mak     |  40 ++++
 hw/arm/smmu-internal.h                      |  37 +++
 hw/arm/smmuv3-internal.h                    |  12 +-
 include/hw/arm/fsl-imx6.h                   |   2 +
 include/hw/arm/smmu-common.h                |  45 +++-
 include/hw/arm/smmuv3.h                     |   4 +
 include/qemu/help-texts.h                   |   2 +-
 hw/arm/fsl-imx6.c                           |   8 +
 hw/arm/sbsa-ref.c                           |  19 +-
 hw/arm/smmu-common.c                        | 209 ++++++++++++++--
 hw/arm/smmuv3.c                             | 357 ++++++++++++++++++++++++----
 hw/arm/xlnx-zynqmp.c                        |   2 +-
 hw/dma/xilinx_axidma.c                      |  11 +-
 target/arm/tcg/tlb_helper.c                 |  13 +-
 hw/arm/Kconfig                              | 123 ++++++----
 hw/arm/trace-events                         |  14 +-
 target/arm/Kconfig                          |   3 +
 tests/qtest/meson.build                     |   7 +-
 21 files changed, 773 insertions(+), 145 deletions(-)


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2023-04-21 10:49 ` Richard Henderson
@ 2023-04-21 11:54   ` Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2023-04-21 11:54 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

On Fri, 21 Apr 2023 at 11:49, Richard Henderson
<richard.henderson@linaro.org> wrote:
> Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as appropriate.

8.1 :-)  (I created the 8.1 page yesterday.)

-- PMM


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2023-04-20 10:04 Peter Maydell
@ 2023-04-21 10:49 ` Richard Henderson
  2023-04-21 11:54   ` Peter Maydell
  0 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2023-04-21 10:49 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel

On 4/20/23 11:04, Peter Maydell wrote:
> Hi; here's the first target-arm pullreq for the 8.1 cycle.
> Nothing particularly huge in here, just the various things
> that had accumulated during the freeze.
> 
> thanks
> -- PMM
> 
> The following changes since commit 2d82c32b2ceaca3dc3da5e36e10976f34bfcb598:
> 
>    Open 8.1 development tree (2023-04-20 10:05:25 +0100)
> 
> are available in the Git repository at:
> 
>    https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230420
> 
> for you to fetch changes up to 1ed1f338520cda0574b7e04f5e8e85e049740548:
> 
>    arm/mcimx7d-sabre: Set fec2-phy-connected property to false (2023-04-20 10:46:43 +0100)
> 
> ----------------------------------------------------------------
> target-arm queue:
>   * hw/arm: Fix some typos in comments (most found by codespell)
>   * exynos: Fix out-of-bounds access in exynos4210_gcomp_find debug printf
>   * Orangepi-PC, Cubieboard: add Allwinner WDT watchdog emulation
>   * tests/avocado: Add reboot tests to Cubieboard
>   * hw/timer/imx_epit: Fix bugs in timer limit checking
>   * target/arm: Remove KVM AArch32 CPU definitions
>   * hw/arm/virt: Restrict Cortex-A7 check to TCG
>   * target/arm: Initialize debug capabilities only once
>   * target/arm: Implement FEAT_PAN3
>   * docs/devel/kconfig.rst: Fix incorrect markup
>   * target/arm: Report pauth information to gdb as 'pauth_v2'
>   * mcimxd7-sabre, mcimx6ul-evk: Correctly model the way the PHY
>     on the second ethernet device must be configured via the
>     first one

Applied, thanks.  Please update https://wiki.qemu.org/ChangeLog/7.1 as appropriate.


r~




^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 00/21] target-arm queue
@ 2023-04-20 10:04 Peter Maydell
  2023-04-21 10:49 ` Richard Henderson
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2023-04-20 10:04 UTC (permalink / raw)
  To: qemu-devel

Hi; here's the first target-arm pullreq for the 8.1 cycle.
Nothing particularly huge in here, just the various things
that had accumulated during the freeze.

thanks
-- PMM

The following changes since commit 2d82c32b2ceaca3dc3da5e36e10976f34bfcb598:

  Open 8.1 development tree (2023-04-20 10:05:25 +0100)

are available in the Git repository at:

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

for you to fetch changes up to 1ed1f338520cda0574b7e04f5e8e85e049740548:

  arm/mcimx7d-sabre: Set fec2-phy-connected property to false (2023-04-20 10:46:43 +0100)

----------------------------------------------------------------
target-arm queue:
 * hw/arm: Fix some typos in comments (most found by codespell)
 * exynos: Fix out-of-bounds access in exynos4210_gcomp_find debug printf
 * Orangepi-PC, Cubieboard: add Allwinner WDT watchdog emulation
 * tests/avocado: Add reboot tests to Cubieboard
 * hw/timer/imx_epit: Fix bugs in timer limit checking
 * target/arm: Remove KVM AArch32 CPU definitions
 * hw/arm/virt: Restrict Cortex-A7 check to TCG
 * target/arm: Initialize debug capabilities only once
 * target/arm: Implement FEAT_PAN3
 * docs/devel/kconfig.rst: Fix incorrect markup
 * target/arm: Report pauth information to gdb as 'pauth_v2'
 * mcimxd7-sabre, mcimx6ul-evk: Correctly model the way the PHY
   on the second ethernet device must be configured via the
   first one

----------------------------------------------------------------
Akihiko Odaki (1):
      target/arm: Initialize debug capabilities only once

Axel Heider (2):
      hw/timer/imx_epit: don't shadow variable
      hw/timer/imx_epit: fix limit check

Feng Jiang (1):
      exynos: Fix out-of-bounds access in exynos4210_gcomp_find debug printf

Guenter Roeck (5):
      hw/net/imx_fec: Support two Ethernet interfaces connected to single MDIO bus
      fsl-imx6ul: Add fec[12]-phy-connected properties
      arm/mcimx6ul-evk: Set fec1-phy-connected property to false
      fsl-imx7: Add fec[12]-phy-connected properties
      arm/mcimx7d-sabre: Set fec2-phy-connected property to false

Peter Maydell (5):
      target/arm: Pass ARMMMUFaultInfo to merge_syn_data_abort()
      target/arm: Don't set ISV when reporting stage 1 faults in ESR_EL2
      target/arm: Implement FEAT_PAN3
      docs/devel/kconfig.rst: Fix incorrect markup
      target/arm: Report pauth information to gdb as 'pauth_v2'

Philippe Mathieu-Daudé (2):
      target/arm: Remove KVM AArch32 CPU definitions
      hw/arm/virt: Restrict Cortex-A7 check to TCG

Stefan Weil (1):
      hw/arm: Fix some typos in comments (most found by codespell)

Strahinja Jankovic (4):
      hw/watchdog: Allwinner WDT emulation for system reset
      hw/arm: Add WDT to Allwinner-A10 and Cubieboard
      hw/arm: Add WDT to Allwinner-H3 and Orangepi-PC
      tests/avocado: Add reboot tests to Cubieboard

 docs/devel/kconfig.rst              |   2 +-
 docs/system/arm/cubieboard.rst      |   1 +
 docs/system/arm/emulation.rst       |   1 +
 docs/system/arm/orangepi.rst        |   1 +
 include/hw/arm/allwinner-a10.h      |   2 +
 include/hw/arm/allwinner-h3.h       |   5 +-
 include/hw/arm/fsl-imx6ul.h         |   1 +
 include/hw/arm/fsl-imx7.h           |   1 +
 include/hw/net/imx_fec.h            |   2 +
 include/hw/watchdog/allwinner-wdt.h | 123 +++++++++++
 target/arm/cpu.h                    |   5 +
 target/arm/kvm-consts.h             |   9 +-
 target/arm/kvm_arm.h                |   8 +
 hw/arm/allwinner-a10.c              |   7 +
 hw/arm/allwinner-h3.c               |   8 +
 hw/arm/exynos4210.c                 |   4 +-
 hw/arm/fsl-imx6ul.c                 |  20 ++
 hw/arm/fsl-imx7.c                   |  20 ++
 hw/arm/mcimx6ul-evk.c               |   2 +
 hw/arm/mcimx7d-sabre.c              |   2 +
 hw/arm/musicpal.c                   |   2 +-
 hw/arm/omap1.c                      |   2 +-
 hw/arm/omap2.c                      |   2 +-
 hw/arm/virt-acpi-build.c            |   2 +-
 hw/arm/virt.c                       |   4 +-
 hw/arm/xlnx-versal-virt.c           |   2 +-
 hw/net/imx_fec.c                    |  27 ++-
 hw/timer/exynos4210_mct.c           |  13 +-
 hw/timer/imx_epit.c                 |   2 +-
 hw/watchdog/allwinner-wdt.c         | 416 ++++++++++++++++++++++++++++++++++++
 target/arm/cpu64.c                  |   2 +-
 target/arm/cpu_tcg.c                |   2 -
 target/arm/gdbstub.c                |   9 +-
 target/arm/kvm.c                    |   2 +
 target/arm/kvm64.c                  |  18 +-
 target/arm/ptw.c                    |  14 +-
 target/arm/tcg/tlb_helper.c         |  26 ++-
 gdb-xml/aarch64-pauth.xml           |   2 +-
 hw/arm/Kconfig                      |   4 +-
 hw/watchdog/Kconfig                 |   4 +
 hw/watchdog/meson.build             |   1 +
 hw/watchdog/trace-events            |   7 +
 tests/avocado/boot_linux_console.py |  15 +-
 43 files changed, 738 insertions(+), 64 deletions(-)
 create mode 100644 include/hw/watchdog/allwinner-wdt.h
 create mode 100644 hw/watchdog/allwinner-wdt.c


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2023-03-06 15:34 Peter Maydell
@ 2023-03-07 12:42 ` Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2023-03-07 12:42 UTC (permalink / raw)
  To: qemu-devel

On Mon, 6 Mar 2023 at 15:34, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> The following changes since commit f003dd8d81f7d88f4b1f8802309eaa76f6eb223a:
>
>   Merge tag 'pull-tcg-20230305' of https://gitlab.com/rth7680/qemu into staging (2023-03-06 10:20:04 +0000)
>
> are available in the Git repository at:
>
>   https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230306
>
> for you to fetch changes up to 2ddc45954f97cd1d7ee5cbca0def05e980d1da9f:
>
>   hw: arm: allwinner-h3: Fix and complete H3 i2c devices (2023-03-06 15:31:24 +0000)
>
> ----------------------------------------------------------------
> target-arm queue:
>  * allwinner-h3: Fix I2C controller model for Sun6i SoCs
>  * allwinner-h3: Add missing i2c controllers
>  * Expose M-profile system registers to gdbstub
>  * Expose pauth information to gdbstub
>  * Support direct boot for Linux/arm64 EFI zboot images
>  * Fix incorrect stage 2 MMU setup validation
>
> ----------------------------------------------------------------


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/8.0
for any user-visible changes.

-- PMM


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 00/21] target-arm queue
@ 2023-03-06 15:34 Peter Maydell
  2023-03-07 12:42 ` Peter Maydell
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2023-03-06 15:34 UTC (permalink / raw)
  To: qemu-devel

The following changes since commit f003dd8d81f7d88f4b1f8802309eaa76f6eb223a:

  Merge tag 'pull-tcg-20230305' of https://gitlab.com/rth7680/qemu into staging (2023-03-06 10:20:04 +0000)

are available in the Git repository at:

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

for you to fetch changes up to 2ddc45954f97cd1d7ee5cbca0def05e980d1da9f:

  hw: arm: allwinner-h3: Fix and complete H3 i2c devices (2023-03-06 15:31:24 +0000)

----------------------------------------------------------------
target-arm queue:
 * allwinner-h3: Fix I2C controller model for Sun6i SoCs
 * allwinner-h3: Add missing i2c controllers
 * Expose M-profile system registers to gdbstub
 * Expose pauth information to gdbstub
 * Support direct boot for Linux/arm64 EFI zboot images
 * Fix incorrect stage 2 MMU setup validation

----------------------------------------------------------------
Ard Biesheuvel (1):
      hw: arm: Support direct boot for Linux/arm64 EFI zboot images

David Reiss (2):
      target/arm: Export arm_v7m_mrs_control
      target/arm: Export arm_v7m_get_sp_ptr

Richard Henderson (16):
      target/arm: Normalize aarch64 gdbstub get/set function names
      target/arm: Unexport arm_gen_dynamic_sysreg_xml
      target/arm: Move arm_gen_dynamic_svereg_xml to gdbstub64.c
      target/arm: Split out output_vector_union_type
      target/arm: Simplify register counting in arm_gen_dynamic_svereg_xml
      target/arm: Hoist pred_width in arm_gen_dynamic_svereg_xml
      target/arm: Fix svep width in arm_gen_dynamic_svereg_xml
      target/arm: Add name argument to output_vector_union_type
      target/arm: Simplify iteration over bit widths
      target/arm: Create pauth_ptr_mask
      target/arm: Implement gdbstub pauth extension
      target/arm: Implement gdbstub m-profile systemreg and secext
      target/arm: Handle m-profile in arm_is_secure
      target/arm: Stub arm_hcr_el2_eff for m-profile
      target/arm: Diagnose incorrect usage of arm_is_secure subroutines
      target/arm: Rewrite check_s2_mmu_setup

qianfan Zhao (2):
      hw: allwinner-i2c: Fix TWI_CNTR_INT_FLAG on SUN6i SoCs
      hw: arm: allwinner-h3: Fix and complete H3 i2c devices

 configs/targets/aarch64-linux-user.mak    |   2 +-
 configs/targets/aarch64-softmmu.mak       |   2 +-
 configs/targets/aarch64_be-linux-user.mak |   2 +-
 include/hw/arm/allwinner-h3.h             |   6 +
 include/hw/i2c/allwinner-i2c.h            |   6 +
 include/hw/loader.h                       |  19 ++
 target/arm/cpu.h                          |  17 +-
 target/arm/internals.h                    |  34 +++-
 hw/arm/allwinner-h3.c                     |  29 +++-
 hw/arm/boot.c                             |   6 +
 hw/core/loader.c                          |  91 ++++++++++
 hw/i2c/allwinner-i2c.c                    |  26 ++-
 target/arm/gdbstub.c                      | 278 ++++++++++++++++++------------
 target/arm/gdbstub64.c                    | 175 ++++++++++++++++++-
 target/arm/helper.c                       |   3 +
 target/arm/ptw.c                          | 173 +++++++++++--------
 target/arm/tcg/m_helper.c                 |  90 +++++-----
 target/arm/tcg/pauth_helper.c             |  26 ++-
 gdb-xml/aarch64-pauth.xml                 |  15 ++
 19 files changed, 742 insertions(+), 258 deletions(-)
 create mode 100644 gdb-xml/aarch64-pauth.xml


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2022-03-18 13:22 Peter Maydell
@ 2022-03-19 10:09 ` Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2022-03-19 10:09 UTC (permalink / raw)
  To: qemu-devel

On Fri, 18 Mar 2022 at 13:23, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> Mostly straightforward bugfixes. The new Xilinx devices are
> arguably 'new feature', but they're fixing a regression where
> our changes to PSCI in commit 3f37979bf mean that EL3 guest
> code now needs to talk to a proper emulated power-controller
> device to turn on secondary CPUs; and it's not yet rc1 and
> they only affect the Xilinx board, so it seems OK to me.
>
> thanks
> -- PMM
>
> The following changes since commit 1d60bb4b14601e38ed17384277aa4c30c57925d3:
>
>   Merge tag 'pull-request-2022-03-15v2' of https://gitlab.com/thuth/qemu into staging (2022-03-16 10:43:58 +0000)
>
> are available in the Git repository at:
>
>   https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220318
>
> for you to fetch changes up to 79d54c9eac04c554e3c081589542f801ace71797:
>
>   util/osdep: Remove some early cruft (2022-03-18 11:32:13 +0000)
>
> ----------------------------------------------------------------
> target-arm queue:
>  * Fix sve2 ldnt1 and stnt1
>  * Fix pauth_check_trap vs SEL2
>  * Fix handling of LPAE block descriptors
>  * hw/dma/xlnx_csu_dma: Set TYPE_XLNX_CSU_DMA class_size
>  * hw/misc/npcm7xx_clk: Don't leak string in npcm7xx_clk_sel_init()
>  * nsis installer: List emulators in alphabetical order
>  * nsis installer: Suppress "ANSI targets are deprecated" warning
>  * nsis installer: Fix mouse-over descriptions for emulators
>  * hw/arm/virt: Fix gic-version=max when CONFIG_ARM_GICV3_TCG is unset
>  * Improve M-profile vector table access logging
>  * Xilinx ZynqMP: model CRF and APU control
>  * Fix compile issues on modern Solaris
>


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/7.0
for any user-visible changes.

-- PMM


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 00/21] target-arm queue
@ 2022-03-18 13:22 Peter Maydell
  2022-03-19 10:09 ` Peter Maydell
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2022-03-18 13:22 UTC (permalink / raw)
  To: qemu-devel

Mostly straightforward bugfixes. The new Xilinx devices are
arguably 'new feature', but they're fixing a regression where
our changes to PSCI in commit 3f37979bf mean that EL3 guest
code now needs to talk to a proper emulated power-controller
device to turn on secondary CPUs; and it's not yet rc1 and
they only affect the Xilinx board, so it seems OK to me.

thanks
-- PMM

The following changes since commit 1d60bb4b14601e38ed17384277aa4c30c57925d3:

  Merge tag 'pull-request-2022-03-15v2' of https://gitlab.com/thuth/qemu into staging (2022-03-16 10:43:58 +0000)

are available in the Git repository at:

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

for you to fetch changes up to 79d54c9eac04c554e3c081589542f801ace71797:

  util/osdep: Remove some early cruft (2022-03-18 11:32:13 +0000)

----------------------------------------------------------------
target-arm queue:
 * Fix sve2 ldnt1 and stnt1
 * Fix pauth_check_trap vs SEL2
 * Fix handling of LPAE block descriptors
 * hw/dma/xlnx_csu_dma: Set TYPE_XLNX_CSU_DMA class_size
 * hw/misc/npcm7xx_clk: Don't leak string in npcm7xx_clk_sel_init()
 * nsis installer: List emulators in alphabetical order
 * nsis installer: Suppress "ANSI targets are deprecated" warning
 * nsis installer: Fix mouse-over descriptions for emulators
 * hw/arm/virt: Fix gic-version=max when CONFIG_ARM_GICV3_TCG is unset
 * Improve M-profile vector table access logging
 * Xilinx ZynqMP: model CRF and APU control
 * Fix compile issues on modern Solaris

----------------------------------------------------------------
Andrew Deason (3):
      util/osdep: Avoid madvise proto on modern Solaris
      hw/i386/acpi-build: Avoid 'sun' identifier
      util/osdep: Remove some early cruft

Edgar E. Iglesias (6):
      hw/arm/xlnx-zynqmp: Add an unimplemented SERDES area
      target/arm: Make rvbar settable after realize
      hw/misc: Add a model of the Xilinx ZynqMP CRF
      hw/arm/xlnx-zynqmp: Connect the ZynqMP CRF
      hw/misc: Add a model of the Xilinx ZynqMP APU Control
      hw/arm/xlnx-zynqmp: Connect the ZynqMP APU Control

Eric Auger (2):
      hw/intc: Rename CONFIG_ARM_GIC_TCG into CONFIG_ARM_GICV3_TCG
      hw/arm/virt: Fix gic-version=max when CONFIG_ARM_GICV3_TCG is unset

Peter Maydell (8):
      target/arm: Fix handling of LPAE block descriptors
      hw/dma/xlnx_csu_dma: Set TYPE_XLNX_CSU_DMA class_size
      hw/misc/npcm7xx_clk: Don't leak string in npcm7xx_clk_sel_init()
      nsis installer: List emulators in alphabetical order
      nsis installer: Suppress "ANSI targets are deprecated" warning
      nsis installer: Fix mouse-over descriptions for emulators
      target/arm: Log M-profile vector table accesses
      target/arm: Log fault address for M-profile faults

Richard Henderson (2):
      target/arm: Fix sve2 ldnt1 and stnt1
      target/arm: Fix pauth_check_trap vs SEL2

 meson.build                            |  23 ++-
 include/hw/arm/xlnx-zynqmp.h           |   4 +
 include/hw/misc/xlnx-zynqmp-apu-ctrl.h |  93 ++++++++++++
 include/hw/misc/xlnx-zynqmp-crf.h      | 211 ++++++++++++++++++++++++++
 include/qemu/osdep.h                   |   8 +
 target/arm/cpu.h                       |   3 +-
 target/arm/sve.decode                  |   5 +-
 hw/arm/virt.c                          |   7 +-
 hw/arm/xlnx-zynqmp.c                   |  46 +++++-
 hw/dma/xlnx_csu_dma.c                  |   1 +
 hw/i386/acpi-build.c                   |   4 +-
 hw/misc/npcm7xx_clk.c                  |   4 +-
 hw/misc/xlnx-zynqmp-apu-ctrl.c         | 253 +++++++++++++++++++++++++++++++
 hw/misc/xlnx-zynqmp-crf.c              | 266 +++++++++++++++++++++++++++++++++
 target/arm/cpu.c                       |  17 ++-
 target/arm/helper.c                    |  20 ++-
 target/arm/m_helper.c                  |  11 ++
 target/arm/pauth_helper.c              |   2 +-
 target/arm/translate-sve.c             |  51 ++++++-
 tests/tcg/aarch64/test-826.c           |  50 +++++++
 util/osdep.c                           |  10 --
 hw/intc/Kconfig                        |   2 +-
 hw/intc/meson.build                    |   4 +-
 hw/misc/meson.build                    |   2 +
 qemu.nsi                               |   8 +-
 scripts/nsis.py                        |  17 ++-
 tests/tcg/aarch64/Makefile.target      |   4 +
 tests/tcg/configure.sh                 |   4 +
 28 files changed, 1084 insertions(+), 46 deletions(-)
 create mode 100644 include/hw/misc/xlnx-zynqmp-apu-ctrl.h
 create mode 100644 include/hw/misc/xlnx-zynqmp-crf.h
 create mode 100644 hw/misc/xlnx-zynqmp-apu-ctrl.c
 create mode 100644 hw/misc/xlnx-zynqmp-crf.c
 create mode 100644 tests/tcg/aarch64/test-826.c


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2021-08-02 11:57 Peter Maydell
@ 2021-08-02 13:51 ` Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2021-08-02 13:51 UTC (permalink / raw)
  To: QEMU Developers

On Mon, 2 Aug 2021 at 12:58, Peter Maydell <peter.maydell@linaro.org> wrote:
>
> A largish pullreq but it's almost all docs fixes.
>
> -- PMM
>
> The following changes since commit 10a3c4a4b3e14208cfed274514d1911e5230935f:
>
>   Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging (2021-08-02 09:47:07 +0100)
>
> are available in the Git repository at:
>
>   https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210802
>
> for you to fetch changes up to 4a64939db76b10d8d41d2af3c6aad8142da55450:
>
>   docs: Move user-facing barrier docs into system manual (2021-08-02 12:55:51 +0100)
>
> ----------------------------------------------------------------
> target-arm queue:
>  * Add documentation of Arm 'mainstone', 'kzm', 'imx25-pdk' boards
>  * MAINTAINERS: Don't list Andrzej Zaborowski for various components
>  * docs: Remove stale TODO comments about license and version
>  * docs: Move licence/copyright from HTML output to rST comments
>  * docs: Format literal text correctly
>  * hw/arm/boot: Report error if there is no fw_cfg device in the machine
>  * docs: rSTify barrier.txt and bootindex.txt


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/6.1
for any user-visible changes.

-- PMM


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 00/21] target-arm queue
@ 2021-08-02 11:57 Peter Maydell
  2021-08-02 13:51 ` Peter Maydell
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2021-08-02 11:57 UTC (permalink / raw)
  To: qemu-devel

A largish pullreq but it's almost all docs fixes.

-- PMM

The following changes since commit 10a3c4a4b3e14208cfed274514d1911e5230935f:

  Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging (2021-08-02 09:47:07 +0100)

are available in the Git repository at:

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

for you to fetch changes up to 4a64939db76b10d8d41d2af3c6aad8142da55450:

  docs: Move user-facing barrier docs into system manual (2021-08-02 12:55:51 +0100)

----------------------------------------------------------------
target-arm queue:
 * Add documentation of Arm 'mainstone', 'kzm', 'imx25-pdk' boards
 * MAINTAINERS: Don't list Andrzej Zaborowski for various components
 * docs: Remove stale TODO comments about license and version
 * docs: Move licence/copyright from HTML output to rST comments
 * docs: Format literal text correctly
 * hw/arm/boot: Report error if there is no fw_cfg device in the machine
 * docs: rSTify barrier.txt and bootindex.txt

----------------------------------------------------------------
Peter Maydell (21):
      docs: Add documentation of Arm 'mainstone' board
      docs: Add documentation of Arm 'kzm' board
      docs: Add documentation of Arm 'imx25-pdk' board
      MAINTAINERS: Don't list Andrzej Zaborowski for various components
      docs: Remove stale TODO comments about license and version
      docs: Move licence/copyright from HTML output to rST comments
      docs/devel/build-system.rst: Format literals correctly
      docs/devel/build-system.rst: Correct typo in example code
      docs/devel/ebpf_rss.rst: Format literals correctly
      docs/devel/migration.rst: Format literals correctly
      docs/devel: Format literals correctly
      docs/system/s390x/protvirt.rst: Format literals correctly
      docs/system/arm/cpu-features.rst: Format literals correctly
      docs: Format literals correctly
      docs/about/removed-features: Fix markup error
      docs/tools/virtiofsd.rst: Delete stray backtick
      hw/arm/boot: Report error if there is no fw_cfg device in the machine
      docs: Move bootindex.txt into system section and rstify
      docs: Move the protocol part of barrier.txt into interop
      ui/input-barrier: Move TODOs from barrier.txt to a comment
      docs: Move user-facing barrier docs into system manual

 docs/about/index.rst                         |   2 +-
 docs/about/removed-features.rst              |   2 +-
 docs/barrier.txt                             | 370 -----------------------
 docs/bootindex.txt                           |  52 ----
 docs/devel/build-system.rst                  | 160 +++++-----
 docs/devel/ebpf_rss.rst                      |  18 +-
 docs/devel/migration.rst                     |  36 +--
 docs/devel/qgraph.rst                        |   8 +-
 docs/devel/tcg-plugins.rst                   |  14 +-
 docs/devel/testing.rst                       |   8 +-
 docs/interop/barrier.rst                     | 426 +++++++++++++++++++++++++++
 docs/interop/index.rst                       |   1 +
 docs/interop/live-block-operations.rst       |   2 +-
 docs/interop/qemu-ga-ref.rst                 |   9 -
 docs/interop/qemu-qmp-ref.rst                |   9 -
 docs/interop/qemu-storage-daemon-qmp-ref.rst |   9 -
 docs/interop/vhost-user-gpu.rst              |   7 +-
 docs/interop/vhost-user.rst                  |  12 +-
 docs/system/arm/cpu-features.rst             | 116 ++++----
 docs/system/arm/imx25-pdk.rst                |  19 ++
 docs/system/arm/kzm.rst                      |  18 ++
 docs/system/arm/mainstone.rst                |  25 ++
 docs/system/arm/nuvoton.rst                  |   2 +-
 docs/system/arm/sbsa.rst                     |   4 +-
 docs/system/arm/virt.rst                     |   2 +-
 docs/system/barrier.rst                      |  44 +++
 docs/system/bootindex.rst                    |  76 +++++
 docs/system/cpu-hotplug.rst                  |   2 +-
 docs/system/generic-loader.rst               |   4 +-
 docs/system/guest-loader.rst                 |   6 +-
 docs/system/index.rst                        |   2 +
 docs/system/ppc/powernv.rst                  |   8 +-
 docs/system/riscv/microchip-icicle-kit.rst   |   2 +-
 docs/system/riscv/virt.rst                   |   2 +-
 docs/system/s390x/protvirt.rst               |  12 +-
 docs/system/target-arm.rst                   |   3 +
 docs/tools/virtiofsd.rst                     |   2 +-
 hw/arm/boot.c                                |   9 +
 hw/arm/sbsa-ref.c                            |   7 -
 ui/input-barrier.c                           |   5 +
 MAINTAINERS                                  |   8 +-
 41 files changed, 849 insertions(+), 674 deletions(-)
 delete mode 100644 docs/barrier.txt
 delete mode 100644 docs/bootindex.txt
 create mode 100644 docs/interop/barrier.rst
 create mode 100644 docs/system/arm/imx25-pdk.rst
 create mode 100644 docs/system/arm/kzm.rst
 create mode 100644 docs/system/arm/mainstone.rst
 create mode 100644 docs/system/barrier.rst
 create mode 100644 docs/system/bootindex.rst


^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2021-02-03  9:22 ` Philippe Mathieu-Daudé
@ 2021-02-03 10:12   ` P J P
  0 siblings, 0 replies; 39+ messages in thread
From: P J P @ 2021-02-03 10:12 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: Peter Maydell, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 802 bytes --]

+-- On Wed, 3 Feb 2021, Philippe Mathieu-Daudé wrote --+
| FYI Prasad mentioned a CVE was requested:
| https://www.mail-archive.com/qemu-devel@nongnu.org/msg778659.html
| 
| As you said it is an odd configuration, I am not sure it is worth
| to wait for the CVE number to add it to the commit (which helps
| downstream distributions tracking these).
| 
| [updating]
| 
| Just got detail from Prasad on IRC, it usually takes ~1 day to get
| the CVE number assigned, so maybe worth postponing this until tomorrow.
| 
| Prasad, can you reply to this message ASAP once you get the number?

'CVE-2021-20221' assigned by Red Hat Inc.
  -> https://bugs.launchpad.net/qemu/+bug/1914353/comments/3

Thank you.
--
Prasad J Pandit / Red Hat Product Security Team
8685 545E B54C 486B C6EB 271E E285 8B5A F050 DE8D

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PULL 00/21] target-arm queue
  2021-02-02 17:54 Peter Maydell
@ 2021-02-03  9:22 ` Philippe Mathieu-Daudé
  2021-02-03 10:12   ` P J P
  0 siblings, 1 reply; 39+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-03  9:22 UTC (permalink / raw)
  To: Peter Maydell, Prasad J Pandit; +Cc: Prasad J Pandit, qemu-devel

Hi Peter,

On 2/2/21 6:54 PM, Peter Maydell wrote:
> Mostly just bug fixes. The important one here is
>   hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register
> which fixes a buffer overrun that's a security issue if you're running
> KVM on Arm with kernel-irqchip=off (which hopefully nobody is doing in
> a security context, because kernel-irqchip=on is the default and the
> sensible choice for performance).

FYI Prasad mentioned a CVE was requested:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg778659.html

As you said it is an odd configuration, I am not sure it is worth
to wait for the CVE number to add it to the commit (which helps
downstream distributions tracking these).

[updating]

Just got detail from Prasad on IRC, it usually takes ~1 day to get
the CVE number assigned, so maybe worth postponing this until tomorrow.

Prasad, can you reply to this message ASAP once you get the number?

Thanks,

Phil.

> -- PMM
> 
> The following changes since commit cf7ca7d5b9faca13f1f8e3ea92cfb2f741eb0c0e:
> 
>   Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/tracing-pull-request' into staging (2021-02-01 16:28:00 +0000)
> 
> are available in the Git repository at:
> 
>   https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210202-1
> 
> for you to fetch changes up to 14657850c9cc10948551fbb884c30eb5a3a7370a:
> 
>   hw/arm: Display CPU type in machine description (2021-02-02 17:53:44 +0000)
> 
> ----------------------------------------------------------------
> target-arm queue:
>  * hw/intc/arm_gic: Allow to use QTest without crashing
>  * hw/char/exynos4210_uart: Fix buffer size reporting with FIFO disabled
>  * hw/char/exynos4210_uart: Fix missing call to report ready for input
>  * hw/arm/smmuv3: Fix addr_mask for range-based invalidation
>  * hw/ssi/imx_spi: Fix various minor bugs
>  * hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register
>  * hw/arm: Add missing Kconfig dependencies
>  * hw/arm: Display CPU type in machine description
> 
> ----------------------------------------------------------------
> Bin Meng (5):
>       hw/ssi: imx_spi: Use a macro for number of chip selects supported
>       hw/ssi: imx_spi: Remove imx_spi_update_irq() in imx_spi_reset()
>       hw/ssi: imx_spi: Round up the burst length to be multiple of 8
>       hw/ssi: imx_spi: Correct the burst length > 32 bit transfer logic
>       hw/ssi: imx_spi: Correct tx and rx fifo endianness
> 
> Iris Johnson (2):
>       hw/char/exynos4210_uart: Fix buffer size reporting with FIFO disabled
>       hw/char/exynos4210_uart: Fix missing call to report ready for input
> 
> Philippe Mathieu-Daudé (12):
>       hw/intc/arm_gic: Allow to use QTest without crashing
>       hw/ssi: imx_spi: Remove pointless variable initialization
>       hw/ssi: imx_spi: Rework imx_spi_reset() to keep CONREG register value
>       hw/ssi: imx_spi: Rework imx_spi_read() to handle block disabled
>       hw/ssi: imx_spi: Rework imx_spi_write() to handle block disabled
>       hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register
>       hw/arm/stm32f405_soc: Add missing dependency on OR_IRQ
>       hw/arm/exynos4210: Add missing dependency on OR_IRQ
>       hw/arm/xlnx-versal: Versal SoC requires ZDMA
>       hw/arm/xlnx-versal: Versal SoC requires ZynqMP peripherals
>       hw/net/can: ZynqMP CAN device requires PTIMER
>       hw/arm: Display CPU type in machine description
> 
> Xuzhou Cheng (1):
>       hw/ssi: imx_spi: Disable chip selects when controller is disabled
> 
> Zenghui Yu (1):
>       hw/arm/smmuv3: Fix addr_mask for range-based invalidation
> 
>  include/hw/ssi/imx_spi.h  |   5 +-
>  hw/arm/digic_boards.c     |   2 +-
>  hw/arm/microbit.c         |   2 +-
>  hw/arm/netduino2.c        |   2 +-
>  hw/arm/netduinoplus2.c    |   2 +-
>  hw/arm/orangepi.c         |   2 +-
>  hw/arm/smmuv3.c           |   4 +-
>  hw/arm/stellaris.c        |   4 +-
>  hw/char/exynos4210_uart.c |   7 ++-
>  hw/intc/arm_gic.c         |   5 +-
>  hw/ssi/imx_spi.c          | 153 +++++++++++++++++++++++++++++-----------------
>  hw/Kconfig                |   1 +
>  hw/arm/Kconfig            |   5 ++
>  hw/dma/Kconfig            |   3 +
>  hw/dma/meson.build        |   2 +-
>  15 files changed, 130 insertions(+), 69 deletions(-)
> 



^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 00/21] target-arm queue
@ 2021-02-02 17:54 Peter Maydell
  2021-02-03  9:22 ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 39+ messages in thread
From: Peter Maydell @ 2021-02-02 17:54 UTC (permalink / raw)
  To: qemu-devel

Mostly just bug fixes. The important one here is
  hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register
which fixes a buffer overrun that's a security issue if you're running
KVM on Arm with kernel-irqchip=off (which hopefully nobody is doing in
a security context, because kernel-irqchip=on is the default and the
sensible choice for performance).

-- PMM

The following changes since commit cf7ca7d5b9faca13f1f8e3ea92cfb2f741eb0c0e:

  Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/tracing-pull-request' into staging (2021-02-01 16:28:00 +0000)

are available in the Git repository at:

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

for you to fetch changes up to 14657850c9cc10948551fbb884c30eb5a3a7370a:

  hw/arm: Display CPU type in machine description (2021-02-02 17:53:44 +0000)

----------------------------------------------------------------
target-arm queue:
 * hw/intc/arm_gic: Allow to use QTest without crashing
 * hw/char/exynos4210_uart: Fix buffer size reporting with FIFO disabled
 * hw/char/exynos4210_uart: Fix missing call to report ready for input
 * hw/arm/smmuv3: Fix addr_mask for range-based invalidation
 * hw/ssi/imx_spi: Fix various minor bugs
 * hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register
 * hw/arm: Add missing Kconfig dependencies
 * hw/arm: Display CPU type in machine description

----------------------------------------------------------------
Bin Meng (5):
      hw/ssi: imx_spi: Use a macro for number of chip selects supported
      hw/ssi: imx_spi: Remove imx_spi_update_irq() in imx_spi_reset()
      hw/ssi: imx_spi: Round up the burst length to be multiple of 8
      hw/ssi: imx_spi: Correct the burst length > 32 bit transfer logic
      hw/ssi: imx_spi: Correct tx and rx fifo endianness

Iris Johnson (2):
      hw/char/exynos4210_uart: Fix buffer size reporting with FIFO disabled
      hw/char/exynos4210_uart: Fix missing call to report ready for input

Philippe Mathieu-Daudé (12):
      hw/intc/arm_gic: Allow to use QTest without crashing
      hw/ssi: imx_spi: Remove pointless variable initialization
      hw/ssi: imx_spi: Rework imx_spi_reset() to keep CONREG register value
      hw/ssi: imx_spi: Rework imx_spi_read() to handle block disabled
      hw/ssi: imx_spi: Rework imx_spi_write() to handle block disabled
      hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register
      hw/arm/stm32f405_soc: Add missing dependency on OR_IRQ
      hw/arm/exynos4210: Add missing dependency on OR_IRQ
      hw/arm/xlnx-versal: Versal SoC requires ZDMA
      hw/arm/xlnx-versal: Versal SoC requires ZynqMP peripherals
      hw/net/can: ZynqMP CAN device requires PTIMER
      hw/arm: Display CPU type in machine description

Xuzhou Cheng (1):
      hw/ssi: imx_spi: Disable chip selects when controller is disabled

Zenghui Yu (1):
      hw/arm/smmuv3: Fix addr_mask for range-based invalidation

 include/hw/ssi/imx_spi.h  |   5 +-
 hw/arm/digic_boards.c     |   2 +-
 hw/arm/microbit.c         |   2 +-
 hw/arm/netduino2.c        |   2 +-
 hw/arm/netduinoplus2.c    |   2 +-
 hw/arm/orangepi.c         |   2 +-
 hw/arm/smmuv3.c           |   4 +-
 hw/arm/stellaris.c        |   4 +-
 hw/char/exynos4210_uart.c |   7 ++-
 hw/intc/arm_gic.c         |   5 +-
 hw/ssi/imx_spi.c          | 153 +++++++++++++++++++++++++++++-----------------
 hw/Kconfig                |   1 +
 hw/arm/Kconfig            |   5 ++
 hw/dma/Kconfig            |   3 +
 hw/dma/meson.build        |   2 +-
 15 files changed, 130 insertions(+), 69 deletions(-)


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PULL 00/21] target-arm queue
@ 2021-01-12 16:57 Peter Maydell
  0 siblings, 0 replies; 39+ messages in thread
From: Peter Maydell @ 2021-01-12 16:57 UTC (permalink / raw)
  To: qemu-devel

Arm queue; not huge but I figured I might as well send it out since
I've been doing code review today and there's no queue of unprocessed
pullreqs...

thanks
-- PMM

The following changes since commit b3f846c59d8405bb87c551187721fc92ff2f1b92:

  Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2021-01-11v2' into staging (2021-01-11 15:15:35 +0000)

are available in the Git repository at:

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

for you to fetch changes up to 19d131395ccaf503db21dadd8257e6dc9fc1d7de:

  ui/cocoa: Fix openFile: deprecation on Big Sur (2021-01-12 11:38:37 +0000)

----------------------------------------------------------------
target-arm queue:
 * arm: Support emulation of ARMv8.4-TTST extension
 * arm: Update cpu.h ID register field definitions
 * arm: Fix breakage of XScale instruction emulation
 * hw/net/lan9118: Fix RX Status FIFO PEEK value
 * npcm7xx: Add ADC and PWM emulation
 * ui/cocoa: Make "open docs" help menu entry work again when binary
   is run from the build tree
 * ui/cocoa: Fix openFile: deprecation on Big Sur
 * docs: Add qemu-storage-daemon(1) manpage to meson.build
 * docs: Build and install all the docs in a single manual

----------------------------------------------------------------
Hao Wu (6):
      hw/misc: Add clock converter in NPCM7XX CLK module
      hw/timer: Refactor NPCM7XX Timer to use CLK clock
      hw/adc: Add an ADC module for NPCM7XX
      hw/misc: Add a PWM module for NPCM7XX
      hw/misc: Add QTest for NPCM7XX PWM Module
      hw/*: Use type casting for SysBusDevice in NPCM7XX

Leif Lindholm (6):
      target/arm: fix typo in cpu.h ID_AA64PFR1 field name
      target/arm: make ARMCPU.clidr 64-bit
      target/arm: make ARMCPU.ctr 64-bit
      target/arm: add descriptions of CLIDR_EL1, CCSIDR_EL1, CTR_EL0 to cpu.h
      target/arm: add aarch64 ID register fields to cpu.h
      target/arm: add aarch32 ID register fields to cpu.h

Peter Maydell (5):
      docs: Add qemu-storage-daemon(1) manpage to meson.build
      docs: Build and install all the docs in a single manual
      target/arm: Don't decode insns in the XScale/iWMMXt space as cp insns
      hw/net/lan9118: Fix RX Status FIFO PEEK value
      hw/net/lan9118: Add symbolic constants for register offsets

Roman Bolshakov (2):
      ui/cocoa: Update path to docs in build tree
      ui/cocoa: Fix openFile: deprecation on Big Sur

Rémi Denis-Courmont (2):
      target/arm: ARMv8.4-TTST extension
      target/arm: enable Small Translation tables in max CPU

 docs/conf.py                     |  46 ++-
 docs/devel/conf.py               |  15 -
 docs/index.html.in               |  17 -
 docs/interop/conf.py             |  28 --
 docs/meson.build                 |  65 ++--
 docs/specs/conf.py               |  16 -
 docs/system/arm/nuvoton.rst      |   4 +-
 docs/system/conf.py              |  28 --
 docs/tools/conf.py               |  37 --
 docs/user/conf.py                |  15 -
 meson.build                      |   1 +
 hw/adc/trace.h                   |   1 +
 include/hw/adc/npcm7xx_adc.h     |  69 ++++
 include/hw/arm/npcm7xx.h         |   4 +
 include/hw/misc/npcm7xx_clk.h    | 146 ++++++-
 include/hw/misc/npcm7xx_pwm.h    | 105 +++++
 include/hw/timer/npcm7xx_timer.h |   1 +
 target/arm/cpu.h                 |  85 ++++-
 hw/adc/npcm7xx_adc.c             | 301 +++++++++++++++
 hw/arm/npcm7xx.c                 |  55 ++-
 hw/arm/npcm7xx_boards.c          |   2 +-
 hw/mem/npcm7xx_mc.c              |   2 +-
 hw/misc/npcm7xx_clk.c            | 807 ++++++++++++++++++++++++++++++++++++++-
 hw/misc/npcm7xx_gcr.c            |   2 +-
 hw/misc/npcm7xx_pwm.c            | 550 ++++++++++++++++++++++++++
 hw/misc/npcm7xx_rng.c            |   2 +-
 hw/net/lan9118.c                 |  26 +-
 hw/nvram/npcm7xx_otp.c           |   2 +-
 hw/ssi/npcm7xx_fiu.c             |   2 +-
 hw/timer/npcm7xx_timer.c         |  39 +-
 target/arm/cpu64.c               |   1 +
 target/arm/helper.c              |  15 +-
 target/arm/translate.c           |   7 +
 tests/qtest/npcm7xx_adc-test.c   | 377 ++++++++++++++++++
 tests/qtest/npcm7xx_pwm-test.c   | 490 ++++++++++++++++++++++++
 hw/adc/meson.build               |   1 +
 hw/adc/trace-events              |   5 +
 hw/misc/meson.build              |   1 +
 hw/misc/trace-events             |   6 +
 tests/qtest/meson.build          |   4 +-
 ui/cocoa.m                       |   7 +-
 41 files changed, 3124 insertions(+), 263 deletions(-)
 delete mode 100644 docs/devel/conf.py
 delete mode 100644 docs/index.html.in
 delete mode 100644 docs/interop/conf.py
 delete mode 100644 docs/specs/conf.py
 delete mode 100644 docs/system/conf.py
 delete mode 100644 docs/tools/conf.py
 delete mode 100644 docs/user/conf.py
 create mode 100644 hw/adc/trace.h
 create mode 100644 include/hw/adc/npcm7xx_adc.h
 create mode 100644 include/hw/misc/npcm7xx_pwm.h
 create mode 100644 hw/adc/npcm7xx_adc.c
 create mode 100644 hw/misc/npcm7xx_pwm.c
 create mode 100644 tests/qtest/npcm7xx_adc-test.c
 create mode 100644 tests/qtest/npcm7xx_pwm-test.c
 create mode 100644 hw/adc/trace-events


^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2024-04-30 23:02 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-16 15:12 [PULL 00/21] target-arm queue Peter Maydell
2024-01-16 15:12 ` [PULL 01/21] docs/devel/docs: Document .hx file syntax Peter Maydell
2024-01-16 15:12 ` [PULL 02/21] target/arm: arm_pamax() no longer needs to do feature propagation Peter Maydell
2024-01-16 15:12 ` [PULL 03/21] docs/system/arm/virt.rst: Improve 'highmem' option docs Peter Maydell
2024-01-16 15:12 ` [PULL 04/21] hw/misc: Implement STM32L4x5 EXTI Peter Maydell
2024-01-16 15:12 ` [PULL 05/21] hw/arm: Connect STM32L4x5 EXTI to STM32L4x5 SoC Peter Maydell
2024-01-16 15:12 ` [PULL 06/21] tests/qtest: Add STM32L4x5 EXTI QTest testcase Peter Maydell
2024-01-16 15:12 ` [PULL 07/21] hw/misc: Implement STM32L4x5 SYSCFG Peter Maydell
2024-01-16 15:12 ` [PULL 08/21] hw/arm: Connect STM32L4x5 SYSCFG to STM32L4x5 SoC Peter Maydell
2024-01-16 15:12 ` [PULL 09/21] tests/qtest: Add STM32L4x5 SYSCFG QTest testcase Peter Maydell
2024-01-16 15:12 ` [PULL 10/21] hw/misc: Add Nuvoton's PCI Mailbox Module Peter Maydell
2024-01-16 15:12 ` [PULL 11/21] hw/arm: Add PCI mailbox module to Nuvoton SoC Peter Maydell
2024-01-16 15:12 ` [PULL 12/21] hw/misc: Add qtest for NPCM7xx PCI Mailbox Peter Maydell
2024-01-16 15:12 ` [PULL 13/21] hw/net: Add NPCMXXX GMAC device Peter Maydell
2024-01-16 15:12 ` [PULL 14/21] hw/arm: Add GMAC devices to NPCM7XX SoC Peter Maydell
2024-01-16 15:12 ` [PULL 15/21] tests/qtest: Creating qtest for GMAC Module Peter Maydell
2024-01-16 15:12 ` [PULL 16/21] hw/net: GMAC Rx Implementation Peter Maydell
2024-01-16 15:12 ` [PULL 17/21] hw/net: GMAC Tx Implementation Peter Maydell
2024-01-16 15:12 ` [PULL 18/21] tests/qtest: Adding PCS Module test to GMAC Qtest Peter Maydell
2024-01-16 15:12 ` [PULL 19/21] hw/timer: fix systick trace message Peter Maydell
2024-01-16 15:12 ` [PULL 20/21] hw/arm/virt: Consolidate valid CPU types Peter Maydell
2024-01-16 15:12 ` [PULL 21/21] load_elf: fix iterator's type for elf file processing Peter Maydell
  -- strict thread matches above, loose matches on Subject: below --
2024-04-30 16:48 [PULL 00/21] target-arm queue Peter Maydell
2024-04-30 23:01 ` Richard Henderson
2023-05-30 13:25 Peter Maydell
2023-05-30 14:13 ` Richard Henderson
2023-04-20 10:04 Peter Maydell
2023-04-21 10:49 ` Richard Henderson
2023-04-21 11:54   ` Peter Maydell
2023-03-06 15:34 Peter Maydell
2023-03-07 12:42 ` Peter Maydell
2022-03-18 13:22 Peter Maydell
2022-03-19 10:09 ` Peter Maydell
2021-08-02 11:57 Peter Maydell
2021-08-02 13:51 ` Peter Maydell
2021-02-02 17:54 Peter Maydell
2021-02-03  9:22 ` Philippe Mathieu-Daudé
2021-02-03 10:12   ` P J P
2021-01-12 16:57 Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.