From: Brian Cain <[email protected]>

Some header includes are modified here: these are uniquely required for
basic system emulation functionality and had not been required for linux-user.

Acked-by: Markus Armbruster <[email protected]>
Co-authored-by: Mike Lambert <[email protected]>
Co-authored-by: Sid Manning <[email protected]>
Reviewed-by: Pierrick Bouvier <[email protected]>
Signed-off-by: Brian Cain <[email protected]>
---
 MAINTAINERS                            |  14 +-
 include/hw/hexagon/hexagon.h           | 161 ++++++++++++++++++
 hw/hexagon/machine_cfg_v66g_1024.h.inc |  64 +++++++
 hw/hexagon/hexagon_dsp.c               | 220 +++++++++++++++++++++++++
 system/qdev-monitor.c                  |   2 +-
 target/hexagon/translate.c             |   1 +
 hw/Kconfig                             |   1 +
 hw/hexagon/Kconfig                     |   4 +
 hw/hexagon/meson.build                 |   6 +
 hw/meson.build                         |   1 +
 10 files changed, 471 insertions(+), 3 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 e670e22c197..0528387ce17 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -260,8 +260,6 @@ F: configs/targets/hexagon-linux-user/default.mak
 F: docker/dockerfiles/debian-hexagon-cross.docker
 F: gdbstub/gdb-xml/hexagon*.xml
 F: docs/system/target-hexagon.rst
-F: docs/system/hexagon/
-F: docs/devel/hexagon-sys.rst
 T: git https://github.com/quic/qemu.git hex-next
 
 Hexagon idef-parser
@@ -1348,6 +1346,18 @@ F: pc-bios/hppa-firmware.img
 F: roms/seabios-hppa/
 F: tests/functional/hppa/
 
+Hexagon Machines
+----------------
+V66G_1024, V68N_1024, sa8775-cdsp0
+M: Brian Cain <[email protected]>
+R: Pierrick Bouvier <[email protected]>
+S: Supported
+F: hw/hexagon/
+F: include/hw/hexagon/
+F: configs/devices/hexagon-softmmu/default.mak
+F: docs/system/hexagon/
+F: docs/devel/hexagon-sys.rst
+
 LoongArch Machines
 ------------------
 Virt
diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h
new file mode 100644
index 00000000000..1034b09c2ac
--- /dev/null
+++ b/include/hw/hexagon/hexagon.h
@@ -0,0 +1,161 @@
+/*
+ * Hexagon Baseboard System emulation.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+
+#ifndef HW_HEXAGON_H
+#define HW_HEXAGON_H
+
+#include "system/memory.h"
+#include "hw/core/boards.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)
+
+union hexagon_config_table {
+    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];
+};
+
+struct hexagon_machine_config {
+    /* 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_region;
+    union hexagon_config_table cfgtable;
+};
+
+#define TYPE_HEXAGON_COMMON_MACHINE "hexagon-common-machine"
+OBJECT_DECLARE_SIMPLE_TYPE(HexagonCommonMachineState, HEXAGON_COMMON_MACHINE)
+
+struct HexagonCommonMachineState {
+    MachineState parent_obj;
+
+    MemoryRegion ram;
+    MemoryRegion cfgtable_rom;
+};
+
+#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 00000000000..cc4d89b89c9
--- /dev/null
+++ b/hw/hexagon/machine_cfg_v66g_1024.h.inc
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+static const struct hexagon_machine_config v66g_1024 = {
+    .cfgbase =        0xd8180000,
+    .l2tcm_size =     0x00000000,
+    .l2vic_base =     0xfc910000,
+    .l2vic_size =     0x00001000,
+    .csr_base =       0xfc900000,
+    .qtmr_region =    0xfc921000,
+    .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,
+        .reserved4 = 0x00000000,
+        .reserved5 = 0x00000000,
+        .reserved6 = 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 00000000000..5934a99b522
--- /dev/null
+++ b/hw/hexagon/hexagon_dsp.c
@@ -0,0 +1,220 @@
+/*
+ * Hexagon DSP Subsystem emulation.  This represents a generic DSP
+ * subsystem with few peripherals, like the Compute DSP.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "system/address-spaces.h"
+#include "hw/core/boards.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/hexagon/hexagon.h"
+#include "hw/hexagon/hexagon_globalreg.h"
+#include "hw/hexagon/hexagon_tlb.h"
+#include "hw/core/loader.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "elf.h"
+#include "cpu.h"
+#include "migration/cpu.h"
+#include "system/system.h"
+#include "target/hexagon/internal.h"
+#include "system/reset.h"
+
+#include "machine_cfg_v66g_1024.h.inc"
+
+#define TYPE_HEXAGON_DSP_MACHINE "hexagon-dsp-machine"
+OBJECT_DECLARE_SIMPLE_TYPE(HexagonDspMachineState, HEXAGON_DSP_MACHINE)
+
+struct HexagonDspMachineState {
+    HexagonCommonMachineState parent_obj;
+
+    hwaddr isdb_secure_flag;
+    hwaddr isdb_trusted_flag;
+};
+
+static HexagonDspMachineState *current_dms;
+
+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)) {
+        current_dms->isdb_secure_flag = st_value;
+    }
+    if (!g_strcmp0("isdb_trusted_flag", st_name)) {
+        current_dms->isdb_trusted_flag = st_value;
+    }
+}
+
+/* Board init.  */
+static struct hexagon_board_boot_info hexagon_binfo;
+
+static void hexagon_load_kernel(HexagonDspMachineState *dms, HexagonCPU *cpu)
+{
+    uint64_t pentry;
+    long kernel_size;
+
+    current_dms = dms;
+    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);
+    current_dms = NULL;
+
+    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(HexagonDspMachineState *dms, HexagonCPU 
*cpu)
+{
+    MachineState *machine = MACHINE(dms);
+
+    if (machine->kernel_filename) {
+        uint32_t mem = 1;
+
+        hexagon_load_kernel(dms, cpu);
+        if (dms->isdb_secure_flag) {
+            cpu_physical_memory_write(dms->isdb_secure_flag,
+                                     &mem, sizeof(mem));
+        }
+        if (dms->isdb_trusted_flag) {
+            cpu_physical_memory_write(dms->isdb_trusted_flag,
+                                     &mem, sizeof(mem));
+        }
+    }
+}
+
+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,
+                                const struct hexagon_machine_config *m_cfg)
+{
+    HexagonCommonMachineState *hms = HEXAGON_COMMON_MACHINE(machine);
+    HexagonDspMachineState *dms = HEXAGON_DSP_MACHINE(machine);
+    MemoryRegion *address_space;
+    DeviceState *glob_regs_dev;
+    DeviceState *tlb_dev;
+
+    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;
+
+    address_space = get_system_memory();
+
+    memory_region_init_rom(&hms->cfgtable_rom, NULL, "config_table.rom",
+                           sizeof(m_cfg->cfgtable), &error_fatal);
+    memory_region_add_subregion(address_space, m_cfg->cfgbase,
+                                &hms->cfgtable_rom);
+
+    memory_region_init_ram(&hms->ram, NULL, "ddr.ram",
+                           machine->ram_size, &error_fatal);
+    memory_region_add_subregion(address_space, 0x0, &hms->ram);
+
+    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);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(glob_regs_dev), &error_fatal);
+
+    tlb_dev = qdev_new(TYPE_HEXAGON_TLB);
+    object_property_add_child(OBJECT(machine), "tlb", OBJECT(tlb_dev));
+    qdev_prop_set_uint32(tlb_dev, "num-entries",
+                         m_cfg->cfgtable.jtlb_size_entries);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(tlb_dev), &error_fatal);
+
+    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));
+        if (i == 0) {
+            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);
+        qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);
+    }
+}
+
+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, const 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 = TYPE_HEXAGON_COMMON_MACHINE,
+        .parent = TYPE_MACHINE,
+        .instance_size = sizeof(HexagonCommonMachineState),
+        .abstract = true,
+    },
+    {
+        .name = TYPE_HEXAGON_DSP_MACHINE,
+        .parent = TYPE_HEXAGON_COMMON_MACHINE,
+        .instance_size = sizeof(HexagonDspMachineState),
+        .abstract = true,
+    },
+    {
+        .name = MACHINE_TYPE_NAME("V66G_1024"),
+        .parent = TYPE_HEXAGON_DSP_MACHINE,
+        .class_init = v66g_1024_init,
+    },
+};
+
+DEFINE_TYPES(hexagon_machine_types)
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index dfc95a08c10..00fed791cce 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -71,7 +71,7 @@ typedef struct QDevAlias
                               QEMU_ARCH_SPARC | \
                               QEMU_ARCH_XTENSA)
 #define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
-#define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
+#define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K | QEMU_ARCH_HEXAGON)
 
 /* Please keep this table sorted by typename. */
 static const QDevAlias qdev_alias_table[] = {
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index c37770bd92e..6979cf8c0d8 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -32,6 +32,7 @@
 #include "translate.h"
 #include "genptr.h"
 #include "printinsn.h"
+#include "exec/target_page.h"
 
 #define HELPER_H "helper.h"
 #include "exec/helper-info.c.inc"
diff --git a/hw/Kconfig b/hw/Kconfig
index c109f5537b2..c92ca2b13a3 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -53,6 +53,7 @@ source arm/Kconfig
 source cpu/Kconfig
 source alpha/Kconfig
 source avr/Kconfig
+source hexagon/Kconfig
 source hppa/Kconfig
 source i386/Kconfig
 source loongarch/Kconfig
diff --git a/hw/hexagon/Kconfig b/hw/hexagon/Kconfig
new file mode 100644
index 00000000000..cdf7770a305
--- /dev/null
+++ b/hw/hexagon/Kconfig
@@ -0,0 +1,4 @@
+config HEX_DSP
+    bool
+    default y
+    depends on HEXAGON
diff --git a/hw/hexagon/meson.build b/hw/hexagon/meson.build
new file mode 100644
index 00000000000..f528d2bc4ab
--- /dev/null
+++ b/hw/hexagon/meson.build
@@ -0,0 +1,6 @@
+hexagon_ss = ss.source_set()
+hexagon_ss.add(files('hexagon_tlb.c'))
+hexagon_ss.add(files('hexagon_globalreg.c'))
+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 ef65ba51950..7fa81db453e 100644
--- a/hw/meson.build
+++ b/hw/meson.build
@@ -3,6 +3,7 @@ subdir('alpha')
 subdir('arm')
 subdir('avr')
 subdir('hppa')
+subdir('hexagon')
 subdir('xenpv') # i386 uses it
 subdir('i386')
 subdir('loongarch')
-- 
2.34.1

Reply via email to