Let the hexagon-sim-style machines their QDSP6 subsystem, and with it the l2vic and QTimer.
The config table's subsystem base is updated to align with the chosen address. Reviewed-by: Anton Johansson <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- MAINTAINERS | 1 + include/hw/hexagon/hexagon.h | 4 ++ hw/hexagon/hexagon_dsp.c | 71 +++++++++++++++++++++++++++- tests/qtest/hexagon-config-test.c | 78 +++++++++++++++++++++++++++++++ tests/qtest/meson.build | 3 +- 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 tests/qtest/hexagon-config-test.c diff --git a/MAINTAINERS b/MAINTAINERS index 0bbd7986658..72082ce854d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1391,6 +1391,7 @@ F: include/hw/misc/qcom-qdsp6ss-clk.h F: configs/devices/hexagon-softmmu/default.mak F: docs/system/hexagon/ F: tests/functional/hexagon/ +F: tests/qtest/hexagon-config-test.c F: tests/qtest/qcom-dsp-test.c F: docs/devel/hexagon-sys.rst diff --git a/include/hw/hexagon/hexagon.h b/include/hw/hexagon/hexagon.h index c4e78216fb8..678e658a6d3 100644 --- a/include/hw/hexagon/hexagon.h +++ b/include/hw/hexagon/hexagon.h @@ -47,6 +47,10 @@ typedef enum { #define HEXAGON_CFGSPACE_ENTRIES (128) +/* Offsets of q6ss cfg peripherals from the subsystem base. */ +#define HEXAGON_L2VIC_OFFSET 0x10000 +#define HEXAGON_QTIMER_OFFSET 0x21000 + union hexagon_config_table { struct { /* Base address of L2TCM space */ diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c index 3854342014f..05b95f39aa2 100644 --- a/hw/hexagon/hexagon_dsp.c +++ b/hw/hexagon/hexagon_dsp.c @@ -17,6 +17,7 @@ #include "hw/hexagon/hex-subsys.h" #include "hw/core/loader.h" #include "qapi/error.h" +#include "qapi/visitor.h" #include "qemu/error-report.h" #include "qemu/log.h" #include "elf.h" @@ -38,6 +39,8 @@ #include "machine_cfg_v85qa_1.h.inc" #define TYPE_HEXAGON_DSP_MACHINE "hexagon-dsp-machine" +#define HEXAGON_DSP_SUBSYSTEM_BASE 0xfc900000 +#define HEXAGON_DSP_SUBSYSTEM_SIZE (HEXAGON_QTIMER_OFFSET + 0x1000) OBJECT_DECLARE_SIMPLE_TYPE(HexagonDspMachineState, HEXAGON_DSP_MACHINE) struct HexagonDspMachineState { @@ -45,6 +48,8 @@ struct HexagonDspMachineState { hwaddr isdb_secure_flag; hwaddr isdb_trusted_flag; + uint32_t subsystem_base; + struct hexagon_machine_config config; }; static HexagonDspMachineState *current_dms; @@ -110,6 +115,58 @@ static void do_cpu_reset(void *opaque) cpu_reset(cs); } +static void hexagon_sim_get_subsystem_base(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + HexagonDspMachineState *dms = HEXAGON_DSP_MACHINE(obj); + uint32_t value = dms->subsystem_base; + + visit_type_uint32(v, name, &value, errp); +} + +static void hexagon_sim_set_subsystem_base(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + HexagonDspMachineState *dms = HEXAGON_DSP_MACHINE(obj); + uint64_t subsystem_end; + uint32_t value; + + if (!visit_type_uint32(v, name, &value, errp)) { + return; + } + if (!value || !QEMU_IS_ALIGNED(value, 64 * KiB)) { + error_setg(errp, "subsystem-base must be nonzero and 64 KiB aligned"); + return; + } + subsystem_end = (uint64_t)value + HEXAGON_DSP_SUBSYSTEM_SIZE; + if (subsystem_end > (uint64_t)UINT32_MAX + 1) { + error_setg(errp, "subsystem-base 0x%x requires 0x%x bytes for the " + "subsystem, beyond the end of the address space", + value, HEXAGON_DSP_SUBSYSTEM_SIZE); + return; + } + + dms->subsystem_base = value; +} + +static void add_dsp_properties(ObjectClass *oc) +{ + object_class_property_add(oc, "subsystem-base", "uint32", + hexagon_sim_get_subsystem_base, + hexagon_sim_set_subsystem_base, NULL, NULL); + object_class_property_set_description(oc, "subsystem-base", + "Simulator subsystem base address"); +} + +static void hexagon_dsp_init(Object *obj) +{ + HexagonDspMachineState *dms = HEXAGON_DSP_MACHINE(obj); + + dms->subsystem_base = HEXAGON_DSP_SUBSYSTEM_BASE; +} + static void hexagon_common_init(MachineState *machine, Rev_t rev, const struct hexagon_machine_config *m_cfg) { @@ -124,7 +181,13 @@ static void hexagon_common_init(MachineState *machine, Rev_t rev, machine->enable_graphics = 0; - hex_subsys_create(hms, m_cfg, rev); + dms->config = *m_cfg; + dms->config.csr_base = dms->subsystem_base; + dms->config.l2vic_base = dms->subsystem_base + HEXAGON_L2VIC_OFFSET; + dms->config.qtmr_region = dms->subsystem_base + HEXAGON_QTIMER_OFFSET; + dms->config.cfgtable.subsystem_base = dms->subsystem_base >> 16; + + hex_subsys_create(hms, &dms->config, rev); g_autofree HexagonCPU **cpus = g_new(HexagonCPU *, machine->smp.cpus); @@ -186,6 +249,7 @@ static void v66g_1024_init(ObjectClass *oc, const void *data) mc->is_default = true; mc->default_cpu_type = TYPE_HEXAGON_CPU_V66; mc->default_cpus = 4; + add_dsp_properties(oc); } static void v68n_1024_config_init(MachineState *machine) @@ -202,6 +266,7 @@ static void v68n_1024_init(ObjectClass *oc, const void *data) init_mc(mc); mc->default_cpu_type = TYPE_HEXAGON_CPU_V68; mc->default_cpus = 6; + add_dsp_properties(oc); } static void v73nc_1_config_init(MachineState *machine) @@ -239,6 +304,7 @@ static void v79na_1_init(ObjectClass *oc, const void *data) init_mc(mc); mc->default_cpu_type = TYPE_HEXAGON_CPU_V79; mc->default_cpus = 8; + add_dsp_properties(oc); } static void v81dgb_1_init(ObjectClass *oc, const void *data) @@ -251,6 +317,7 @@ static void v81dgb_1_init(ObjectClass *oc, const void *data) mc->default_cpu_type = TYPE_HEXAGON_CPU_V81; mc->max_cpus = 12; mc->default_cpus = 12; + add_dsp_properties(oc); } static void v81qa_1_config_init(MachineState *machine) @@ -268,6 +335,7 @@ static void v81qa_1_init(ObjectClass *oc, const void *data) mc->default_cpu_type = TYPE_HEXAGON_CPU_V81; mc->max_cpus = 12; mc->default_cpus = 12; + add_dsp_properties(oc); } static void v85qa_1_config_init(MachineState *machine) @@ -316,6 +384,7 @@ static const TypeInfo hexagon_machine_types[] = { .name = TYPE_HEXAGON_DSP_MACHINE, .parent = TYPE_HEXAGON_COMMON_MACHINE, .instance_size = sizeof(HexagonDspMachineState), + .instance_init = hexagon_dsp_init, .abstract = true, }, { diff --git a/tests/qtest/hexagon-config-test.c b/tests/qtest/hexagon-config-test.c new file mode 100644 index 00000000000..9554fce57ca --- /dev/null +++ b/tests/qtest/hexagon-config-test.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" +#include "hw/hexagon/hexagon.h" + +#include "hw/hexagon/machine_cfg_v66g_1024.h.inc" +#include "hw/hexagon/machine_cfg_v68n_1024.h.inc" +#include "hw/hexagon/machine_cfg_v79na_1.h.inc" +#include "hw/hexagon/machine_cfg_v81dgb_1.h.inc" +#include "hw/hexagon/machine_cfg_v81qa_1.h.inc" + +typedef struct { + const char *machine; + const struct hexagon_machine_config *cfg; + uint32_t subsystem_base; +} HexagonMachineCfg; + +static const HexagonMachineCfg hexagon_machines[] = { + { "V66G_1024", &v66g_1024, 0 }, + { "V68N_1024", &v68n_1024, 0 }, + { "V79NA_1", &v79na_1, 0 }, + { "V81DGB_1", &v81dgb_1, 0 }, + { "V81QA_1", &v81qa_1, 0 }, + { "V81QA_1", &v81qa_1, 0xfca00000 }, +}; + +static void test_config_table(gconstpointer data) +{ + const HexagonMachineCfg *mc = data; + uint64_t subsystem_base; + uint32_t subsystem_base_entry; + g_autofree char *args; + + if (mc->subsystem_base) { + args = g_strdup_printf("-machine %s,subsystem-base=0x%x", mc->machine, + mc->subsystem_base); + } else { + args = g_strdup_printf("-machine %s", mc->machine); + } + + qtest_start(args); + + subsystem_base_entry = readl(mc->cfg->cfgbase + + offsetof(union hexagon_config_table, + subsystem_base)); + subsystem_base = (uint64_t)subsystem_base_entry << 16; + g_assert_cmphex(subsystem_base, ==, + mc->subsystem_base ?: mc->cfg->csr_base); + writel(subsystem_base + HEXAGON_L2VIC_OFFSET + 0x200, 1); + g_assert_cmphex(readl(subsystem_base + HEXAGON_L2VIC_OFFSET + 0x100), + ==, 1); + g_assert_cmphex(readl(subsystem_base + HEXAGON_QTIMER_OFFSET + 0x10), + ==, 19200000); + + qtest_end(); +} + +int main(int argc, char **argv) +{ + size_t i; + + g_test_init(&argc, &argv, NULL); + + for (i = 0; i < ARRAY_SIZE(hexagon_machines); i++) { + const HexagonMachineCfg *mc = &hexagon_machines[i]; + g_autofree char *path = g_strdup_printf("/config/%s/%x", mc->machine, + mc->subsystem_base); + + qtest_add_data_func(path, mc, test_config_table); + } + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 7ab472a8100..46d4fc1d2b0 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -321,7 +321,8 @@ qtests_riscv64 = ['riscv-csr-test'] + \ ['k230-ddr-test', 'k230-wdt-test', 'k230-gsdma-test', 'k230-decomp-gzip-test'] : []) + \ ['milkv-duo-test'] -qtests_hexagon = ['boot-serial-test', 'l2vic-test', 'qcom-dsp-test', +qtests_hexagon = ['boot-serial-test', 'hexagon-config-test', 'l2vic-test', + 'qcom-dsp-test', 'qct-qtimer-test'] qos_test_ss = ss.source_set() -- 2.34.1
