On 15/7/26 20:56, Brian Cain wrote:
Instantiate the L2VIC device in both machine models, map its slow and
MMIO regions, and link it to each CPU via the "l2vic" property.

"slow and MMIO" description is not clear to me.


Reviewed-by: Pierrick Bouvier <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
  include/hw/hexagon/hexagon.h           |  1 +
  include/hw/hexagon/hexagon_globalreg.h |  4 +++
  hw/hexagon/hexagon_dsp.c               | 20 +++++++++++++
  hw/hexagon/hexagon_globalreg.c         | 41 ++++++++++++++++++++++----
  hw/hexagon/virt.c                      | 22 ++++++++++++++
  5 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h
index 1034b09c2ac..6753ae32cde 100644
--- a/include/hw/hexagon/hexagon.h
+++ b/include/hw/hexagon/hexagon.h
@@ -156,6 +156,7 @@ struct HexagonCommonMachineState {
MemoryRegion ram;
      MemoryRegion cfgtable_rom;
+    DeviceState *l2vic_dev;

s/_dev//

  };
#endif
diff --git a/include/hw/hexagon/hexagon_globalreg.h 
b/include/hw/hexagon/hexagon_globalreg.h
index 950099808fd..397dc6854c9 100644
--- a/include/hw/hexagon/hexagon_globalreg.h
+++ b/include/hw/hexagon/hexagon_globalreg.h
@@ -10,6 +10,7 @@
#include "hw/core/qdev.h"
  #include "hw/core/sysbus.h"
+#include "hw/intc/hex-l2vic.h"
  #include "qom/object.h"
  #include "target/hexagon/cpu.h"
@@ -22,6 +23,9 @@ struct HexagonGlobalRegState {
      /* Array of system registers */
      uint32_t regs[NUM_SREGS];
+ /* L2VIC interface used to back the VID/VID1 registers */
+    HexL2VicInterface *l2vic;
+
      /* Global performance cycle counter base */
      uint64_t g_pcycle_base;
diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c
index aa493993229..4cf88627c8f 100644
--- a/hw/hexagon/hexagon_dsp.c
+++ b/hw/hexagon/hexagon_dsp.c
@@ -16,6 +16,7 @@
  #include "hw/hexagon/hexagon.h"
  #include "hw/hexagon/hexagon_globalreg.h"
  #include "hw/hexagon/hexagon_tlb.h"
+#include "hw/intc/hex-l2vic.h"
  #include "hw/core/loader.h"
  #include "qapi/error.h"
  #include "qemu/error-report.h"
@@ -111,6 +112,7 @@ static void hexagon_common_init(MachineState *machine, 
Rev_t rev,
      MemoryRegion *address_space;
      DeviceState *glob_regs_dev;
      DeviceState *tlb_dev;
+    DeviceState *cpu0 = NULL;
memset(&hexagon_binfo, 0, sizeof(hexagon_binfo));
      if (machine->kernel_filename) {
@@ -131,11 +133,21 @@ static void hexagon_common_init(MachineState *machine, 
Rev_t rev,
                             machine->ram_size, &error_fatal);
      memory_region_add_subregion(address_space, 0x0, &hms->ram);
+ hms->l2vic_dev = qdev_new(TYPE_HEX_L2VIC);
+    object_property_add_child(OBJECT(machine), "l2vic",
+                              OBJECT(hms->l2vic_dev));
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(hms->l2vic_dev), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(hms->l2vic_dev), 0, m_cfg->l2vic_base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(hms->l2vic_dev), 1,
+                    m_cfg->cfgtable.fastl2vic_base << 16);
+
      glob_regs_dev = qdev_new(TYPE_HEXAGON_GLOBALREG);
      object_property_add_child(OBJECT(machine), "global-regs",
                                OBJECT(glob_regs_dev));
      qdev_prop_set_uint64(glob_regs_dev, "config-table-addr", m_cfg->cfgbase);
      qdev_prop_set_uint32(glob_regs_dev, "dsp-rev", rev);
+    object_property_set_link(OBJECT(glob_regs_dev), "l2vic",
+                             OBJECT(hms->l2vic_dev), &error_fatal);
      sysbus_realize_and_unref(SYS_BUS_DEVICE(glob_regs_dev), &error_fatal);
tlb_dev = qdev_new(TYPE_HEXAGON_TLB);
@@ -154,15 +166,23 @@ static void hexagon_common_init(MachineState *machine, 
Rev_t rev,
           */
          qdev_prop_set_bit(DEVICE(cpu), "start-powered-off", (i != 0));
          if (i == 0) {
+            cpu0 = DEVICE(cpu);

Alternatively call sysbus_connect_irq() here.

              hexagon_init_bootstrap(dms, cpu);
          }
          object_property_set_link(OBJECT(cpu), "global-regs",
                                   OBJECT(glob_regs_dev), &error_fatal);
          object_property_set_link(OBJECT(cpu), "tlb",
                                   OBJECT(tlb_dev), &error_fatal);
+        object_property_set_link(OBJECT(cpu), "l2vic",
+                                 OBJECT(hms->l2vic_dev), &error_fatal);
          qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);
      }
+ for (int i = 0; i < 8; i++) {
+        sysbus_connect_irq(SYS_BUS_DEVICE(hms->l2vic_dev), i,
+                           qdev_get_gpio_in(cpu0, i));
+    }
+
      rom_add_blob_fixed_as("config_table.rom", &m_cfg->cfgtable,
                            sizeof(m_cfg->cfgtable), m_cfg->cfgbase,
                            &address_space_memory);
diff --git a/hw/hexagon/hexagon_globalreg.c b/hw/hexagon/hexagon_globalreg.c
index b5e5913507e..3d0d6f9516c 100644
--- a/hw/hexagon/hexagon_globalreg.c
+++ b/hw/hexagon/hexagon_globalreg.c
@@ -11,6 +11,7 @@
  #include "hw/core/qdev-properties.h"
  #include "hw/core/sysbus.h"
  #include "hw/core/resettable.h"
+#include "hw/intc/hex-l2vic.h"
  #include "migration/vmstate.h"
  #include "qom/object.h"
  #include "target/hexagon/cpu.h"
@@ -135,6 +136,32 @@ static inline uint32_t apply_write_mask(uint32_t new_val, 
uint32_t cur_val,
      return new_val;
  }
+static inline bool is_vid_reg(uint32_t reg)
+{
+    return reg == HEX_SREG_VID || reg == HEX_SREG_VID1;
+}
+
+/*
+ * HEX_SREG_VID/VID1 are backed by the L2VIC's VID group registers
+ * rather than the plain regs[] array, when an L2VIC is wired up.
+ */
+static uint32_t get_reg_value(HexagonGlobalRegState *s, uint32_t reg)
+{
+    if (is_vid_reg(reg) && s->l2vic) {

Do we still want an optional l2vic? Otherwise we should make it
unconditional, checking the link is set in hexagon_globalreg_realize().

+        return l2vic_read_vid(s->l2vic, reg == HEX_SREG_VID ? 0 : 1);
+    }
+    return s->regs[reg];
+}
+
+static void set_reg_value(HexagonGlobalRegState *s, uint32_t reg,
+                          uint32_t value)
+{
+    s->regs[reg] = value;

IIUC HEX_SREG_VID,1 are read-only and shouldn't be updated, is that right?

+    if (is_vid_reg(reg) && s->l2vic) {
+        l2vic_update_vid(s->l2vic, reg == HEX_SREG_VID ? 0 : 1, value);
+    }
+}
+
  uint32_t hexagon_globalreg_read(HexagonGlobalRegState *s, uint32_t reg,
                                  uint32_t htid)
  {
@@ -146,7 +173,7 @@ uint32_t hexagon_globalreg_read(HexagonGlobalRegState *s, 
uint32_t reg,
      g_assert(reg < NUM_SREGS);
      g_assert(reg >= HEX_SREG_GLB_START);
- value = s->regs[reg];
+    value = get_reg_value(s, reg);
trace_hexagon_globalreg_read(htid, get_sreg_name(reg), value);
      return value;
@@ -160,7 +187,7 @@ void hexagon_globalreg_write(HexagonGlobalRegState *s, 
uint32_t reg,
      }
      g_assert(reg < NUM_SREGS);
      g_assert(reg >= HEX_SREG_GLB_START);
-    s->regs[reg] = value;
+    set_reg_value(s, reg, value);

A preliminary patch with extracting get_reg_value/set_reg_value stubs
would reduce this diff.

      trace_hexagon_globalreg_write(htid, get_sreg_name(reg), value);
  }
@@ -168,6 +195,7 @@ uint32_t hexagon_globalreg_masked_value(HexagonGlobalRegState *s, uint32_t reg,
                                          uint32_t value)
  {
      uint32_t reg_mask;
+    uint32_t cur_val;
if (!s) {
          return value;
@@ -175,9 +203,10 @@ uint32_t 
hexagon_globalreg_masked_value(HexagonGlobalRegState *s, uint32_t reg,
      g_assert(reg < NUM_SREGS);
      g_assert(reg >= HEX_SREG_GLB_START);
      reg_mask = global_sreg_immut_masks[reg];
+    cur_val = get_reg_value(s, reg);
      return reg_mask == IMMUTABLE ?
-            s->regs[reg] :
-            apply_write_mask(value, s->regs[reg], reg_mask);
+            cur_val :
+            apply_write_mask(value, cur_val, reg_mask);
  }
void hexagon_globalreg_write_masked(HexagonGlobalRegState *s, uint32_t reg,
@@ -186,7 +215,7 @@ void hexagon_globalreg_write_masked(HexagonGlobalRegState 
*s, uint32_t reg,
      if (!s) {
          return;
      }
-    s->regs[reg] = hexagon_globalreg_masked_value(s, reg, value);
+    set_reg_value(s, reg, hexagon_globalreg_masked_value(s, reg, value));
  }
uint64_t hexagon_globalreg_get_pcycle_base(HexagonGlobalRegState *s)
@@ -275,6 +304,8 @@ static const VMStateDescription vmstate_hexagon_globalreg = 
{
  };
static const Property hexagon_globalreg_properties[] = {
+    DEFINE_PROP_LINK("l2vic", HexagonGlobalRegState, l2vic,
+                     TYPE_HEX_L2VIC_INTERFACE, HexL2VicInterface *),
      DEFINE_PROP_UINT32("boot-evb", HexagonGlobalRegState, boot_evb, 0x0),
      DEFINE_PROP_UINT64("config-table-addr", HexagonGlobalRegState,
                         config_table_addr, 0xffffffffULL),
diff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c
index a3638998b87..2256d3d53a5 100644
--- a/hw/hexagon/virt.c
+++ b/hw/hexagon/virt.c
@@ -15,6 +15,7 @@
  #include "hw/hexagon/hexagon.h"
  #include "hw/hexagon/hexagon_globalreg.h"
  #include "hw/hexagon/hexagon_tlb.h"
+#include "hw/intc/hex-l2vic.h"
  #include "hw/core/loader.h"
  #include "hw/core/qdev-properties.h"
  #include "hw/core/qdev-clock.h"
@@ -268,10 +269,22 @@ static void virt_init(MachineState *ms)
                                  &vms->parent_obj.cfgtable_rom);
      fdt_add_hvx(vms, m_cfg);
+ vms->parent_obj.l2vic_dev = qdev_new(TYPE_HEX_L2VIC);
+    object_property_add_child(OBJECT(ms), "l2vic",
+                              OBJECT(vms->parent_obj.l2vic_dev));
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(vms->parent_obj.l2vic_dev),
+                             &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(vms->parent_obj.l2vic_dev), 0,
+                    m_cfg->l2vic_base);
+    sysbus_mmio_map(SYS_BUS_DEVICE(vms->parent_obj.l2vic_dev), 1,
+                    m_cfg->cfgtable.fastl2vic_base << 16);
+
      gsregs_dev = qdev_new(TYPE_HEXAGON_GLOBALREG);
      object_property_add_child(OBJECT(ms), "global-regs", OBJECT(gsregs_dev));
      qdev_prop_set_uint64(gsregs_dev, "config-table-addr", m_cfg->cfgbase);
      qdev_prop_set_uint32(gsregs_dev, "dsp-rev", v68_rev);
+    object_property_set_link(OBJECT(gsregs_dev), "l2vic",
+                             OBJECT(vms->parent_obj.l2vic_dev), &error_fatal);
      sysbus_realize_and_unref(SYS_BUS_DEVICE(gsregs_dev), &error_fatal);
tlb_dev = qdev_new(TYPE_HEXAGON_TLB);
@@ -301,9 +314,18 @@ static void virt_init(MachineState *ms)
                                   OBJECT(gsregs_dev), &error_fatal);
          object_property_set_link(OBJECT(cpu), "tlb",
                                   OBJECT(tlb_dev), &error_fatal);
+        object_property_set_link(OBJECT(cpu), "l2vic",
+                                 OBJECT(vms->parent_obj.l2vic_dev),
+                                 &error_fatal);
qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);
      }
+
+    for (int i = 0; i < 8; i++) {
+        sysbus_connect_irq(SYS_BUS_DEVICE(vms->parent_obj.l2vic_dev), i,
+                           qdev_get_gpio_in(cpu0, i));
+    }
+
      fdt_add_cpu_nodes(vms);
      clk_phandle = fdt_add_clocks(vms);
      fdt_add_uart(vms, VIRT_UART0, clk_phandle);


Reply via email to