qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] hexagon system emu, part 3/3
@ 2025-03-01 17:20 Brian Cain
  2025-03-01 17:20 ` [PATCH 1/8] hw/intc: Add l2vic interrupt controller Brian Cain
                   ` (7 more replies)
  0 siblings, 8 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym

hexagon architecture system emulation: part 3/3

This series contains some initial machine definitions, an interrupt
controller device and a test case.  Hexagon "Standalone OS" is used
by the Hexagon SDK to create simple baremetal bootable programs that
can be run on QEMU or the instruction set simulator included with
the Hexagon SDK.  These programs generally depend on semihosting
support, which will come later.

Brian Cain (6):
  hw/hexagon: Add machine configs for sysemu
  hw/hexagon: Add v68, sa8775-cdsp0 defs
  hw/hexagon: Modify "Standalone" symbols
  target/hexagon: add build config for softmmu
  hw/hexagon: Define hexagon "virt" machine
  tests/functional: Add a hexagon minivm test

Sid Manning (2):
  hw/intc: Add l2vic interrupt controller
  hw/hexagon: Add support for cfgbase

 MAINTAINERS                                 |   6 +
 docs/devel/hexagon-l2vic.rst                |  59 +++
 docs/devel/index-internals.rst              |   1 +
 configs/devices/hexagon-softmmu/default.mak |   8 +
 configs/targets/hexagon-softmmu.mak         |   7 +
 qapi/machine.json                           |   2 +-
 include/hw/hexagon/hexagon.h                | 151 +++++++
 include/hw/hexagon/virt.h                   |  41 ++
 include/hw/intc/l2vic.h                     |  37 ++
 target/hexagon/cpu.h                        |   1 +
 hw/hexagon/machine_cfg_sa8775_cdsp0.h.inc   |  64 +++
 hw/hexagon/machine_cfg_v66g_1024.h.inc      |  64 +++
 hw/hexagon/machine_cfg_v68n_1024.h.inc      |  65 +++
 hw/hexagon/hexagon_dsp.c                    | 202 ++++++++++
 hw/hexagon/virt.c                           | 395 ++++++++++++++++++
 hw/intc/l2vic.c                             | 417 ++++++++++++++++++++
 target/hexagon/cpu.c                        |   8 +-
 target/hexagon/machine.c                    |   1 -
 hw/Kconfig                                  |   1 +
 hw/hexagon/Kconfig                          |  14 +
 hw/hexagon/meson.build                      |   7 +
 hw/intc/Kconfig                             |   3 +
 hw/intc/meson.build                         |   2 +
 hw/intc/trace-events                        |   4 +
 hw/meson.build                              |   1 +
 target/Kconfig                              |   1 +
 target/hexagon/Kconfig                      |   2 +
 target/hexagon/meson.build                  |   9 +
 tests/functional/meson.build                |   8 +
 tests/functional/test_hexagon_minivm.py     |  42 ++
 30 files changed, 1620 insertions(+), 3 deletions(-)
 create mode 100644 docs/devel/hexagon-l2vic.rst
 create mode 100644 configs/devices/hexagon-softmmu/default.mak
 create mode 100644 configs/targets/hexagon-softmmu.mak
 create mode 100644 include/hw/hexagon/hexagon.h
 create mode 100644 include/hw/hexagon/virt.h
 create mode 100644 include/hw/intc/l2vic.h
 create mode 100644 hw/hexagon/machine_cfg_sa8775_cdsp0.h.inc
 create mode 100644 hw/hexagon/machine_cfg_v66g_1024.h.inc
 create mode 100644 hw/hexagon/machine_cfg_v68n_1024.h.inc
 create mode 100644 hw/hexagon/hexagon_dsp.c
 create mode 100644 hw/hexagon/virt.c
 create mode 100644 hw/intc/l2vic.c
 create mode 100644 hw/hexagon/Kconfig
 create mode 100644 hw/hexagon/meson.build
 create mode 100644 target/hexagon/Kconfig
 create mode 100755 tests/functional/test_hexagon_minivm.py

-- 
2.34.1


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

* [PATCH 1/8] hw/intc: Add l2vic interrupt controller
  2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
@ 2025-03-01 17:20 ` Brian Cain
  2025-03-03 12:26   ` Philippe Mathieu-Daudé
  2025-03-24 19:40   ` ltaylorsimpson
  2025-03-01 17:20 ` [PATCH 2/8] hw/hexagon: Add machine configs for sysemu Brian Cain
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Damien Hedde, Paolo Bonzini

From: Sid Manning <sidneym@quicinc.com>

Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
Co-authored-by: Damien Hedde <damien.hedde@dahe.fr>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 MAINTAINERS                    |   2 +
 docs/devel/hexagon-l2vic.rst   |  59 +++++
 docs/devel/index-internals.rst |   1 +
 include/hw/intc/l2vic.h        |  37 +++
 hw/intc/l2vic.c                | 417 +++++++++++++++++++++++++++++++++
 hw/intc/Kconfig                |   3 +
 hw/intc/meson.build            |   2 +
 hw/intc/trace-events           |   4 +
 8 files changed, 525 insertions(+)
 create mode 100644 docs/devel/hexagon-l2vic.rst
 create mode 100644 include/hw/intc/l2vic.h
 create mode 100644 hw/intc/l2vic.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 804c07bcd5..a842f7fe1b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -232,6 +232,7 @@ Hexagon TCG CPUs
 M: Brian Cain <brian.cain@oss.qualcomm.com>
 S: Supported
 F: target/hexagon/
+F: hw/intc/l2vic.[ch]
 X: target/hexagon/idef-parser/
 X: target/hexagon/gen_idef_parser_funcs.py
 F: linux-user/hexagon/
@@ -242,6 +243,7 @@ F: docker/dockerfiles/debian-hexagon-cross.docker
 F: gdb-xml/hexagon*.xml
 F: docs/system/target-hexagon.rst
 F: docs/devel/hexagon-sys.rst
+F: docs/devel/hexagon-l2vic.rst
 T: git https://github.com/quic/qemu.git hex-next
 
 Hexagon idef-parser
diff --git a/docs/devel/hexagon-l2vic.rst b/docs/devel/hexagon-l2vic.rst
new file mode 100644
index 0000000000..0885636274
--- /dev/null
+++ b/docs/devel/hexagon-l2vic.rst
@@ -0,0 +1,59 @@
+Hexagon L2 Vectored Interrupt Controller
+========================================
+
+
+.. code-block:: none
+
+              +-------+
+              |       |             +----------------+
+              | l2vic |             |  hexagon core  |
+              |       |             |                |
+              | +-----|             |                |
+        ------> |VID0 >------------->irq2 -\         |
+        ------> |     |             |      |         |
+         ...  > |     |             |      |         |
+        ------> |     |             | <int steering> |
+              | +-----|             |   / |  | \     |
+              |  ...  |             |  |  |  |  |    |
+              | +-----|             | t0 t1 t2 t3 ...|
+        ------> |VIDN |             |                |
+        ------> |     |             |                |
+        ------> |     |             |                |
+        ------> |     |             |                |
+              | +-----|             |                |
+              |       |             |Global SREG File|
+              | State |             |                |
+              | [    ]|<============|=>[VID ]        |
+              | [    ]|<============|=>[VID1]        |
+              | [    ]|             |                |
+              | [    ]|             |                |
+              |       |             |                |
+              +-------+             +----------------+
+
+L2VIC/Core Integration
+----------------------
+
+* hexagon core supports 8 external interrupt sources
+* l2vic supports 1024 input interrupts mapped among 4 output interrupts
+* l2vic has four output signals: { VID0, VID1, VID2, VID3 }
+* l2vic device has a bank of registers per-VID that can be used to query
+  the status or assert new interrupts.
+* Interrupts are 'steered' to threads based on { thread priority, 'EX' state,
+  thread interrupt mask, thread interrupt enable, global interrupt enable,
+  etc. }.
+* Any hardware thread could conceivably handle any input interrupt, dependent
+  on state.
+* The system register transfer instruction can read the VID0-VID3 values from
+  the l2vic when reading from hexagon core system registers "VID" and "VID1".
+* When l2vic VID0 has multiple active interrupts, it pulses the VID0 output
+  IRQ and stores the IRQ number for the VID0 register field.  Only after this
+  interrupt is cleared can the l2vic pulse the VID0 output IRQ again and provide
+  the next interrupt number on the VID0 register.
+* The ``ciad`` instruction clears the l2vic input interrupt and un-disables the
+  core interrupt.  If some/an l2vic VID0 interrupt is pending when this occurs,
+  the next interrupt should fire and any subseqeunt reads of the VID register
+  should reflect the newly raised interrupt.
+* In QEMU, on an external interrupt or an unmasked-pending interrupt,
+  all vCPUs are triggered (has_work==true) and each will grab the IO lock
+  while considering the steering logic to determine whether they're the thread
+  that must handle the interrupt.
diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst
index 27259a552c..35958f1c23 100644
--- a/docs/devel/index-internals.rst
+++ b/docs/devel/index-internals.rst
@@ -15,6 +15,7 @@ Details about QEMU's various subsystems including how to add features to them.
    clocks
    ebpf_rss
    hexagon-sys
+   hexagon-l2vic
    migration/index
    multi-process
    reset
diff --git a/include/hw/intc/l2vic.h b/include/hw/intc/l2vic.h
new file mode 100644
index 0000000000..ed8ccf33b1
--- /dev/null
+++ b/include/hw/intc/l2vic.h
@@ -0,0 +1,37 @@
+/*
+ * QEMU L2VIC Interrupt Controller
+ *
+ * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#define L2VIC_VID_GRP_0 0x0 /* Read */
+#define L2VIC_VID_GRP_1 0x4 /* Read */
+#define L2VIC_VID_GRP_2 0x8 /* Read */
+#define L2VIC_VID_GRP_3 0xC /* Read */
+#define L2VIC_VID_0 0x10 /* Read SOFTWARE DEFINED */
+#define L2VIC_VID_1 0x14 /* Read SOFTWARE DEFINED NOT YET USED */
+#define L2VIC_INT_ENABLEn 0x100 /* Read/Write */
+#define L2VIC_INT_ENABLE_CLEARn 0x180 /* Write */
+#define L2VIC_INT_ENABLE_SETn 0x200 /* Write */
+#define L2VIC_INT_TYPEn 0x280 /* Read/Write */
+#define L2VIC_INT_STATUSn 0x380 /* Read */
+#define L2VIC_INT_CLEARn 0x400 /* Write */
+#define L2VIC_SOFT_INTn 0x480 /* Write */
+#define L2VIC_INT_PENDINGn 0x500 /* Read */
+#define L2VIC_INT_GRPn_0 0x600 /* Read/Write */
+#define L2VIC_INT_GRPn_1 0x680 /* Read/Write */
+#define L2VIC_INT_GRPn_2 0x700 /* Read/Write */
+#define L2VIC_INT_GRPn_3 0x780 /* Read/Write */
+
+#define L2VIC_INTERRUPT_MAX 1024
+#define L2VIC_CIAD_INSTRUCTION -1
+/*
+ * Note about l2vic groups:
+ * Each interrupt to L2VIC can be configured to associate with one of
+ * four groups.
+ * Group 0 interrupts go to IRQ2 via VID 0 (SSR: 0xC2, the default)
+ * Group 1 interrupts go to IRQ3 via VID 1 (SSR: 0xC3)
+ * Group 2 interrupts go to IRQ4 via VID 2 (SSR: 0xC4)
+ * Group 3 interrupts go to IRQ5 via VID 3 (SSR: 0xC5)
+ */
diff --git a/hw/intc/l2vic.c b/hw/intc/l2vic.c
new file mode 100644
index 0000000000..9df6575214
--- /dev/null
+++ b/hw/intc/l2vic.c
@@ -0,0 +1,417 @@
+/*
+ * QEMU L2VIC Interrupt Controller
+ *
+ * Arm PrimeCell PL190 Vector Interrupt Controller was used as a reference.
+ * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "hw/intc/l2vic.h"
+#include "trace.h"
+
+#define L2VICA(s, n) (s[(n) >> 2])
+
+#define TYPE_L2VIC "l2vic"
+#define L2VIC(obj) OBJECT_CHECK(L2VICState, (obj), TYPE_L2VIC)
+
+#define SLICE_MAX (L2VIC_INTERRUPT_MAX / 32)
+
+typedef struct L2VICState {
+    SysBusDevice parent_obj;
+
+    QemuMutex active;
+    MemoryRegion iomem;
+    MemoryRegion fast_iomem;
+    uint32_t level;
+    /*
+     * offset 0:vid group 0 etc, 10 bits in each group
+     * are used:
+     */
+    uint32_t vid_group[4];
+    uint32_t vid0;
+    /* Clear Status of Active Edge interrupt, not used: */
+    uint32_t int_clear[SLICE_MAX] QEMU_ALIGNED(16);
+    /* Enable interrupt source */
+    uint32_t int_enable[SLICE_MAX] QEMU_ALIGNED(16);
+    /* Clear (set to 0) corresponding bit in int_enable */
+    uint32_t int_enable_clear;
+    /* Set (to 1) corresponding bit in int_enable */
+    uint32_t int_enable_set;
+    /* Present for debugging, not used */
+    uint32_t int_pending[SLICE_MAX] QEMU_ALIGNED(16);
+    /* Generate an interrupt */
+    uint32_t int_soft;
+    /* Which enabled interrupt is active */
+    uint32_t int_status[SLICE_MAX] QEMU_ALIGNED(16);
+    /* Edge or Level interrupt */
+    uint32_t int_type[SLICE_MAX] QEMU_ALIGNED(16);
+    /* L2 interrupt group 0-3 0x600-0x7FF */
+    uint32_t int_group_n0[SLICE_MAX] QEMU_ALIGNED(16);
+    uint32_t int_group_n1[SLICE_MAX] QEMU_ALIGNED(16);
+    uint32_t int_group_n2[SLICE_MAX] QEMU_ALIGNED(16);
+    uint32_t int_group_n3[SLICE_MAX] QEMU_ALIGNED(16);
+    qemu_irq irq[8];
+} L2VICState;
+
+
+/*
+ * Find out if this irq is associated with a group other than
+ * the default group
+ */
+static uint32_t *get_int_group(L2VICState *s, int irq)
+{
+    int n = irq & 0x1f;
+    if (n < 8) {
+        return s->int_group_n0;
+    }
+    if (n < 16) {
+        return s->int_group_n1;
+    }
+    if (n < 24) {
+        return s->int_group_n2;
+    }
+    return s->int_group_n3;
+}
+
+static int find_slice(int irq)
+{
+    return irq / 32;
+}
+
+static int get_vid(L2VICState *s, int irq)
+{
+    uint32_t *group = get_int_group(s, irq);
+    uint32_t slice = group[find_slice(irq)];
+    /* Mask with 0x7 to remove the GRP:EN bit */
+    uint32_t val = slice >> ((irq & 0x7) * 4);
+    if (val & 0x8) {
+        return val & 0x7;
+    } else {
+        return 0;
+    }
+}
+
+static inline bool vid_active(L2VICState *s)
+
+{
+    /* scan all 1024 bits in int_status arrary */
+    const int size = sizeof(s->int_status) * CHAR_BIT;
+    const int active_irq = find_first_bit((unsigned long *)s->int_status, size);
+    return ((active_irq != size)) ? true : false;
+}
+
+static bool l2vic_update(L2VICState *s, int irq)
+{
+    if (vid_active(s)) {
+        return true;
+    }
+
+    bool pending = test_bit(irq, (unsigned long *)s->int_pending);
+    bool enable = test_bit(irq, (unsigned long *)s->int_enable);
+    if (pending && enable) {
+        int vid = get_vid(s, irq);
+        set_bit(irq, (unsigned long *)s->int_status);
+        clear_bit(irq, (unsigned long *)s->int_pending);
+        clear_bit(irq, (unsigned long *)s->int_enable);
+        /* ensure the irq line goes low after going high */
+        s->vid0 = irq;
+        s->vid_group[get_vid(s, irq)] = irq;
+
+        /* already low: now call pulse */
+        /*     pulse: calls qemu_upper() and then qemu_lower()) */
+        qemu_irq_pulse(s->irq[vid + 2]);
+        trace_l2vic_delivered(irq, vid);
+        return true;
+    }
+    return false;
+}
+
+static void l2vic_update_all(L2VICState *s)
+{
+    for (int i = 0; i < L2VIC_INTERRUPT_MAX; i++) {
+        if (l2vic_update(s, i) == true) {
+            /* once vid is active, no-one else can set it until ciad */
+            return;
+        }
+    }
+}
+
+static void l2vic_set_irq(void *opaque, int irq, int level)
+{
+    L2VICState *s = (L2VICState *)opaque;
+    if (level) {
+        qemu_mutex_lock(&s->active);
+        set_bit(irq, (unsigned long *)s->int_pending);
+        qemu_mutex_unlock(&s->active);
+    }
+    l2vic_update(s, irq);
+}
+
+static void l2vic_write(void *opaque, hwaddr offset, uint64_t val,
+                        unsigned size)
+{
+    L2VICState *s = (L2VICState *)opaque;
+    qemu_mutex_lock(&s->active);
+    trace_l2vic_reg_write((unsigned)offset, (uint32_t)val);
+
+    if (offset == L2VIC_VID_0) {
+        if ((int)val != L2VIC_CIAD_INSTRUCTION) {
+            s->vid0 = val;
+        } else {
+            /* ciad issued: clear int_status */
+            clear_bit(s->vid0, (unsigned long *)s->int_status);
+        }
+    } else if (offset >= L2VIC_INT_ENABLEn &&
+               offset < (L2VIC_INT_ENABLE_CLEARn)) {
+        L2VICA(s->int_enable, offset - L2VIC_INT_ENABLEn) = val;
+    } else if (offset >= L2VIC_INT_ENABLE_CLEARn &&
+               offset < L2VIC_INT_ENABLE_SETn) {
+        L2VICA(s->int_enable, offset - L2VIC_INT_ENABLE_CLEARn) &= ~val;
+    } else if (offset >= L2VIC_INT_ENABLE_SETn && offset < L2VIC_INT_TYPEn) {
+        L2VICA(s->int_enable, offset - L2VIC_INT_ENABLE_SETn) |= val;
+    } else if (offset >= L2VIC_INT_TYPEn && offset < L2VIC_INT_TYPEn + 0x80) {
+        L2VICA(s->int_type, offset - L2VIC_INT_TYPEn) = val;
+    } else if (offset >= L2VIC_INT_STATUSn && offset < L2VIC_INT_CLEARn) {
+        L2VICA(s->int_status, offset - L2VIC_INT_STATUSn) = val;
+    } else if (offset >= L2VIC_INT_CLEARn && offset < L2VIC_SOFT_INTn) {
+        L2VICA(s->int_clear, offset - L2VIC_INT_CLEARn) = val;
+    } else if (offset >= L2VIC_INT_PENDINGn &&
+               offset < L2VIC_INT_PENDINGn + 0x80) {
+        L2VICA(s->int_pending, offset - L2VIC_INT_PENDINGn) = val;
+    } else if (offset >= L2VIC_SOFT_INTn && offset < L2VIC_INT_PENDINGn) {
+        L2VICA(s->int_enable, offset - L2VIC_SOFT_INTn) |= val;
+        /*
+         *  Need to reverse engineer the actual irq number.
+         */
+        int irq = find_first_bit((unsigned long *)&val,
+                                 sizeof(s->int_enable[0]) * CHAR_BIT);
+        hwaddr byteoffset = offset - L2VIC_SOFT_INTn;
+        g_assert(irq != sizeof(s->int_enable[0]) * CHAR_BIT);
+        irq += byteoffset * 8;
+
+        /* The soft-int interface only works with edge-triggered interrupts */
+        if (test_bit(irq, (unsigned long *)s->int_type)) {
+            qemu_mutex_unlock(&s->active);
+            l2vic_set_irq(opaque, irq, 1);
+            qemu_mutex_lock(&s->active);
+        }
+    } else if (offset >= L2VIC_INT_GRPn_0 && offset < L2VIC_INT_GRPn_1) {
+        L2VICA(s->int_group_n0, offset - L2VIC_INT_GRPn_0) = val;
+    } else if (offset >= L2VIC_INT_GRPn_1 && offset < L2VIC_INT_GRPn_2) {
+        L2VICA(s->int_group_n1, offset - L2VIC_INT_GRPn_1) = val;
+    } else if (offset >= L2VIC_INT_GRPn_2 && offset < L2VIC_INT_GRPn_3) {
+        L2VICA(s->int_group_n2, offset - L2VIC_INT_GRPn_2) = val;
+    } else if (offset >= L2VIC_INT_GRPn_3 && offset < L2VIC_INT_GRPn_3 + 0x80) {
+        L2VICA(s->int_group_n3, offset - L2VIC_INT_GRPn_3) = val;
+    } else {
+        qemu_log_mask(LOG_UNIMP, "%s: offset %x unimplemented\n", __func__,
+                      (int)offset);
+    }
+    l2vic_update_all(s);
+    qemu_mutex_unlock(&s->active);
+    return;
+}
+
+static uint64_t l2vic_read(void *opaque, hwaddr offset, unsigned size)
+{
+    uint64_t value;
+    L2VICState *s = (L2VICState *)opaque;
+    qemu_mutex_lock(&s->active);
+
+    if (offset == L2VIC_VID_GRP_0) {
+        value = s->vid_group[0];
+    } else if (offset == L2VIC_VID_GRP_1) {
+        value = s->vid_group[1];
+    } else if (offset == L2VIC_VID_GRP_2) {
+        value = s->vid_group[2];
+    } else if (offset == L2VIC_VID_GRP_3) {
+        value = s->vid_group[3];
+    } else if (offset == L2VIC_VID_0) {
+        value = s->vid0;
+    } else if (offset >= L2VIC_INT_ENABLEn &&
+               offset < L2VIC_INT_ENABLE_CLEARn) {
+        value = L2VICA(s->int_enable, offset - L2VIC_INT_ENABLEn);
+    } else if (offset >= L2VIC_INT_ENABLE_CLEARn &&
+               offset < L2VIC_INT_ENABLE_SETn) {
+        value = 0;
+    } else if (offset >= L2VIC_INT_ENABLE_SETn && offset < L2VIC_INT_TYPEn) {
+        value = 0;
+    } else if (offset >= L2VIC_INT_TYPEn && offset < L2VIC_INT_TYPEn + 0x80) {
+        value = L2VICA(s->int_type, offset - L2VIC_INT_TYPEn);
+    } else if (offset >= L2VIC_INT_STATUSn && offset < L2VIC_INT_CLEARn) {
+        value = L2VICA(s->int_status, offset - L2VIC_INT_STATUSn);
+    } else if (offset >= L2VIC_INT_CLEARn && offset < L2VIC_SOFT_INTn) {
+        value = L2VICA(s->int_clear, offset - L2VIC_INT_CLEARn);
+    } else if (offset >= L2VIC_SOFT_INTn && offset < L2VIC_INT_PENDINGn) {
+        value = 0;
+    } else if (offset >= L2VIC_INT_PENDINGn &&
+               offset < L2VIC_INT_PENDINGn + 0x80) {
+        value = L2VICA(s->int_pending, offset - L2VIC_INT_PENDINGn);
+    } else if (offset >= L2VIC_INT_GRPn_0 && offset < L2VIC_INT_GRPn_1) {
+        value = L2VICA(s->int_group_n0, offset - L2VIC_INT_GRPn_0);
+    } else if (offset >= L2VIC_INT_GRPn_1 && offset < L2VIC_INT_GRPn_2) {
+        value = L2VICA(s->int_group_n1, offset - L2VIC_INT_GRPn_1);
+    } else if (offset >= L2VIC_INT_GRPn_2 && offset < L2VIC_INT_GRPn_3) {
+        value = L2VICA(s->int_group_n2, offset - L2VIC_INT_GRPn_2);
+    } else if (offset >= L2VIC_INT_GRPn_3 && offset < L2VIC_INT_GRPn_3 + 0x80) {
+        value = L2VICA(s->int_group_n3, offset - L2VIC_INT_GRPn_3);
+    } else {
+        value = 0;
+        qemu_log_mask(LOG_GUEST_ERROR, "L2VIC: %s: offset 0x%x\n", __func__,
+                      (int)offset);
+    }
+
+    trace_l2vic_reg_read((unsigned)offset, value);
+    qemu_mutex_unlock(&s->active);
+
+    return value;
+}
+
+static const MemoryRegionOps l2vic_ops = {
+    .read = l2vic_read,
+    .write = l2vic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .valid.unaligned = false,
+};
+
+#define FASTL2VIC_ENABLE 0x0
+#define FASTL2VIC_DISABLE 0x1
+#define FASTL2VIC_INT 0x2
+
+static void fastl2vic_write(void *opaque, hwaddr offset, uint64_t val,
+                            unsigned size)
+{
+    if (offset == 0) {
+        uint32_t cmd = (val >> 16) & 0x3;
+        uint32_t irq = val & 0x3ff;
+        uint32_t slice = (irq / 32) * 4;
+        val = 1 << (irq % 32);
+
+        if (cmd == FASTL2VIC_ENABLE) {
+            l2vic_write(opaque, L2VIC_INT_ENABLE_SETn + slice, val, size);
+        } else if (cmd == FASTL2VIC_DISABLE) {
+            l2vic_write(opaque, L2VIC_INT_ENABLE_CLEARn + slice, val, size);
+        } else if (cmd == FASTL2VIC_INT) {
+            l2vic_write(opaque, L2VIC_SOFT_INTn + slice, val, size);
+        }
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid write cmd %" PRId32 "\n",
+            __func__, cmd);
+        return;
+    }
+    qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid write offset 0x%08" HWADDR_PRIx
+            "\n", __func__, offset);
+}
+
+static const MemoryRegionOps fastl2vic_ops = {
+    .write = fastl2vic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .valid.unaligned = false,
+};
+
+static void l2vic_reset_hold(Object *obj, G_GNUC_UNUSED ResetType res_type)
+{
+    L2VICState *s = L2VIC(obj);
+    memset(s->int_clear, 0, sizeof(s->int_clear));
+    memset(s->int_enable, 0, sizeof(s->int_enable));
+    memset(s->int_pending, 0, sizeof(s->int_pending));
+    memset(s->int_status, 0, sizeof(s->int_status));
+    memset(s->int_type, 0, sizeof(s->int_type));
+    memset(s->int_group_n0, 0, sizeof(s->int_group_n0));
+    memset(s->int_group_n1, 0, sizeof(s->int_group_n1));
+    memset(s->int_group_n2, 0, sizeof(s->int_group_n2));
+    memset(s->int_group_n3, 0, sizeof(s->int_group_n3));
+    s->int_soft = 0;
+    s->vid0 = 0;
+
+    l2vic_update_all(s);
+}
+
+
+static void reset_irq_handler(void *opaque, int irq, int level)
+{
+    L2VICState *s = (L2VICState *)opaque;
+    Object *obj = OBJECT(opaque);
+    if (level) {
+        l2vic_reset_hold(obj, RESET_TYPE_COLD);
+    }
+    l2vic_update_all(s);
+}
+
+static void l2vic_init(Object *obj)
+{
+    DeviceState *dev = DEVICE(obj);
+    L2VICState *s = L2VIC(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    int i;
+
+    memory_region_init_io(&s->iomem, obj, &l2vic_ops, s, "l2vic", 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+    memory_region_init_io(&s->fast_iomem, obj, &fastl2vic_ops, s, "fast",
+                          0x10000);
+    sysbus_init_mmio(sbd, &s->fast_iomem);
+
+    qdev_init_gpio_in(dev, l2vic_set_irq, L2VIC_INTERRUPT_MAX);
+    qdev_init_gpio_in_named(dev, reset_irq_handler, "reset", 1);
+    for (i = 0; i < 8; i++) {
+        sysbus_init_irq(sbd, &s->irq[i]);
+    }
+    qemu_mutex_init(&s->active); /* TODO: Remove this is an experiment */
+}
+
+static const VMStateDescription vmstate_l2vic = {
+    .name = "l2vic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields =
+        (VMStateField[]){
+            VMSTATE_UINT32(level, L2VICState),
+            VMSTATE_UINT32_ARRAY(vid_group, L2VICState, 4),
+            VMSTATE_UINT32(vid0, L2VICState),
+            VMSTATE_UINT32_ARRAY(int_enable, L2VICState, SLICE_MAX),
+            VMSTATE_UINT32(int_enable_clear, L2VICState),
+            VMSTATE_UINT32(int_enable_set, L2VICState),
+            VMSTATE_UINT32_ARRAY(int_type, L2VICState, SLICE_MAX),
+            VMSTATE_UINT32_ARRAY(int_status, L2VICState, SLICE_MAX),
+            VMSTATE_UINT32_ARRAY(int_clear, L2VICState, SLICE_MAX),
+            VMSTATE_UINT32(int_soft, L2VICState),
+            VMSTATE_UINT32_ARRAY(int_pending, L2VICState, SLICE_MAX),
+            VMSTATE_UINT32_ARRAY(int_group_n0, L2VICState, SLICE_MAX),
+            VMSTATE_UINT32_ARRAY(int_group_n1, L2VICState, SLICE_MAX),
+            VMSTATE_UINT32_ARRAY(int_group_n2, L2VICState, SLICE_MAX),
+            VMSTATE_UINT32_ARRAY(int_group_n3, L2VICState, SLICE_MAX),
+            VMSTATE_END_OF_LIST() }
+};
+
+static void l2vic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    dc->vmsd = &vmstate_l2vic;
+    rc->phases.hold = l2vic_reset_hold;
+}
+
+static const TypeInfo l2vic_info = {
+    .name = TYPE_L2VIC,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(L2VICState),
+    .instance_init = l2vic_init,
+    .class_init = l2vic_class_init,
+};
+
+static void l2vic_register_types(void)
+{
+    type_register_static(&l2vic_info);
+}
+
+type_init(l2vic_register_types)
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index dd405bdb5d..471e02df27 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -8,6 +8,9 @@ config I8259
 config PL190
     bool
 
+config L2VIC
+    bool
+
 config IOAPIC
     bool
     select I8259
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 510fdfb688..919abe5eec 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -67,6 +67,8 @@ specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('xics_spapr.c', 'spapr_xi
 specific_ss.add(when: 'CONFIG_XIVE', if_true: files('xive.c'))
 specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'],
 		if_true: files('spapr_xive_kvm.c'))
+
+specific_ss.add(when: 'CONFIG_L2VIC', if_true: files('l2vic.c'))
 specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
 specific_ss.add(when: 'CONFIG_LOONGSON_IPI_COMMON', if_true: files('loongson_ipi_common.c'))
 specific_ss.add(when: 'CONFIG_LOONGSON_IPI', if_true: files('loongson_ipi.c'))
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 3dcf147198..bc66260fc0 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -303,6 +303,10 @@ sh_intc_register(const char *s, int id, unsigned short v, int c, int m) "%s %u -
 sh_intc_read(unsigned size, uint64_t offset, unsigned long val) "size %u 0x%" PRIx64 " -> 0x%lx"
 sh_intc_write(unsigned size, uint64_t offset, unsigned long val) "size %u 0x%" PRIx64 " <- 0x%lx"
 sh_intc_set(int id, int enable) "setting interrupt group %d to %d"
+# l2vic.c
+l2vic_reg_write(unsigned int addr, uint32_t value) "addr: 0x%03x value: 0x%08"PRIx32
+l2vic_reg_read(unsigned int addr, uint32_t value) "addr: 0x%03x value: 0x%08"PRIx32
+l2vic_delivered(int irq, int vid) "l2vic: delivered %d (vid %d)"
 
 # loongson_ipi.c
 loongson_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
-- 
2.34.1


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

* [PATCH 2/8] hw/hexagon: Add machine configs for sysemu
  2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
  2025-03-01 17:20 ` [PATCH 1/8] hw/intc: Add l2vic interrupt controller Brian Cain
@ 2025-03-01 17:20 ` Brian Cain
  2025-03-04  6:27   ` Markus Armbruster
  2025-03-24 19:48   ` ltaylorsimpson
  2025-03-01 17:20 ` [PATCH 3/8] hw/hexagon: Add v68, sa8775-cdsp0 defs Brian Cain
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Brian Cain, Mike Lambert, Paolo Bonzini, Eduardo Habkost,
	Marcel Apfelbaum, Yanan Wang, Zhao Liu, Eric Blake,
	Markus Armbruster

From: Brian Cain <bcain@quicinc.com>

Co-authored-by: Mike Lambert <mlambert@quicinc.com>
Co-authored-by: Sid Manning <sidneym@quicinc.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 MAINTAINERS                            |   2 +
 qapi/machine.json                      |   2 +-
 include/hw/hexagon/hexagon.h           | 151 +++++++++++++++++++++
 hw/hexagon/machine_cfg_v66g_1024.h.inc |  64 +++++++++
 hw/hexagon/hexagon_dsp.c               | 177 +++++++++++++++++++++++++
 target/hexagon/machine.c               |   1 -
 hw/Kconfig                             |   1 +
 hw/hexagon/Kconfig                     |   6 +
 hw/hexagon/meson.build                 |   5 +
 hw/meson.build                         |   1 +
 10 files changed, 408 insertions(+), 2 deletions(-)
 create mode 100644 include/hw/hexagon/hexagon.h
 create mode 100644 hw/hexagon/machine_cfg_v66g_1024.h.inc
 create mode 100644 hw/hexagon/hexagon_dsp.c
 create mode 100644 hw/hexagon/Kconfig
 create mode 100644 hw/hexagon/meson.build

diff --git a/MAINTAINERS b/MAINTAINERS
index a842f7fe1b..0fb5711184 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -233,6 +233,8 @@ M: Brian Cain <brian.cain@oss.qualcomm.com>
 S: Supported
 F: target/hexagon/
 F: hw/intc/l2vic.[ch]
+F: hw/hexagon/
+F: include/hw/hexagon/
 X: target/hexagon/idef-parser/
 X: target/hexagon/gen_idef_parser_funcs.py
 F: linux-user/hexagon/
diff --git a/qapi/machine.json b/qapi/machine.json
index a6b8795b09..a7070bad4d 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -33,7 +33,7 @@
 # Since: 3.0
 ##
 { 'enum' : 'SysEmuTarget',
-  'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'hppa', 'i386',
+  'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'hexagon', 'hppa', 'i386',
              'loongarch64', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
              'mips64el', 'mipsel', 'or1k', 'ppc',
              'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h
new file mode 100644
index 0000000000..0afaac3b1f
--- /dev/null
+++ b/include/hw/hexagon/hexagon.h
@@ -0,0 +1,151 @@
+/*
+ * Hexagon Baseboard System emulation.
+ *
+ * Copyright (c) 2020-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+
+#ifndef HW_HEXAGON_H
+#define HW_HEXAGON_H
+
+#include "exec/memory.h"
+
+struct hexagon_board_boot_info {
+    uint64_t ram_size;
+    const char *kernel_filename;
+    uint32_t kernel_elf_flags;
+};
+
+typedef enum {
+    unknown_rev = 0,
+    v66_rev = 0xa666,
+    v67_rev = 0x2667,
+    v68_rev = 0x8d68,
+    v69_rev = 0x8c69,
+    v71_rev = 0x8c71,
+    v73_rev = 0x8c73,
+    v73m_rev = 0xcc73,
+} Rev_t;
+#define HEXAGON_LATEST_REV v73
+#define HEXAGON_LATEST_REV_UPPER V73
+
+/*
+ * Config table address bases represent bits [35:16].
+ */
+#define HEXAGON_CFG_ADDR_BASE(addr) (((addr) >> 16) & 0x0fffff)
+
+#define HEXAGON_CFGSPACE_ENTRIES (128)
+
+typedef  union {
+  struct {
+    /* Base address of L2TCM space */
+    uint32_t l2tcm_base;
+    uint32_t reserved0;
+    /* Base address of subsystem space */
+    uint32_t subsystem_base;
+    /* Base address of ETM space */
+    uint32_t etm_base;
+    /* Base address of L2 configuration space */
+    uint32_t l2cfg_base;
+    uint32_t reserved1;
+    /* Base address of L1S */
+    uint32_t l1s0_base;
+    /* Base address of AXI2 */
+    uint32_t axi2_lowaddr;
+    /* Base address of streamer base */
+    uint32_t streamer_base;
+    uint32_t reserved2;
+    /* Base address of fast L2VIC */
+    uint32_t fastl2vic_base;
+    /* Number of entries in JTLB */
+    uint32_t jtlb_size_entries;
+    /* Coprocessor type */
+    uint32_t coproc_present;
+    /* Number of extension execution contexts available */
+    uint32_t ext_contexts;
+    /* Base address of Hexagon Vector Tightly Coupled Memory (VTCM) */
+    uint32_t vtcm_base;
+    /* Size of VTCM (in KB) */
+    uint32_t vtcm_size_kb;
+    /* L2 tag size */
+    uint32_t l2tag_size;
+    /* Amount of physical L2 memory in released version */
+    uint32_t l2ecomem_size;
+    /* Hardware threads available on the core */
+    uint32_t thread_enable_mask;
+    /* Base address of the ECC registers */
+    uint32_t eccreg_base;
+    /* L2 line size */
+    uint32_t l2line_size;
+    /* Small Core processor (also implies audio extension) */
+    uint32_t tiny_core;
+    /* Size of L2TCM */
+    uint32_t l2itcm_size;
+    /* Base address of L2-ITCM */
+    uint32_t l2itcm_base;
+    uint32_t reserved3;
+    /* DTM is present */
+    uint32_t dtm_present;
+    /* Version of the DMA */
+    uint32_t dma_version;
+    /* Native HVX vector length in log of bytes */
+    uint32_t hvx_vec_log_length;
+    /* Core ID of the multi-core */
+    uint32_t core_id;
+    /* Number of multi-core cores */
+    uint32_t core_count;
+    uint32_t coproc2_reg0;
+    uint32_t coproc2_reg1;
+    /* Supported HVX vector length */
+    uint32_t v2x_mode;
+    uint32_t coproc2_reg2;
+    uint32_t coproc2_reg3;
+    uint32_t coproc2_reg4;
+    uint32_t coproc2_reg5;
+    uint32_t coproc2_reg6;
+    uint32_t coproc2_reg7;
+    /* Voltage droop mitigation technique parameter */
+    uint32_t acd_preset;
+    /* Voltage droop mitigation technique parameter */
+    uint32_t mnd_preset;
+    /* L1 data cache size (in KB) */
+    uint32_t l1d_size_kb;
+    /* L1 instruction cache size in (KB) */
+    uint32_t l1i_size_kb;
+    /* L1 data cache write policy: see HexagonL1WritePolicy */
+    uint32_t l1d_write_policy;
+    /* VTCM bank width  */
+    uint32_t vtcm_bank_width;
+    uint32_t reserved4;
+    uint32_t reserved5;
+    uint32_t reserved6;
+    uint32_t coproc2_cvt_mpy_size;
+    uint32_t consistency_domain;
+    uint32_t capacity_domain;
+    uint32_t axi3_lowaddr;
+    uint32_t coproc2_int8_subcolumns;
+    uint32_t corecfg_present;
+    uint32_t coproc2_fp16_acc_exp;
+    uint32_t AXIM2_secondary_base;
+  };
+  uint32_t raw[HEXAGON_CFGSPACE_ENTRIES];
+} hexagon_config_table;
+
+typedef struct {
+    /* Base address of config table */
+    uint32_t cfgbase;
+    /* Size of L2 TCM */
+    uint32_t l2tcm_size;
+    /* Base address of L2VIC */
+    uint32_t l2vic_base;
+    /* Size of L2VIC region */
+    uint32_t l2vic_size;
+    /* QTimer csr base */
+    uint32_t csr_base;
+    uint32_t qtmr_rg0;
+    uint32_t qtmr_rg1;
+    hexagon_config_table cfgtable;
+} hexagon_machine_config;
+
+#endif
diff --git a/hw/hexagon/machine_cfg_v66g_1024.h.inc b/hw/hexagon/machine_cfg_v66g_1024.h.inc
new file mode 100644
index 0000000000..604cc7777c
--- /dev/null
+++ b/hw/hexagon/machine_cfg_v66g_1024.h.inc
@@ -0,0 +1,64 @@
+
+static hexagon_machine_config v66g_1024 = {
+    .cfgbase =        0xd8180000,
+    .l2tcm_size =     0x00000000,
+    .l2vic_base =     0xfc910000,
+    .l2vic_size =     0x00001000,
+    .csr_base =       0xfc900000,
+    .qtmr_rg0 =       0xfc921000,
+    .qtmr_rg1 =       0xfc922000,
+    .cfgtable = {
+        .l2tcm_base = 0x0000d800,
+        .reserved0 = 0x0000d400,
+        .subsystem_base = 0x0000fc90,
+        .etm_base = 0x0000d805,
+        .l2cfg_base = 0x0000d81a,
+        .reserved1 = 0x00000000,
+        .l1s0_base = 0x0000d820,
+        .axi2_lowaddr = 0x00003000,
+        .streamer_base = 0x00000000,
+        .reserved2 = 0x0000d819,
+        .fastl2vic_base = 0x0000d81e,
+        .jtlb_size_entries = 0x00000080,
+        .coproc_present = 0x00000001,
+        .ext_contexts = 0x00000004,
+        .vtcm_base = 0x0000d820,
+        .vtcm_size_kb = 0x00000100,
+        .l2tag_size = 0x00000400,
+        .l2ecomem_size = 0x00000400,
+        .thread_enable_mask = 0x0000000f,
+        .eccreg_base = 0x0000d81f,
+        .l2line_size = 0x00000080,
+        .tiny_core = 0x00000000,
+        .l2itcm_size = 0x00000000,
+        .l2itcm_base = 0x0000d820,
+        .reserved3 = 0x00000000,
+        .dtm_present = 0x00000000,
+        .dma_version = 0x00000000,
+        .hvx_vec_log_length = 0x00000080,
+        .core_id = 0x00000000,
+        .core_count = 0x00000000,
+        .coproc2_reg0 = 0x00000000,
+        .coproc2_reg1 = 0x00000000,
+        .v2x_mode = 0x00000000,
+        .coproc2_reg2 = 0x00000000,
+        .coproc2_reg3 = 0x00000000,
+        .coproc2_reg4 = 0x00000000,
+        .coproc2_reg5 = 0x00000000,
+        .coproc2_reg6 = 0x00000000,
+        .coproc2_reg7 = 0x00000000,
+        .acd_preset = 0x00000000,
+        .mnd_preset = 0x00000000,
+        .l1d_size_kb = 0x00000000,
+        .l1i_size_kb = 0x00000000,
+        .l1d_write_policy = 0x00000000,
+        .vtcm_bank_width = 0x00000000,
+        .reserved3 = 0x00000000,
+        .reserved4 = 0x00000000,
+        .reserved5 = 0x00000000,
+        .coproc2_cvt_mpy_size = 0x00000000,
+        .consistency_domain = 0x00000000,
+        .capacity_domain = 0x00000000,
+        .axi3_lowaddr = 0x00000000,
+    },
+};
diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c
new file mode 100644
index 0000000000..9f18cb6e3a
--- /dev/null
+++ b/hw/hexagon/hexagon_dsp.c
@@ -0,0 +1,177 @@
+/*
+ * Hexagon DSP Subsystem emulation.  This represents a generic DSP
+ * subsystem with few peripherals, like the Compute DSP.
+ *
+ * Copyright (c) 2020-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "exec/address-spaces.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/qdev-properties.h"
+#include "hw/hexagon/hexagon.h"
+#include "hw/loader.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "elf.h"
+#include "cpu.h"
+#include "include/migration/cpu.h"
+#include "include/system/system.h"
+#include "target/hexagon/internal.h"
+#include "system/reset.h"
+
+#include "machine_cfg_v66g_1024.h.inc"
+
+static void hex_symbol_callback(const char *st_name, int st_info,
+                                uint64_t st_value, uint64_t st_size)
+{
+}
+
+/* Board init.  */
+static struct hexagon_board_boot_info hexagon_binfo;
+
+static void hexagon_load_kernel(HexagonCPU *cpu)
+{
+    uint64_t pentry;
+    long kernel_size;
+
+    kernel_size = load_elf_ram_sym(hexagon_binfo.kernel_filename, NULL, NULL,
+                      NULL, &pentry, NULL, NULL,
+                      &hexagon_binfo.kernel_elf_flags, 0, EM_HEXAGON, 0, 0,
+                      &address_space_memory, false, hex_symbol_callback);
+
+    if (kernel_size <= 0) {
+        error_report("no kernel file '%s'",
+            hexagon_binfo.kernel_filename);
+        exit(1);
+    }
+
+    qdev_prop_set_uint32(DEVICE(cpu), "exec-start-addr", pentry);
+}
+
+static void hexagon_init_bootstrap(MachineState *machine, HexagonCPU *cpu)
+{
+    if (machine->kernel_filename) {
+        hexagon_load_kernel(cpu);
+    }
+}
+
+static void do_cpu_reset(void *opaque)
+{
+    HexagonCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
+    cpu_reset(cs);
+}
+
+static void hexagon_common_init(MachineState *machine, Rev_t rev,
+                                hexagon_machine_config *m_cfg)
+{
+    memset(&hexagon_binfo, 0, sizeof(hexagon_binfo));
+    if (machine->kernel_filename) {
+        hexagon_binfo.ram_size = machine->ram_size;
+        hexagon_binfo.kernel_filename = machine->kernel_filename;
+    }
+
+    machine->enable_graphics = 0;
+
+    MemoryRegion *address_space = get_system_memory();
+
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sram, NULL, "ddr.ram",
+        machine->ram_size, &error_fatal);
+    memory_region_add_subregion(address_space, 0x0, sram);
+
+    Error **errp = NULL;
+
+    for (int i = 0; i < machine->smp.cpus; i++) {
+        HexagonCPU *cpu = HEXAGON_CPU(object_new(machine->cpu_type));
+        qemu_register_reset(do_cpu_reset, cpu);
+
+        /*
+         * CPU #0 is the only CPU running at boot, others must be
+         * explicitly enabled via start instruction.
+         */
+        qdev_prop_set_bit(DEVICE(cpu), "start-powered-off", (i != 0));
+        qdev_prop_set_uint32(DEVICE(cpu), "l2vic-base-addr", m_cfg->l2vic_base);
+        qdev_prop_set_uint32(DEVICE(cpu), "config-table-addr", m_cfg->cfgbase);
+        qdev_prop_set_uint32(DEVICE(cpu), "hvx-contexts",
+                             m_cfg->cfgtable.ext_contexts);
+        qdev_prop_set_uint32(DEVICE(cpu), "jtlb-entries",
+                             m_cfg->cfgtable.jtlb_size_entries);
+
+
+        if (i == 0) {
+            hexagon_init_bootstrap(machine, cpu);
+            if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) {
+                return;
+            }
+            DeviceState *l2vic_dev;
+            l2vic_dev = sysbus_create_varargs("l2vic", m_cfg->l2vic_base,
+                    /* IRQ#, Evnt#,CauseCode */
+                    qdev_get_gpio_in(DEVICE(cpu), 0),
+                    qdev_get_gpio_in(DEVICE(cpu), 1),
+                    qdev_get_gpio_in(DEVICE(cpu), 2),
+                    qdev_get_gpio_in(DEVICE(cpu), 3),
+                    qdev_get_gpio_in(DEVICE(cpu), 4),
+                    qdev_get_gpio_in(DEVICE(cpu), 5),
+                    qdev_get_gpio_in(DEVICE(cpu), 6),
+                    qdev_get_gpio_in(DEVICE(cpu), 7),
+                    NULL);
+            sysbus_mmio_map(SYS_BUS_DEVICE(l2vic_dev), 1,
+                m_cfg->cfgtable.fastl2vic_base << 16);
+        } else if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) {
+            return;
+        }
+
+    }
+}
+
+static void init_mc(MachineClass *mc)
+{
+    mc->block_default_type = IF_SD;
+    mc->default_ram_size = 4 * GiB;
+    mc->no_parallel = 1;
+    mc->no_floppy = 1;
+    mc->no_cdrom = 1;
+    mc->no_serial = 1;
+    mc->is_default = false;
+    mc->max_cpus = 8;
+}
+
+/* ----------------------------------------------------------------- */
+/* Core-specific configuration settings are defined below this line. */
+/* Config table values defined in machine_configs.h.inc              */
+/* ----------------------------------------------------------------- */
+
+static void v66g_1024_config_init(MachineState *machine)
+{
+    hexagon_common_init(machine, v66_rev, &v66g_1024);
+}
+
+static void v66g_1024_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "Hexagon V66G_1024";
+    mc->init = v66g_1024_config_init;
+    init_mc(mc);
+    mc->is_default = true;
+    mc->default_cpu_type = TYPE_HEXAGON_CPU_V66;
+    mc->default_cpus = 4;
+}
+
+static const TypeInfo hexagon_machine_types[] = {
+    {
+        .name = MACHINE_TYPE_NAME("V66G_1024"),
+        .parent = TYPE_MACHINE,
+        .class_init = v66g_1024_init,
+    },
+};
+
+DEFINE_TYPES(hexagon_machine_types)
diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
index 4baa22d51f..79e9b7effa 100644
--- a/target/hexagon/machine.c
+++ b/target/hexagon/machine.c
@@ -79,7 +79,6 @@ const VMStateDescription vmstate_hexagon_cpu = {
         VMSTATE_UINT64(env.t_cycle_count, HexagonCPU),
         VMSTATE_POINTER(env.g_pcycle_base, HexagonCPU, 0,
                         vmstate_info_uint64_ptr, uint64_t *),
-
         VMSTATE_END_OF_LIST()
     },
 };
diff --git a/hw/Kconfig b/hw/Kconfig
index 1b4e9bb07f..b363d4561a 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -65,6 +65,7 @@ source sparc/Kconfig
 source sparc64/Kconfig
 source tricore/Kconfig
 source xtensa/Kconfig
+source hexagon/Kconfig
 
 # Symbols used by multiple targets
 config TEST_DEVICES
diff --git a/hw/hexagon/Kconfig b/hw/hexagon/Kconfig
new file mode 100644
index 0000000000..3fc14756e6
--- /dev/null
+++ b/hw/hexagon/Kconfig
@@ -0,0 +1,6 @@
+config HEX_DSP
+    bool
+    default y
+    depends on HEXAGON && TCG
+    imply PTIMER
+    select L2VIC  # Vector PIC
diff --git a/hw/hexagon/meson.build b/hw/hexagon/meson.build
new file mode 100644
index 0000000000..2ef3dbcd34
--- /dev/null
+++ b/hw/hexagon/meson.build
@@ -0,0 +1,5 @@
+hexagon_ss = ss.source_set()
+hexagon_ss.add(when: 'CONFIG_HEX_DSP', if_true: files('hexagon_dsp.c',))
+
+hw_arch += {'hexagon': hexagon_ss}
+
diff --git a/hw/meson.build b/hw/meson.build
index b827c82c5d..91969d6fec 100644
--- a/hw/meson.build
+++ b/hw/meson.build
@@ -64,3 +64,4 @@ subdir('sparc')
 subdir('sparc64')
 subdir('tricore')
 subdir('xtensa')
+subdir('hexagon')
-- 
2.34.1


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

* [PATCH 3/8] hw/hexagon: Add v68, sa8775-cdsp0 defs
  2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
  2025-03-01 17:20 ` [PATCH 1/8] hw/intc: Add l2vic interrupt controller Brian Cain
  2025-03-01 17:20 ` [PATCH 2/8] hw/hexagon: Add machine configs for sysemu Brian Cain
@ 2025-03-01 17:20 ` Brian Cain
  2025-03-24 19:50   ` ltaylorsimpson
  2025-03-01 17:20 ` [PATCH 4/8] hw/hexagon: Add support for cfgbase Brian Cain
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 hw/hexagon/machine_cfg_sa8775_cdsp0.h.inc | 64 ++++++++++++++++++++++
 hw/hexagon/machine_cfg_v68n_1024.h.inc    | 65 +++++++++++++++++++++++
 2 files changed, 129 insertions(+)
 create mode 100644 hw/hexagon/machine_cfg_sa8775_cdsp0.h.inc
 create mode 100644 hw/hexagon/machine_cfg_v68n_1024.h.inc

diff --git a/hw/hexagon/machine_cfg_sa8775_cdsp0.h.inc b/hw/hexagon/machine_cfg_sa8775_cdsp0.h.inc
new file mode 100644
index 0000000000..d8fa961f6d
--- /dev/null
+++ b/hw/hexagon/machine_cfg_sa8775_cdsp0.h.inc
@@ -0,0 +1,64 @@
+
+static hexagon_machine_config SA8775P_cdsp0 = {
+    .cfgbase =         0x24000000 + 0x180000,
+    .l2tcm_size =      0x00000000,
+    .l2vic_base =      0x26300000 + 0x90000,
+    .l2vic_size =      0x00001000,
+    .csr_base =        0x26300000,
+    .qtmr_rg0 =        0x26300000 + 0xA1000,
+    .qtmr_rg1 =        0x26300000 + 0xA2000,
+    .cfgtable = {
+        .l2tcm_base = 0x00002400,
+        .reserved0 = 0x00000000,
+        .subsystem_base = 0x00002638,
+        .etm_base = 0x00002419,
+        .l2cfg_base = 0x0000241a,
+        .reserved1 = 0x0000241b,
+        .l1s0_base = 0x00002500,
+        .axi2_lowaddr = 0x00000000,
+        .streamer_base = 0x00000000,
+        .reserved2 = 0x00000000,
+        .fastl2vic_base = 0x0000241e,
+        .jtlb_size_entries = 0x00000080,
+        .coproc_present = 0x00000001,
+        .ext_contexts = 0x00000004,
+        .vtcm_base = 0x00002500,
+        .vtcm_size_kb = 0x00002000,
+        .l2tag_size = 0x00000400,
+        .l2ecomem_size = 0x00000000,
+        .thread_enable_mask = 0x0000003f,
+        .eccreg_base = 0x0000241f,
+        .l2line_size = 0x00000080,
+        .tiny_core = 0x00000000,
+        .l2itcm_size = 0x00000000,
+        .l2itcm_base = 0x00002400,
+        .reserved3 = 0x00000000,
+        .dtm_present = 0x00000000,
+        .dma_version = 0x00000003,
+        .hvx_vec_log_length = 0x00000007,
+        .core_id = 0x00000000,
+        .core_count = 0x00000000,
+        .coproc2_reg0 = 0x00000040,
+        .coproc2_reg1 = 0x00000020,
+        .v2x_mode = 0x00000001,
+        .coproc2_reg2 = 0x00000008,
+        .coproc2_reg3 = 0x00000020,
+        .coproc2_reg4 = 0x00000000,
+        .coproc2_reg5 = 0x00000002,
+        .coproc2_reg6 = 0x00000016,
+        .coproc2_reg7 = 0x00000006,
+        .acd_preset = 0x00000001,
+        .mnd_preset = 0x00000000,
+        .l1d_size_kb = 0x00000010,
+        .l1i_size_kb = 0x00000020,
+        .l1d_write_policy = 0x00000002,
+        .vtcm_bank_width = 0x00000080,
+        .reserved3 = 0x00000001,
+        .reserved4 = 0x00000000,
+        .reserved5 = 0x00000003,
+        .coproc2_cvt_mpy_size = 0x0000000a,
+        .consistency_domain = 0x000000e0,
+        .capacity_domain = 0x00000080,
+        .axi3_lowaddr = 0x00000000,
+    },
+};
diff --git a/hw/hexagon/machine_cfg_v68n_1024.h.inc b/hw/hexagon/machine_cfg_v68n_1024.h.inc
new file mode 100644
index 0000000000..60eb112a11
--- /dev/null
+++ b/hw/hexagon/machine_cfg_v68n_1024.h.inc
@@ -0,0 +1,65 @@
+
+static hexagon_machine_config v68n_1024 = {
+    .cfgbase =           0xde000000,
+    .l2tcm_size =        0x00000000,
+    .l2vic_base =        0xfc910000,
+    .l2vic_size =        0x00001000,
+    .csr_base =          0xfc900000,
+    .qtmr_rg0 =          0xfc921000,
+    .qtmr_rg1 =          0xfc922000,
+    .cfgtable = {
+        .l2tcm_base = 0x0000d800,
+        .reserved0 = 0x00000000,
+        .subsystem_base = 0x0000fc90,
+        .etm_base = 0x0000d819,
+        .l2cfg_base = 0x0000d81a,
+        .reserved1 = 0x00000000,
+        .l1s0_base = 0x0000d840,
+        .axi2_lowaddr = 0x00003000,
+        .streamer_base = 0x0000d81c,
+        .reserved2 = 0x0000d81d,
+        .fastl2vic_base = 0x0000d81e,
+        .jtlb_size_entries = 0x00000080,
+        .coproc_present = 0x00000001,
+        .ext_contexts = 0x00000004,
+        .vtcm_base = 0x0000d840,
+        .vtcm_size_kb = 0x00001000,
+        .l2tag_size = 0x00000400,
+        .l2ecomem_size = 0x00000400,
+        .thread_enable_mask = 0x0000003f,
+        .eccreg_base = 0x0000d81f,
+        .l2line_size = 0x00000080,
+        .tiny_core = 0x00000000,
+        .l2itcm_size = 0x00000000,
+        .l2itcm_base = 0x0000d820,
+        .reserved3 = 0x00000000,
+        .dtm_present = 0x00000000,
+        .dma_version = 0x00000001,
+        .hvx_vec_log_length = 0x00000007,
+        .core_id = 0x00000000,
+        .core_count = 0x00000000,
+        .coproc2_reg0 = 0x00000040,
+        .coproc2_reg1 = 0x00000020,
+        .v2x_mode = 0x1f1f1f1f,
+        .coproc2_reg2 = 0x1f1f1f1f,
+        .coproc2_reg3 = 0x1f1f1f1f,
+        .coproc2_reg4 = 0x1f1f1f1f,
+        .coproc2_reg5 = 0x1f1f1f1f,
+        .coproc2_reg6 = 0x1f1f1f1f,
+        .coproc2_reg7 = 0x1f1f1f1f,
+        .acd_preset = 0x1f1f1f1f,
+        .mnd_preset = 0x1f1f1f1f,
+        .l1d_size_kb = 0x1f1f1f1f,
+        .l1i_size_kb = 0x1f1f1f1f,
+        .l1d_write_policy = 0x1f1f1f1f,
+        .vtcm_bank_width = 0x1f1f1f1f,
+        .reserved3 = 0x1f1f1f1f,
+        .reserved4 = 0x1f1f1f1f,
+        .reserved5 = 0x1f1f1f1f,
+        .coproc2_cvt_mpy_size = 0x1f1f1f1f,
+        .consistency_domain = 0x1f1f1f1f,
+        .capacity_domain = 0x1f1f1f1f,
+        .axi3_lowaddr = 0x1f1f1f1f,
+    },
+};
+
-- 
2.34.1


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

* [PATCH 4/8] hw/hexagon: Add support for cfgbase
  2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
                   ` (2 preceding siblings ...)
  2025-03-01 17:20 ` [PATCH 3/8] hw/hexagon: Add v68, sa8775-cdsp0 defs Brian Cain
@ 2025-03-01 17:20 ` Brian Cain
  2025-03-24 20:01   ` ltaylorsimpson
  2025-03-01 17:20 ` [PATCH 5/8] hw/hexagon: Modify "Standalone" symbols Brian Cain
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym

From: Sid Manning <sidneym@quicinc.com>

Signed-off-by: Sid Manning <sidneym@quicinc.com>
---
 target/hexagon/cpu.h     |  1 +
 hw/hexagon/hexagon_dsp.c | 10 ++++++++++
 target/hexagon/cpu.c     |  6 ++++++
 3 files changed, 17 insertions(+)

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 73c3bb34b0..0608d3265c 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -195,6 +195,7 @@ struct ArchCPU {
     uint32_t l2vic_base_addr;
     uint32_t hvx_contexts;
     uint32_t boot_addr;
+    uint64_t config_table_addr;
 #endif
 };
 
diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c
index 9f18cb6e3a..c4962a98bc 100644
--- a/hw/hexagon/hexagon_dsp.c
+++ b/hw/hexagon/hexagon_dsp.c
@@ -82,6 +82,12 @@ static void hexagon_common_init(MachineState *machine, Rev_t rev,
 
     MemoryRegion *address_space = get_system_memory();
 
+    MemoryRegion *config_table_rom = g_new(MemoryRegion, 1);
+    memory_region_init_rom(config_table_rom, NULL, "config_table.rom",
+                           sizeof(m_cfg->cfgtable), &error_fatal);
+    memory_region_add_subregion(address_space, m_cfg->cfgbase,
+                                config_table_rom);
+
     MemoryRegion *sram = g_new(MemoryRegion, 1);
     memory_region_init_ram(sram, NULL, "ddr.ram",
         machine->ram_size, &error_fatal);
@@ -130,6 +136,10 @@ static void hexagon_common_init(MachineState *machine, Rev_t rev,
         }
 
     }
+
+    rom_add_blob_fixed_as("config_table.rom", &m_cfg->cfgtable,
+                          sizeof(m_cfg->cfgtable), m_cfg->cfgbase,
+                          &address_space_memory);
 }
 
 static void init_mc(MachineClass *mc)
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 4ca6add834..34940e9a84 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -67,6 +67,8 @@ static const Property hexagon_cpu_properties[] = {
         0xffffffffULL),
     DEFINE_PROP_UINT32("hvx-contexts", HexagonCPU, hvx_contexts, 0),
     DEFINE_PROP_UINT32("exec-start-addr", HexagonCPU, boot_addr, 0xffffffffULL),
+    DEFINE_PROP_UINT64("config-table-addr", HexagonCPU, config_table_addr,
+                       0xffffffffULL),
 #endif
     DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false),
     DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust, 0,
@@ -361,6 +363,8 @@ void hexagon_cpu_soft_reset(CPUHexagonState *env)
 }
 #endif
 
+
+#define HEXAGON_CFG_ADDR_BASE(addr) (((addr) >> 16) & 0x0fffff)
 static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
 {
     CPUState *cs = CPU(obj);
@@ -401,6 +405,8 @@ static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
     env->wait_next_pc = 0;
     env->cause_code = -1;
     arch_set_thread_reg(env, HEX_REG_PC, cpu->boot_addr);
+    arch_set_system_reg(env, HEX_SREG_CFGBASE,
+                        HEXAGON_CFG_ADDR_BASE(cpu->config_table_addr));
 #endif
 }
 
-- 
2.34.1


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

* [PATCH 5/8] hw/hexagon: Modify "Standalone" symbols
  2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
                   ` (3 preceding siblings ...)
  2025-03-01 17:20 ` [PATCH 4/8] hw/hexagon: Add support for cfgbase Brian Cain
@ 2025-03-01 17:20 ` Brian Cain
  2025-03-24 20:04   ` ltaylorsimpson
  2025-03-01 17:20 ` [PATCH 6/8] target/hexagon: add build config for softmmu Brian Cain
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Brian Cain

From: Brian Cain <bcain@quicinc.com>

These symbols are used by Hexagon Standalone OS to indicate whether
the program should halt and wait for interrupts at startup.  For QEMU,
we want these programs to just continue crt0 startup through to the user
program's main().

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 hw/hexagon/hexagon_dsp.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c
index c4962a98bc..34bbe98149 100644
--- a/hw/hexagon/hexagon_dsp.c
+++ b/hw/hexagon/hexagon_dsp.c
@@ -28,9 +28,17 @@
 
 #include "machine_cfg_v66g_1024.h.inc"
 
+static hwaddr isdb_secure_flag;
+static hwaddr isdb_trusted_flag;
 static void hex_symbol_callback(const char *st_name, int st_info,
                                 uint64_t st_value, uint64_t st_size)
 {
+    if (!g_strcmp0("isdb_secure_flag", st_name)) {
+        isdb_secure_flag = st_value;
+    }
+    if (!g_strcmp0("isdb_trusted_flag", st_name)) {
+        isdb_trusted_flag = st_value;
+    }
 }
 
 /* Board init.  */
@@ -59,6 +67,13 @@ static void hexagon_init_bootstrap(MachineState *machine, HexagonCPU *cpu)
 {
     if (machine->kernel_filename) {
         hexagon_load_kernel(cpu);
+        uint32_t mem = 1;
+        if (isdb_secure_flag) {
+            cpu_physical_memory_write(isdb_secure_flag, &mem, sizeof(mem));
+        }
+        if (isdb_trusted_flag) {
+            cpu_physical_memory_write(isdb_trusted_flag, &mem, sizeof(mem));
+        }
     }
 }
 
-- 
2.34.1


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

* [PATCH 6/8] target/hexagon: add build config for softmmu
  2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
                   ` (4 preceding siblings ...)
  2025-03-01 17:20 ` [PATCH 5/8] hw/hexagon: Modify "Standalone" symbols Brian Cain
@ 2025-03-01 17:20 ` Brian Cain
  2025-03-04 15:25   ` Philippe Mathieu-Daudé
  2025-03-24 20:12   ` ltaylorsimpson
  2025-03-01 17:20 ` [PATCH 7/8] hw/hexagon: Define hexagon "virt" machine Brian Cain
  2025-03-01 17:20 ` [PATCH 8/8] tests/functional: Add a hexagon minivm test Brian Cain
  7 siblings, 2 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Paolo Bonzini

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 MAINTAINERS                                 | 1 +
 configs/devices/hexagon-softmmu/default.mak | 7 +++++++
 configs/targets/hexagon-softmmu.mak         | 6 ++++++
 target/Kconfig                              | 1 +
 target/hexagon/Kconfig                      | 2 ++
 target/hexagon/meson.build                  | 9 +++++++++
 6 files changed, 26 insertions(+)
 create mode 100644 configs/devices/hexagon-softmmu/default.mak
 create mode 100644 configs/targets/hexagon-softmmu.mak
 create mode 100644 target/hexagon/Kconfig

diff --git a/MAINTAINERS b/MAINTAINERS
index 0fb5711184..deeb7878c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -241,6 +241,7 @@ F: linux-user/hexagon/
 F: tests/tcg/hexagon/
 F: disas/hexagon.c
 F: configs/targets/hexagon-linux-user/default.mak
+F: configs/devices/hexagon-softmmu/default.mak
 F: docker/dockerfiles/debian-hexagon-cross.docker
 F: gdb-xml/hexagon*.xml
 F: docs/system/target-hexagon.rst
diff --git a/configs/devices/hexagon-softmmu/default.mak b/configs/devices/hexagon-softmmu/default.mak
new file mode 100644
index 0000000000..08e709aea7
--- /dev/null
+++ b/configs/devices/hexagon-softmmu/default.mak
@@ -0,0 +1,7 @@
+# Default configuration for hexagon-softmmu
+
+# Uncomment the following lines to disable these optional devices:
+
+# Boards are selected by default, uncomment to keep out of the build.
+# CONFIG_HEX_DSP=y
+# CONFIG_L2VIC=y
diff --git a/configs/targets/hexagon-softmmu.mak b/configs/targets/hexagon-softmmu.mak
new file mode 100644
index 0000000000..8c208bf468
--- /dev/null
+++ b/configs/targets/hexagon-softmmu.mak
@@ -0,0 +1,6 @@
+# Default configuration for hexagon-softmmu
+
+TARGET_ARCH=hexagon
+TARGET_SUPPORTS_MTTCG=y
+TARGET_XML_FILES=gdb-xml/hexagon-core.xml gdb-xml/hexagon-hvx.xml gdb-xml/hexagon-sys.xml
+TARGET_LONG_BITS=32
diff --git a/target/Kconfig b/target/Kconfig
index d0c7b59d9c..37781146b9 100644
--- a/target/Kconfig
+++ b/target/Kconfig
@@ -16,6 +16,7 @@ source sh4/Kconfig
 source sparc/Kconfig
 source tricore/Kconfig
 source xtensa/Kconfig
+source hexagon/Kconfig
 
 config TARGET_BIG_ENDIAN
     bool
diff --git a/target/hexagon/Kconfig b/target/hexagon/Kconfig
new file mode 100644
index 0000000000..7e556f3506
--- /dev/null
+++ b/target/hexagon/Kconfig
@@ -0,0 +1,2 @@
+config HEXAGON
+    bool
diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
index aa729a3683..d2b56b9e65 100644
--- a/target/hexagon/meson.build
+++ b/target/hexagon/meson.build
@@ -245,6 +245,7 @@ decodetree_trans_funcs_generated = custom_target(
     command: [python, files('gen_trans_funcs.py'), semantics_generated, '@OUTPUT@'],
 )
 hexagon_ss.add(decodetree_trans_funcs_generated)
+hexagon_softmmu_ss = ss.source_set()
 
 hexagon_ss.add(files(
     'cpu.c',
@@ -264,6 +265,13 @@ hexagon_ss.add(files(
     'mmvec/system_ext_mmvec.c',
 ))
 
+hexagon_softmmu_ss.add(files(
+    'hex_mmu.c',
+    'hex_interrupts.c',
+    'hexswi.c',
+    'machine.c',
+))
+
 #
 # Step 4.5
 # We use flex/bison based idef-parser to generate TCG code for a lot
@@ -401,3 +409,4 @@ analyze_funcs_generated = custom_target(
 hexagon_ss.add(analyze_funcs_generated)
 
 target_arch += {'hexagon': hexagon_ss}
+target_system_arch += {'hexagon': hexagon_softmmu_ss}
-- 
2.34.1


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

* [PATCH 7/8] hw/hexagon: Define hexagon "virt" machine
  2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
                   ` (5 preceding siblings ...)
  2025-03-01 17:20 ` [PATCH 6/8] target/hexagon: add build config for softmmu Brian Cain
@ 2025-03-01 17:20 ` Brian Cain
  2025-03-04 15:38   ` Philippe Mathieu-Daudé
  2025-03-01 17:20 ` [PATCH 8/8] tests/functional: Add a hexagon minivm test Brian Cain
  7 siblings, 1 reply; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Brian Cain, Paolo Bonzini

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 configs/devices/hexagon-softmmu/default.mak |   1 +
 configs/targets/hexagon-softmmu.mak         |   1 +
 include/hw/hexagon/virt.h                   |  41 ++
 hw/hexagon/virt.c                           | 395 ++++++++++++++++++++
 target/hexagon/cpu.c                        |   2 +-
 hw/hexagon/Kconfig                          |   8 +
 hw/hexagon/meson.build                      |   2 +
 7 files changed, 449 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/hexagon/virt.h
 create mode 100644 hw/hexagon/virt.c

diff --git a/configs/devices/hexagon-softmmu/default.mak b/configs/devices/hexagon-softmmu/default.mak
index 08e709aea7..37b4f9f323 100644
--- a/configs/devices/hexagon-softmmu/default.mak
+++ b/configs/devices/hexagon-softmmu/default.mak
@@ -3,5 +3,6 @@
 # Uncomment the following lines to disable these optional devices:
 
 # Boards are selected by default, uncomment to keep out of the build.
+# CONFIG_HEX_VIRT=y
 # CONFIG_HEX_DSP=y
 # CONFIG_L2VIC=y
diff --git a/configs/targets/hexagon-softmmu.mak b/configs/targets/hexagon-softmmu.mak
index 8c208bf468..9f8fca1dc1 100644
--- a/configs/targets/hexagon-softmmu.mak
+++ b/configs/targets/hexagon-softmmu.mak
@@ -4,3 +4,4 @@ TARGET_ARCH=hexagon
 TARGET_SUPPORTS_MTTCG=y
 TARGET_XML_FILES=gdb-xml/hexagon-core.xml gdb-xml/hexagon-hvx.xml gdb-xml/hexagon-sys.xml
 TARGET_LONG_BITS=32
+TARGET_NEED_FDT=y
diff --git a/include/hw/hexagon/virt.h b/include/hw/hexagon/virt.h
new file mode 100644
index 0000000000..0c165a786d
--- /dev/null
+++ b/include/hw/hexagon/virt.h
@@ -0,0 +1,41 @@
+/*
+ * Definitions for hexagon virt board.
+ *
+ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_HEXAGONVIRT_H
+#define HW_HEXAGONVIRT_H
+
+#include "hw/boards.h"
+#include "target/hexagon/cpu.h"
+
+struct HexagonVirtMachineState {
+    /*< private >*/
+    MachineState parent_obj;
+
+    int fdt_size;
+    MemoryRegion *sys;
+    MemoryRegion cfgtable;
+    MemoryRegion ram;
+    MemoryRegion tcm;
+    MemoryRegion vtcm;
+    DeviceState *l2vic;
+};
+
+void hexagon_load_fdt(const struct HexagonVirtMachineState *vms);
+
+enum {
+    VIRT_UART0,
+    VIRT_QTMR0,
+    VIRT_QTMR1,
+    VIRT_GPT,
+    VIRT_MMIO,
+    VIRT_FDT,
+};
+
+#define TYPE_HEXAGON_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+OBJECT_DECLARE_SIMPLE_TYPE(HexagonVirtMachineState, HEXAGON_VIRT_MACHINE)
+
+#endif /* HW_HEXAGONVIRT_H */
diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c
new file mode 100644
index 0000000000..a2e4cc8c6c
--- /dev/null
+++ b/hw/hexagon/virt.c
@@ -0,0 +1,395 @@
+/*
+ * Hexagon virt emulation
+ *
+ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "exec/address-spaces.h"
+#include "hw/char/pl011.h"
+#include "hw/core/sysbus-fdt.h"
+#include "hw/hexagon/hexagon.h"
+#include "hw/hexagon/virt.h"
+#include "hw/loader.h"
+#include "hw/qdev-properties.h"
+#include "hw/register.h"
+#include "qemu/error-report.h"
+#include "qemu/guest-random.h"
+#include "qemu/units.h"
+#include "elf.h"
+#include "machine_cfg_v68n_1024.h.inc"
+#include "system/device_tree.h"
+#include "system/reset.h"
+#include "system/system.h"
+#include <libfdt.h>
+
+static const int VIRTIO_DEV_COUNT = 2;
+
+static const MemMapEntry base_memmap[] = {
+    [VIRT_UART0] = { 0x10000000, 0x00000200 },
+    [VIRT_MMIO] = { 0x11000000, 0x1000000, },
+    [VIRT_GPT] = { 0xab000000, 0x00001000 },
+    [VIRT_FDT] = { 0x99900000, 0x00000200 },
+};
+
+static const int irqmap[] = {
+    [VIRT_MMIO] = 18, /* ...to 18 + VIRTIO_DEV_COUNT - 1 */
+    [VIRT_GPT] = 12,
+    [VIRT_UART0] = 15,
+    [VIRT_QTMR0] = 2,
+    [VIRT_QTMR1] = 4,
+};
+
+
+static void create_fdt(HexagonVirtMachineState *vms)
+{
+    MachineState *ms = MACHINE(vms);
+    void *fdt = create_device_tree(&vms->fdt_size);
+
+    if (!fdt) {
+        error_report("create_device_tree() failed");
+        exit(1);
+    }
+
+    ms->fdt = fdt;
+
+    qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,hexagon-virt");
+    qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2);
+    qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x1);
+    qemu_fdt_setprop_string(fdt, "/", "model", "linux,hexagon-virt");
+
+    qemu_fdt_setprop_string(fdt, "/", "model", "hexagon-virt,qemu");
+    qemu_fdt_setprop_string(fdt, "/", "compatible", "qcom,sm8150");
+
+    qemu_fdt_add_subnode(fdt, "/soc");
+    qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2);
+    qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x1);
+    qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0);
+
+    qemu_fdt_add_subnode(fdt, "/chosen");
+
+    uint8_t rng_seed[32];
+    qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
+    qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
+}
+
+static void fdt_add_hvx(HexagonVirtMachineState *vms,
+                        const hexagon_machine_config *m_cfg, Error **errp)
+{
+    const MachineState *ms = MACHINE(vms);
+    uint32_t vtcm_size_bytes = m_cfg->cfgtable.vtcm_size_kb * 1024;
+    if (vtcm_size_bytes > 0) {
+        memory_region_init_ram(&vms->vtcm, NULL, "vtcm.ram", vtcm_size_bytes,
+                               errp);
+        memory_region_add_subregion(vms->sys, m_cfg->cfgtable.vtcm_base << 16,
+                                    &vms->vtcm);
+
+        qemu_fdt_add_subnode(ms->fdt, "/soc/vtcm");
+        qemu_fdt_setprop_string(ms->fdt, "/soc/vtcm", "compatible",
+                                "qcom,hexagon_vtcm");
+
+        assert(sizeof(m_cfg->cfgtable.vtcm_base) == sizeof(uint32_t));
+        qemu_fdt_setprop_cells(ms->fdt, "/soc/vtcm", "reg", 0,
+                               m_cfg->cfgtable.vtcm_base << 16,
+                               vtcm_size_bytes);
+    }
+
+    if (m_cfg->cfgtable.ext_contexts > 0) {
+        qemu_fdt_add_subnode(ms->fdt, "/soc/hvx");
+        qemu_fdt_setprop_string(ms->fdt, "/soc/hvx", "compatible",
+                                "qcom,hexagon-hvx");
+        qemu_fdt_setprop_cells(ms->fdt, "/soc/hvx", "qcom,hvx-max-ctxts",
+                               m_cfg->cfgtable.ext_contexts);
+        qemu_fdt_setprop_cells(ms->fdt, "/soc/hvx", "qcom,hvx-vlength",
+                               m_cfg->cfgtable.hvx_vec_log_length);
+    }
+}
+
+static int32_t irq_hvm_ic_phandle = -1;
+static void fdt_add_hvm_pic_node(HexagonVirtMachineState *vms,
+                                 const hexagon_machine_config *m_cfg)
+{
+    MachineState *ms = MACHINE(vms);
+    irq_hvm_ic_phandle = qemu_fdt_alloc_phandle(ms->fdt);
+
+    qemu_fdt_setprop_cell(ms->fdt, "/soc", "interrupt-parent",
+                          irq_hvm_ic_phandle);
+
+    qemu_fdt_add_subnode(ms->fdt, "/soc/interrupt-controller");
+    qemu_fdt_setprop_cell(ms->fdt, "/soc/interrupt-controller",
+                          "#address-cells", 2);
+    qemu_fdt_setprop_cell(ms->fdt, "/soc/interrupt-controller",
+                          "#interrupt-cells", 2);
+    qemu_fdt_setprop_string(ms->fdt, "/soc/interrupt-controller", "compatible",
+                            "qcom,h2-pic,hvm-pic");
+    qemu_fdt_setprop(ms->fdt, "/soc/interrupt-controller",
+                     "interrupt-controller", NULL, 0);
+    qemu_fdt_setprop_cell(ms->fdt, "/soc/interrupt-controller", "phandle",
+                          irq_hvm_ic_phandle);
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(vms->l2vic), 1,
+                    m_cfg->cfgtable.fastl2vic_base << 16);
+}
+
+
+static void fdt_add_gpt_node(HexagonVirtMachineState *vms)
+{
+    g_autofree char *name = NULL;
+    MachineState *ms = MACHINE(vms);
+
+    name = g_strdup_printf("/soc/gpt@%" PRIx64,
+                           (int64_t)base_memmap[VIRT_GPT].base);
+    qemu_fdt_add_subnode(ms->fdt, name);
+    qemu_fdt_setprop_string(ms->fdt, name, "compatible",
+                            "qcom,h2-timer,hvm-timer");
+    qemu_fdt_setprop_cells(ms->fdt, name, "interrupts", irqmap[VIRT_GPT], 0);
+    qemu_fdt_setprop_cells(ms->fdt, name, "reg", 0x0,
+                           base_memmap[VIRT_GPT].base,
+                           base_memmap[VIRT_GPT].size);
+}
+
+static int32_t clock_phandle = -1;
+static void fdt_add_clocks(const HexagonVirtMachineState *vms)
+{
+    MachineState *ms = MACHINE(vms);
+    clock_phandle = qemu_fdt_alloc_phandle(ms->fdt);
+    qemu_fdt_add_subnode(ms->fdt, "/apb-pclk");
+    qemu_fdt_setprop_string(ms->fdt, "/apb-pclk", "compatible", "fixed-clock");
+    qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "#clock-cells", 0x0);
+    qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "clock-frequency", 24000000);
+    qemu_fdt_setprop_string(ms->fdt, "/apb-pclk", "clock-output-names",
+                            "clk24mhz");
+    qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "phandle", clock_phandle);
+}
+
+static void fdt_add_uart(const HexagonVirtMachineState *vms, int uart)
+{
+    char *nodename;
+    hwaddr base = base_memmap[uart].base;
+    hwaddr size = base_memmap[uart].size;
+    assert(uart == 0);
+    int irq = irqmap[VIRT_UART0 + uart];
+    const char compat[] = "arm,pl011\0arm,primecell";
+    const char clocknames[] = "uartclk\0apb_pclk";
+    MachineState *ms = MACHINE(vms);
+
+    pl011_create(base, qdev_get_gpio_in(vms->l2vic, irq), serial_hd(0));
+
+    nodename = g_strdup_printf("/pl011@%" PRIx64, base);
+    qemu_fdt_add_subnode(ms->fdt, nodename);
+
+    /* Note that we can't use setprop_string because of the embedded NUL */
+    qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
+    qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, size);
+    qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts", 32 + irq, 0);
+    qemu_fdt_setprop_cells(ms->fdt, nodename, "clocks", clock_phandle,
+                           clock_phandle);
+    qemu_fdt_setprop(ms->fdt, nodename, "clock-names", clocknames,
+                     sizeof(clocknames));
+    qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
+                          irq_hvm_ic_phandle);
+
+    qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
+    qemu_fdt_add_subnode(ms->fdt, "/aliases");
+    qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", nodename);
+
+    g_free(nodename);
+}
+
+static void fdt_add_cpu_nodes(const HexagonVirtMachineState *vms)
+{
+    MachineState *ms = MACHINE(vms);
+    qemu_fdt_add_subnode(ms->fdt, "/cpus");
+    qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#address-cells", 0x1);
+    qemu_fdt_setprop_cell(ms->fdt, "/cpus", "#size-cells", 0x0);
+
+    /* cpu nodes */
+    for (int num = ms->smp.cpus - 1; num >= 0; num--) {
+        char *nodename = g_strdup_printf("/cpus/cpu@%d", num);
+        qemu_fdt_add_subnode(ms->fdt, nodename);
+        qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "cpu");
+        qemu_fdt_setprop_cell(ms->fdt, nodename, "reg", num);
+        qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
+                              qemu_fdt_alloc_phandle(ms->fdt));
+        g_free(nodename);
+    }
+}
+
+
+static void fdt_add_virtio_devices(const HexagonVirtMachineState *vms)
+{
+    MachineState *ms = MACHINE(vms);
+    /* VirtIO MMIO devices */
+    for (int i = 0; i < VIRTIO_DEV_COUNT; i++) {
+        char *nodename;
+        int irq = irqmap[VIRT_MMIO] + i;
+        size_t size = base_memmap[VIRT_MMIO].size;
+        hwaddr base = base_memmap[VIRT_MMIO].base + i * size;
+
+        nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base);
+        qemu_fdt_add_subnode(ms->fdt, nodename);
+        qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "virtio,mmio");
+        qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 1,
+                                     size);
+        qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts", irq, 0);
+        qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
+                              irq_hvm_ic_phandle);
+
+        sysbus_create_simple(
+            "virtio-mmio", base,
+            qdev_get_gpio_in(vms->l2vic, irqmap[VIRT_MMIO] + i));
+
+        g_free(nodename);
+    }
+}
+
+static void virt_instance_init(Object *obj)
+{
+    HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(obj);
+
+    create_fdt(vms);
+}
+
+void hexagon_load_fdt(const HexagonVirtMachineState *vms)
+{
+    MachineState *ms = MACHINE(vms);
+    hwaddr fdt_addr = base_memmap[VIRT_FDT].base;
+    uint32_t fdtsize = vms->fdt_size;
+
+    /* copy in the device tree */
+    qemu_fdt_dumpdtb(ms->fdt, fdtsize);
+
+    rom_add_blob_fixed_as("fdt", ms->fdt, fdtsize, fdt_addr,
+                          &address_space_memory);
+    qemu_register_reset_nosnapshotload(
+        qemu_fdt_randomize_seeds,
+        rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize));
+}
+
+static uint64_t load_kernel(const HexagonVirtMachineState *vms)
+{
+    MachineState *ms = MACHINE(vms);
+    uint64_t entry = 0;
+    if (load_elf_ram_sym(ms->kernel_filename, NULL, NULL, NULL, NULL, &entry,
+                         NULL, NULL, 0, EM_HEXAGON, 0, 0, &address_space_memory,
+                         false, NULL) > 0) {
+        return entry;
+    }
+    error_report("error loading '%s'", ms->kernel_filename);
+    exit(1);
+}
+
+static void do_cpu_reset(void *opaque)
+{
+    HexagonCPU *cpu = opaque;
+    CPUState *cs = CPU(cpu);
+    cpu_reset(cs);
+}
+
+static void virt_init(MachineState *ms)
+{
+    HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(ms);
+    Error **errp = NULL;
+    const hexagon_machine_config *m_cfg = &v68n_1024;
+
+    qemu_fdt_setprop_string(ms->fdt, "/chosen", "bootargs", ms->kernel_cmdline);
+
+    vms->sys = get_system_memory();
+
+    memory_region_init_ram(&vms->ram, NULL, "ddr.ram", ms->ram_size, errp);
+    memory_region_add_subregion(vms->sys, 0x0, &vms->ram);
+
+    if (m_cfg->l2tcm_size) {
+        memory_region_init_ram(&vms->tcm, NULL, "tcm.ram", m_cfg->l2tcm_size,
+                               errp);
+        memory_region_add_subregion(vms->sys, m_cfg->cfgtable.l2tcm_base << 16,
+                                    &vms->tcm);
+    }
+
+    memory_region_init_rom(&vms->cfgtable, NULL, "config_table.rom",
+                           sizeof(m_cfg->cfgtable), errp);
+    memory_region_add_subregion(vms->sys, m_cfg->cfgbase, &vms->cfgtable);
+    fdt_add_hvx(vms, m_cfg, errp);
+    const char *cpu_model = ms->cpu_type;
+
+    if (!cpu_model) {
+        cpu_model = HEXAGON_CPU_TYPE_NAME("v73");
+    }
+
+    HexagonCPU *cpu_0 = NULL;
+    for (int i = 0; i < ms->smp.cpus; i++) {
+        HexagonCPU *cpu = HEXAGON_CPU(object_new(ms->cpu_type));
+        qemu_register_reset(do_cpu_reset, cpu);
+
+        if (i == 0) {
+            cpu_0 = cpu;
+            if (ms->kernel_filename) {
+                uint64_t entry = load_kernel(vms);
+
+                qdev_prop_set_uint32(DEVICE(cpu_0), "exec-start-addr", entry);
+            }
+        }
+        qdev_prop_set_bit(DEVICE(cpu), "start-powered-off", (i != 0));
+        qdev_prop_set_uint32(DEVICE(cpu), "hvx-contexts",
+                             m_cfg->cfgtable.ext_contexts);
+        qdev_prop_set_uint32(DEVICE(cpu), "config-table-addr", m_cfg->cfgbase);
+        qdev_prop_set_uint32(DEVICE(cpu), "l2vic-base-addr", m_cfg->l2vic_base);
+        qdev_prop_set_uint32(DEVICE(cpu), "jtlb-entries",
+                             m_cfg->cfgtable.jtlb_size_entries);
+
+        if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) {
+            return;
+        }
+    }
+    vms->l2vic = sysbus_create_varargs(
+        "l2vic", m_cfg->l2vic_base, qdev_get_gpio_in(DEVICE(cpu_0), 0),
+        qdev_get_gpio_in(DEVICE(cpu_0), 1), qdev_get_gpio_in(DEVICE(cpu_0), 2),
+        qdev_get_gpio_in(DEVICE(cpu_0), 3), qdev_get_gpio_in(DEVICE(cpu_0), 4),
+        qdev_get_gpio_in(DEVICE(cpu_0), 5), qdev_get_gpio_in(DEVICE(cpu_0), 6),
+        qdev_get_gpio_in(DEVICE(cpu_0), 7), NULL);
+
+    fdt_add_hvm_pic_node(vms, m_cfg);
+    fdt_add_virtio_devices(vms);
+    fdt_add_cpu_nodes(vms);
+    fdt_add_clocks(vms);
+    fdt_add_uart(vms, VIRT_UART0);
+    fdt_add_gpt_node(vms);
+
+    rom_add_blob_fixed_as("config_table.rom", &m_cfg->cfgtable,
+                          sizeof(m_cfg->cfgtable), m_cfg->cfgbase,
+                          &address_space_memory);
+
+
+    hexagon_load_fdt(vms);
+}
+
+
+static void virt_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->init = virt_init;
+    mc->default_cpu_type = HEXAGON_CPU_TYPE_NAME("v73");
+    mc->default_ram_size = 4 * GiB;
+    mc->max_cpus = 8;
+    mc->default_cpus = 8;
+    mc->is_default = false;
+    mc->default_kernel_irqchip_split = false;
+    mc->block_default_type = IF_VIRTIO;
+    mc->default_boot_order = NULL;
+    mc->no_cdrom = 1;
+    mc->numa_mem_supported = false;
+    mc->default_nic = "virtio-mmio-bus";
+}
+
+
+static const TypeInfo virt_machine_types[] = { {
+    .name = TYPE_HEXAGON_VIRT_MACHINE,
+    .parent = TYPE_MACHINE,
+    .instance_size = sizeof(HexagonVirtMachineState),
+    .class_init = virt_class_init,
+    .instance_init = virt_instance_init,
+} };
+
+DEFINE_TYPES(virt_machine_types)
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 34940e9a84..7f8f716d6d 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *  Copyright(c) 2019-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
  *
  *  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
diff --git a/hw/hexagon/Kconfig b/hw/hexagon/Kconfig
index 3fc14756e6..f3f0115731 100644
--- a/hw/hexagon/Kconfig
+++ b/hw/hexagon/Kconfig
@@ -4,3 +4,11 @@ config HEX_DSP
     depends on HEXAGON && TCG
     imply PTIMER
     select L2VIC  # Vector PIC
+
+config HEX_VIRT
+    bool
+    default y
+    depends on HEX_DSP && FDT
+    select DEVICE_TREE
+    select VIRTIO_MMIO
+    select PL011
diff --git a/hw/hexagon/meson.build b/hw/hexagon/meson.build
index 2ef3dbcd34..649ad6dc02 100644
--- a/hw/hexagon/meson.build
+++ b/hw/hexagon/meson.build
@@ -3,3 +3,5 @@ hexagon_ss.add(when: 'CONFIG_HEX_DSP', if_true: files('hexagon_dsp.c',))
 
 hw_arch += {'hexagon': hexagon_ss}
 
+hexagon_ss.add(when: 'CONFIG_HEX_VIRT', if_true: files('virt.c',))
+
-- 
2.34.1


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

* [PATCH 8/8] tests/functional: Add a hexagon minivm test
  2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
                   ` (6 preceding siblings ...)
  2025-03-01 17:20 ` [PATCH 7/8] hw/hexagon: Define hexagon "virt" machine Brian Cain
@ 2025-03-01 17:20 ` Brian Cain
  2025-03-04 15:46   ` Philippe Mathieu-Daudé
  7 siblings, 1 reply; 32+ messages in thread
From: Brian Cain @ 2025-03-01 17:20 UTC (permalink / raw)
  To: qemu-devel
  Cc: brian.cain, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Brian Cain

From: Brian Cain <bcain@quicinc.com>

Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 MAINTAINERS                             |  1 +
 tests/functional/meson.build            |  8 +++++
 tests/functional/test_hexagon_minivm.py | 42 +++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
 create mode 100755 tests/functional/test_hexagon_minivm.py

diff --git a/MAINTAINERS b/MAINTAINERS
index deeb7878c8..48a5e7c005 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -247,6 +247,7 @@ F: gdb-xml/hexagon*.xml
 F: docs/system/target-hexagon.rst
 F: docs/devel/hexagon-sys.rst
 F: docs/devel/hexagon-l2vic.rst
+F: tests/functional/test_hexagon_minivm.py
 T: git https://github.com/quic/qemu.git hex-next
 
 Hexagon idef-parser
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index 111d8bab26..78b42e58f9 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -135,6 +135,14 @@ tests_i386_system_quick = [
   'migration',
 ]
 
+test_timeouts += {
+  'hexagon_minivm': 180,
+}
+
+tests_hexagon_system_quick = [
+  'hexagon_minivm',
+]
+
 tests_i386_system_thorough = [
   'i386_tuxrun',
 ]
diff --git a/tests/functional/test_hexagon_minivm.py b/tests/functional/test_hexagon_minivm.py
new file mode 100755
index 0000000000..2ba92bcce3
--- /dev/null
+++ b/tests/functional/test_hexagon_minivm.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+#
+# Copyright(c) 2024-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+from glob import glob
+from qemu_test import QemuSystemTest, Asset
+from qemu_test import wait_for_console_pattern
+
+class MiniVMTest(QemuSystemTest):
+
+    timeout = 180
+    GUEST_ENTRY = 0xc0000000
+
+    REPO = 'https://artifacts.codelinaro.org/artifactory'
+    ASSET_TARBALL = \
+        Asset(f'{REPO}/codelinaro-toolchain-for-hexagon/'
+               '19.1.5/hexagon_minivm_2024_Dec_15.tar.gz',
+        'd7920b5ff14bed5a10b23ada7d4eb927ede08635281f25067e0d5711feee2c2a')
+
+    def test_minivm(self):
+        self.set_machine('virt')
+        self.archive_extract(self.ASSET_TARBALL)
+        rootfs_path = f'{self.workdir}/hexagon-unknown-linux-musl-rootfs'
+        kernel_path = f'{rootfs_path}/boot/minivm'
+
+        assert(os.path.exists(kernel_path))
+        for test_bin_path in glob(f'{rootfs_path}/boot/test_*'):
+            print(f'# Testing "{os.path.basename(test_bin_path)}"')
+
+            vm = self.get_vm()
+            vm.add_args('-kernel', kernel_path,
+                  '-device',
+                  f'loader,addr={hex(self.GUEST_ENTRY)},file={test_bin_path}')
+            vm.launch()
+            vm.wait()
+            self.assertEqual(vm.exitcode(), 0)
+
+if __name__ == '__main__':
+    QemuSystemTest.main()
-- 
2.34.1


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

* Re: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
  2025-03-01 17:20 ` [PATCH 1/8] hw/intc: Add l2vic interrupt controller Brian Cain
@ 2025-03-03 12:26   ` Philippe Mathieu-Daudé
  2025-04-02  1:07     ` Brian Cain
  2025-04-03 17:41     ` Brian Cain
  2025-03-24 19:40   ` ltaylorsimpson
  1 sibling, 2 replies; 32+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-03 12:26 UTC (permalink / raw)
  To: Brian Cain, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Damien Hedde,
	Paolo Bonzini

Hi Brian and Sid,

On 1/3/25 18:20, Brian Cain wrote:
> From: Sid Manning <sidneym@quicinc.com>
> 
> Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
> Co-authored-by: Damien Hedde <damien.hedde@dahe.fr>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>   MAINTAINERS                    |   2 +
>   docs/devel/hexagon-l2vic.rst   |  59 +++++
>   docs/devel/index-internals.rst |   1 +
>   include/hw/intc/l2vic.h        |  37 +++
>   hw/intc/l2vic.c                | 417 +++++++++++++++++++++++++++++++++
>   hw/intc/Kconfig                |   3 +
>   hw/intc/meson.build            |   2 +
>   hw/intc/trace-events           |   4 +
>   8 files changed, 525 insertions(+)
>   create mode 100644 docs/devel/hexagon-l2vic.rst
>   create mode 100644 include/hw/intc/l2vic.h
>   create mode 100644 hw/intc/l2vic.c


> diff --git a/hw/intc/l2vic.c b/hw/intc/l2vic.c
> new file mode 100644
> index 0000000000..9df6575214
> --- /dev/null
> +++ b/hw/intc/l2vic.c
> @@ -0,0 +1,417 @@
> +/*
> + * QEMU L2VIC Interrupt Controller
> + *
> + * Arm PrimeCell PL190 Vector Interrupt Controller was used as a reference.
> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/irq.h"
> +#include "hw/sysbus.h"
> +#include "migration/vmstate.h"
> +#include "qemu/log.h"
> +#include "qemu/module.h"
> +#include "hw/intc/l2vic.h"
> +#include "trace.h"
> +
> +#define L2VICA(s, n) (s[(n) >> 2])
> +
> +#define TYPE_L2VIC "l2vic"
> +#define L2VIC(obj) OBJECT_CHECK(L2VICState, (obj), TYPE_L2VIC)

Why not use OBJECT_DECLARE_SIMPLE_TYPE()?

> +
> +#define SLICE_MAX (L2VIC_INTERRUPT_MAX / 32)
> +
> +typedef struct L2VICState {
> +    SysBusDevice parent_obj;
> +
> +    QemuMutex active;
> +    MemoryRegion iomem;
> +    MemoryRegion fast_iomem;
> +    uint32_t level;
> +    /*
> +     * offset 0:vid group 0 etc, 10 bits in each group
> +     * are used:
> +     */
> +    uint32_t vid_group[4];
> +    uint32_t vid0;
> +    /* Clear Status of Active Edge interrupt, not used: */
> +    uint32_t int_clear[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* Enable interrupt source */
> +    uint32_t int_enable[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* Clear (set to 0) corresponding bit in int_enable */
> +    uint32_t int_enable_clear;
> +    /* Set (to 1) corresponding bit in int_enable */
> +    uint32_t int_enable_set;
> +    /* Present for debugging, not used */
> +    uint32_t int_pending[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* Generate an interrupt */
> +    uint32_t int_soft;
> +    /* Which enabled interrupt is active */
> +    uint32_t int_status[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* Edge or Level interrupt */
> +    uint32_t int_type[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* L2 interrupt group 0-3 0x600-0x7FF */
> +    uint32_t int_group_n0[SLICE_MAX] QEMU_ALIGNED(16);
> +    uint32_t int_group_n1[SLICE_MAX] QEMU_ALIGNED(16);
> +    uint32_t int_group_n2[SLICE_MAX] QEMU_ALIGNED(16);
> +    uint32_t int_group_n3[SLICE_MAX] QEMU_ALIGNED(16);
> +    qemu_irq irq[8];
> +} L2VICState;

OBJECT_DECLARE_SIMPLE_TYPE(L2VICState, L2VIC)


> +static inline bool vid_active(L2VICState *s)
> +
> +{
> +    /* scan all 1024 bits in int_status arrary */
> +    const int size = sizeof(s->int_status) * CHAR_BIT;
> +    const int active_irq = find_first_bit((unsigned long *)s->int_status, size);

Maybe this file could leverage the 32-bit bitops.h API:

$ git grep bit32\( include/qemu/bitops.h
include/qemu/bitops.h:38: * - Bits stored in an array of 'uint32_t': 
set_bit32(), clear_bit32(), etc
include/qemu/bitops.h:270:static inline void set_bit32(long nr, uint32_t 
*addr)
include/qemu/bitops.h:296:static inline void clear_bit32(long nr, 
uint32_t *addr)
include/qemu/bitops.h:322:static inline void change_bit32(long nr, 
uint32_t *addr)
include/qemu/bitops.h:335:static inline int test_and_set_bit32(long nr, 
uint32_t *addr)
include/qemu/bitops.h:350:static inline int test_and_clear_bit32(long 
nr, uint32_t *addr)
include/qemu/bitops.h:365:static inline int test_and_change_bit32(long 
nr, uint32_t *addr)
include/qemu/bitops.h:380:static inline int test_bit32(long nr, const 
uint32_t *addr)

> +    return ((active_irq != size)) ? true : false;
> +}
> +
> +static bool l2vic_update(L2VICState *s, int irq)
> +{
> +    if (vid_active(s)) {
> +        return true;
> +    }
> +
> +    bool pending = test_bit(irq, (unsigned long *)s->int_pending);
> +    bool enable = test_bit(irq, (unsigned long *)s->int_enable);
> +    if (pending && enable) {
> +        int vid = get_vid(s, irq);
> +        set_bit(irq, (unsigned long *)s->int_status);
> +        clear_bit(irq, (unsigned long *)s->int_pending);
> +        clear_bit(irq, (unsigned long *)s->int_enable);
> +        /* ensure the irq line goes low after going high */
> +        s->vid0 = irq;
> +        s->vid_group[get_vid(s, irq)] = irq;
> +
> +        /* already low: now call pulse */
> +        /*     pulse: calls qemu_upper() and then qemu_lower()) */
> +        qemu_irq_pulse(s->irq[vid + 2]);
> +        trace_l2vic_delivered(irq, vid);
> +        return true;
> +    }
> +    return false;
> +}



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

* Re: [PATCH 2/8] hw/hexagon: Add machine configs for sysemu
  2025-03-01 17:20 ` [PATCH 2/8] hw/hexagon: Add machine configs for sysemu Brian Cain
@ 2025-03-04  6:27   ` Markus Armbruster
  2025-03-04 13:12     ` Brian Cain
  2025-03-24 19:48   ` ltaylorsimpson
  1 sibling, 1 reply; 32+ messages in thread
From: Markus Armbruster @ 2025-03-04  6:27 UTC (permalink / raw)
  To: Brian Cain
  Cc: qemu-devel, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Brian Cain, Mike Lambert, Paolo Bonzini, Eduardo Habkost,
	Marcel Apfelbaum, Yanan Wang, Zhao Liu, Eric Blake

Brian Cain <brian.cain@oss.qualcomm.com> writes:

> From: Brian Cain <bcain@quicinc.com>
>
> Co-authored-by: Mike Lambert <mlambert@quicinc.com>
> Co-authored-by: Sid Manning <sidneym@quicinc.com>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

[...]

> diff --git a/qapi/machine.json b/qapi/machine.json
> index a6b8795b09..a7070bad4d 100644
> --- a/qapi/machine.json
> +++ b/qapi/machine.json
> @@ -33,7 +33,7 @@



   ##
   # @SysEmuTarget:
   #
   # The comprehensive enumeration of QEMU system emulation ("softmmu")
   # targets.  Run "./configure --help" in the project root directory,
   # and look for the \*-softmmu targets near the "--target-list" option.
   # The individual target constants are not documented here, for the
   # time being.
   #
   # @rx: since 5.0
   #
   # @avr: since 5.1
   #
   # @loongarch64: since 7.1
   #

Please add a line "@hexagon: since 10.0".

   # .. note:: The resulting QMP strings can be appended to the
   #    "qemu-system-" prefix to produce the corresponding QEMU
   #    executable name.  This is true even for "qemu-system-x86_64".
   #
>  # Since: 3.0
>  ##
>  { 'enum' : 'SysEmuTarget',
> -  'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'hppa', 'i386',
> +  'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'hexagon', 'hppa', 'i386',
>               'loongarch64', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
>               'mips64el', 'mipsel', 'or1k', 'ppc',
>               'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',

[...]

With that doc fix
Acked-by: Markus Armbruster <armbru@redhat.com>



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

* Re: [PATCH 2/8] hw/hexagon: Add machine configs for sysemu
  2025-03-04  6:27   ` Markus Armbruster
@ 2025-03-04 13:12     ` Brian Cain
  0 siblings, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-04 13:12 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: qemu-devel, richard.henderson, philmd, quic_mathbern, ale, anjo,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Brian Cain, Mike Lambert, Paolo Bonzini, Eduardo Habkost,
	Marcel Apfelbaum, Yanan Wang, Zhao Liu, Eric Blake


On 3/4/2025 12:27 AM, Markus Armbruster wrote:
> Brian Cain <brian.cain@oss.qualcomm.com> writes:
>
>> From: Brian Cain <bcain@quicinc.com>
>>
>> Co-authored-by: Mike Lambert <mlambert@quicinc.com>
>> Co-authored-by: Sid Manning <sidneym@quicinc.com>
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> [...]
>
>> diff --git a/qapi/machine.json b/qapi/machine.json
>> index a6b8795b09..a7070bad4d 100644
>> --- a/qapi/machine.json
>> +++ b/qapi/machine.json
>> @@ -33,7 +33,7 @@
>
>
>     ##
>     # @SysEmuTarget:
>     #
>     # The comprehensive enumeration of QEMU system emulation ("softmmu")
>     # targets.  Run "./configure --help" in the project root directory,
>     # and look for the \*-softmmu targets near the "--target-list" option.
>     # The individual target constants are not documented here, for the
>     # time being.
>     #
>     # @rx: since 5.0
>     #
>     # @avr: since 5.1
>     #
>     # @loongarch64: since 7.1
>     #
>
> Please add a line "@hexagon: since 10.0".
I don't think it will make the cutoff for 10.0.  But ok, whichever one 
it's bound for.  Thanks for catching it, the next revision will include 
this fix.
>     # .. note:: The resulting QMP strings can be appended to the
>     #    "qemu-system-" prefix to produce the corresponding QEMU
>     #    executable name.  This is true even for "qemu-system-x86_64".
>     #
>>   # Since: 3.0
>>   ##
>>   { 'enum' : 'SysEmuTarget',
>> -  'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'hppa', 'i386',
>> +  'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'hexagon', 'hppa', 'i386',
>>                'loongarch64', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
>>                'mips64el', 'mipsel', 'or1k', 'ppc',
>>                'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
> [...]
>
> With that doc fix
> Acked-by: Markus Armbruster <armbru@redhat.com>
>


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

* Re: [PATCH 6/8] target/hexagon: add build config for softmmu
  2025-03-01 17:20 ` [PATCH 6/8] target/hexagon: add build config for softmmu Brian Cain
@ 2025-03-04 15:25   ` Philippe Mathieu-Daudé
  2025-03-04 15:59     ` Anton Johansson via
  2025-03-24 20:12   ` ltaylorsimpson
  1 sibling, 1 reply; 32+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-04 15:25 UTC (permalink / raw)
  To: Brian Cain, qemu-devel, ale, anjo
  Cc: richard.henderson, quic_mathbern, quic_mliebel, ltaylorsimpson,
	alex.bennee, quic_mburton, sidneym, Paolo Bonzini

Hi Brian,

On 1/3/25 18:20, Brian Cain wrote:
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>   MAINTAINERS                                 | 1 +
>   configs/devices/hexagon-softmmu/default.mak | 7 +++++++
>   configs/targets/hexagon-softmmu.mak         | 6 ++++++
>   target/Kconfig                              | 1 +
>   target/hexagon/Kconfig                      | 2 ++
>   target/hexagon/meson.build                  | 9 +++++++++
>   6 files changed, 26 insertions(+)
>   create mode 100644 configs/devices/hexagon-softmmu/default.mak
>   create mode 100644 configs/targets/hexagon-softmmu.mak
>   create mode 100644 target/hexagon/Kconfig
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0fb5711184..deeb7878c8 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -241,6 +241,7 @@ F: linux-user/hexagon/
>   F: tests/tcg/hexagon/
>   F: disas/hexagon.c
>   F: configs/targets/hexagon-linux-user/default.mak
> +F: configs/devices/hexagon-softmmu/default.mak
>   F: docker/dockerfiles/debian-hexagon-cross.docker
>   F: gdb-xml/hexagon*.xml
>   F: docs/system/target-hexagon.rst
> diff --git a/configs/devices/hexagon-softmmu/default.mak b/configs/devices/hexagon-softmmu/default.mak
> new file mode 100644
> index 0000000000..08e709aea7
> --- /dev/null
> +++ b/configs/devices/hexagon-softmmu/default.mak
> @@ -0,0 +1,7 @@
> +# Default configuration for hexagon-softmmu
> +
> +# Uncomment the following lines to disable these optional devices:
> +
> +# Boards are selected by default, uncomment to keep out of the build.
> +# CONFIG_HEX_DSP=y
> +# CONFIG_L2VIC=y
> diff --git a/configs/targets/hexagon-softmmu.mak b/configs/targets/hexagon-softmmu.mak
> new file mode 100644
> index 0000000000..8c208bf468
> --- /dev/null
> +++ b/configs/targets/hexagon-softmmu.mak
> @@ -0,0 +1,6 @@
> +# Default configuration for hexagon-softmmu
> +
> +TARGET_ARCH=hexagon
> +TARGET_SUPPORTS_MTTCG=y
> +TARGET_XML_FILES=gdb-xml/hexagon-core.xml gdb-xml/hexagon-hvx.xml gdb-xml/hexagon-sys.xml
> +TARGET_LONG_BITS=32
> diff --git a/target/Kconfig b/target/Kconfig
> index d0c7b59d9c..37781146b9 100644
> --- a/target/Kconfig
> +++ b/target/Kconfig
> @@ -16,6 +16,7 @@ source sh4/Kconfig
>   source sparc/Kconfig
>   source tricore/Kconfig
>   source xtensa/Kconfig
> +source hexagon/Kconfig
>   
>   config TARGET_BIG_ENDIAN
>       bool
> diff --git a/target/hexagon/Kconfig b/target/hexagon/Kconfig
> new file mode 100644
> index 0000000000..7e556f3506
> --- /dev/null
> +++ b/target/hexagon/Kconfig
> @@ -0,0 +1,2 @@
> +config HEXAGON
> +    bool
> diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
> index aa729a3683..d2b56b9e65 100644
> --- a/target/hexagon/meson.build
> +++ b/target/hexagon/meson.build
> @@ -245,6 +245,7 @@ decodetree_trans_funcs_generated = custom_target(
>       command: [python, files('gen_trans_funcs.py'), semantics_generated, '@OUTPUT@'],
>   )
>   hexagon_ss.add(decodetree_trans_funcs_generated)
> +hexagon_softmmu_ss = ss.source_set()
>   
>   hexagon_ss.add(files(
>       'cpu.c',
> @@ -264,6 +265,13 @@ hexagon_ss.add(files(
>       'mmvec/system_ext_mmvec.c',
>   ))
>   
> +hexagon_softmmu_ss.add(files(
> +    'hex_mmu.c',
> +    'hex_interrupts.c',
> +    'hexswi.c',
> +    'machine.c',
> +))
> +
>   #
>   # Step 4.5
>   # We use flex/bison based idef-parser to generate TCG code for a lot

Expanding diff:

     bison = generator(
         find_program('bison', version: '>=3.0'),
         output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'],
         arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@']
     )

On default macOS I get:

   Program bison found: NO found 2.3 but need: '>=3.0' (/usr/bin/bison)

Fixed by installing via brew and:

   export PATH=/opt/homebrew/opt/bison/bin:$PATH

> @@ -401,3 +409,4 @@ analyze_funcs_generated = custom_target(
>   hexagon_ss.add(analyze_funcs_generated)
>   
>   target_arch += {'hexagon': hexagon_ss}
> +target_system_arch += {'hexagon': hexagon_softmmu_ss}

But then I get:
[1/1980] Generating target/hexagon/idef_parser_input.preprocessed.h.inc 
with a custom command
FAILED: target/hexagon/idef_parser_input.preprocessed.h.inc
target/hexagon/idef-parser/prepare 
target/hexagon/idef_parser_input.h.inc -Itarget/hexagon/idef-parser -o 
target/hexagon/idef_parser_input.preprocessed.h.inc
target/hexagon/idef_parser_input.h.inc:1:10: fatal error: 'macros.h.inc' 
file not found
     1 | #include "macros.h.inc"
       |          ^~~~~~~~~~~~~~
# 1 "target/hexagon/idef_parser_input.h.inc"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 423 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "target/hexagon/idef_parser_input.h.inc" 2


J4_hintjumpr(in RsV) {
     {fHINTJR(RsV);}
}

J2_loop0r(in RsV, riV) {
     { fIMMEXT(riV); fPCALIGN(riV); fWRITE_LOOP_REGS0( fREAD_PC()+riV, 
RsV); fSET_LPCFG(0); }
}
[...]

$ find . -name macros.h.inc
./target/hexagon/idef-parser/macros.h.inc

$ cat target/hexagon/idef-parser/prepare
#!/usr/bin/env bash
...
# Run the preprocessor and drop comments
cpp "$@"

$ which cpp
/usr/bin/cpp

$ cpp --version
Apple clang version 16.0.0 (clang-1600.0.26.6)

Since this works on Linux for user emulation, I suppose this is a
macOS vs Linux issue with default cpp command line arguments...


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

* Re: [PATCH 7/8] hw/hexagon: Define hexagon "virt" machine
  2025-03-01 17:20 ` [PATCH 7/8] hw/hexagon: Define hexagon "virt" machine Brian Cain
@ 2025-03-04 15:38   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 32+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-04 15:38 UTC (permalink / raw)
  To: Brian Cain, qemu-devel, Peter Maydell
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Brian Cain,
	Paolo Bonzini

On 1/3/25 18:20, Brian Cain wrote:
> From: Brian Cain <bcain@quicinc.com>
> 
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>   configs/devices/hexagon-softmmu/default.mak |   1 +
>   configs/targets/hexagon-softmmu.mak         |   1 +
>   include/hw/hexagon/virt.h                   |  41 ++
>   hw/hexagon/virt.c                           | 395 ++++++++++++++++++++
>   target/hexagon/cpu.c                        |   2 +-
>   hw/hexagon/Kconfig                          |   8 +
>   hw/hexagon/meson.build                      |   2 +
>   7 files changed, 449 insertions(+), 1 deletion(-)
>   create mode 100644 include/hw/hexagon/virt.h
>   create mode 100644 hw/hexagon/virt.c


> +static void fdt_add_clocks(const HexagonVirtMachineState *vms)
> +{
> +    MachineState *ms = MACHINE(vms);
> +    clock_phandle = qemu_fdt_alloc_phandle(ms->fdt);
> +    qemu_fdt_add_subnode(ms->fdt, "/apb-pclk");
> +    qemu_fdt_setprop_string(ms->fdt, "/apb-pclk", "compatible", "fixed-clock");
> +    qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "#clock-cells", 0x0);
> +    qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "clock-frequency", 24000000);
> +    qemu_fdt_setprop_string(ms->fdt, "/apb-pclk", "clock-output-names",
> +                            "clk24mhz");
> +    qemu_fdt_setprop_cell(ms->fdt, "/apb-pclk", "phandle", clock_phandle);
> +}
> +
> +static void fdt_add_uart(const HexagonVirtMachineState *vms, int uart)
> +{
> +    char *nodename;
> +    hwaddr base = base_memmap[uart].base;
> +    hwaddr size = base_memmap[uart].size;
> +    assert(uart == 0);
> +    int irq = irqmap[VIRT_UART0 + uart];
> +    const char compat[] = "arm,pl011\0arm,primecell";
> +    const char clocknames[] = "uartclk\0apb_pclk";
> +    MachineState *ms = MACHINE(vms);
> +
> +    pl011_create(base, qdev_get_gpio_in(vms->l2vic, irq), serial_hd(0));

pl011_create() seems an incomplete API since it let the UART with
no clock connected. IIUC here you feed with a 24MHz from APB.

> +
> +    nodename = g_strdup_printf("/pl011@%" PRIx64, base);
> +    qemu_fdt_add_subnode(ms->fdt, nodename);
> +
> +    /* Note that we can't use setprop_string because of the embedded NUL */
> +    qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat));
> +    qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, size);
> +    qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts", 32 + irq, 0);
> +    qemu_fdt_setprop_cells(ms->fdt, nodename, "clocks", clock_phandle,
> +                           clock_phandle);
> +    qemu_fdt_setprop(ms->fdt, nodename, "clock-names", clocknames,
> +                     sizeof(clocknames));
> +    qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
> +                          irq_hvm_ic_phandle);
> +
> +    qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
> +    qemu_fdt_add_subnode(ms->fdt, "/aliases");
> +    qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", nodename);
> +
> +    g_free(nodename);
> +}



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

* Re: [PATCH 8/8] tests/functional: Add a hexagon minivm test
  2025-03-01 17:20 ` [PATCH 8/8] tests/functional: Add a hexagon minivm test Brian Cain
@ 2025-03-04 15:46   ` Philippe Mathieu-Daudé
  2025-03-04 16:07     ` Brian Cain
                       ` (3 more replies)
  0 siblings, 4 replies; 32+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-03-04 15:46 UTC (permalink / raw)
  To: Brian Cain, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Brian Cain,
	Thomas Huth

Hi Brian,

On 1/3/25 18:20, Brian Cain wrote:
> From: Brian Cain <bcain@quicinc.com>

A bit opaque...

> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>   MAINTAINERS                             |  1 +
>   tests/functional/meson.build            |  8 +++++
>   tests/functional/test_hexagon_minivm.py | 42 +++++++++++++++++++++++++
>   3 files changed, 51 insertions(+)
>   create mode 100755 tests/functional/test_hexagon_minivm.py
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index deeb7878c8..48a5e7c005 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -247,6 +247,7 @@ F: gdb-xml/hexagon*.xml
>   F: docs/system/target-hexagon.rst
>   F: docs/devel/hexagon-sys.rst
>   F: docs/devel/hexagon-l2vic.rst
> +F: tests/functional/test_hexagon_minivm.py
>   T: git https://github.com/quic/qemu.git hex-next
>   
>   Hexagon idef-parser
> diff --git a/tests/functional/meson.build b/tests/functional/meson.build
> index 111d8bab26..78b42e58f9 100644
> --- a/tests/functional/meson.build
> +++ b/tests/functional/meson.build
> @@ -135,6 +135,14 @@ tests_i386_system_quick = [
>     'migration',
>   ]
>   
> +test_timeouts += {
> +  'hexagon_minivm': 180,
> +}
> +
> +tests_hexagon_system_quick = [
> +  'hexagon_minivm',
> +]
> +
>   tests_i386_system_thorough = [
>     'i386_tuxrun',
>   ]
> diff --git a/tests/functional/test_hexagon_minivm.py b/tests/functional/test_hexagon_minivm.py
> new file mode 100755
> index 0000000000..2ba92bcce3
> --- /dev/null
> +++ b/tests/functional/test_hexagon_minivm.py
> @@ -0,0 +1,42 @@
> +#!/usr/bin/env python3
> +#
> +# Copyright(c) 2024-2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
> +#
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +import os
> +from glob import glob
> +from qemu_test import QemuSystemTest, Asset
> +from qemu_test import wait_for_console_pattern
> +
> +class MiniVMTest(QemuSystemTest):
> +
> +    timeout = 180
> +    GUEST_ENTRY = 0xc0000000
> +
> +    REPO = 'https://artifacts.codelinaro.org/artifactory'
> +    ASSET_TARBALL = \
> +        Asset(f'{REPO}/codelinaro-toolchain-for-hexagon/'
> +               '19.1.5/hexagon_minivm_2024_Dec_15.tar.gz',
> +        'd7920b5ff14bed5a10b23ada7d4eb927ede08635281f25067e0d5711feee2c2a')
> +
> +    def test_minivm(self):
> +        self.set_machine('virt')
> +        self.archive_extract(self.ASSET_TARBALL)
> +        rootfs_path = f'{self.workdir}/hexagon-unknown-linux-musl-rootfs'
> +        kernel_path = f'{rootfs_path}/boot/minivm'

$ readelf -h hexagon-unknown-linux-musl-rootfs/boot/minivm
   Entry point address:               0xffff0000

I suppose this is a bootloader which runs guest code at
GUEST_ENTRY = 0xc0000000.

> +
> +        assert(os.path.exists(kernel_path))
> +        for test_bin_path in glob(f'{rootfs_path}/boot/test_*'):
> +            print(f'# Testing "{os.path.basename(test_bin_path)}"')

$ ls -1 hexagon-unknown-linux-musl-rootfs/boot/test_*
hexagon-unknown-linux-musl-rootfs/boot/test_interrupts
hexagon-unknown-linux-musl-rootfs/boot/test_mmu
hexagon-unknown-linux-musl-rootfs/boot/test_processors

I'd rather 1 test per binary to easily see which one failed.

> +
> +            vm = self.get_vm()
> +            vm.add_args('-kernel', kernel_path,
> +                  '-device',
> +                  f'loader,addr={hex(self.GUEST_ENTRY)},file={test_bin_path}')
> +            vm.launch()
> +            vm.wait()
> +            self.assertEqual(vm.exitcode(), 0)

...
----------------
IN:
0xc0000000:  0x6a09c019 { R25 = C9/pc }
0xc0000004:  0x00004040 { immext(#0x1000)
0xc0000008:  0x7800c018  R24 = ##0x1000 }
0xc000000c:  0xf318d918 { R24 = add(R24,R25) }
0xc0000010:  0x00004000 { immext(#0x0)
0xc0000014:  0x7800c03a  R26 = ##0x1 }
0xc0000018:  0x0c004000 { immext(#0xc0000000)
0xc000001c:  0x7800c001  R1 = ##0xc0000000 }
0xc0000020:  0x0ffc4000 { immext(#0xffc00000)
0xc0000024:  0x7601c001  R1 = and(R1,##0xffc00000) }
0xc0000028:  0x8c01d622 { R2 = lsr(R1,#0x16) }
0xc000002c:  0xc402d840 { R0 = addasl(R24,R2,#0x2) }
0xc0000030:  0xb0e1f8a1 { R1 = add(R1,#0xfc5) }
0xc0000034:  0x00044000 { immext(#0x400000)
0xc0000038:  0x7800c002  R2 = ##0x400000 }
0xc000003c:  0x601ac008 { loop0(PC+4,R26) }
0xc0000040:  0xab80c108 { memw(R0++#0x4) = R1 }
0xc0000044:  0xf3018201 { R1 = add(R1,R2)
0xc0000048:  0x7f00c000  nop }  :endloop0
...
do_raise_exception: 0x00000002, @ 20000090
  hexagon_cpu_do_interrupt: event 0x2:(null), cause 0x25(37)
  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
0x20000104:  0x5400c000 { trap0(#0x0) }

  hexagon_cpu_do_interrupt: event 0x8:HEX_EVENT_TRAP0, cause 0x0(0)
  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)

0xc00002a0:  0x7060c002 { R2 = R0 }
0xc00002a4:  0x5480c20c { trap1(R0,#0x13) }

  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x13(19)
0xffff0518:  0x5800c02a { jump PC+84 }
0xffff056c:  0x6460c000 { stop(R0) }

How can we be sure errors won't exit(0) or hang?

(qemu) info mtree
address-space: memory
   0000000000000000-ffffffffffffffff (prio 0, i/o): system
     0000000000000000-00000000ffffffff (prio 0, ram): ddr.ram
     0000000010000000-0000000010000fff (prio 0, i/o): pl011
     0000000011000000-00000000110001ff (prio 0, i/o): virtio-mmio
     0000000012000000-00000000120001ff (prio 0, i/o): virtio-mmio
     00000000d81e0000-00000000d81effff (prio 0, i/o): fast
     00000000d8400000-00000000d87fffff (prio 0, ram): vtcm.ram
     00000000de000000-00000000de0001ff (prio 0, rom): config_table.rom
     00000000fc910000-00000000fc910fff (prio 0, i/o): l2vic

Could we have minimal debug output on the console?

> +
> +if __name__ == '__main__':
> +    QemuSystemTest.main()

Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 6/8] target/hexagon: add build config for softmmu
  2025-03-04 15:25   ` Philippe Mathieu-Daudé
@ 2025-03-04 15:59     ` Anton Johansson via
  0 siblings, 0 replies; 32+ messages in thread
From: Anton Johansson via @ 2025-03-04 15:59 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Brian Cain, qemu-devel, ale, richard.henderson, quic_mathbern,
	quic_mliebel, ltaylorsimpson, alex.bennee, quic_mburton, sidneym,
	Paolo Bonzini

On 04/03/25, Philippe Mathieu-Daudé wrote:
>
> On default macOS I get:
> 
>   Program bison found: NO found 2.3 but need: '>=3.0' (/usr/bin/bison)
> 
> Fixed by installing via brew and:
> 
>   export PATH=/opt/homebrew/opt/bison/bin:$PATH
> 
> > @@ -401,3 +409,4 @@ analyze_funcs_generated = custom_target(
> >   hexagon_ss.add(analyze_funcs_generated)
> >   target_arch += {'hexagon': hexagon_ss}
> > +target_system_arch += {'hexagon': hexagon_softmmu_ss}
> 
> But then I get:
> [1/1980] Generating target/hexagon/idef_parser_input.preprocessed.h.inc with
> a custom command
> FAILED: target/hexagon/idef_parser_input.preprocessed.h.inc
> target/hexagon/idef-parser/prepare target/hexagon/idef_parser_input.h.inc
> -Itarget/hexagon/idef-parser -o
> target/hexagon/idef_parser_input.preprocessed.h.inc
> target/hexagon/idef_parser_input.h.inc:1:10: fatal error: 'macros.h.inc'
> file not found
>     1 | #include "macros.h.inc"
>       |          ^~~~~~~~~~~~~~
> # 1 "target/hexagon/idef_parser_input.h.inc"
> # 1 "<built-in>" 1
> # 1 "<built-in>" 3
> # 423 "<built-in>" 3
> # 1 "<command line>" 1
> # 1 "<built-in>" 2
> # 1 "target/hexagon/idef_parser_input.h.inc" 2
> 
> 
> J4_hintjumpr(in RsV) {
>     {fHINTJR(RsV);}
> }
> 
> J2_loop0r(in RsV, riV) {
>     { fIMMEXT(riV); fPCALIGN(riV); fWRITE_LOOP_REGS0( fREAD_PC()+riV, RsV);
> fSET_LPCFG(0); }
> }
> [...]
> 
> $ find . -name macros.h.inc
> ./target/hexagon/idef-parser/macros.h.inc
> 
> $ cat target/hexagon/idef-parser/prepare
> #!/usr/bin/env bash
> ...
> # Run the preprocessor and drop comments
> cpp "$@"
> 
> $ which cpp
> /usr/bin/cpp
> 
> $ cpp --version
> Apple clang version 16.0.0 (clang-1600.0.26.6)
> 
> Since this works on Linux for user emulation, I suppose this is a
> macOS vs Linux issue with default cpp command line arguments...


Hi Phil,

yes this is an issue of default arguments added by cpp on mac, I ran
into this a little while ago on a downstream fork.

cpp on mac expands  clang ... -traditional-cpp which alsos break
macro concatenation..

I carry a patch which:

* Removes indent pass on idef-parser output, as indent is not available
  on mac;
* Replaces cpp with ${compiler} ... -E ... where compiler is gotten from
  meson.

I'm a bit sad about the default meson version being outdated though..:(

-- 
Anton Johansson
rev.ng Labs Srl.


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

* Re: [PATCH 8/8] tests/functional: Add a hexagon minivm test
  2025-03-04 15:46   ` Philippe Mathieu-Daudé
@ 2025-03-04 16:07     ` Brian Cain
  2025-03-04 16:15     ` Brian Cain
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-04 16:07 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Brian Cain,
	Thomas Huth


On 3/4/2025 9:46 AM, Philippe Mathieu-Daudé wrote:
> Hi Brian,
>
> On 1/3/25 18:20, Brian Cain wrote:
>> From: Brian Cain <bcain@quicinc.com>
>
> A bit opaque...
>
Whoops -- will fix it.
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                             |  1 +
>>   tests/functional/meson.build            |  8 +++++
>>   tests/functional/test_hexagon_minivm.py | 42 +++++++++++++++++++++++++
>>   3 files changed, 51 insertions(+)
>>   create mode 100755 tests/functional/test_hexagon_minivm.py
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index deeb7878c8..48a5e7c005 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -247,6 +247,7 @@ F: gdb-xml/hexagon*.xml
>>   F: docs/system/target-hexagon.rst
>>   F: docs/devel/hexagon-sys.rst
>>   F: docs/devel/hexagon-l2vic.rst
>> +F: tests/functional/test_hexagon_minivm.py
>>   T: git https://github.com/quic/qemu.git hex-next
>>     Hexagon idef-parser
>> diff --git a/tests/functional/meson.build b/tests/functional/meson.build
>> index 111d8bab26..78b42e58f9 100644
>> --- a/tests/functional/meson.build
>> +++ b/tests/functional/meson.build
>> @@ -135,6 +135,14 @@ tests_i386_system_quick = [
>>     'migration',
>>   ]
>>   +test_timeouts += {
>> +  'hexagon_minivm': 180,
>> +}
>> +
>> +tests_hexagon_system_quick = [
>> +  'hexagon_minivm',
>> +]
>> +
>>   tests_i386_system_thorough = [
>>     'i386_tuxrun',
>>   ]
>> diff --git a/tests/functional/test_hexagon_minivm.py 
>> b/tests/functional/test_hexagon_minivm.py
>> new file mode 100755
>> index 0000000000..2ba92bcce3
>> --- /dev/null
>> +++ b/tests/functional/test_hexagon_minivm.py
>> @@ -0,0 +1,42 @@
>> +#!/usr/bin/env python3
>> +#
>> +# Copyright(c) 2024-2025 Qualcomm Innovation Center, Inc. All Rights 
>> Reserved.
>> +#
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +
>> +import os
>> +from glob import glob
>> +from qemu_test import QemuSystemTest, Asset
>> +from qemu_test import wait_for_console_pattern
>> +
>> +class MiniVMTest(QemuSystemTest):
>> +
>> +    timeout = 180
>> +    GUEST_ENTRY = 0xc0000000
>> +
>> +    REPO = 'https://artifacts.codelinaro.org/artifactory'
>> +    ASSET_TARBALL = \
>> +        Asset(f'{REPO}/codelinaro-toolchain-for-hexagon/'
>> +               '19.1.5/hexagon_minivm_2024_Dec_15.tar.gz',
>> + 'd7920b5ff14bed5a10b23ada7d4eb927ede08635281f25067e0d5711feee2c2a')
>> +
>> +    def test_minivm(self):
>> +        self.set_machine('virt')
>> +        self.archive_extract(self.ASSET_TARBALL)
>> +        rootfs_path = 
>> f'{self.workdir}/hexagon-unknown-linux-musl-rootfs'
>> +        kernel_path = f'{rootfs_path}/boot/minivm'
>
> $ readelf -h hexagon-unknown-linux-musl-rootfs/boot/minivm
>   Entry point address:               0xffff0000
>
> I suppose this is a bootloader which runs guest code at
> GUEST_ENTRY = 0xc0000000.
>
Yes, this is indeed the case.  The source for minivm and the test cases 
is found at https://github.com/quic/hexagonMVM
>> +
>> +        assert(os.path.exists(kernel_path))
>> +        for test_bin_path in glob(f'{rootfs_path}/boot/test_*'):
>> +            print(f'# Testing "{os.path.basename(test_bin_path)}"')
>
> $ ls -1 hexagon-unknown-linux-musl-rootfs/boot/test_*
> hexagon-unknown-linux-musl-rootfs/boot/test_interrupts
> hexagon-unknown-linux-musl-rootfs/boot/test_mmu
> hexagon-unknown-linux-musl-rootfs/boot/test_processors
>
> I'd rather 1 test per binary to easily see which one failed.
>
Okay, I'll make that change.
>> +
>> +            vm = self.get_vm()
>> +            vm.add_args('-kernel', kernel_path,
>> +                  '-device',
>> + f'loader,addr={hex(self.GUEST_ENTRY)},file={test_bin_path}')
>> +            vm.launch()
>> +            vm.wait()
>> +            self.assertEqual(vm.exitcode(), 0)
>
> ...
> ----------------
> IN:
> 0xc0000000:  0x6a09c019 { R25 = C9/pc }
> 0xc0000004:  0x00004040 { immext(#0x1000)
> 0xc0000008:  0x7800c018  R24 = ##0x1000 }
> 0xc000000c:  0xf318d918 { R24 = add(R24,R25) }
> 0xc0000010:  0x00004000 { immext(#0x0)
> 0xc0000014:  0x7800c03a  R26 = ##0x1 }
> 0xc0000018:  0x0c004000 { immext(#0xc0000000)
> 0xc000001c:  0x7800c001  R1 = ##0xc0000000 }
> 0xc0000020:  0x0ffc4000 { immext(#0xffc00000)
> 0xc0000024:  0x7601c001  R1 = and(R1,##0xffc00000) }
> 0xc0000028:  0x8c01d622 { R2 = lsr(R1,#0x16) }
> 0xc000002c:  0xc402d840 { R0 = addasl(R24,R2,#0x2) }
> 0xc0000030:  0xb0e1f8a1 { R1 = add(R1,#0xfc5) }
> 0xc0000034:  0x00044000 { immext(#0x400000)
> 0xc0000038:  0x7800c002  R2 = ##0x400000 }
> 0xc000003c:  0x601ac008 { loop0(PC+4,R26) }
> 0xc0000040:  0xab80c108 { memw(R0++#0x4) = R1 }
> 0xc0000044:  0xf3018201 { R1 = add(R1,R2)
> 0xc0000048:  0x7f00c000  nop }  :endloop0
> ...
> do_raise_exception: 0x00000002, @ 20000090
>  hexagon_cpu_do_interrupt: event 0x2:(null), cause 0x25(37)
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
> 0x20000104:  0x5400c000 { trap0(#0x0) }
>
>  hexagon_cpu_do_interrupt: event 0x8:HEX_EVENT_TRAP0, cause 0x0(0)
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
>
> 0xc00002a0:  0x7060c002 { R2 = R0 }
> 0xc00002a4:  0x5480c20c { trap1(R0,#0x13) }
>
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x13(19)
> 0xffff0518:  0x5800c02a { jump PC+84 }
> 0xffff056c:  0x6460c000 { stop(R0) }
>
> How can we be sure errors won't exit(0) or hang?
>
The most likely failure mode for errors seems like a hang to me. Which 
is good that it's at least detected but I would agree that it would be 
preferable to
> (qemu) info mtree
> address-space: memory
>   0000000000000000-ffffffffffffffff (prio 0, i/o): system
>     0000000000000000-00000000ffffffff (prio 0, ram): ddr.ram
>     0000000010000000-0000000010000fff (prio 0, i/o): pl011
>     0000000011000000-00000000110001ff (prio 0, i/o): virtio-mmio
>     0000000012000000-00000000120001ff (prio 0, i/o): virtio-mmio
>     00000000d81e0000-00000000d81effff (prio 0, i/o): fast
>     00000000d8400000-00000000d87fffff (prio 0, ram): vtcm.ram
>     00000000de000000-00000000de0001ff (prio 0, rom): config_table.rom
>     00000000fc910000-00000000fc910fff (prio 0, i/o): l2vic
>
> Could we have minimal debug output on the console?
>
Hmm - there's no UART support in minivm nor its tests.  But it is easy 
enough to add debug output via semihosting.  Since semihosting spec is 
still under review, I've omitted that from these initial series.


How about we revise the minivm tests to emit some debug output and we 
can also use that kind of thing to verify correctness?  But would it 
suffice to land the test design as-is and follow up after semihosting 
lands?  Or would you prefer to see semihosting be included here before 
this test is enabled?

>> +
>> +if __name__ == '__main__':
>> +    QemuSystemTest.main()
>
> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>


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

* Re: [PATCH 8/8] tests/functional: Add a hexagon minivm test
  2025-03-04 15:46   ` Philippe Mathieu-Daudé
  2025-03-04 16:07     ` Brian Cain
@ 2025-03-04 16:15     ` Brian Cain
  2025-03-04 20:34       ` Brian Cain
  2025-03-05  8:05     ` Thomas Huth
  2025-09-02  2:52     ` Brian Cain
  3 siblings, 1 reply; 32+ messages in thread
From: Brian Cain @ 2025-03-04 16:15 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Brian Cain,
	Thomas Huth


On 3/4/2025 9:46 AM, Philippe Mathieu-Daudé wrote:
> Hi Brian,
>
> On 1/3/25 18:20, Brian Cain wrote:
>> From: Brian Cain <bcain@quicinc.com>
>
> A bit opaque...
>
Whoops -- will fix it.
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                             |  1 +
>>   tests/functional/meson.build            |  8 +++++
>>   tests/functional/test_hexagon_minivm.py | 42 +++++++++++++++++++++++++
>>   3 files changed, 51 insertions(+)
>>   create mode 100755 tests/functional/test_hexagon_minivm.py
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index deeb7878c8..48a5e7c005 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -247,6 +247,7 @@ F: gdb-xml/hexagon*.xml
>>   F: docs/system/target-hexagon.rst
>>   F: docs/devel/hexagon-sys.rst
>>   F: docs/devel/hexagon-l2vic.rst
>> +F: tests/functional/test_hexagon_minivm.py
>>   T: git https://github.com/quic/qemu.git hex-next
>>     Hexagon idef-parser
>> diff --git a/tests/functional/meson.build b/tests/functional/meson.build
>> index 111d8bab26..78b42e58f9 100644
>> --- a/tests/functional/meson.build
>> +++ b/tests/functional/meson.build
>> @@ -135,6 +135,14 @@ tests_i386_system_quick = [
>>     'migration',
>>   ]
>>   +test_timeouts += {
>> +  'hexagon_minivm': 180,
>> +}
>> +
>> +tests_hexagon_system_quick = [
>> +  'hexagon_minivm',
>> +]
>> +
>>   tests_i386_system_thorough = [
>>     'i386_tuxrun',
>>   ]
>> diff --git a/tests/functional/test_hexagon_minivm.py 
>> b/tests/functional/test_hexagon_minivm.py
>> new file mode 100755
>> index 0000000000..2ba92bcce3
>> --- /dev/null
>> +++ b/tests/functional/test_hexagon_minivm.py
>> @@ -0,0 +1,42 @@
>> +#!/usr/bin/env python3
>> +#
>> +# Copyright(c) 2024-2025 Qualcomm Innovation Center, Inc. All Rights 
>> Reserved.
>> +#
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +
>> +import os
>> +from glob import glob
>> +from qemu_test import QemuSystemTest, Asset
>> +from qemu_test import wait_for_console_pattern
>> +
>> +class MiniVMTest(QemuSystemTest):
>> +
>> +    timeout = 180
>> +    GUEST_ENTRY = 0xc0000000
>> +
>> +    REPO = 'https://artifacts.codelinaro.org/artifactory'
>> +    ASSET_TARBALL = \
>> +        Asset(f'{REPO}/codelinaro-toolchain-for-hexagon/'
>> +               '19.1.5/hexagon_minivm_2024_Dec_15.tar.gz',
>> + 'd7920b5ff14bed5a10b23ada7d4eb927ede08635281f25067e0d5711feee2c2a')
>> +
>> +    def test_minivm(self):
>> +        self.set_machine('virt')
>> +        self.archive_extract(self.ASSET_TARBALL)
>> +        rootfs_path = 
>> f'{self.workdir}/hexagon-unknown-linux-musl-rootfs'
>> +        kernel_path = f'{rootfs_path}/boot/minivm'
>
> $ readelf -h hexagon-unknown-linux-musl-rootfs/boot/minivm
>   Entry point address:               0xffff0000
>
> I suppose this is a bootloader which runs guest code at
> GUEST_ENTRY = 0xc0000000.
>
Yes, this is indeed the case.  The source for minivm and the test cases 
is found at https://github.com/quic/hexagonMVM
>> +
>> +        assert(os.path.exists(kernel_path))
>> +        for test_bin_path in glob(f'{rootfs_path}/boot/test_*'):
>> +            print(f'# Testing "{os.path.basename(test_bin_path)}"')
>
> $ ls -1 hexagon-unknown-linux-musl-rootfs/boot/test_*
> hexagon-unknown-linux-musl-rootfs/boot/test_interrupts
> hexagon-unknown-linux-musl-rootfs/boot/test_mmu
> hexagon-unknown-linux-musl-rootfs/boot/test_processors
>
> I'd rather 1 test per binary to easily see which one failed.
>
Okay, I'll make that change.
>> +
>> +            vm = self.get_vm()
>> +            vm.add_args('-kernel', kernel_path,
>> +                  '-device',
>> + f'loader,addr={hex(self.GUEST_ENTRY)},file={test_bin_path}')
>> +            vm.launch()
>> +            vm.wait()
>> +            self.assertEqual(vm.exitcode(), 0)
>
> ...
> ----------------
> IN:
> 0xc0000000:  0x6a09c019 { R25 = C9/pc }
> 0xc0000004:  0x00004040 { immext(#0x1000)
> 0xc0000008:  0x7800c018  R24 = ##0x1000 }
> 0xc000000c:  0xf318d918 { R24 = add(R24,R25) }
> 0xc0000010:  0x00004000 { immext(#0x0)
> 0xc0000014:  0x7800c03a  R26 = ##0x1 }
> 0xc0000018:  0x0c004000 { immext(#0xc0000000)
> 0xc000001c:  0x7800c001  R1 = ##0xc0000000 }
> 0xc0000020:  0x0ffc4000 { immext(#0xffc00000)
> 0xc0000024:  0x7601c001  R1 = and(R1,##0xffc00000) }
> 0xc0000028:  0x8c01d622 { R2 = lsr(R1,#0x16) }
> 0xc000002c:  0xc402d840 { R0 = addasl(R24,R2,#0x2) }
> 0xc0000030:  0xb0e1f8a1 { R1 = add(R1,#0xfc5) }
> 0xc0000034:  0x00044000 { immext(#0x400000)
> 0xc0000038:  0x7800c002  R2 = ##0x400000 }
> 0xc000003c:  0x601ac008 { loop0(PC+4,R26) }
> 0xc0000040:  0xab80c108 { memw(R0++#0x4) = R1 }
> 0xc0000044:  0xf3018201 { R1 = add(R1,R2)
> 0xc0000048:  0x7f00c000  nop }  :endloop0
> ...
> do_raise_exception: 0x00000002, @ 20000090
>  hexagon_cpu_do_interrupt: event 0x2:(null), cause 0x25(37)
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
> 0x20000104:  0x5400c000 { trap0(#0x0) }
>
>  hexagon_cpu_do_interrupt: event 0x8:HEX_EVENT_TRAP0, cause 0x0(0)
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
>
> 0xc00002a0:  0x7060c002 { R2 = R0 }
> 0xc00002a4:  0x5480c20c { trap1(R0,#0x13) }
>
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x13(19)
> 0xffff0518:  0x5800c02a { jump PC+84 }
> 0xffff056c:  0x6460c000 { stop(R0) }
>
> How can we be sure errors won't exit(0) or hang?
>
The most likely failure mode for errors seems like a hang to me. Which 
is good that it's at least detected but I would agree that it would be 
preferable to
> (qemu) info mtree
> address-space: memory
>   0000000000000000-ffffffffffffffff (prio 0, i/o): system
>     0000000000000000-00000000ffffffff (prio 0, ram): ddr.ram
>     0000000010000000-0000000010000fff (prio 0, i/o): pl011
>     0000000011000000-00000000110001ff (prio 0, i/o): virtio-mmio
>     0000000012000000-00000000120001ff (prio 0, i/o): virtio-mmio
>     00000000d81e0000-00000000d81effff (prio 0, i/o): fast
>     00000000d8400000-00000000d87fffff (prio 0, ram): vtcm.ram
>     00000000de000000-00000000de0001ff (prio 0, rom): config_table.rom
>     00000000fc910000-00000000fc910fff (prio 0, i/o): l2vic
>
> Could we have minimal debug output on the console?
>
Hmm - there's no UART support in minivm nor its tests.  But it is easy 
enough to add debug output via semihosting.  Since semihosting spec is 
still under review, I've omitted that from these initial series.


How about we revise the minivm tests to emit some debug output and we 
can also use that kind of thing to verify correctness?  But would it 
suffice to land the test design as-is and follow up after semihosting 
lands?  Or would you prefer to see semihosting be included

>> +
>> +if __name__ == '__main__':
>> +    QemuSystemTest.main()
>
> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>


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

* Re: [PATCH 8/8] tests/functional: Add a hexagon minivm test
  2025-03-04 16:15     ` Brian Cain
@ 2025-03-04 20:34       ` Brian Cain
  0 siblings, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-04 20:34 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Brian Cain,
	Thomas Huth


On 3/4/2025 10:15 AM, Brian Cain wrote:
>
> On 3/4/2025 9:46 AM, Philippe Mathieu-Daudé wrote:
>> Hi Brian,
>>
>> On 1/3/25 18:20, Brian Cain wrote:
>>> From: Brian Cain <bcain@quicinc.com>
>>
>> A bit opaque...
>>
> Whoops -- will fix it.
>>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>>> ---
>>>   MAINTAINERS                             |  1 +
>>>   tests/functional/meson.build            |  8 +++++
>>>   tests/functional/test_hexagon_minivm.py | 42 
>>> +++++++++++++++++++++++++
>>>   3 files changed, 51 insertions(+)
>>>   create mode 100755 tests/functional/test_hexagon_minivm.py
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index deeb7878c8..48a5e7c005 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -247,6 +247,7 @@ F: gdb-xml/hexagon*.xml
>>>   F: docs/system/target-hexagon.rst
>>>   F: docs/devel/hexagon-sys.rst
>>>   F: docs/devel/hexagon-l2vic.rst
>>> +F: tests/functional/test_hexagon_minivm.py
>>>   T: git https://github.com/quic/qemu.git hex-next
>>>     Hexagon idef-parser
>>> diff --git a/tests/functional/meson.build 
>>> b/tests/functional/meson.build
>>> index 111d8bab26..78b42e58f9 100644
>>> --- a/tests/functional/meson.build
>>> +++ b/tests/functional/meson.build
>>> @@ -135,6 +135,14 @@ tests_i386_system_quick = [
>>>     'migration',
>>>   ]
>>>   +test_timeouts += {
>>> +  'hexagon_minivm': 180,
>>> +}
>>> +
>>> +tests_hexagon_system_quick = [
>>> +  'hexagon_minivm',
>>> +]
>>> +
>>>   tests_i386_system_thorough = [
>>>     'i386_tuxrun',
>>>   ]
>>> diff --git a/tests/functional/test_hexagon_minivm.py 
>>> b/tests/functional/test_hexagon_minivm.py
>>> new file mode 100755
>>> index 0000000000..2ba92bcce3
>>> --- /dev/null
>>> +++ b/tests/functional/test_hexagon_minivm.py
>>> @@ -0,0 +1,42 @@
>>> +#!/usr/bin/env python3
>>> +#
>>> +# Copyright(c) 2024-2025 Qualcomm Innovation Center, Inc. All 
>>> Rights Reserved.
>>> +#
>>> +# SPDX-License-Identifier: GPL-2.0-or-later
>>> +
>>> +import os
>>> +from glob import glob
>>> +from qemu_test import QemuSystemTest, Asset
>>> +from qemu_test import wait_for_console_pattern
>>> +
>>> +class MiniVMTest(QemuSystemTest):
>>> +
>>> +    timeout = 180
>>> +    GUEST_ENTRY = 0xc0000000
>>> +
>>> +    REPO = 'https://artifacts.codelinaro.org/artifactory'
>>> +    ASSET_TARBALL = \
>>> +        Asset(f'{REPO}/codelinaro-toolchain-for-hexagon/'
>>> +               '19.1.5/hexagon_minivm_2024_Dec_15.tar.gz',
>>> + 'd7920b5ff14bed5a10b23ada7d4eb927ede08635281f25067e0d5711feee2c2a')
>>> +
>>> +    def test_minivm(self):
>>> +        self.set_machine('virt')
>>> +        self.archive_extract(self.ASSET_TARBALL)
>>> +        rootfs_path = 
>>> f'{self.workdir}/hexagon-unknown-linux-musl-rootfs'
>>> +        kernel_path = f'{rootfs_path}/boot/minivm'
>>
>> $ readelf -h hexagon-unknown-linux-musl-rootfs/boot/minivm
>>   Entry point address:               0xffff0000
>>
>> I suppose this is a bootloader which runs guest code at
>> GUEST_ENTRY = 0xc0000000.
>>
> Yes, this is indeed the case.  The source for minivm and the test 
> cases is found at https://github.com/quic/hexagonMVM
>>> +
>>> +        assert(os.path.exists(kernel_path))
>>> +        for test_bin_path in glob(f'{rootfs_path}/boot/test_*'):
>>> +            print(f'# Testing "{os.path.basename(test_bin_path)}"')
>>
>> $ ls -1 hexagon-unknown-linux-musl-rootfs/boot/test_*
>> hexagon-unknown-linux-musl-rootfs/boot/test_interrupts
>> hexagon-unknown-linux-musl-rootfs/boot/test_mmu
>> hexagon-unknown-linux-musl-rootfs/boot/test_processors
>>
>> I'd rather 1 test per binary to easily see which one failed.
>>
> Okay, I'll make that change.
>>> +
>>> +            vm = self.get_vm()
>>> +            vm.add_args('-kernel', kernel_path,
>>> +                  '-device',
>>> + f'loader,addr={hex(self.GUEST_ENTRY)},file={test_bin_path}')
>>> +            vm.launch()
>>> +            vm.wait()
>>> +            self.assertEqual(vm.exitcode(), 0)
>>
>> ...
>> ----------------
>> IN:
>> 0xc0000000:  0x6a09c019 { R25 = C9/pc }
>> 0xc0000004:  0x00004040 { immext(#0x1000)
>> 0xc0000008:  0x7800c018  R24 = ##0x1000 }
>> 0xc000000c:  0xf318d918 { R24 = add(R24,R25) }
>> 0xc0000010:  0x00004000 { immext(#0x0)
>> 0xc0000014:  0x7800c03a  R26 = ##0x1 }
>> 0xc0000018:  0x0c004000 { immext(#0xc0000000)
>> 0xc000001c:  0x7800c001  R1 = ##0xc0000000 }
>> 0xc0000020:  0x0ffc4000 { immext(#0xffc00000)
>> 0xc0000024:  0x7601c001  R1 = and(R1,##0xffc00000) }
>> 0xc0000028:  0x8c01d622 { R2 = lsr(R1,#0x16) }
>> 0xc000002c:  0xc402d840 { R0 = addasl(R24,R2,#0x2) }
>> 0xc0000030:  0xb0e1f8a1 { R1 = add(R1,#0xfc5) }
>> 0xc0000034:  0x00044000 { immext(#0x400000)
>> 0xc0000038:  0x7800c002  R2 = ##0x400000 }
>> 0xc000003c:  0x601ac008 { loop0(PC+4,R26) }
>> 0xc0000040:  0xab80c108 { memw(R0++#0x4) = R1 }
>> 0xc0000044:  0xf3018201 { R1 = add(R1,R2)
>> 0xc0000048:  0x7f00c000  nop }  :endloop0
>> ...
>> do_raise_exception: 0x00000002, @ 20000090
>>  hexagon_cpu_do_interrupt: event 0x2:(null), cause 0x25(37)
>>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
>> 0x20000104:  0x5400c000 { trap0(#0x0) }
>>
>>  hexagon_cpu_do_interrupt: event 0x8:HEX_EVENT_TRAP0, cause 0x0(0)
>>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
>>
>> 0xc00002a0:  0x7060c002 { R2 = R0 }
>> 0xc00002a4:  0x5480c20c { trap1(R0,#0x13) }
>>
>>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x13(19)
>> 0xffff0518:  0x5800c02a { jump PC+84 }
>> 0xffff056c:  0x6460c000 { stop(R0) }
>>
>> How can we be sure errors won't exit(0) or hang?
>>
> The most likely failure mode for errors seems like a hang to me. Which 
> is good that it's at least detected but I would agree that it would be 
> preferable to
>> (qemu) info mtree
>> address-space: memory
>>   0000000000000000-ffffffffffffffff (prio 0, i/o): system
>>     0000000000000000-00000000ffffffff (prio 0, ram): ddr.ram
>>     0000000010000000-0000000010000fff (prio 0, i/o): pl011
>>     0000000011000000-00000000110001ff (prio 0, i/o): virtio-mmio
>>     0000000012000000-00000000120001ff (prio 0, i/o): virtio-mmio
>>     00000000d81e0000-00000000d81effff (prio 0, i/o): fast
>>     00000000d8400000-00000000d87fffff (prio 0, ram): vtcm.ram
>>     00000000de000000-00000000de0001ff (prio 0, rom): config_table.rom
>>     00000000fc910000-00000000fc910fff (prio 0, i/o): l2vic
>>
>> Could we have minimal debug output on the console?
>>
> Hmm - there's no UART support in minivm nor its tests.  But it is easy 
> enough to add debug output via semihosting.  Since semihosting spec is 
> still under review, I've omitted that from these initial series.
>
>
> How about we revise the minivm tests to emit some debug output and we 
> can also use that kind of thing to verify correctness?  But would it 
> suffice to land the test design as-is and follow up after semihosting 
> lands?  Or would you prefer to see semihosting be included
>

Oh - I see these tests do already emit `PASS` or `FAIL` via 
semihosting.  See 
https://github.com/quic/hexagonMVM/blob/ca5704e8fd7aa0b856c947933fca045ff7a9dadd/tests/test_processors.S#L109-L116 
for an example.

Would it be okay to just check for this output after that semihosting 
lands?  And do you prefer more detailed debug output beyond PASS/FAIL?


>>> +
>>> +if __name__ == '__main__':
>>> +    QemuSystemTest.main()
>>
>> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>>


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

* Re: [PATCH 8/8] tests/functional: Add a hexagon minivm test
  2025-03-04 15:46   ` Philippe Mathieu-Daudé
  2025-03-04 16:07     ` Brian Cain
  2025-03-04 16:15     ` Brian Cain
@ 2025-03-05  8:05     ` Thomas Huth
  2025-03-05 14:35       ` Brian Cain
  2025-09-02  2:52     ` Brian Cain
  3 siblings, 1 reply; 32+ messages in thread
From: Thomas Huth @ 2025-03-05  8:05 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Brian Cain, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Brian Cain,
	Daniel P. Berrange

On 04/03/2025 16.46, Philippe Mathieu-Daudé wrote:
> Hi Brian,
> 
> On 1/3/25 18:20, Brian Cain wrote:
>> From: Brian Cain <bcain@quicinc.com>
> 
> A bit opaque...
> 
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                             |  1 +
>>   tests/functional/meson.build            |  8 +++++
>>   tests/functional/test_hexagon_minivm.py | 42 +++++++++++++++++++++++++
>>   3 files changed, 51 insertions(+)
>>   create mode 100755 tests/functional/test_hexagon_minivm.py
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index deeb7878c8..48a5e7c005 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -247,6 +247,7 @@ F: gdb-xml/hexagon*.xml
>>   F: docs/system/target-hexagon.rst
>>   F: docs/devel/hexagon-sys.rst
>>   F: docs/devel/hexagon-l2vic.rst
>> +F: tests/functional/test_hexagon_minivm.py
>>   T: git https://github.com/quic/qemu.git hex-next
>>   Hexagon idef-parser
>> diff --git a/tests/functional/meson.build b/tests/functional/meson.build
>> index 111d8bab26..78b42e58f9 100644
>> --- a/tests/functional/meson.build
>> +++ b/tests/functional/meson.build
>> @@ -135,6 +135,14 @@ tests_i386_system_quick = [
>>     'migration',
>>   ]
>> +test_timeouts += {
>> +  'hexagon_minivm': 180,
>> +}
>> +
>> +tests_hexagon_system_quick = [
>> +  'hexagon_minivm',
>> +]
>> +
>>   tests_i386_system_thorough = [
>>     'i386_tuxrun',
>>   ]
>> diff --git a/tests/functional/test_hexagon_minivm.py b/tests/functional/ 
>> test_hexagon_minivm.py
>> new file mode 100755
>> index 0000000000..2ba92bcce3
>> --- /dev/null
>> +++ b/tests/functional/test_hexagon_minivm.py
>> @@ -0,0 +1,42 @@
>> +#!/usr/bin/env python3
>> +#
>> +# Copyright(c) 2024-2025 Qualcomm Innovation Center, Inc. All Rights 
>> Reserved.
>> +#
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +
>> +import os
>> +from glob import glob
>> +from qemu_test import QemuSystemTest, Asset
>> +from qemu_test import wait_for_console_pattern
>> +
>> +class MiniVMTest(QemuSystemTest):
>> +
>> +    timeout = 180
>> +    GUEST_ENTRY = 0xc0000000
>> +
>> +    REPO = 'https://artifacts.codelinaro.org/artifactory'
>> +    ASSET_TARBALL = \
>> +        Asset(f'{REPO}/codelinaro-toolchain-for-hexagon/'
>> +               '19.1.5/hexagon_minivm_2024_Dec_15.tar.gz',
>> +        'd7920b5ff14bed5a10b23ada7d4eb927ede08635281f25067e0d5711feee2c2a')

Tests that download assets should go into the "thorough" category, not into 
the quick one, so please replace tests_hexagon_system_quick with 
tests_hexagon_system_thorough in the meson.build file.

(yes, I know, it's a little bit confusing that tests that finish quickly 
should still go into the thorough category instead ... but we needed a way 
to distinguish the tests that download assets and the ones that can run 
without downloads, see also the description in 
docs/devel/testing/functional.rst)

  Thomas



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

* Re: [PATCH 8/8] tests/functional: Add a hexagon minivm test
  2025-03-05  8:05     ` Thomas Huth
@ 2025-03-05 14:35       ` Brian Cain
  0 siblings, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-05 14:35 UTC (permalink / raw)
  To: Thomas Huth, Philippe Mathieu-Daudé, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Brian Cain,
	Daniel P. Berrange


On 3/5/2025 2:05 AM, Thomas Huth wrote:
> On 04/03/2025 16.46, Philippe Mathieu-Daudé wrote:
>> Hi Brian,
>>
>> On 1/3/25 18:20, Brian Cain wrote:
>>> From: Brian Cain <bcain@quicinc.com>
>>
>> A bit opaque...
>>
>>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>>> ---
>>>   MAINTAINERS                             |  1 +
>>>   tests/functional/meson.build            |  8 +++++
>>>   tests/functional/test_hexagon_minivm.py | 42 
>>> +++++++++++++++++++++++++
>>>   3 files changed, 51 insertions(+)
>>>   create mode 100755 tests/functional/test_hexagon_minivm.py
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index deeb7878c8..48a5e7c005 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -247,6 +247,7 @@ F: gdb-xml/hexagon*.xml
>>>   F: docs/system/target-hexagon.rst
>>>   F: docs/devel/hexagon-sys.rst
>>>   F: docs/devel/hexagon-l2vic.rst
>>> +F: tests/functional/test_hexagon_minivm.py
>>>   T: git https://github.com/quic/qemu.git hex-next
>>>   Hexagon idef-parser
>>> diff --git a/tests/functional/meson.build 
>>> b/tests/functional/meson.build
>>> index 111d8bab26..78b42e58f9 100644
>>> --- a/tests/functional/meson.build
>>> +++ b/tests/functional/meson.build
>>> @@ -135,6 +135,14 @@ tests_i386_system_quick = [
>>>     'migration',
>>>   ]
>>> +test_timeouts += {
>>> +  'hexagon_minivm': 180,
>>> +}
>>> +
>>> +tests_hexagon_system_quick = [
>>> +  'hexagon_minivm',
>>> +]
>>> +
>>>   tests_i386_system_thorough = [
>>>     'i386_tuxrun',
>>>   ]
>>> diff --git a/tests/functional/test_hexagon_minivm.py 
>>> b/tests/functional/ test_hexagon_minivm.py
>>> new file mode 100755
>>> index 0000000000..2ba92bcce3
>>> --- /dev/null
>>> +++ b/tests/functional/test_hexagon_minivm.py
>>> @@ -0,0 +1,42 @@
>>> +#!/usr/bin/env python3
>>> +#
>>> +# Copyright(c) 2024-2025 Qualcomm Innovation Center, Inc. All 
>>> Rights Reserved.
>>> +#
>>> +# SPDX-License-Identifier: GPL-2.0-or-later
>>> +
>>> +import os
>>> +from glob import glob
>>> +from qemu_test import QemuSystemTest, Asset
>>> +from qemu_test import wait_for_console_pattern
>>> +
>>> +class MiniVMTest(QemuSystemTest):
>>> +
>>> +    timeout = 180
>>> +    GUEST_ENTRY = 0xc0000000
>>> +
>>> +    REPO = 'https://artifacts.codelinaro.org/artifactory'
>>> +    ASSET_TARBALL = \
>>> +        Asset(f'{REPO}/codelinaro-toolchain-for-hexagon/'
>>> +               '19.1.5/hexagon_minivm_2024_Dec_15.tar.gz',
>>> + 'd7920b5ff14bed5a10b23ada7d4eb927ede08635281f25067e0d5711feee2c2a')
>
> Tests that download assets should go into the "thorough" category, not 
> into the quick one, so please replace tests_hexagon_system_quick with 
> tests_hexagon_system_thorough in the meson.build file.
>
> (yes, I know, it's a little bit confusing that tests that finish 
> quickly should still go into the thorough category instead ... but we 
> needed a way to distinguish the tests that download assets and the 
> ones that can run without downloads, see also the description in 
> docs/devel/testing/functional.rst)


Thanks -- I'll fix this.


>
>  Thomas
>


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

* RE: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
  2025-03-01 17:20 ` [PATCH 1/8] hw/intc: Add l2vic interrupt controller Brian Cain
  2025-03-03 12:26   ` Philippe Mathieu-Daudé
@ 2025-03-24 19:40   ` ltaylorsimpson
  2025-03-24 20:47     ` Brian Cain
  2025-09-02  2:46     ` Brian Cain
  1 sibling, 2 replies; 32+ messages in thread
From: ltaylorsimpson @ 2025-03-24 19:40 UTC (permalink / raw)
  To: 'Brian Cain', qemu-devel
  Cc: richard.henderson, philmd, quic_mathbern, ale, anjo, quic_mliebel,
	alex.bennee, quic_mburton, sidneym, 'Damien Hedde',
	'Paolo Bonzini'



> -----Original Message-----
> From: Brian Cain <brian.cain@oss.qualcomm.com>
> Sent: Saturday, March 1, 2025 11:21 AM
> To: qemu-devel@nongnu.org
> Cc: brian.cain@oss.qualcomm.com; richard.henderson@linaro.org;
> philmd@linaro.org; quic_mathbern@quicinc.com; ale@rev.ng; anjo@rev.ng;
> quic_mliebel@quicinc.com; ltaylorsimpson@gmail.com;
> alex.bennee@linaro.org; quic_mburton@quicinc.com;
> sidneym@quicinc.com; Damien Hedde <damien.hedde@dahe.fr>; Paolo
> Bonzini <pbonzini@redhat.com>
> Subject: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
> 
> From: Sid Manning <sidneym@quicinc.com>
> 
> Co-authored-by: Matheus Tavares Bernardino
> <quic_mathbern@quicinc.com>
> Co-authored-by: Damien Hedde <damien.hedde@dahe.fr>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> ---
>  MAINTAINERS                    |   2 +
>  docs/devel/hexagon-l2vic.rst   |  59 +++++
>  docs/devel/index-internals.rst |   1 +
>  include/hw/intc/l2vic.h        |  37 +++
>  hw/intc/l2vic.c                | 417 +++++++++++++++++++++++++++++++++
>  hw/intc/Kconfig                |   3 +
>  hw/intc/meson.build            |   2 +
>  hw/intc/trace-events           |   4 +
>  8 files changed, 525 insertions(+)
>  create mode 100644 docs/devel/hexagon-l2vic.rst  create mode 100644
> include/hw/intc/l2vic.h  create mode 100644 hw/intc/l2vic.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 804c07bcd5..a842f7fe1b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -232,6 +232,7 @@ Hexagon TCG CPUs
>  M: Brian Cain <brian.cain@oss.qualcomm.com>
>  S: Supported
>  F: target/hexagon/
> +F: hw/intc/l2vic.[ch]

Consider naming all the files outside target/hexagon as hex_* or hexagon_*
That will make it clear they belong to hexagon and you can use an easy wild card in the MAINTAINERS file.
Ditto for the docs files.

>  X: target/hexagon/idef-parser/
>  X: target/hexagon/gen_idef_parser_funcs.py
>  F: linux-user/hexagon/
> diff --git a/include/hw/intc/l2vic.h b/include/hw/intc/l2vic.h new file mode
> 100644 index 0000000000..ed8ccf33b1
> --- /dev/null
> +++ b/include/hw/intc/l2vic.h
> @@ -0,0 +1,37 @@
> +/*
> + * QEMU L2VIC Interrupt Controller
> + *
> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights
> Reserved.
> + * SPDX-License-Identifier: GPL-2.0-or-later  */
> +
> +#define L2VIC_VID_GRP_0 0x0 /* Read */
> +#define L2VIC_VID_GRP_1 0x4 /* Read */
> +#define L2VIC_VID_GRP_2 0x8 /* Read */
> +#define L2VIC_VID_GRP_3 0xC /* Read */
> +#define L2VIC_VID_0 0x10 /* Read SOFTWARE DEFINED */ #define
> +L2VIC_VID_1 0x14 /* Read SOFTWARE DEFINED NOT YET USED */ #define
> +L2VIC_INT_ENABLEn 0x100 /* Read/Write */ #define
> +L2VIC_INT_ENABLE_CLEARn 0x180 /* Write */ #define
> L2VIC_INT_ENABLE_SETn
> +0x200 /* Write */ #define L2VIC_INT_TYPEn 0x280 /* Read/Write */
> +#define L2VIC_INT_STATUSn 0x380 /* Read */ #define L2VIC_INT_CLEARn
> +0x400 /* Write */ #define L2VIC_SOFT_INTn 0x480 /* Write */ #define
> +L2VIC_INT_PENDINGn 0x500 /* Read */ #define L2VIC_INT_GRPn_0 0x600
> /*
> +Read/Write */ #define L2VIC_INT_GRPn_1 0x680 /* Read/Write */ #define
> +L2VIC_INT_GRPn_2 0x700 /* Read/Write */ #define L2VIC_INT_GRPn_3
> 0x780
> +/* Read/Write */
> +
> +#define L2VIC_INTERRUPT_MAX 1024
> +#define L2VIC_CIAD_INSTRUCTION -1
> +/*
> + * Note about l2vic groups:
> + * Each interrupt to L2VIC can be configured to associate with one of
> + * four groups.
> + * Group 0 interrupts go to IRQ2 via VID 0 (SSR: 0xC2, the default)
> + * Group 1 interrupts go to IRQ3 via VID 1 (SSR: 0xC3)
> + * Group 2 interrupts go to IRQ4 via VID 2 (SSR: 0xC4)
> + * Group 3 interrupts go to IRQ5 via VID 3 (SSR: 0xC5)  */
> diff --git a/hw/intc/l2vic.c b/hw/intc/l2vic.c new file mode 100644 index
> 0000000000..9df6575214
> --- /dev/null
> +++ b/hw/intc/l2vic.c
> @@ -0,0 +1,417 @@
> +/*
> + * QEMU L2VIC Interrupt Controller
> + *
> + * Arm PrimeCell PL190 Vector Interrupt Controller was used as a reference.
> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights
> Reserved.
> + * SPDX-License-Identifier: GPL-2.0-or-later  */
> +
> +#include "qemu/osdep.h"
> +#include "hw/irq.h"
> +#include "hw/sysbus.h"
> +#include "migration/vmstate.h"
> +#include "qemu/log.h"
> +#include "qemu/module.h"
> +#include "hw/intc/l2vic.h"
> +#include "trace.h"
> +
> +#define L2VICA(s, n) (s[(n) >> 2])
> +
> +#define TYPE_L2VIC "l2vic"
> +#define L2VIC(obj) OBJECT_CHECK(L2VICState, (obj), TYPE_L2VIC)
> +
> +#define SLICE_MAX (L2VIC_INTERRUPT_MAX / 32)
> +
> +typedef struct L2VICState {
> +    SysBusDevice parent_obj;
> +
> +    QemuMutex active;
> +    MemoryRegion iomem;
> +    MemoryRegion fast_iomem;
> +    uint32_t level;
> +    /*
> +     * offset 0:vid group 0 etc, 10 bits in each group
> +     * are used:
> +     */
> +    uint32_t vid_group[4];
> +    uint32_t vid0;
> +    /* Clear Status of Active Edge interrupt, not used: */
> +    uint32_t int_clear[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* Enable interrupt source */
> +    uint32_t int_enable[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* Clear (set to 0) corresponding bit in int_enable */
> +    uint32_t int_enable_clear;
> +    /* Set (to 1) corresponding bit in int_enable */
> +    uint32_t int_enable_set;
> +    /* Present for debugging, not used */
> +    uint32_t int_pending[SLICE_MAX] QEMU_ALIGNED(16);

Consider using DECLARE_BITMAP32 since you use test_bit/set_bit/clear_bit.
Are these alignments needed?

> +    /* Generate an interrupt */
> +    uint32_t int_soft;
> +    /* Which enabled interrupt is active */
> +    uint32_t int_status[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* Edge or Level interrupt */
> +    uint32_t int_type[SLICE_MAX] QEMU_ALIGNED(16);
> +    /* L2 interrupt group 0-3 0x600-0x7FF */
> +    uint32_t int_group_n0[SLICE_MAX] QEMU_ALIGNED(16);
> +    uint32_t int_group_n1[SLICE_MAX] QEMU_ALIGNED(16);
> +    uint32_t int_group_n2[SLICE_MAX] QEMU_ALIGNED(16);
> +    uint32_t int_group_n3[SLICE_MAX] QEMU_ALIGNED(16);
> +    qemu_irq irq[8];
> +} L2VICState;
> +



> +
> +static void l2vic_set_irq(void *opaque, int irq, int level) {
> +    L2VICState *s = (L2VICState *)opaque;
> +    if (level) {
> +        qemu_mutex_lock(&s->active);
> +        set_bit(irq, (unsigned long *)s->int_pending);

Here's an example of the set_bit mentioned above.

> +        qemu_mutex_unlock(&s->active);
> +    }
> +    l2vic_update(s, irq);
> +}
> +
> +static void l2vic_reset_hold(Object *obj, G_GNUC_UNUSED ResetType
> +res_type) {
> +    L2VICState *s = L2VIC(obj);
> +    memset(s->int_clear, 0, sizeof(s->int_clear));
> +    memset(s->int_enable, 0, sizeof(s->int_enable));
> +    memset(s->int_pending, 0, sizeof(s->int_pending));
> +    memset(s->int_status, 0, sizeof(s->int_status));
> +    memset(s->int_type, 0, sizeof(s->int_type));
> +    memset(s->int_group_n0, 0, sizeof(s->int_group_n0));
> +    memset(s->int_group_n1, 0, sizeof(s->int_group_n1));
> +    memset(s->int_group_n2, 0, sizeof(s->int_group_n2));
> +    memset(s->int_group_n3, 0, sizeof(s->int_group_n3));
> +    s->int_soft = 0;
> +    s->vid0 = 0;

How about a single memset(s, 0, sizeof(L2VICState))?

> +
> +    l2vic_update_all(s);
> +}



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

* RE: [PATCH 2/8] hw/hexagon: Add machine configs for sysemu
  2025-03-01 17:20 ` [PATCH 2/8] hw/hexagon: Add machine configs for sysemu Brian Cain
  2025-03-04  6:27   ` Markus Armbruster
@ 2025-03-24 19:48   ` ltaylorsimpson
  1 sibling, 0 replies; 32+ messages in thread
From: ltaylorsimpson @ 2025-03-24 19:48 UTC (permalink / raw)
  To: 'Brian Cain', qemu-devel
  Cc: richard.henderson, philmd, quic_mathbern, ale, anjo, quic_mliebel,
	alex.bennee, quic_mburton, sidneym, 'Brian Cain',
	'Mike Lambert', 'Paolo Bonzini',
	'Eduardo Habkost', 'Marcel Apfelbaum',
	'Yanan Wang', 'Zhao Liu', 'Eric Blake',
	'Markus Armbruster'



> -----Original Message-----
> From: Brian Cain <brian.cain@oss.qualcomm.com>
> Sent: Saturday, March 1, 2025 11:21 AM
> To: qemu-devel@nongnu.org
> Cc: brian.cain@oss.qualcomm.com; richard.henderson@linaro.org;
> philmd@linaro.org; quic_mathbern@quicinc.com; ale@rev.ng; anjo@rev.ng;
> quic_mliebel@quicinc.com; ltaylorsimpson@gmail.com;
> alex.bennee@linaro.org; quic_mburton@quicinc.com;
> sidneym@quicinc.com; Brian Cain <bcain@quicinc.com>; Mike Lambert
> <mlambert@quicinc.com>; Paolo Bonzini <pbonzini@redhat.com>; Eduardo
> Habkost <eduardo@habkost.net>; Marcel Apfelbaum
> <marcel.apfelbaum@gmail.com>; Yanan Wang
> <wangyanan55@huawei.com>; Zhao Liu <zhao1.liu@intel.com>; Eric Blake
> <eblake@redhat.com>; Markus Armbruster <armbru@redhat.com>
> Subject: [PATCH 2/8] hw/hexagon: Add machine configs for sysemu
> 
> From: Brian Cain <bcain@quicinc.com>
> 
> Co-authored-by: Mike Lambert <mlambert@quicinc.com>
> Co-authored-by: Sid Manning <sidneym@quicinc.com>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> diff --git a/hw/meson.build b/hw/meson.build index
> b827c82c5d..91969d6fec 100644
> --- a/hw/meson.build
> +++ b/hw/meson.build
> @@ -64,3 +64,4 @@ subdir('sparc')
>  subdir('sparc64')
>  subdir('tricore')
>  subdir('xtensa')
> +subdir('hexagon')

Keep this list in alphabetical order, move hexagon between avr and hppa.

Otherwise
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>




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

* RE: [PATCH 3/8] hw/hexagon: Add v68, sa8775-cdsp0 defs
  2025-03-01 17:20 ` [PATCH 3/8] hw/hexagon: Add v68, sa8775-cdsp0 defs Brian Cain
@ 2025-03-24 19:50   ` ltaylorsimpson
  0 siblings, 0 replies; 32+ messages in thread
From: ltaylorsimpson @ 2025-03-24 19:50 UTC (permalink / raw)
  To: 'Brian Cain', qemu-devel
  Cc: richard.henderson, philmd, quic_mathbern, ale, anjo, quic_mliebel,
	alex.bennee, quic_mburton, sidneym, 'Brian Cain'



> -----Original Message-----
> From: Brian Cain <brian.cain@oss.qualcomm.com>
> Sent: Saturday, March 1, 2025 11:21 AM
> To: qemu-devel@nongnu.org
> Cc: brian.cain@oss.qualcomm.com; richard.henderson@linaro.org;
> philmd@linaro.org; quic_mathbern@quicinc.com; ale@rev.ng; anjo@rev.ng;
> quic_mliebel@quicinc.com; ltaylorsimpson@gmail.com;
> alex.bennee@linaro.org; quic_mburton@quicinc.com;
> sidneym@quicinc.com; Brian Cain <bcain@quicinc.com>
> Subject: [PATCH 3/8] hw/hexagon: Add v68, sa8775-cdsp0 defs
> 
> From: Brian Cain <bcain@quicinc.com>
> 
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Acked-by: Taylor Simpson <ltaylorsimpson@gmail.com>



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

* RE: [PATCH 4/8] hw/hexagon: Add support for cfgbase
  2025-03-01 17:20 ` [PATCH 4/8] hw/hexagon: Add support for cfgbase Brian Cain
@ 2025-03-24 20:01   ` ltaylorsimpson
  0 siblings, 0 replies; 32+ messages in thread
From: ltaylorsimpson @ 2025-03-24 20:01 UTC (permalink / raw)
  To: 'Brian Cain', qemu-devel
  Cc: richard.henderson, philmd, quic_mathbern, ale, anjo, quic_mliebel,
	alex.bennee, quic_mburton, sidneym



> -----Original Message-----
> From: Brian Cain <brian.cain@oss.qualcomm.com>
> Sent: Saturday, March 1, 2025 11:21 AM
> To: qemu-devel@nongnu.org
> Cc: brian.cain@oss.qualcomm.com; richard.henderson@linaro.org;
> philmd@linaro.org; quic_mathbern@quicinc.com; ale@rev.ng; anjo@rev.ng;
> quic_mliebel@quicinc.com; ltaylorsimpson@gmail.com;
> alex.bennee@linaro.org; quic_mburton@quicinc.com;
> sidneym@quicinc.com
> Subject: [PATCH 4/8] hw/hexagon: Add support for cfgbase
> 
> From: Sid Manning <sidneym@quicinc.com>
> 
> Signed-off-by: Sid Manning <sidneym@quicinc.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>




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

* RE: [PATCH 5/8] hw/hexagon: Modify "Standalone" symbols
  2025-03-01 17:20 ` [PATCH 5/8] hw/hexagon: Modify "Standalone" symbols Brian Cain
@ 2025-03-24 20:04   ` ltaylorsimpson
  0 siblings, 0 replies; 32+ messages in thread
From: ltaylorsimpson @ 2025-03-24 20:04 UTC (permalink / raw)
  To: 'Brian Cain', qemu-devel
  Cc: richard.henderson, philmd, quic_mathbern, ale, anjo, quic_mliebel,
	alex.bennee, quic_mburton, sidneym, 'Brian Cain'



> -----Original Message-----
> From: Brian Cain <brian.cain@oss.qualcomm.com>
> Sent: Saturday, March 1, 2025 11:21 AM
> To: qemu-devel@nongnu.org
> Cc: brian.cain@oss.qualcomm.com; richard.henderson@linaro.org;
> philmd@linaro.org; quic_mathbern@quicinc.com; ale@rev.ng; anjo@rev.ng;
> quic_mliebel@quicinc.com; ltaylorsimpson@gmail.com;
> alex.bennee@linaro.org; quic_mburton@quicinc.com;
> sidneym@quicinc.com; Brian Cain <bcain@quicinc.com>
> Subject: [PATCH 5/8] hw/hexagon: Modify "Standalone" symbols
> 
> From: Brian Cain <bcain@quicinc.com>
> 
> These symbols are used by Hexagon Standalone OS to indicate whether the
> program should halt and wait for interrupts at startup.  For QEMU, we want
> these programs to just continue crt0 startup through to the user program's
> main().
> 
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>




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

* RE: [PATCH 6/8] target/hexagon: add build config for softmmu
  2025-03-01 17:20 ` [PATCH 6/8] target/hexagon: add build config for softmmu Brian Cain
  2025-03-04 15:25   ` Philippe Mathieu-Daudé
@ 2025-03-24 20:12   ` ltaylorsimpson
  1 sibling, 0 replies; 32+ messages in thread
From: ltaylorsimpson @ 2025-03-24 20:12 UTC (permalink / raw)
  To: 'Brian Cain', qemu-devel
  Cc: richard.henderson, philmd, quic_mathbern, ale, anjo, quic_mliebel,
	alex.bennee, quic_mburton, sidneym, 'Paolo Bonzini'



> -----Original Message-----
> From: Brian Cain <brian.cain@oss.qualcomm.com>
> Sent: Saturday, March 1, 2025 11:21 AM
> To: qemu-devel@nongnu.org
> Cc: brian.cain@oss.qualcomm.com; richard.henderson@linaro.org;
> philmd@linaro.org; quic_mathbern@quicinc.com; ale@rev.ng; anjo@rev.ng;
> quic_mliebel@quicinc.com; ltaylorsimpson@gmail.com;
> alex.bennee@linaro.org; quic_mburton@quicinc.com;
> sidneym@quicinc.com; Paolo Bonzini <pbonzini@redhat.com>
> Subject: [PATCH 6/8] target/hexagon: add build config for softmmu
> 
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com>



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

* Re: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
  2025-03-24 19:40   ` ltaylorsimpson
@ 2025-03-24 20:47     ` Brian Cain
  2025-09-02  2:46     ` Brian Cain
  1 sibling, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-03-24 20:47 UTC (permalink / raw)
  To: ltaylorsimpson, qemu-devel
  Cc: richard.henderson, philmd, quic_mathbern, ale, anjo, quic_mliebel,
	alex.bennee, quic_mburton, sidneym, 'Damien Hedde',
	'Paolo Bonzini'


On 3/24/2025 2:40 PM, ltaylorsimpson@gmail.com wrote:
>
>> -----Original Message-----
>> From: Brian Cain <brian.cain@oss.qualcomm.com>
>> Sent: Saturday, March 1, 2025 11:21 AM
>> To: qemu-devel@nongnu.org
>> Cc: brian.cain@oss.qualcomm.com; richard.henderson@linaro.org;
>> philmd@linaro.org; quic_mathbern@quicinc.com; ale@rev.ng; anjo@rev.ng;
>> quic_mliebel@quicinc.com; ltaylorsimpson@gmail.com;
>> alex.bennee@linaro.org; quic_mburton@quicinc.com;
>> sidneym@quicinc.com; Damien Hedde <damien.hedde@dahe.fr>; Paolo
>> Bonzini <pbonzini@redhat.com>
>> Subject: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
>>
>> From: Sid Manning <sidneym@quicinc.com>
>>
>> Co-authored-by: Matheus Tavares Bernardino
>> <quic_mathbern@quicinc.com>
>> Co-authored-by: Damien Hedde <damien.hedde@dahe.fr>
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                    |   2 +
>>   docs/devel/hexagon-l2vic.rst   |  59 +++++
>>   docs/devel/index-internals.rst |   1 +
>>   include/hw/intc/l2vic.h        |  37 +++
>>   hw/intc/l2vic.c                | 417 +++++++++++++++++++++++++++++++++
>>   hw/intc/Kconfig                |   3 +
>>   hw/intc/meson.build            |   2 +
>>   hw/intc/trace-events           |   4 +
>>   8 files changed, 525 insertions(+)
>>   create mode 100644 docs/devel/hexagon-l2vic.rst  create mode 100644
>> include/hw/intc/l2vic.h  create mode 100644 hw/intc/l2vic.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 804c07bcd5..a842f7fe1b 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -232,6 +232,7 @@ Hexagon TCG CPUs
>>   M: Brian Cain <brian.cain@oss.qualcomm.com>
>>   S: Supported
>>   F: target/hexagon/
>> +F: hw/intc/l2vic.[ch]
> Consider naming all the files outside target/hexagon as hex_* or hexagon_*
> That will make it clear they belong to hexagon and you can use an easy wild card in the MAINTAINERS file.
> Ditto for the docs files.

I'm not sure we can do this in all cases.  Devices aren't necessarily 
bound to one particular architecture.  Of course, for interrupt 
controllers in all practical terms they are bound to an architecture.  
So sure - we can make it hex_l2vic.*

But for example for the QTimer device (yet to be sent to the list for 
review), that wouldn't make sense IMO.


>>   X: target/hexagon/idef-parser/
>>   X: target/hexagon/gen_idef_parser_funcs.py
>>   F: linux-user/hexagon/
>> diff --git a/include/hw/intc/l2vic.h b/include/hw/intc/l2vic.h new file mode
>> 100644 index 0000000000..ed8ccf33b1
>> --- /dev/null
>> +++ b/include/hw/intc/l2vic.h
>> @@ -0,0 +1,37 @@
>> +/*
>> + * QEMU L2VIC Interrupt Controller
>> + *
>> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights
>> Reserved.
>> + * SPDX-License-Identifier: GPL-2.0-or-later  */
>> +
>> +#define L2VIC_VID_GRP_0 0x0 /* Read */
>> +#define L2VIC_VID_GRP_1 0x4 /* Read */
>> +#define L2VIC_VID_GRP_2 0x8 /* Read */
>> +#define L2VIC_VID_GRP_3 0xC /* Read */
>> +#define L2VIC_VID_0 0x10 /* Read SOFTWARE DEFINED */ #define
>> +L2VIC_VID_1 0x14 /* Read SOFTWARE DEFINED NOT YET USED */ #define
>> +L2VIC_INT_ENABLEn 0x100 /* Read/Write */ #define
>> +L2VIC_INT_ENABLE_CLEARn 0x180 /* Write */ #define
>> L2VIC_INT_ENABLE_SETn
>> +0x200 /* Write */ #define L2VIC_INT_TYPEn 0x280 /* Read/Write */
>> +#define L2VIC_INT_STATUSn 0x380 /* Read */ #define L2VIC_INT_CLEARn
>> +0x400 /* Write */ #define L2VIC_SOFT_INTn 0x480 /* Write */ #define
>> +L2VIC_INT_PENDINGn 0x500 /* Read */ #define L2VIC_INT_GRPn_0 0x600
>> /*
>> +Read/Write */ #define L2VIC_INT_GRPn_1 0x680 /* Read/Write */ #define
>> +L2VIC_INT_GRPn_2 0x700 /* Read/Write */ #define L2VIC_INT_GRPn_3
>> 0x780
>> +/* Read/Write */
>> +
>> +#define L2VIC_INTERRUPT_MAX 1024
>> +#define L2VIC_CIAD_INSTRUCTION -1
>> +/*
>> + * Note about l2vic groups:
>> + * Each interrupt to L2VIC can be configured to associate with one of
>> + * four groups.
>> + * Group 0 interrupts go to IRQ2 via VID 0 (SSR: 0xC2, the default)
>> + * Group 1 interrupts go to IRQ3 via VID 1 (SSR: 0xC3)
>> + * Group 2 interrupts go to IRQ4 via VID 2 (SSR: 0xC4)
>> + * Group 3 interrupts go to IRQ5 via VID 3 (SSR: 0xC5)  */
>> diff --git a/hw/intc/l2vic.c b/hw/intc/l2vic.c new file mode 100644 index
>> 0000000000..9df6575214
>> --- /dev/null
>> +++ b/hw/intc/l2vic.c
>> @@ -0,0 +1,417 @@
>> +/*
>> + * QEMU L2VIC Interrupt Controller
>> + *
>> + * Arm PrimeCell PL190 Vector Interrupt Controller was used as a reference.
>> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights
>> Reserved.
>> + * SPDX-License-Identifier: GPL-2.0-or-later  */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/irq.h"
>> +#include "hw/sysbus.h"
>> +#include "migration/vmstate.h"
>> +#include "qemu/log.h"
>> +#include "qemu/module.h"
>> +#include "hw/intc/l2vic.h"
>> +#include "trace.h"
>> +
>> +#define L2VICA(s, n) (s[(n) >> 2])
>> +
>> +#define TYPE_L2VIC "l2vic"
>> +#define L2VIC(obj) OBJECT_CHECK(L2VICState, (obj), TYPE_L2VIC)
>> +
>> +#define SLICE_MAX (L2VIC_INTERRUPT_MAX / 32)
>> +
>> +typedef struct L2VICState {
>> +    SysBusDevice parent_obj;
>> +
>> +    QemuMutex active;
>> +    MemoryRegion iomem;
>> +    MemoryRegion fast_iomem;
>> +    uint32_t level;
>> +    /*
>> +     * offset 0:vid group 0 etc, 10 bits in each group
>> +     * are used:
>> +     */
>> +    uint32_t vid_group[4];
>> +    uint32_t vid0;
>> +    /* Clear Status of Active Edge interrupt, not used: */
>> +    uint32_t int_clear[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Enable interrupt source */
>> +    uint32_t int_enable[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Clear (set to 0) corresponding bit in int_enable */
>> +    uint32_t int_enable_clear;
>> +    /* Set (to 1) corresponding bit in int_enable */
>> +    uint32_t int_enable_set;
>> +    /* Present for debugging, not used */
>> +    uint32_t int_pending[SLICE_MAX] QEMU_ALIGNED(16);
> Consider using DECLARE_BITMAP32 since you use test_bit/set_bit/clear_bit.
> Are these alignments needed?
>
>> +    /* Generate an interrupt */
>> +    uint32_t int_soft;
>> +    /* Which enabled interrupt is active */
>> +    uint32_t int_status[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Edge or Level interrupt */
>> +    uint32_t int_type[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* L2 interrupt group 0-3 0x600-0x7FF */
>> +    uint32_t int_group_n0[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n1[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n2[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n3[SLICE_MAX] QEMU_ALIGNED(16);
>> +    qemu_irq irq[8];
>> +} L2VICState;
>> +
>
>
>> +
>> +static void l2vic_set_irq(void *opaque, int irq, int level) {
>> +    L2VICState *s = (L2VICState *)opaque;
>> +    if (level) {
>> +        qemu_mutex_lock(&s->active);
>> +        set_bit(irq, (unsigned long *)s->int_pending);
> Here's an example of the set_bit mentioned above.
>
>> +        qemu_mutex_unlock(&s->active);
>> +    }
>> +    l2vic_update(s, irq);
>> +}
>> +
>> +static void l2vic_reset_hold(Object *obj, G_GNUC_UNUSED ResetType
>> +res_type) {
>> +    L2VICState *s = L2VIC(obj);
>> +    memset(s->int_clear, 0, sizeof(s->int_clear));
>> +    memset(s->int_enable, 0, sizeof(s->int_enable));
>> +    memset(s->int_pending, 0, sizeof(s->int_pending));
>> +    memset(s->int_status, 0, sizeof(s->int_status));
>> +    memset(s->int_type, 0, sizeof(s->int_type));
>> +    memset(s->int_group_n0, 0, sizeof(s->int_group_n0));
>> +    memset(s->int_group_n1, 0, sizeof(s->int_group_n1));
>> +    memset(s->int_group_n2, 0, sizeof(s->int_group_n2));
>> +    memset(s->int_group_n3, 0, sizeof(s->int_group_n3));
>> +    s->int_soft = 0;
>> +    s->vid0 = 0;
> How about a single memset(s, 0, sizeof(L2VICState))?
>
>> +
>> +    l2vic_update_all(s);
>> +}


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

* Re: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
  2025-03-03 12:26   ` Philippe Mathieu-Daudé
@ 2025-04-02  1:07     ` Brian Cain
  2025-04-03 17:41     ` Brian Cain
  1 sibling, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-04-02  1:07 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Damien Hedde,
	Paolo Bonzini


On 3/3/2025 6:26 AM, Philippe Mathieu-Daudé wrote:
> Hi Brian and Sid,
>
> On 1/3/25 18:20, Brian Cain wrote:
>> From: Sid Manning <sidneym@quicinc.com>
>>
>> Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
>> Co-authored-by: Damien Hedde <damien.hedde@dahe.fr>
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                    |   2 +
>>   docs/devel/hexagon-l2vic.rst   |  59 +++++
>>   docs/devel/index-internals.rst |   1 +
>>   include/hw/intc/l2vic.h        |  37 +++
>>   hw/intc/l2vic.c                | 417 +++++++++++++++++++++++++++++++++
>>   hw/intc/Kconfig                |   3 +
>>   hw/intc/meson.build            |   2 +
>>   hw/intc/trace-events           |   4 +
>>   8 files changed, 525 insertions(+)
>>   create mode 100644 docs/devel/hexagon-l2vic.rst
>>   create mode 100644 include/hw/intc/l2vic.h
>>   create mode 100644 hw/intc/l2vic.c
>
>
>> diff --git a/hw/intc/l2vic.c b/hw/intc/l2vic.c
>> new file mode 100644
>> index 0000000000..9df6575214
>> --- /dev/null
>> +++ b/hw/intc/l2vic.c
>> @@ -0,0 +1,417 @@
>> +/*
>> + * QEMU L2VIC Interrupt Controller
>> + *
>> + * Arm PrimeCell PL190 Vector Interrupt Controller was used as a 
>> reference.
>> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All 
>> Rights Reserved.
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/irq.h"
>> +#include "hw/sysbus.h"
>> +#include "migration/vmstate.h"
>> +#include "qemu/log.h"
>> +#include "qemu/module.h"
>> +#include "hw/intc/l2vic.h"
>> +#include "trace.h"
>> +
>> +#define L2VICA(s, n) (s[(n) >> 2])
>> +
>> +#define TYPE_L2VIC "l2vic"
>> +#define L2VIC(obj) OBJECT_CHECK(L2VICState, (obj), TYPE_L2VIC)
>
> Why not use OBJECT_DECLARE_SIMPLE_TYPE()?
>

Will do, thanks.


>> +
>> +#define SLICE_MAX (L2VIC_INTERRUPT_MAX / 32)
>> +
>> +typedef struct L2VICState {
>> +    SysBusDevice parent_obj;
>> +
>> +    QemuMutex active;
>> +    MemoryRegion iomem;
>> +    MemoryRegion fast_iomem;
>> +    uint32_t level;
>> +    /*
>> +     * offset 0:vid group 0 etc, 10 bits in each group
>> +     * are used:
>> +     */
>> +    uint32_t vid_group[4];
>> +    uint32_t vid0;
>> +    /* Clear Status of Active Edge interrupt, not used: */
>> +    uint32_t int_clear[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Enable interrupt source */
>> +    uint32_t int_enable[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Clear (set to 0) corresponding bit in int_enable */
>> +    uint32_t int_enable_clear;
>> +    /* Set (to 1) corresponding bit in int_enable */
>> +    uint32_t int_enable_set;
>> +    /* Present for debugging, not used */
>> +    uint32_t int_pending[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Generate an interrupt */
>> +    uint32_t int_soft;
>> +    /* Which enabled interrupt is active */
>> +    uint32_t int_status[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Edge or Level interrupt */
>> +    uint32_t int_type[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* L2 interrupt group 0-3 0x600-0x7FF */
>> +    uint32_t int_group_n0[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n1[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n2[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n3[SLICE_MAX] QEMU_ALIGNED(16);
>> +    qemu_irq irq[8];
>> +} L2VICState;
>
> OBJECT_DECLARE_SIMPLE_TYPE(L2VICState, L2VIC)
>
>
>> +static inline bool vid_active(L2VICState *s)
>> +
>> +{
>> +    /* scan all 1024 bits in int_status arrary */
>> +    const int size = sizeof(s->int_status) * CHAR_BIT;
>> +    const int active_irq = find_first_bit((unsigned long 
>> *)s->int_status, size);
>
> Maybe this file could leverage the 32-bit bitops.h API:
>
> $ git grep bit32\( include/qemu/bitops.h
> include/qemu/bitops.h:38: * - Bits stored in an array of 'uint32_t': 
> set_bit32(), clear_bit32(), etc
> include/qemu/bitops.h:270:static inline void set_bit32(long nr, 
> uint32_t *addr)
> include/qemu/bitops.h:296:static inline void clear_bit32(long nr, 
> uint32_t *addr)
> include/qemu/bitops.h:322:static inline void change_bit32(long nr, 
> uint32_t *addr)
> include/qemu/bitops.h:335:static inline int test_and_set_bit32(long 
> nr, uint32_t *addr)
> include/qemu/bitops.h:350:static inline int test_and_clear_bit32(long 
> nr, uint32_t *addr)
> include/qemu/bitops.h:365:static inline int test_and_change_bit32(long 
> nr, uint32_t *addr)
> include/qemu/bitops.h:380:static inline int test_bit32(long nr, const 
> uint32_t *addr)
>

I think your suggestion is based on the fact the state to hold the 
interrupt status (et al) were declared as uint32_t arrays. But in fact 
it might be clearer to take Taylor's suggestion from this thread and use 
DECLARE_BITMAP() instead?

In which case, perhaps the call to find_first_bit() could remain?


>> +    return ((active_irq != size)) ? true : false;
>> +}
>> +
>> +static bool l2vic_update(L2VICState *s, int irq)
>> +{
>> +    if (vid_active(s)) {
>> +        return true;
>> +    }
>> +
>> +    bool pending = test_bit(irq, (unsigned long *)s->int_pending);
>> +    bool enable = test_bit(irq, (unsigned long *)s->int_enable);
>> +    if (pending && enable) {
>> +        int vid = get_vid(s, irq);
>> +        set_bit(irq, (unsigned long *)s->int_status);
>> +        clear_bit(irq, (unsigned long *)s->int_pending);
>> +        clear_bit(irq, (unsigned long *)s->int_enable);
>> +        /* ensure the irq line goes low after going high */
>> +        s->vid0 = irq;
>> +        s->vid_group[get_vid(s, irq)] = irq;
>> +
>> +        /* already low: now call pulse */
>> +        /*     pulse: calls qemu_upper() and then qemu_lower()) */
>> +        qemu_irq_pulse(s->irq[vid + 2]);
>> +        trace_l2vic_delivered(irq, vid);
>> +        return true;
>> +    }
>> +    return false;
>> +}
>


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

* Re: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
  2025-03-03 12:26   ` Philippe Mathieu-Daudé
  2025-04-02  1:07     ` Brian Cain
@ 2025-04-03 17:41     ` Brian Cain
  1 sibling, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-04-03 17:41 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Damien Hedde,
	Paolo Bonzini


On 3/3/2025 6:26 AM, Philippe Mathieu-Daudé wrote:
> Hi Brian and Sid,
>
> On 1/3/25 18:20, Brian Cain wrote:
>> From: Sid Manning <sidneym@quicinc.com>
>>
>> Co-authored-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com>
>> Co-authored-by: Damien Hedde <damien.hedde@dahe.fr>
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                    |   2 +
>>   docs/devel/hexagon-l2vic.rst   |  59 +++++
>>   docs/devel/index-internals.rst |   1 +
>>   include/hw/intc/l2vic.h        |  37 +++
>>   hw/intc/l2vic.c                | 417 +++++++++++++++++++++++++++++++++
>>   hw/intc/Kconfig                |   3 +
>>   hw/intc/meson.build            |   2 +
>>   hw/intc/trace-events           |   4 +
>>   8 files changed, 525 insertions(+)
>>   create mode 100644 docs/devel/hexagon-l2vic.rst
>>   create mode 100644 include/hw/intc/l2vic.h
>>   create mode 100644 hw/intc/l2vic.c
>
>
>> diff --git a/hw/intc/l2vic.c b/hw/intc/l2vic.c
>> new file mode 100644
>> index 0000000000..9df6575214
>> --- /dev/null
>> +++ b/hw/intc/l2vic.c
>> @@ -0,0 +1,417 @@
>> +/*
>> + * QEMU L2VIC Interrupt Controller
>> + *
>> + * Arm PrimeCell PL190 Vector Interrupt Controller was used as a 
>> reference.
>> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All 
>> Rights Reserved.
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/irq.h"
>> +#include "hw/sysbus.h"
>> +#include "migration/vmstate.h"
>> +#include "qemu/log.h"
>> +#include "qemu/module.h"
>> +#include "hw/intc/l2vic.h"
>> +#include "trace.h"
>> +
>> +#define L2VICA(s, n) (s[(n) >> 2])
>> +
>> +#define TYPE_L2VIC "l2vic"
>> +#define L2VIC(obj) OBJECT_CHECK(L2VICState, (obj), TYPE_L2VIC)
>
> Why not use OBJECT_DECLARE_SIMPLE_TYPE()?
>

Great suggestion, ty.  Will do.


>> +
>> +#define SLICE_MAX (L2VIC_INTERRUPT_MAX / 32)
>> +
>> +typedef struct L2VICState {
>> +    SysBusDevice parent_obj;
>> +
>> +    QemuMutex active;
>> +    MemoryRegion iomem;
>> +    MemoryRegion fast_iomem;
>> +    uint32_t level;
>> +    /*
>> +     * offset 0:vid group 0 etc, 10 bits in each group
>> +     * are used:
>> +     */
>> +    uint32_t vid_group[4];
>> +    uint32_t vid0;
>> +    /* Clear Status of Active Edge interrupt, not used: */
>> +    uint32_t int_clear[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Enable interrupt source */
>> +    uint32_t int_enable[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Clear (set to 0) corresponding bit in int_enable */
>> +    uint32_t int_enable_clear;
>> +    /* Set (to 1) corresponding bit in int_enable */
>> +    uint32_t int_enable_set;
>> +    /* Present for debugging, not used */
>> +    uint32_t int_pending[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Generate an interrupt */
>> +    uint32_t int_soft;
>> +    /* Which enabled interrupt is active */
>> +    uint32_t int_status[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Edge or Level interrupt */
>> +    uint32_t int_type[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* L2 interrupt group 0-3 0x600-0x7FF */
>> +    uint32_t int_group_n0[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n1[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n2[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n3[SLICE_MAX] QEMU_ALIGNED(16);
>> +    qemu_irq irq[8];
>> +} L2VICState;
>
> OBJECT_DECLARE_SIMPLE_TYPE(L2VICState, L2VIC)
>
>
>> +static inline bool vid_active(L2VICState *s)
>> +
>> +{
>> +    /* scan all 1024 bits in int_status arrary */
>> +    const int size = sizeof(s->int_status) * CHAR_BIT;
>> +    const int active_irq = find_first_bit((unsigned long 
>> *)s->int_status, size);
>
> Maybe this file could leverage the 32-bit bitops.h API:
>
> $ git grep bit32\( include/qemu/bitops.h
> include/qemu/bitops.h:38: * - Bits stored in an array of 'uint32_t': 
> set_bit32(), clear_bit32(), etc
> include/qemu/bitops.h:270:static inline void set_bit32(long nr, 
> uint32_t *addr)
> include/qemu/bitops.h:296:static inline void clear_bit32(long nr, 
> uint32_t *addr)
> include/qemu/bitops.h:322:static inline void change_bit32(long nr, 
> uint32_t *addr)
> include/qemu/bitops.h:335:static inline int test_and_set_bit32(long 
> nr, uint32_t *addr)
> include/qemu/bitops.h:350:static inline int test_and_clear_bit32(long 
> nr, uint32_t *addr)
> include/qemu/bitops.h:365:static inline int test_and_change_bit32(long 
> nr, uint32_t *addr)
> include/qemu/bitops.h:380:static inline int test_bit32(long nr, const 
> uint32_t *addr)
>

Okay - I will make this change.


There's several places in the code today where we do this L2VICA() macro 
to assign all of the bits to/from a single uint32_t word.  And if we 
take your and Taylor's suggestion to use the DECLARE_BITMAP32, we can 
probably change these to use bitmap_copy_with_{src,dst}_offset() 
instead, I think?


>> +    return ((active_irq != size)) ? true : false;
>> +}
>> +
>> +static bool l2vic_update(L2VICState *s, int irq)
>> +{
>> +    if (vid_active(s)) {
>> +        return true;
>> +    }
>> +
>> +    bool pending = test_bit(irq, (unsigned long *)s->int_pending);
>> +    bool enable = test_bit(irq, (unsigned long *)s->int_enable);
>> +    if (pending && enable) {
>> +        int vid = get_vid(s, irq);
>> +        set_bit(irq, (unsigned long *)s->int_status);
>> +        clear_bit(irq, (unsigned long *)s->int_pending);
>> +        clear_bit(irq, (unsigned long *)s->int_enable);
>> +        /* ensure the irq line goes low after going high */
>> +        s->vid0 = irq;
>> +        s->vid_group[get_vid(s, irq)] = irq;
>> +
>> +        /* already low: now call pulse */
>> +        /*     pulse: calls qemu_upper() and then qemu_lower()) */
>> +        qemu_irq_pulse(s->irq[vid + 2]);
>> +        trace_l2vic_delivered(irq, vid);
>> +        return true;
>> +    }
>> +    return false;
>> +}
>


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

* Re: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
  2025-03-24 19:40   ` ltaylorsimpson
  2025-03-24 20:47     ` Brian Cain
@ 2025-09-02  2:46     ` Brian Cain
  1 sibling, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-09-02  2:46 UTC (permalink / raw)
  To: ltaylorsimpson, qemu-devel
  Cc: richard.henderson, philmd, quic_mathbern, ale, anjo, quic_mliebel,
	alex.bennee, quic_mburton, sidneym, 'Damien Hedde',
	'Paolo Bonzini'


On 3/24/2025 2:40 PM, ltaylorsimpson@gmail.com wrote:
>
>> -----Original Message-----
>> From: Brian Cain <brian.cain@oss.qualcomm.com>
>> Sent: Saturday, March 1, 2025 11:21 AM
>> To: qemu-devel@nongnu.org
>> Cc: brian.cain@oss.qualcomm.com; richard.henderson@linaro.org;
>> philmd@linaro.org; quic_mathbern@quicinc.com; ale@rev.ng; anjo@rev.ng;
>> quic_mliebel@quicinc.com; ltaylorsimpson@gmail.com;
>> alex.bennee@linaro.org; quic_mburton@quicinc.com;
>> sidneym@quicinc.com; Damien Hedde <damien.hedde@dahe.fr>; Paolo
>> Bonzini <pbonzini@redhat.com>
>> Subject: [PATCH 1/8] hw/intc: Add l2vic interrupt controller
>>
>> From: Sid Manning <sidneym@quicinc.com>
>>
>> Co-authored-by: Matheus Tavares Bernardino
>> <quic_mathbern@quicinc.com>
>> Co-authored-by: Damien Hedde <damien.hedde@dahe.fr>
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                    |   2 +
>>   docs/devel/hexagon-l2vic.rst   |  59 +++++
>>   docs/devel/index-internals.rst |   1 +
>>   include/hw/intc/l2vic.h        |  37 +++
>>   hw/intc/l2vic.c                | 417 +++++++++++++++++++++++++++++++++
>>   hw/intc/Kconfig                |   3 +
>>   hw/intc/meson.build            |   2 +
>>   hw/intc/trace-events           |   4 +
>>   8 files changed, 525 insertions(+)
>>   create mode 100644 docs/devel/hexagon-l2vic.rst  create mode 100644
>> include/hw/intc/l2vic.h  create mode 100644 hw/intc/l2vic.c
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 804c07bcd5..a842f7fe1b 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -232,6 +232,7 @@ Hexagon TCG CPUs
>>   M: Brian Cain <brian.cain@oss.qualcomm.com>
>>   S: Supported
>>   F: target/hexagon/
>> +F: hw/intc/l2vic.[ch]
> Consider naming all the files outside target/hexagon as hex_* or hexagon_*
> That will make it clear they belong to hexagon and you can use an easy wild card in the MAINTAINERS file.
> Ditto for the docs files.

Ok - I will rename l2vic hex_l2vic in v3.


>>   X: target/hexagon/idef-parser/
>>   X: target/hexagon/gen_idef_parser_funcs.py
>>   F: linux-user/hexagon/
>> diff --git a/include/hw/intc/l2vic.h b/include/hw/intc/l2vic.h new file mode
>> 100644 index 0000000000..ed8ccf33b1
>> --- /dev/null
>> +++ b/include/hw/intc/l2vic.h
>> @@ -0,0 +1,37 @@
>> +/*
>> + * QEMU L2VIC Interrupt Controller
>> + *
>> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights
>> Reserved.
>> + * SPDX-License-Identifier: GPL-2.0-or-later  */
>> +
>> +#define L2VIC_VID_GRP_0 0x0 /* Read */
>> +#define L2VIC_VID_GRP_1 0x4 /* Read */
>> +#define L2VIC_VID_GRP_2 0x8 /* Read */
>> +#define L2VIC_VID_GRP_3 0xC /* Read */
>> +#define L2VIC_VID_0 0x10 /* Read SOFTWARE DEFINED */ #define
>> +L2VIC_VID_1 0x14 /* Read SOFTWARE DEFINED NOT YET USED */ #define
>> +L2VIC_INT_ENABLEn 0x100 /* Read/Write */ #define
>> +L2VIC_INT_ENABLE_CLEARn 0x180 /* Write */ #define
>> L2VIC_INT_ENABLE_SETn
>> +0x200 /* Write */ #define L2VIC_INT_TYPEn 0x280 /* Read/Write */
>> +#define L2VIC_INT_STATUSn 0x380 /* Read */ #define L2VIC_INT_CLEARn
>> +0x400 /* Write */ #define L2VIC_SOFT_INTn 0x480 /* Write */ #define
>> +L2VIC_INT_PENDINGn 0x500 /* Read */ #define L2VIC_INT_GRPn_0 0x600
>> /*
>> +Read/Write */ #define L2VIC_INT_GRPn_1 0x680 /* Read/Write */ #define
>> +L2VIC_INT_GRPn_2 0x700 /* Read/Write */ #define L2VIC_INT_GRPn_3
>> 0x780
>> +/* Read/Write */
>> +
>> +#define L2VIC_INTERRUPT_MAX 1024
>> +#define L2VIC_CIAD_INSTRUCTION -1
>> +/*
>> + * Note about l2vic groups:
>> + * Each interrupt to L2VIC can be configured to associate with one of
>> + * four groups.
>> + * Group 0 interrupts go to IRQ2 via VID 0 (SSR: 0xC2, the default)
>> + * Group 1 interrupts go to IRQ3 via VID 1 (SSR: 0xC3)
>> + * Group 2 interrupts go to IRQ4 via VID 2 (SSR: 0xC4)
>> + * Group 3 interrupts go to IRQ5 via VID 3 (SSR: 0xC5)  */
>> diff --git a/hw/intc/l2vic.c b/hw/intc/l2vic.c new file mode 100644 index
>> 0000000000..9df6575214
>> --- /dev/null
>> +++ b/hw/intc/l2vic.c
>> @@ -0,0 +1,417 @@
>> +/*
>> + * QEMU L2VIC Interrupt Controller
>> + *
>> + * Arm PrimeCell PL190 Vector Interrupt Controller was used as a reference.
>> + * Copyright(c) 2020-2025 Qualcomm Innovation Center, Inc. All Rights
>> Reserved.
>> + * SPDX-License-Identifier: GPL-2.0-or-later  */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/irq.h"
>> +#include "hw/sysbus.h"
>> +#include "migration/vmstate.h"
>> +#include "qemu/log.h"
>> +#include "qemu/module.h"
>> +#include "hw/intc/l2vic.h"
>> +#include "trace.h"
>> +
>> +#define L2VICA(s, n) (s[(n) >> 2])
>> +
>> +#define TYPE_L2VIC "l2vic"
>> +#define L2VIC(obj) OBJECT_CHECK(L2VICState, (obj), TYPE_L2VIC)
>> +
>> +#define SLICE_MAX (L2VIC_INTERRUPT_MAX / 32)
>> +
>> +typedef struct L2VICState {
>> +    SysBusDevice parent_obj;
>> +
>> +    QemuMutex active;
>> +    MemoryRegion iomem;
>> +    MemoryRegion fast_iomem;
>> +    uint32_t level;
>> +    /*
>> +     * offset 0:vid group 0 etc, 10 bits in each group
>> +     * are used:
>> +     */
>> +    uint32_t vid_group[4];
>> +    uint32_t vid0;
>> +    /* Clear Status of Active Edge interrupt, not used: */
>> +    uint32_t int_clear[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Enable interrupt source */
>> +    uint32_t int_enable[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Clear (set to 0) corresponding bit in int_enable */
>> +    uint32_t int_enable_clear;
>> +    /* Set (to 1) corresponding bit in int_enable */
>> +    uint32_t int_enable_set;
>> +    /* Present for debugging, not used */
>> +    uint32_t int_pending[SLICE_MAX] QEMU_ALIGNED(16);
> Consider using DECLARE_BITMAP32 since you use test_bit/set_bit/clear_bit.
Ok, will be fixed in v3.
> Are these alignments needed?

The assignments below resulted in unaligned accesses which were flagged 
by UBSan.  We'll revisit whether or not the alignments are necessary 
after making the other suggested changes for v3 and we'll ideally omit them.


>> +    /* Generate an interrupt */
>> +    uint32_t int_soft;
>> +    /* Which enabled interrupt is active */
>> +    uint32_t int_status[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* Edge or Level interrupt */
>> +    uint32_t int_type[SLICE_MAX] QEMU_ALIGNED(16);
>> +    /* L2 interrupt group 0-3 0x600-0x7FF */
>> +    uint32_t int_group_n0[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n1[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n2[SLICE_MAX] QEMU_ALIGNED(16);
>> +    uint32_t int_group_n3[SLICE_MAX] QEMU_ALIGNED(16);
>> +    qemu_irq irq[8];
>> +} L2VICState;
>> +
>
>
>> +
>> +static void l2vic_set_irq(void *opaque, int irq, int level) {
>> +    L2VICState *s = (L2VICState *)opaque;
>> +    if (level) {
>> +        qemu_mutex_lock(&s->active);
>> +        set_bit(irq, (unsigned long *)s->int_pending);
> Here's an example of the set_bit mentioned above.
>
>> +        qemu_mutex_unlock(&s->active);
>> +    }
>> +    l2vic_update(s, irq);
>> +}
>> +
>> +static void l2vic_reset_hold(Object *obj, G_GNUC_UNUSED ResetType
>> +res_type) {
>> +    L2VICState *s = L2VIC(obj);
>> +    memset(s->int_clear, 0, sizeof(s->int_clear));
>> +    memset(s->int_enable, 0, sizeof(s->int_enable));
>> +    memset(s->int_pending, 0, sizeof(s->int_pending));
>> +    memset(s->int_status, 0, sizeof(s->int_status));
>> +    memset(s->int_type, 0, sizeof(s->int_type));
>> +    memset(s->int_group_n0, 0, sizeof(s->int_group_n0));
>> +    memset(s->int_group_n1, 0, sizeof(s->int_group_n1));
>> +    memset(s->int_group_n2, 0, sizeof(s->int_group_n2));
>> +    memset(s->int_group_n3, 0, sizeof(s->int_group_n3));
>> +    s->int_soft = 0;
>> +    s->vid0 = 0;
> How about a single memset(s, 0, sizeof(L2VICState))?

Ok, will revisit this.


>> +
>> +    l2vic_update_all(s);
>> +}


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

* Re: [PATCH 8/8] tests/functional: Add a hexagon minivm test
  2025-03-04 15:46   ` Philippe Mathieu-Daudé
                       ` (2 preceding siblings ...)
  2025-03-05  8:05     ` Thomas Huth
@ 2025-09-02  2:52     ` Brian Cain
  3 siblings, 0 replies; 32+ messages in thread
From: Brian Cain @ 2025-09-02  2:52 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, qemu-devel
  Cc: richard.henderson, quic_mathbern, ale, anjo, quic_mliebel,
	ltaylorsimpson, alex.bennee, quic_mburton, sidneym, Brian Cain,
	Thomas Huth


On 3/4/2025 9:46 AM, Philippe Mathieu-Daudé wrote:
> Hi Brian,
>
> On 1/3/25 18:20, Brian Cain wrote:
>> From: Brian Cain <bcain@quicinc.com>
>
> A bit opaque...
>
>> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                             |  1 +
>>   tests/functional/meson.build            |  8 +++++
>>   tests/functional/test_hexagon_minivm.py | 42 +++++++++++++++++++++++++
>>   3 files changed, 51 insertions(+)
>>   create mode 100755 tests/functional/test_hexagon_minivm.py
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index deeb7878c8..48a5e7c005 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -247,6 +247,7 @@ F: gdb-xml/hexagon*.xml
>>   F: docs/system/target-hexagon.rst
>>   F: docs/devel/hexagon-sys.rst
>>   F: docs/devel/hexagon-l2vic.rst
>> +F: tests/functional/test_hexagon_minivm.py
>>   T: git https://github.com/quic/qemu.git hex-next
>>     Hexagon idef-parser
>> diff --git a/tests/functional/meson.build b/tests/functional/meson.build
>> index 111d8bab26..78b42e58f9 100644
>> --- a/tests/functional/meson.build
>> +++ b/tests/functional/meson.build
>> @@ -135,6 +135,14 @@ tests_i386_system_quick = [
>>     'migration',
>>   ]
>>   +test_timeouts += {
>> +  'hexagon_minivm': 180,
>> +}
>> +
>> +tests_hexagon_system_quick = [
>> +  'hexagon_minivm',
>> +]
>> +
>>   tests_i386_system_thorough = [
>>     'i386_tuxrun',
>>   ]
>> diff --git a/tests/functional/test_hexagon_minivm.py 
>> b/tests/functional/test_hexagon_minivm.py
>> new file mode 100755
>> index 0000000000..2ba92bcce3
>> --- /dev/null
>> +++ b/tests/functional/test_hexagon_minivm.py
>> @@ -0,0 +1,42 @@
>> +#!/usr/bin/env python3
>> +#
>> +# Copyright(c) 2024-2025 Qualcomm Innovation Center, Inc. All Rights 
>> Reserved.
>> +#
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +
>> +import os
>> +from glob import glob
>> +from qemu_test import QemuSystemTest, Asset
>> +from qemu_test import wait_for_console_pattern
>> +
>> +class MiniVMTest(QemuSystemTest):
>> +
>> +    timeout = 180
>> +    GUEST_ENTRY = 0xc0000000
>> +
>> +    REPO = 'https://artifacts.codelinaro.org/artifactory'
>> +    ASSET_TARBALL = \
>> +        Asset(f'{REPO}/codelinaro-toolchain-for-hexagon/'
>> +               '19.1.5/hexagon_minivm_2024_Dec_15.tar.gz',
>> + 'd7920b5ff14bed5a10b23ada7d4eb927ede08635281f25067e0d5711feee2c2a')
>> +
>> +    def test_minivm(self):
>> +        self.set_machine('virt')
>> +        self.archive_extract(self.ASSET_TARBALL)
>> +        rootfs_path = 
>> f'{self.workdir}/hexagon-unknown-linux-musl-rootfs'
>> +        kernel_path = f'{rootfs_path}/boot/minivm'
>
> $ readelf -h hexagon-unknown-linux-musl-rootfs/boot/minivm
>   Entry point address:               0xffff0000
>
> I suppose this is a bootloader which runs guest code at
> GUEST_ENTRY = 0xc0000000.
>
>> +
>> +        assert(os.path.exists(kernel_path))
>> +        for test_bin_path in glob(f'{rootfs_path}/boot/test_*'):
>> +            print(f'# Testing "{os.path.basename(test_bin_path)}"')
>
> $ ls -1 hexagon-unknown-linux-musl-rootfs/boot/test_*
> hexagon-unknown-linux-musl-rootfs/boot/test_interrupts
> hexagon-unknown-linux-musl-rootfs/boot/test_mmu
> hexagon-unknown-linux-musl-rootfs/boot/test_processors
>
> I'd rather 1 test per binary to easily see which one failed.
>
>> +
>> +            vm = self.get_vm()
>> +            vm.add_args('-kernel', kernel_path,
>> +                  '-device',
>> + f'loader,addr={hex(self.GUEST_ENTRY)},file={test_bin_path}')
>> +            vm.launch()
>> +            vm.wait()
>> +            self.assertEqual(vm.exitcode(), 0)
>
> ...
> ----------------
> IN:
> 0xc0000000:  0x6a09c019 { R25 = C9/pc }
> 0xc0000004:  0x00004040 { immext(#0x1000)
> 0xc0000008:  0x7800c018  R24 = ##0x1000 }
> 0xc000000c:  0xf318d918 { R24 = add(R24,R25) }
> 0xc0000010:  0x00004000 { immext(#0x0)
> 0xc0000014:  0x7800c03a  R26 = ##0x1 }
> 0xc0000018:  0x0c004000 { immext(#0xc0000000)
> 0xc000001c:  0x7800c001  R1 = ##0xc0000000 }
> 0xc0000020:  0x0ffc4000 { immext(#0xffc00000)
> 0xc0000024:  0x7601c001  R1 = and(R1,##0xffc00000) }
> 0xc0000028:  0x8c01d622 { R2 = lsr(R1,#0x16) }
> 0xc000002c:  0xc402d840 { R0 = addasl(R24,R2,#0x2) }
> 0xc0000030:  0xb0e1f8a1 { R1 = add(R1,#0xfc5) }
> 0xc0000034:  0x00044000 { immext(#0x400000)
> 0xc0000038:  0x7800c002  R2 = ##0x400000 }
> 0xc000003c:  0x601ac008 { loop0(PC+4,R26) }
> 0xc0000040:  0xab80c108 { memw(R0++#0x4) = R1 }
> 0xc0000044:  0xf3018201 { R1 = add(R1,R2)
> 0xc0000048:  0x7f00c000  nop }  :endloop0
> ...
> do_raise_exception: 0x00000002, @ 20000090
>  hexagon_cpu_do_interrupt: event 0x2:(null), cause 0x25(37)
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
> 0x20000104:  0x5400c000 { trap0(#0x0) }
>
>  hexagon_cpu_do_interrupt: event 0x8:HEX_EVENT_TRAP0, cause 0x0(0)
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x1(1)
>
> 0xc00002a0:  0x7060c002 { R2 = R0 }
> 0xc00002a4:  0x5480c20c { trap1(R0,#0x13) }
>
>  hexagon_cpu_do_interrupt: event 0x9:HEX_EVENT_TRAP1, cause 0x13(19)
> 0xffff0518:  0x5800c02a { jump PC+84 }
> 0xffff056c:  0x6460c000 { stop(R0) }
>
> How can we be sure errors won't exit(0) or hang?
>
> (qemu) info mtree
> address-space: memory
>   0000000000000000-ffffffffffffffff (prio 0, i/o): system
>     0000000000000000-00000000ffffffff (prio 0, ram): ddr.ram
>     0000000010000000-0000000010000fff (prio 0, i/o): pl011
>     0000000011000000-00000000110001ff (prio 0, i/o): virtio-mmio
>     0000000012000000-00000000120001ff (prio 0, i/o): virtio-mmio
>     00000000d81e0000-00000000d81effff (prio 0, i/o): fast
>    00000000d8400000-00000000d87fffff (prio 0, ram): vtcm.ram
>     00000000de000000-00000000de0001ff (prio 0, rom): config_table.rom
>     00000000fc910000-00000000fc910fff (prio 0, i/o): l2vic
>
> Could we have minimal debug output on the console?
>
For now minivm relies on semihosting, which is convenient.  So I can 
postpone this test until after that's introduced if it helps. We have 
the boot-serial-test in this patch series now, so perhaps that's adequate?

Otherwise, I think the above suggestions other than console output have 
been addressed in v2.

>> +
>> +if __name__ == '__main__':
>> +    QemuSystemTest.main()
>
> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>


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

end of thread, other threads:[~2025-09-02  4:26 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-01 17:20 [PATCH 0/8] hexagon system emu, part 3/3 Brian Cain
2025-03-01 17:20 ` [PATCH 1/8] hw/intc: Add l2vic interrupt controller Brian Cain
2025-03-03 12:26   ` Philippe Mathieu-Daudé
2025-04-02  1:07     ` Brian Cain
2025-04-03 17:41     ` Brian Cain
2025-03-24 19:40   ` ltaylorsimpson
2025-03-24 20:47     ` Brian Cain
2025-09-02  2:46     ` Brian Cain
2025-03-01 17:20 ` [PATCH 2/8] hw/hexagon: Add machine configs for sysemu Brian Cain
2025-03-04  6:27   ` Markus Armbruster
2025-03-04 13:12     ` Brian Cain
2025-03-24 19:48   ` ltaylorsimpson
2025-03-01 17:20 ` [PATCH 3/8] hw/hexagon: Add v68, sa8775-cdsp0 defs Brian Cain
2025-03-24 19:50   ` ltaylorsimpson
2025-03-01 17:20 ` [PATCH 4/8] hw/hexagon: Add support for cfgbase Brian Cain
2025-03-24 20:01   ` ltaylorsimpson
2025-03-01 17:20 ` [PATCH 5/8] hw/hexagon: Modify "Standalone" symbols Brian Cain
2025-03-24 20:04   ` ltaylorsimpson
2025-03-01 17:20 ` [PATCH 6/8] target/hexagon: add build config for softmmu Brian Cain
2025-03-04 15:25   ` Philippe Mathieu-Daudé
2025-03-04 15:59     ` Anton Johansson via
2025-03-24 20:12   ` ltaylorsimpson
2025-03-01 17:20 ` [PATCH 7/8] hw/hexagon: Define hexagon "virt" machine Brian Cain
2025-03-04 15:38   ` Philippe Mathieu-Daudé
2025-03-01 17:20 ` [PATCH 8/8] tests/functional: Add a hexagon minivm test Brian Cain
2025-03-04 15:46   ` Philippe Mathieu-Daudé
2025-03-04 16:07     ` Brian Cain
2025-03-04 16:15     ` Brian Cain
2025-03-04 20:34       ` Brian Cain
2025-03-05  8:05     ` Thomas Huth
2025-03-05 14:35       ` Brian Cain
2025-09-02  2:52     ` Brian Cain

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).