NXP Public
> -----Original Message-----
> From: Bernhard Beschow <[email protected]>
> Sent: 14 September 2026 16:20
> To: Gaurav Sharma <[email protected]>; [email protected]
> Cc: [email protected]; [email protected]
> Subject: RE: [EXT] Re: [PATCHv2 6/7] hw/arm: Enable Cortex-M7 AMP boot on
> i.MX8MP
>
> Caution: This is an external email. Please take care when clicking links or
> opening attachments. When in doubt, report the message using the 'Report
> this email' button
>
>
> Am 12. September 2026 07:53:38 UTC schrieb Gaurav Sharma
> <[email protected]>:
> >
> >
> >
> >NXP Confidential
> >> -----Original Message-----
> >> From: Bernhard Beschow <[email protected]>
> >> Sent: 05 September 2026 12:22
> >> To: [email protected]; Gaurav Sharma
> <[email protected]>
> >> Cc: [email protected]; [email protected]
> >> Subject: [EXT] Re: [PATCHv2 6/7] hw/arm: Enable Cortex-M7 AMP boot on
> >> i.MX8MP
> >>
> >> Caution: This is an external email. Please take care when clicking
> >> links or opening attachments. When in doubt, report the message using
> >> the 'Report this email' button
> >>
> >>
> >> Am 6. Juli 2026 16:28:58 UTC schrieb Gaurav Sharma
> >> <[email protected]>:
> >> >Configure the i.MX8MP to boot the Cortex-M7 core alongside the
> >> >Cortex-A53 cores in an Asymmetric Multiprocessing (AMP) configuration.
> >> >The M7 firmware can be loaded and started from Linux running on the
> >> >A53 cores via the remoteproc framework.
> >> >
> >> >CM7 boot is made optional. A GPR IRQ is connected to a cpuwait handler.
> >> >The handler translates the CPUWAIT into STOP and RUN.It follows the
> >> >classic Cortex-M boot sequence: initial SP and reset vector taken
> >> >from the vector table.
> >> >
> >> >Signed-off-by: Gaurav Sharma <[email protected]>
> >> >---
> >> > docs/system/arm/imx8m.rst | 184
> >> +++++++++++++++++++++++++++++++++++-
> >> > hw/arm/fsl-imx8mp.c | 151 ++++++++++++++++++++++++++---
> >> > hw/arm/imx8mp-evk.c | 3 +-
> >> > include/hw/arm/fsl-imx8mp.h | 13 ++-
> >> > 4 files changed, 333 insertions(+), 18 deletions(-)
> >> >
> >> >diff --git a/docs/system/arm/imx8m.rst b/docs/system/arm/imx8m.rst
> >> >index c482bf180f..294c333127 100644
> >> >--- a/docs/system/arm/imx8m.rst
> >> >+++ b/docs/system/arm/imx8m.rst
> >> >@@ -12,6 +12,7 @@ The ``imx8mp-evk`` and ``imx8mm-evk`` machines
> >> >implement the following devices:
> >> >
> >> > * Up to 4 Cortex-A53 cores
> >> >+ * 1 Cortex-M7 core (``imx8mp-evk`` only)
> >> > * Generic Interrupt Controller (GICv3)
> >> > * 4 UARTs
> >> > * 3 USDHC Storage Controllers
> >> >@@ -36,6 +37,187 @@ Boot options
> >> > The ``imx8mp-evk`` and ``imx8mm-evk`` machines can start a Linux
> >> >kernel directly using the standard ``-kernel`` functionality.
> >> >
> >> >+
> >> >+Asymmetric Multiprocessing (AMP) Boot Recipe (``imx8mp-evk`` only)
> >> >+''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
> >> >+
> >> >+The ``imx8mp-evk`` machine includes a Cortex-M7 core alongside the
> >> >+Cortex-A53 cores, enabling Asymmetric Multiprocessing (AMP). The M7
> >> >+firmware can be loaded from Linux using the remoteproc framework.
> >> >+
> >> >+There are 2 control paths for Cortex-M7 on iMX8MP:- 1.
> >> >+Firmware-mediated (via SMC/ATF) 2. MMIO driven path (via SRC and
> >> >+GPR
> >> >+access)
> >> >+
> >> >+``fsl,imx8mp-cm7-mmio`` exists specifically to select the MMIO path
> >> >+and
> >> avoid dependence on firmware interfaces that aren’t guaranteed in qemu.
> >> >+This mode uses the SRC syscon block and the IOMUXC GPR for
> >> >+start/stop
> >> control.
> >> >+
> >> >+Memory carveouts for resource table, vrings need to be specified in
> >> >+the
> >> ``imx8mp-evk-rpmsg.dts``.
> >> >+Follow this application note to make the necessary changes -
> >> >+https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fw
> >> >+ww%2F&data=05%7C02%7Cgaurav.sharma_7%40nxp.com%7Cc0c95a40
> d8ae4436d2
> >> >+d108df124de4d8%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%
> 7C6392497
> >> >+97915267389%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRy
> dWUsIlYiOiI
> >> >+wLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D
> %7C0%7
> >> >+C%7C%7C&sdata=vlLR4IOOt3GySKKf50V1Cydybg3jmFQdv3YT%2B%2Bd
> Wxuo%3D&re
> >> >+served=0
> >> .
> >> >+nxp.com%2Fdocs%2Fen%2Fapplication-
> >> note%2FAN5317.pdf&data=05%7C02%7Cgau
> >> >+rav.sharma_7%40nxp.com%7Ced0ccff0b93040223a7908df0b1a3c30%7C
> 68
> >> 6ea1d3bc
> >> >+2b4c6fa92cd99c5c301635%7C0%7C0%7C639241879466409660%7CUnkn
> ow
> >> n%7CTWFpbG
> >> >+Zsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW
> 4z
> >> MiIsIkFO
> >> >+IjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=fgR89RxBAK
> wbh
> >> TmwuBGOe4
> >> >+8JRAJmNGlRlhiq%2BonQfiM%3D&reserved=0
> >> >+
> >> >+When Linux boots CM7 via remoteproc, the typical flow is:
> >> >+
> >> >+1. Linux booted with imx8mp-evk-rpmsg.dtb 2. Linux loads the CM7
> >> >+ELF into a reserved DDR region 3. Linux toggles the CM7 start/stop
> >> >+control (SRC/GPR CPUWAIT, etc.) 4. CM7 starts executing from that
> >> >+DDR entry
> >> >+
> >> >+
> >> >+Prerequisites
> >> >+~~~~~~~~~~~~~
> >> >+
> >> >+To manually test Cortex-M7 firmware loading from Linux, the
> >> >+following components are needed:
> >> >+
> >> >+1. Linux kernel configuration to enable i.MX remoteproc support.
> >> >+2. ``imx8mp-evk-rpmsg.dtb`` - device tree that enables the
> >> >+Cortex-M7
> >> remoteproc node, reserves DDR memory regions
> >> >+ for the Cortex-M7 firmware, resource table,vrings and buffers.
> >> >+3. A Cortex-M7 ELF firmware image linked to execute from DDR.
> >> >+
> >> >+NXP application note AN5317 describes the required remoteproc and
> >> >+reserved-memory setup for loading Cortex-M firmware from Linux.
> >> >+
> >> >+
> >> >+Linux kernel configuration
> >> >+~~~~~~~~~~~~~~~~~~~~~~~~~~
> >> >+
> >> >+The guest kernel needs remoteproc support. On official linux-imx
> >> >+kernels,
> >> this support is enabled by default.
> >> >+When using Buildroot, verify that the kernel configuration enables
> >> >+the remoteproc and rpmsg options needed by the i.MX remoteproc
> >> >+driver, for
> >> example:
> >> >+
> >> >+.. code-block:: none
> >> >+
> >> >+ CONFIG_REMOTEPROC=y
> >> >+ CONFIG_IMX_REMOTEPROC=y
> >> >+ CONFIG_RPMSG=y
> >> >+ CONFIG_VIRTIO_RPMSG_BUS=y
> >> >+ CONFIG_RPMSG_CHAR=y
> >> >+
> >> >+Depending on the kernel version and configuration, some options may
> >> >+be selected automatically by the i.MX remoteproc driver.
> >> >+
> >> >+
> >> >+
> >> >+Device tree preparation
> >> >+~~~~~~~~~~~~~~~~~~~~~~~
> >> >+
> >> >+1. Refer to ``9.1 i.MX Linux rproc support`` of application note
> >> >+AN5317 to
> >> add the
> >> >+ following nodes in ``imx8mp-evk-rpmsg.dts`` :-
> >> >+
> >> >+ m7_ddr_alias
> >> >+ m7_itcm
> >> >+ m7_dtcm
> >> >+
> >> >+2. Modify the compatible string of ``imx8mp-cm7`` node from
> >> >+``fsl,imx8mn-cm7`` to ``fsl,imx8mp-cm7-mmio`` 3. Add the following
> >> >+properties to the ``imx8mp-cm7`` node :-
> >> >+
> >> >+ ``syscon = <&src>;``
> >> >+ ``fsl,iomuxc-gpr = <&gpr>;``
> >> >+
> >> >+ These references are needed by imx_rproc_mmio_detect_mode in
> >> >+ i.MX
> >> remoteproc driver
> >> >+ for M7 boot mode detection.
> >> >+
> >> >+
> >> >+ Build ``imx8mp-evk-rpmsg.dtb`` from the above dts changes.
> >> >+
> >> >+
> >> >+
> >> >+Building a Cortex-M7 ELF firmware
> >> >+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >> >+
> >> >+A simple manual test is the MCUXpresso SDK UART polling example for
> >> >+the i.MX8MP EVK. It prints to a UART and is therefore easy to
> >> >+observe from
> >> QEMU.
> >> >+
> >> >+1. Follow this guide to set up MCUXpresso SDK for i.MX8MPEVK :-
> >> >+MCUXSDKIMX8MPGSUG[https://eur01.safelinks.protection.outlook.com
> /?u
> >> rl=
> >> >+https%3A%2F%2Fshare.google%2FqD4D09FCkkydTurqp&data=05%7C02
> %7
> >> Cgaurav.s
> >> >+harma_7%40nxp.com%7Ced0ccff0b93040223a7908df0b1a3c30%7C686
> ea1
> >> d3bc2b4c6
> >> >+fa92cd99c5c301635%7C0%7C0%7C639241879466438460%7CUnknown
> %7C
> >> TWFpbGZsb3d
> >> >+8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIs
> IkF
> >> OIjoiT
> >> >+WFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=XrPUCKlzeehjw%
> 2FH
> >> idRtH8wUq%
> >> >+2F5qQWjnHJSetXGkTvKM%3D&reserved=0]
> >> >+2. Build a DDR-linked Cortex-M7 ELF using the ARM GNU toolchain
> >> >+from the MCUXpresso SDK:-
> >> >+
> >> >+
> >> >+.. code-block:: bash
> >> >+
> >> >+ $ cd
> >> >+
> ${MCUX_SDK}/boards/evkmimx8mp/driver_examples/uart/polling/armgcc
> >> >+ $ ./build_ddr_release.sh
> >> >+
> >> >+As a result, ``iuart_polling_cm7.elf`` will be generated in
> >> >+``ddr_release``
> >> folder.
> >> >+
> >> >+Boot qemu i.MX8MP EVK machine with the updated linux kernel and
> >> >+``imx8mp-evk-rpmsg.dtb``
> >> >+
> >> >+3. Copy the ``iuart_polling_cm7.elf`` to ``/lib/firmware/`` path
> >> >+inside
> >> iMX8MPEVK qemu emulation.
> >> >+
> >> >+
> >> >+Serial ports (UARTs)
> >> >+''''''''''''''''''''
> >> >+
> >> >+The i.MX 8M Plus EVK model provides four UARTs. QEMU connects each
> >> >+UART to a host character backend using the ``-serial`` option. This
> >> >+option can be used multiple times to create and wire multiple serial
> ports.
> >> >+
> >> >+The ``-serial`` options are positional:
> >> >+
> >> >+* the 1st ``-serial ...`` maps to ``serial0`` (UART1)
> >> >+* the 2nd ``-serial ...`` maps to ``serial1`` (UART2)
> >> >+* the 3rd ``-serial ...`` maps to ``serial2`` (UART3)
> >> >+* the 4th ``-serial ...`` maps to ``serial3`` (UART4)
> >> >+
> >> >+Example usage:- To enable serial console for the official M7
> >> >+mcuxpresso sdk driver example - driver_examples/uart/polling which
> >> >+uses UART4, use:-
> >> >+
> >> >+.. code-block:: bash
> >> >+
> >> >+ -serial null -serial stdio -serial null -serial
> >> >+ pty:/tmp/imx8mp-uart4
> >> >+
> >> >+This will create a symlink /tmp/imx8mp-uart4 pointed to the
> >> >+allocated PTY. On a different tab the console for UART4 can be
> >> >+opened using the
> >> >+following:-
> >> >+
> >> >+.. code-block:: bash
> >> >+
> >> >+ $ screen /tmp/imx8mp-uart4 115200
> >> >+
> >> >+
> >> >+Starting QEMU for Cortex-M7 remoteproc testing
> >> >+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >> >+
> >> >+1. Execute the following command to start i.MX8MPEVK emulation:-
> >> >+
> >> >+.. code-block:: bash
> >> >+
> >> >+ $ qemu-system-aarch64 -M imx8mp-evk \
> >> >+ -display none -serial null -serial stdio -serial null -serial
> >> >+ /tmp/imx8mp-
> >> uart4 \
> >> >+ -kernel Image \
> >> >+ -dtb imx8mp-evk-rpmsg.dtb \
> >> >+ -append "root=/dev/mmcblk2p2" \
> >> >+ -drive file=sdcard.img,if=sd,bus=2,format=raw,id=mmcblk2
> >> >+
> >> >+2. On a new tab execute the following to open a console:-
> >> >+
> >> >+.. code-block:: bash
> >> >+
> >> >+ $ screen /tmp/imx8mp-uart4 115200
> >> >+
> >> >+3. Execute the following commands inside emulation to load the
> >> >+firmware elf:-
> >> >+
> >> >+.. code-block:: bash
> >> >+
> >> >+ $ echo iuart_polling_cm7.elf >
> >> /sys/class/remoteproc/remoteproc0/firmware
> >> >+ $ echo start > /sys/class/remoteproc/remoteproc0/state
> >> >+
> >> >+
> >> >+On the tab where the console is opened, you will observe the UART
> >> >+logs. The characters typed from the keyboard will echo on the console.
> >> >+
> >> >+
> >> >+Note:-
> >> >+
> >> >+Only DDR-linked bare-metal ELF images are currently supported by
> >> >+QEMU emulation. If the firmware is linked for a vector table base
> >> >+address other than ``0x80000000``, configure the Cortex-M7 vector
> >> >+base using the SoC property
> >> >+``cm7-vector-base``:-
> >> >+
> >> >+.. code-block:: bash
> >> >+
> >> >+ -global fsl-imx8mp.cm7-vector-base=0x80000000
> >> >+
> >> >+If this property is not provided, QEMU uses ``0x80000000`` by default.
> >> >+
> >> >+
> >> >+
> >> > Direct Linux Kernel Boot
> >> > ''''''''''''''''''''''''
> >> >
> >> >@@ -72,7 +254,7 @@ For i.MX 8M Plus EVK:
> >> > .. code-block:: bash
> >> >
> >> > $ qemu-system-aarch64 -M imx8mp-evk \
> >> >- -display none -serial null -serial stdio \
> >> >+ -display none -serial null -serial stdio -serial null -serial
> >> >+ /tmp/imx8mp-uart4 \
> >> > -kernel Image \
> >> > -dtb imx8mp-evk.dtb \
> >> > -append "root=/dev/mmcblk2p2" \ diff --git
> >> >a/hw/arm/fsl-imx8mp.c b/hw/arm/fsl-imx8mp.c index
> >> >eec83deced..8d6a1c3f4d 100644
> >> >--- a/hw/arm/fsl-imx8mp.c
> >> >+++ b/hw/arm/fsl-imx8mp.c
> >> >@@ -22,6 +22,8 @@
> >> > #include "qapi/error.h"
> >> > #include "qobject/qlist.h"
> >> >
> >> >+#define IMX8MP_NUM_A53 4
> >> >+
> >> > static const struct {
> >> > hwaddr addr;
> >> > size_t size;
> >> >@@ -196,6 +198,10 @@ static void fsl_imx8mp_init(Object *obj)
> >> > FslImx8mpState *s = FSL_IMX8MP(obj);
> >> > int i;
> >> >
> >> >+ s->cm7_booted = false;
> >> >+
> >> >+ object_initialize_child(obj, "cm7", &s->cm7, TYPE_ARMV7M);
> >> >+
> >> > object_initialize_child(obj, "gic", &s->gic,
> >> > gicv3_class_name());
> >> >
> >> > object_initialize_child(obj, "ccm", &s->ccm, TYPE_IMX8MP_CCM);
> >> >@@
> >> >-269,6 +275,93 @@ static void fsl_imx8mp_init(Object *obj)
> >> > TYPE_FSL_IMX8M_PCIE_PHY); }
> >> >
> >> >+static inline void imx8mp_cm7_halt(CPUState *m7cs) {
> >> >+ cpu_interrupt(m7cs, CPU_INTERRUPT_HALT);
> >> >+ m7cs->halted = 1;
> >> >+ qemu_cpu_kick(m7cs);
> >> >+}
> >> >+
> >> >+static inline void imx8mp_cm7_resume(CPUState *m7cs) {
> >> >+ /* Clear HALT interrupt (from STOP) and resume */
> >> >+ cpu_reset_interrupt(m7cs, CPU_INTERRUPT_HALT);
> >> >+ m7cs->halted = 0;
> >> >+ m7cs->stopped = 0;
> >> >+ cpu_resume(m7cs);
> >> >+ cpu_interrupt(m7cs, CPU_INTERRUPT_EXITTB);
> >> >+ qemu_cpu_kick(m7cs);
> >> >+}
> >> >+
> >> >+static void imx8mp_cm7_ctrl_apply(CPUState *cpu, run_on_cpu_data
> >> >+data) {
> >> >+ struct CM7CtlReq *r = data.host_ptr;
> >> >+ FslImx8mpState *s = r->s;
> >> >+ ARMCPU *m7 = s->cm7.cpu;
> >> >+ CPUState *m7cs = CPU(m7);
> >> >+
> >> >+ if (!r->run) {
> >> >+ /* STOP: halt the M7 */
> >> >+ imx8mp_cm7_halt(m7cs);
> >> >+ goto out;
> >> >+ }
> >> >+
> >> >+ /*
> >> >+ * RUN:
> >> >+ * CPUWAIT is modeled as a run/stop gate. On first RUN, boot
> >> >+ from
> >> vector
> >> >+ * table. Subsequent RUN resumes execution without resetting
> >> >+ CM7
> >> state.
> >> >+ */
> >> >+ if (s->cm7_booted) {
> >> >+ imx8mp_cm7_resume(m7cs);
> >> >+ goto out;
> >> >+ }
> >> >+
> >> >+ uint32_t msp_le = 0, pc_le = 0;
> >> >+ uint32_t msp, pc;
> >> >+ hwaddr vbase = s->cm7_vector_base;
> >> >+
> >> >+ address_space_read(&address_space_memory, vbase,
> >> >+ MEMTXATTRS_UNSPECIFIED, &msp_le, sizeof(msp_le));
> >> >+ address_space_read(&address_space_memory, vbase + 4,
> >> >+ MEMTXATTRS_UNSPECIFIED, &pc_le, sizeof(pc_le));
> >> >+ msp = le32_to_cpu(msp_le);
> >> >+ pc = le32_to_cpu(pc_le);
> >> >+
> >> >+
> >> >+ /* Clear Thumb indicator bit (bit0) */
> >> >+ pc &= ~1u;
> >> >+
> >> >+ cpu_reset(m7cs);
> >> >+
> >> >+ /* Set SP (R13) and PC (R15). Cortex-M uses Thumb */
> >> >+ m7->env.regs[13] = msp;
> >> >+ m7->env.regs[15] = pc;
> >> >+ m7->env.thumb = 1;
> >> >+
> >> >+ imx8mp_cm7_resume(m7cs);
> >> >+
> >> >+ s->cm7_booted = true;
> >> >+out:
> >> >+ g_free(r);
> >> >+};
> >> >+
> >> >+static void imx8mp_cm7_cpuwait_handler(void *opaque, int n, int
> >> >+level) {
> >> >+ FslImx8mpState *s = opaque;
> >> >+ (void)n;
> >> >+
> >> >+ if (!s->cm7.cpu) {
> >> >+ return;
> >> >+ }
> >> >+
> >> >+ struct CM7CtlReq *r = g_new0(struct CM7CtlReq, 1);
> >> >+ r->s = s;
> >> >+ r->run = !!level;
> >> >+
> >> >+ async_run_on_cpu(CPU(s->cm7.cpu), imx8mp_cm7_ctrl_apply,
> >> >+ RUN_ON_CPU_HOST_PTR(r)); }
> >> >+
> >> > static void fsl_imx8mp_realize(DeviceState *dev, Error **errp) {
> >> > MachineState *ms = MACHINE(qdev_get_machine()); @@ -277,21
> >> +370,15
> >> >@@ static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
> >> > const char *cpu_type = ms->cpu_type ?:
> >> >ARM_CPU_TYPE_NAME("cortex-
> >> a53");
> >> > int i;
> >> >
> >> >- if (ms->smp.cpus > FSL_IMX8MP_NUM_CPUS) {
> >> >- error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
> >> >- TYPE_FSL_IMX8MP, FSL_IMX8MP_NUM_CPUS, ms-
> >smp.cpus);
> >> >- return;
> >> >- }
> >> >-
> >> >- for (i = 0; i < ms->smp.cpus; i++) {
> >> >+ for (i = 0; i < IMX8MP_NUM_A53; i++) {
> >> > g_autofree char *name = g_strdup_printf("cpu%d", i);
> >> > object_initialize_child(OBJECT(dev), name, &s->cpu[i], cpu_type);
> >> > }
> >> >
> >> > /* CPUs */
> >> >- for (i = 0; i < ms->smp.cpus; i++) {
> >> >+ for (i = 0; i < IMX8MP_NUM_A53; i++) {
> >> > /* On uniprocessor, the CBAR is set to 0 */
> >> >- if (ms->smp.cpus > 1 &&
> >> >+ if (IMX8MP_NUM_A53 > 1 &&
> >> > object_property_find(OBJECT(&s->cpu[i]), "reset-cbar")) {
> >> > object_property_set_int(OBJECT(&s->cpu[i]),
> >> > "reset-cbar",
> >> >
> >> >fsl_imx8mp_memmap[FSL_IMX8MP_GIC_DIST].addr,
> >> >@@ -334,11 +421,11 @@ static void fsl_imx8mp_realize(DeviceState
> >> >*dev,
> >> Error **errp)
> >> > QList *redist_region_count;
> >> > bool pmu = object_property_get_bool(OBJECT(first_cpu),
> >> >"pmu", NULL);
> >> >
> >> >- qdev_prop_set_uint32(gicdev, "num-cpu", ms->smp.cpus);
> >> >+ qdev_prop_set_uint32(gicdev, "num-cpu", IMX8MP_NUM_A53);
> >> > qdev_prop_set_uint32(gicdev, "num-irq",
> >> > FSL_IMX8MP_NUM_IRQS + GIC_INTERNAL);
> >> > redist_region_count = qlist_new();
> >> >- qlist_append_int(redist_region_count, ms->smp.cpus);
> >> >+ qlist_append_int(redist_region_count, IMX8MP_NUM_A53);
> >> > qdev_prop_set_array(gicdev, "redist-region-count",
> >> redist_region_count);
> >> > object_property_set_link(OBJECT(&s->gic), "sysmem",
> >> > OBJECT(get_system_memory()),
> >> >&error_fatal); @@ -353,7 +440,7 @@ static void
> >> fsl_imx8mp_realize(DeviceState *dev, Error **errp)
> >> > * maintenance interrupt signal to the appropriate GIC PPI
> >> > inputs,
> and
> >> > * the GIC's IRQ/FIQ interrupt outputs to the CPU's inputs.
> >> > */
> >> >- for (i = 0; i < ms->smp.cpus; i++) {
> >> >+ for (i = 0; i < IMX8MP_NUM_A53; i++) {
> >> > DeviceState *cpudev = DEVICE(&s->cpu[i]);
> >> > int intidbase = FSL_IMX8MP_NUM_IRQS + i * GIC_INTERNAL;
> >> > qemu_irq irq;
> >> >@@ -383,11 +470,11 @@ static void fsl_imx8mp_realize(DeviceState
> >> >*dev, Error **errp)
> >> >
> >> > sysbus_connect_irq(gicsbd, i,
> >> > qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
> >> >- sysbus_connect_irq(gicsbd, i + ms->smp.cpus,
> >> >+ sysbus_connect_irq(gicsbd, i + IMX8MP_NUM_A53,
> >> > qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
> >> >- sysbus_connect_irq(gicsbd, i + 2 * ms->smp.cpus,
> >> >+ sysbus_connect_irq(gicsbd, i + 2 * IMX8MP_NUM_A53,
> >> > qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
> >> >- sysbus_connect_irq(gicsbd, i + 3 * ms->smp.cpus,
> >> >+ sysbus_connect_irq(gicsbd, i + 3 * IMX8MP_NUM_A53,
> >> > qdev_get_gpio_in(cpudev,
> >> > ARM_CPU_VFIQ));
> >> >
> >> > if (kvm_enabled()) {
> >> >@@ -459,6 +546,38 @@ static void fsl_imx8mp_realize(DeviceState
> >> >*dev,
> >> Error **errp)
> >> > sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpr), 0,
> >> > fsl_imx8mp_memmap[FSL_IMX8MP_IOMUXC_GPR].addr);
> >> >
> >> >+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpr), 0,
> >> >+ qemu_allocate_irq(imx8mp_cm7_cpuwait_handler, s,
> >> >+ 0));
> >> >+
> >> >+ /* Realize Cortex-M7 subsystem */
> >> >+ {
> >> >+ DeviceState *cm7dev = DEVICE(&s->cm7);
> >> >+ DeviceState *ccmdev = DEVICE(&s->ccm);
> >> >+ qdev_prop_set_string(cm7dev, "cpu-type",
> >> >+ ARM_CPU_TYPE_NAME("cortex-m7"));
> >> >+ qdev_prop_set_uint32(cm7dev, "num-irq", 64);
> >>
> >> The reference manual lists 160 IRQs for the M7. Any idea how these
> >> could be wired up?
> >>
> >
> >num-irq is corrected to 160. the same 160 SoC interrupt lines are
> >routed to both the A53 GIC and the M7 NVIC with no mux — so the wiring
> >model is: each peripheral's IRQ output connects to both the GIC SPI
> >input and the corresponding M7 NVIC input at the same index. In the
> >current patch, the 160 NVIC inputs are declared but not yet wired (all
> >inputs float low, which is harmless for the Linux+remoteproc use case).
> >Full wiring would be a follow-up, done incrementally per peripheral as
> >M7 firmware use cases are added
>
> Hi Gaurav,
>
> It shouldn't be too hard to add and wire up the NVIC: First create a patch
> before this one which adds an array of 160 TYPE_SPLIT_IRQ, initialize all in
> the
> init function to have two out IRQs, wire up all 160 gic IRQs at out index 0
> where the GIC is initialized, and wire the peripherals to the array instead of
> the GIC. Then the NVIC could be added in this patch too where all its 160 IRQs
> would be wired to out index 1 of the array. This way, we wouldn't have to
> worry about the IRQ wiring any more. Does this sound feasible or would
> there still something be missing?
>
> Best regards,
> Bernhard
>
Hey Bernhard,
yes absolutely. Split irq sounds very much feasible in this case. PPIs will
remain untouched. Currently I do not foresee any challenge with this. Let me
try it out. I will include these changes in my upcoming patch series.
In a separate patch before this, I will add splitter array, init, re-wire all
existing peripheral→GIC connections through splitters.
Then in this patch, I will wire splitter out[1] → M7 NVIC for all 160 lines
> >
> >> >+ qdev_prop_set_bit(cm7dev, "enable-bitband", true);
> >>
> >> Is this correct?
> >>
> >
> >It has been corrected to 'false'. Will be updated in the next patch series
> version.
> >
> >> Best regards,
> >> Bernhard
> >>
> >> >+
> >> >+ /* CM7 vector table base (configurable) */
> >> >+ qdev_prop_set_uint32(cm7dev, "init-nsvtor",
> >> >+ s->cm7_vector_base);
> >> >+
> >> >+ /* Connect CM7 clocks from CCM exported outputs */
> >> >+ qdev_connect_clock_in(cm7dev, "cpuclk",
> >> >+ qdev_get_clock_out(ccmdev, "cm7_cpuclk"));
> >> >+ qdev_connect_clock_in(cm7dev, "refclk",
> >> >+ qdev_get_clock_out(ccmdev, "cm7_refclk"));
> >> >+ object_property_set_link(OBJECT(&s->cm7), "memory",
> >> >+ OBJECT(get_system_memory()),
> >> >+ &error_abort);
> >> >+
> >> >+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->cm7), errp)) {
> >> >+ return;
> >> >+ }
> >> >+
> >> >+ CPUState *m7cs = CPU(s->cm7.cpu);
> >> >+ cpu_interrupt(m7cs, CPU_INTERRUPT_HALT);
> >> >+ m7cs->halted = 1;
> >> >+ }
> >> >+
> >> > /* GPTs */
> >> > object_property_set_int(OBJECT(&s->gpt5_gpt6_irq), "num-lines", 2,
> >> > &error_abort); @@ -784,6 +903,8 @@
> >> >static void fsl_imx8mp_realize(DeviceState *dev, Error **errp)
> >> >static const Property fsl_imx8mp_properties[] = {
> >> > DEFINE_PROP_UINT32("fec1-phy-num", FslImx8mpState, phy_num, 0),
> >> > DEFINE_PROP_BOOL("fec1-phy-connected", FslImx8mpState,
> >> >phy_connected, true),
> >> >+ DEFINE_PROP_UINT32("cm7-vector-base", FslImx8mpState,
> >> >+ cm7_vector_base, 0x80000000),
> >> > };
> >> >
> >> > static void fsl_imx8mp_class_init(ObjectClass *oc, const void
> >> >*data) diff --git a/hw/arm/imx8mp-evk.c b/hw/arm/imx8mp-evk.c index
> >> >b84ac91a17..0f92bf5dc8 100644
> >> >--- a/hw/arm/imx8mp-evk.c
> >> >+++ b/hw/arm/imx8mp-evk.c
> >> >@@ -117,7 +117,8 @@ static void
> imx8mp_evk_machine_init(MachineClass
> >> >*mc) {
> >> > mc->desc = "NXP i.MX 8M Plus EVK Board";
> >> > mc->init = imx8mp_evk_init;
> >> >- mc->default_cpus = 4;
> >> >+ mc->default_cpus = 5;
> >> >+ mc->min_cpus = 5;
> >> > mc->max_cpus = FSL_IMX8MP_NUM_CPUS;
> >> > mc->default_ram_id = "imx8mp-evk.ram";
> >> > mc->default_ram_size = 6 * GiB; diff --git
> >> >a/include/hw/arm/fsl-imx8mp.h b/include/hw/arm/fsl-imx8mp.h index
> >> >94d198b932..335e4beb6c 100644
> >> >--- a/include/hw/arm/fsl-imx8mp.h
> >> >+++ b/include/hw/arm/fsl-imx8mp.h
> >> >@@ -10,6 +10,7 @@
> >> > #define FSL_IMX8MP_H
> >> >
> >> > #include "target/arm/cpu.h"
> >> >+#include "hw/arm/armv7m.h"
> >> > #include "hw/char/imx_serial.h"
> >> > #include "hw/gpio/imx_gpio.h"
> >> > #include "hw/i2c/imx_i2c.h"
> >> >@@ -30,6 +31,7 @@
> >> > #include "hw/timer/imx_gpt.h"
> >> > #include "hw/usb/hcd-dwc3.h"
> >> > #include "hw/watchdog/wdt_imx2.h"
> >> >+#include "hw/core/qdev-clock.h"
> >> > #include "hw/core/sysbus.h"
> >> > #include "qom/object.h"
> >> > #include "qemu/units.h"
> >> >@@ -43,7 +45,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(FslImx8mpState,
> >> >FSL_IMX8MP) #define FSL_IMX8MP_MU1_A_IRQ 88
> >> >
> >> > enum FslImx8mpConfiguration {
> >> >- FSL_IMX8MP_NUM_CPUS = 4,
> >> >+ FSL_IMX8MP_NUM_CPUS = 5,
> >> > FSL_IMX8MP_NUM_ECSPIS = 3,
> >> > FSL_IMX8MP_NUM_GPIOS = 5,
> >> > FSL_IMX8MP_NUM_GPTS = 6,
> >> >@@ -65,6 +67,10 @@ struct FslImx8mpState {
> >> > SysBusDevice parent_obj;
> >> >
> >> > ARMCPU cpu[FSL_IMX8MP_NUM_CPUS];
> >> >+ ARMv7MState cm7;
> >> >+ bool enable_cm7;
> >> >+ bool cm7_booted;
> >> >+ uint32_t cm7_vector_base;
> >> > GICv3State gic;
> >> > IMX8MPGPCState gpc;
> >> > IMX8MPGPRState gpr;
> >> >@@ -91,6 +97,11 @@ struct FslImx8mpState {
> >> > bool phy_connected;
> >> > };
> >> >
> >> >+struct CM7CtlReq {
> >> >+ FslImx8mpState *s;
> >> >+ bool run;
> >> >+};
> >> >+
> >> > enum FslImx8mpMemoryRegions {
> >> > FSL_IMX8MP_A53_DAP,
> >> > FSL_IMX8MP_AIPS1_CONFIGURATION,