Files
Yaya48 cf256aa081 Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git

Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
2026-08-31 02:15:30 +02:00

201 lines
5.6 KiB
C

/*
* 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/hex-subsys.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/physmem.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) {
physical_memory_write(dms->isdb_secure_flag,
&mem, sizeof(mem));
}
if (dms->isdb_trusted_flag) {
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);
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;
hex_subsys_create(hms, m_cfg, rev);
g_autofree HexagonCPU **cpus = g_new(HexagonCPU *, machine->smp.cpus);
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);
}
hex_subsys_add_cpu(hms, DEVICE(cpu));
cpus[i] = cpu;
}
hex_subsys_realize_cluster(hms);
for (int i = 0; i < machine->smp.cpus; i++) {
hex_subsys_realize_cpu(hms, DEVICE(cpus[i]), (i == 0));
}
}
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)