2 * RX QEMU GDB simulator
4 * Copyright (c) 2019 Yoshinori Sato
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
20 #include "qemu/cutils.h"
21 #include "qemu/error-report.h"
22 #include "qemu/guest-random.h"
23 #include "qemu/units.h"
24 #include "qapi/error.h"
25 #include "hw/loader.h"
26 #include "hw/rx/rx62n.h"
27 #include "sysemu/qtest.h"
28 #include "sysemu/device_tree.h"
29 #include "sysemu/reset.h"
30 #include "hw/boards.h"
31 #include "qom/object.h"
33 /* Same address of GDB integrated simulator */
34 #define SDRAM_BASE EXT_CS_BASE
36 struct RxGdbSimMachineClass
{
38 MachineClass parent_class
;
41 uint32_t xtal_freq_hz
;
43 typedef struct RxGdbSimMachineClass RxGdbSimMachineClass
;
45 struct RxGdbSimMachineState
{
47 MachineState parent_obj
;
51 typedef struct RxGdbSimMachineState RxGdbSimMachineState
;
53 #define TYPE_RX_GDBSIM_MACHINE MACHINE_TYPE_NAME("rx62n-common")
55 DECLARE_OBJ_CHECKERS(RxGdbSimMachineState
, RxGdbSimMachineClass
,
56 RX_GDBSIM_MACHINE
, TYPE_RX_GDBSIM_MACHINE
)
59 static void rx_load_image(RXCPU
*cpu
, const char *filename
,
60 uint32_t start
, uint32_t size
)
62 static uint32_t extable
[32];
66 kernel_size
= load_image_targphys(filename
, start
, size
);
67 if (kernel_size
< 0) {
68 fprintf(stderr
, "qemu: could not load kernel '%s'\n", filename
);
73 /* setup exception trap trampoline */
74 /* linux kernel only works little-endian mode */
75 for (i
= 0; i
< ARRAY_SIZE(extable
); i
++) {
76 extable
[i
] = cpu_to_le32(0x10 + i
* 4);
78 rom_add_blob_fixed("extable", extable
, sizeof(extable
), VECTOR_TABLE_BASE
);
81 static void rx_gdbsim_init(MachineState
*machine
)
83 MachineClass
*mc
= MACHINE_GET_CLASS(machine
);
84 RxGdbSimMachineState
*s
= RX_GDBSIM_MACHINE(machine
);
85 RxGdbSimMachineClass
*rxc
= RX_GDBSIM_MACHINE_GET_CLASS(machine
);
86 MemoryRegion
*sysmem
= get_system_memory();
87 const char *kernel_filename
= machine
->kernel_filename
;
88 const char *dtb_filename
= machine
->dtb
;
91 if (machine
->ram_size
< mc
->default_ram_size
) {
92 char *sz
= size_to_str(mc
->default_ram_size
);
93 error_report("Invalid RAM size, should be more than %s", sz
);
98 /* Allocate memory space */
99 memory_region_add_subregion(sysmem
, SDRAM_BASE
, machine
->ram
);
102 object_initialize_child(OBJECT(machine
), "mcu", &s
->mcu
, rxc
->mcu_name
);
103 object_property_set_link(OBJECT(&s
->mcu
), "main-bus", OBJECT(sysmem
),
105 object_property_set_uint(OBJECT(&s
->mcu
), "xtal-frequency-hz",
106 rxc
->xtal_freq_hz
, &error_abort
);
107 object_property_set_bool(OBJECT(&s
->mcu
), "load-kernel",
108 kernel_filename
!= NULL
, &error_abort
);
110 if (!kernel_filename
) {
111 if (machine
->firmware
) {
112 rom_add_file_fixed(machine
->firmware
, RX62N_CFLASH_BASE
, 0);
113 } else if (!qtest_enabled()) {
114 error_report("No bios or kernel specified");
119 qdev_realize(DEVICE(&s
->mcu
), NULL
, &error_abort
);
121 /* Load kernel and dtb */
122 if (kernel_filename
) {
123 ram_addr_t kernel_offset
;
126 * The kernel image is loaded into
127 * the latter half of the SDRAM space.
129 kernel_offset
= machine
->ram_size
/ 2;
130 rx_load_image(RX_CPU(first_cpu
), kernel_filename
,
131 SDRAM_BASE
+ kernel_offset
, kernel_offset
);
133 ram_addr_t dtb_offset
;
135 g_autofree
void *dtb
= load_device_tree(dtb_filename
, &dtb_size
);
138 error_report("Couldn't open dtb file %s", dtb_filename
);
141 if (machine
->kernel_cmdline
&&
142 qemu_fdt_setprop_string(dtb
, "/chosen", "bootargs",
143 machine
->kernel_cmdline
) < 0) {
144 error_report("Couldn't set /chosen/bootargs");
147 qemu_guest_getrandom_nofail(rng_seed
, sizeof(rng_seed
));
148 qemu_fdt_setprop(dtb
, "/chosen", "rng-seed", rng_seed
, sizeof(rng_seed
));
149 /* DTB is located at the end of SDRAM space. */
150 dtb_offset
= ROUND_DOWN(machine
->ram_size
- dtb_size
, 16);
151 rom_add_blob_fixed("dtb", dtb
, dtb_size
,
152 SDRAM_BASE
+ dtb_offset
);
153 qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds
,
154 rom_ptr(SDRAM_BASE
+ dtb_offset
, dtb_size
));
155 /* Set dtb address to R1 */
156 RX_CPU(first_cpu
)->env
.regs
[1] = SDRAM_BASE
+ dtb_offset
;
161 static void rx_gdbsim_class_init(ObjectClass
*oc
, void *data
)
163 MachineClass
*mc
= MACHINE_CLASS(oc
);
165 mc
->init
= rx_gdbsim_init
;
166 mc
->default_cpu_type
= TYPE_RX62N_CPU
;
167 mc
->default_ram_size
= 16 * MiB
;
168 mc
->default_ram_id
= "ext-sdram";
171 static void rx62n7_class_init(ObjectClass
*oc
, void *data
)
173 RxGdbSimMachineClass
*rxc
= RX_GDBSIM_MACHINE_CLASS(oc
);
174 MachineClass
*mc
= MACHINE_CLASS(oc
);
176 rxc
->mcu_name
= TYPE_R5F562N7_MCU
;
177 rxc
->xtal_freq_hz
= 12 * 1000 * 1000;
178 mc
->desc
= "gdb simulator (R5F562N7 MCU and external RAM)";
181 static void rx62n8_class_init(ObjectClass
*oc
, void *data
)
183 RxGdbSimMachineClass
*rxc
= RX_GDBSIM_MACHINE_CLASS(oc
);
184 MachineClass
*mc
= MACHINE_CLASS(oc
);
186 rxc
->mcu_name
= TYPE_R5F562N8_MCU
;
187 rxc
->xtal_freq_hz
= 12 * 1000 * 1000;
188 mc
->desc
= "gdb simulator (R5F562N8 MCU and external RAM)";
191 static const TypeInfo rx_gdbsim_types
[] = {
193 .name
= MACHINE_TYPE_NAME("gdbsim-r5f562n7"),
194 .parent
= TYPE_RX_GDBSIM_MACHINE
,
195 .class_init
= rx62n7_class_init
,
197 .name
= MACHINE_TYPE_NAME("gdbsim-r5f562n8"),
198 .parent
= TYPE_RX_GDBSIM_MACHINE
,
199 .class_init
= rx62n8_class_init
,
201 .name
= TYPE_RX_GDBSIM_MACHINE
,
202 .parent
= TYPE_MACHINE
,
203 .instance_size
= sizeof(RxGdbSimMachineState
),
204 .class_size
= sizeof(RxGdbSimMachineClass
),
205 .class_init
= rx_gdbsim_class_init
,
210 DEFINE_TYPES(rx_gdbsim_types
)