master
c 200 lines 5.64 KB
Raw
1 /*
2 * Hexagon DSP Subsystem emulation. This represents a generic DSP
3 * subsystem with few peripherals, like the Compute DSP.
4 *
5 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10
11 #include "qemu/osdep.h"
12 #include "qemu/units.h"
13 #include "system/address-spaces.h"
14 #include "hw/core/boards.h"
15 #include "hw/core/qdev-properties.h"
16 #include "hw/hexagon/hexagon.h"
17 #include "hw/hexagon/hex-subsys.h"
18 #include "hw/core/loader.h"
19 #include "qapi/error.h"
20 #include "qemu/error-report.h"
21 #include "qemu/log.h"
22 #include "elf.h"
23 #include "cpu.h"
24 #include "migration/cpu.h"
25 #include "system/system.h"
26 #include "target/hexagon/internal.h"
27 #include "system/physmem.h"
28 #include "system/reset.h"
29
30 #include "machine_cfg_v66g_1024.h.inc"
31
32 #define TYPE_HEXAGON_DSP_MACHINE "hexagon-dsp-machine"
33 OBJECT_DECLARE_SIMPLE_TYPE(HexagonDspMachineState, HEXAGON_DSP_MACHINE)
34
35 struct HexagonDspMachineState {
36 HexagonCommonMachineState parent_obj;
37
38 hwaddr isdb_secure_flag;
39 hwaddr isdb_trusted_flag;
40 };
41
42 static HexagonDspMachineState *current_dms;
43
44 static void hex_symbol_callback(const char *st_name, int st_info,
45 uint64_t st_value, uint64_t st_size)
46 {
47 if (!g_strcmp0("isdb_secure_flag", st_name)) {
48 current_dms->isdb_secure_flag = st_value;
49 }
50 if (!g_strcmp0("isdb_trusted_flag", st_name)) {
51 current_dms->isdb_trusted_flag = st_value;
52 }
53 }
54
55 /* Board init. */
56 static struct hexagon_board_boot_info hexagon_binfo;
57
58 static void hexagon_load_kernel(HexagonDspMachineState *dms, HexagonCPU *cpu)
59 {
60 uint64_t pentry;
61 long kernel_size;
62
63 current_dms = dms;
64 kernel_size = load_elf_ram_sym(hexagon_binfo.kernel_filename, NULL, NULL,
65 NULL, &pentry, NULL, NULL,
66 &hexagon_binfo.kernel_elf_flags, 0, EM_HEXAGON, 0, 0,
67 &address_space_memory, false, hex_symbol_callback);
68 current_dms = NULL;
69
70 if (kernel_size <= 0) {
71 error_report("no kernel file '%s'",
72 hexagon_binfo.kernel_filename);
73 exit(1);
74 }
75
76 qdev_prop_set_uint32(DEVICE(cpu), "exec-start-addr", pentry);
77 }
78
79 static void hexagon_init_bootstrap(HexagonDspMachineState *dms, HexagonCPU *cpu)
80 {
81 MachineState *machine = MACHINE(dms);
82
83 if (machine->kernel_filename) {
84 uint32_t mem = 1;
85
86 hexagon_load_kernel(dms, cpu);
87 if (dms->isdb_secure_flag) {
88 physical_memory_write(dms->isdb_secure_flag,
89 &mem, sizeof(mem));
90 }
91 if (dms->isdb_trusted_flag) {
92 physical_memory_write(dms->isdb_trusted_flag,
93 &mem, sizeof(mem));
94 }
95 }
96 }
97
98 static void do_cpu_reset(void *opaque)
99 {
100 HexagonCPU *cpu = opaque;
101 CPUState *cs = CPU(cpu);
102 cpu_reset(cs);
103 }
104
105 static void hexagon_common_init(MachineState *machine, Rev_t rev,
106 const struct hexagon_machine_config *m_cfg)
107 {
108 HexagonCommonMachineState *hms = HEXAGON_COMMON_MACHINE(machine);
109 HexagonDspMachineState *dms = HEXAGON_DSP_MACHINE(machine);
110
111 memset(&hexagon_binfo, 0, sizeof(hexagon_binfo));
112 if (machine->kernel_filename) {
113 hexagon_binfo.ram_size = machine->ram_size;
114 hexagon_binfo.kernel_filename = machine->kernel_filename;
115 }
116
117 machine->enable_graphics = 0;
118
119 hex_subsys_create(hms, m_cfg, rev);
120
121 g_autofree HexagonCPU **cpus = g_new(HexagonCPU *, machine->smp.cpus);
122
123 for (int i = 0; i < machine->smp.cpus; i++) {
124 HexagonCPU *cpu = HEXAGON_CPU(object_new(machine->cpu_type));
125 qemu_register_reset(do_cpu_reset, cpu);
126
127 /*
128 * CPU #0 is the only CPU running at boot, others must be
129 * explicitly enabled via start instruction.
130 */
131 qdev_prop_set_bit(DEVICE(cpu), "start-powered-off", (i != 0));
132 if (i == 0) {
133 hexagon_init_bootstrap(dms, cpu);
134 }
135 hex_subsys_add_cpu(hms, DEVICE(cpu));
136 cpus[i] = cpu;
137 }
138
139 hex_subsys_realize_cluster(hms);
140
141 for (int i = 0; i < machine->smp.cpus; i++) {
142 hex_subsys_realize_cpu(hms, DEVICE(cpus[i]), (i == 0));
143 }
144 }
145
146 static void init_mc(MachineClass *mc)
147 {
148 mc->block_default_type = IF_SD;
149 mc->default_ram_size = 4 * GiB;
150 mc->no_parallel = 1;
151 mc->no_floppy = 1;
152 mc->no_cdrom = 1;
153 mc->no_serial = 1;
154 mc->is_default = false;
155 mc->max_cpus = 8;
156 }
157
158 /* ----------------------------------------------------------------- */
159 /* Core-specific configuration settings are defined below this line. */
160 /* Config table values defined in machine_configs.h.inc */
161 /* ----------------------------------------------------------------- */
162
163 static void v66g_1024_config_init(MachineState *machine)
164 {
165 hexagon_common_init(machine, v66_rev, &v66g_1024);
166 }
167
168 static void v66g_1024_init(ObjectClass *oc, const void *data)
169 {
170 MachineClass *mc = MACHINE_CLASS(oc);
171
172 mc->desc = "Hexagon V66G_1024";
173 mc->init = v66g_1024_config_init;
174 init_mc(mc);
175 mc->is_default = true;
176 mc->default_cpu_type = TYPE_HEXAGON_CPU_V66;
177 mc->default_cpus = 4;
178 }
179
180 static const TypeInfo hexagon_machine_types[] = {
181 {
182 .name = TYPE_HEXAGON_COMMON_MACHINE,
183 .parent = TYPE_MACHINE,
184 .instance_size = sizeof(HexagonCommonMachineState),
185 .abstract = true,
186 },
187 {
188 .name = TYPE_HEXAGON_DSP_MACHINE,
189 .parent = TYPE_HEXAGON_COMMON_MACHINE,
190 .instance_size = sizeof(HexagonDspMachineState),
191 .abstract = true,
192 },
193 {
194 .name = MACHINE_TYPE_NAME("V66G_1024"),
195 .parent = TYPE_HEXAGON_DSP_MACHINE,
196 .class_init = v66g_1024_init,
197 },
198 };
199
200 DEFINE_TYPES(hexagon_machine_types)