Browse Source
Add the RX machine internally simulated in GDB. Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> [PMD: Use TYPE_RX62N_CPU, use #define for RX62N_NR_TMR/CMT/SCI, renamed CPU -> MCU, device -> microcontroller] Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-Id: <20200224141923.82118-18-ysato@users.sourceforge.jp> [PMD: Split of MCU, rename gdbsim, Add gdbsim-r5f562n7/r5f562n8] Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>pull/107/head
committed by
Philippe Mathieu-Daudé
6 changed files with 215 additions and 0 deletions
@ -1,2 +1,3 @@ |
|||
# Default configuration for rx-softmmu
|
|||
|
|||
CONFIG_RX_GDBSIM=y |
|||
|
|||
@ -1 +1,2 @@ |
|||
obj-$(CONFIG_RX62N_MCU) += rx62n.o |
|||
obj-$(CONFIG_RX_GDBSIM) += rx-gdbsim.o |
|||
|
|||
@ -0,0 +1,198 @@ |
|||
/*
|
|||
* RX QEMU GDB simulator |
|||
* |
|||
* Copyright (c) 2019 Yoshinori Sato |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify it |
|||
* under the terms and conditions of the GNU General Public License, |
|||
* version 2 or later, as published by the Free Software Foundation. |
|||
* |
|||
* This program is distributed in the hope it will be useful, but WITHOUT |
|||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|||
* more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License along with |
|||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "qemu/cutils.h" |
|||
#include "qemu/error-report.h" |
|||
#include "qapi/error.h" |
|||
#include "qemu-common.h" |
|||
#include "cpu.h" |
|||
#include "hw/hw.h" |
|||
#include "hw/sysbus.h" |
|||
#include "hw/loader.h" |
|||
#include "hw/rx/rx62n.h" |
|||
#include "sysemu/sysemu.h" |
|||
#include "sysemu/qtest.h" |
|||
#include "sysemu/device_tree.h" |
|||
#include "hw/boards.h" |
|||
|
|||
/* Same address of GDB integrated simulator */ |
|||
#define SDRAM_BASE EXT_CS_BASE |
|||
|
|||
typedef struct RxGdbSimMachineClass { |
|||
/*< private >*/ |
|||
MachineClass parent_class; |
|||
/*< public >*/ |
|||
const char *mcu_name; |
|||
uint32_t xtal_freq_hz; |
|||
} RxGdbSimMachineClass; |
|||
|
|||
typedef struct RxGdbSimMachineState { |
|||
/*< private >*/ |
|||
MachineState parent_obj; |
|||
/*< public >*/ |
|||
RX62NState mcu; |
|||
} RxGdbSimMachineState; |
|||
|
|||
#define TYPE_RX_GDBSIM_MACHINE MACHINE_TYPE_NAME("rx62n-common") |
|||
|
|||
#define RX_GDBSIM_MACHINE(obj) \ |
|||
OBJECT_CHECK(RxGdbSimMachineState, (obj), TYPE_RX_GDBSIM_MACHINE) |
|||
|
|||
#define RX_GDBSIM_MACHINE_CLASS(klass) \ |
|||
OBJECT_CLASS_CHECK(RxGdbSimMachineClass, (klass), TYPE_RX_GDBSIM_MACHINE) |
|||
#define RX_GDBSIM_MACHINE_GET_CLASS(obj) \ |
|||
OBJECT_GET_CLASS(RxGdbSimMachineClass, (obj), TYPE_RX_GDBSIM_MACHINE) |
|||
|
|||
static void rx_load_image(RXCPU *cpu, const char *filename, |
|||
uint32_t start, uint32_t size) |
|||
{ |
|||
static uint32_t extable[32]; |
|||
long kernel_size; |
|||
int i; |
|||
|
|||
kernel_size = load_image_targphys(filename, start, size); |
|||
if (kernel_size < 0) { |
|||
fprintf(stderr, "qemu: could not load kernel '%s'\n", filename); |
|||
exit(1); |
|||
} |
|||
cpu->env.pc = start; |
|||
|
|||
/* setup exception trap trampoline */ |
|||
/* linux kernel only works little-endian mode */ |
|||
for (i = 0; i < ARRAY_SIZE(extable); i++) { |
|||
extable[i] = cpu_to_le32(0x10 + i * 4); |
|||
} |
|||
rom_add_blob_fixed("extable", extable, sizeof(extable), VECTOR_TABLE_BASE); |
|||
} |
|||
|
|||
static void rx_gdbsim_init(MachineState *machine) |
|||
{ |
|||
MachineClass *mc = MACHINE_GET_CLASS(machine); |
|||
RxGdbSimMachineState *s = RX_GDBSIM_MACHINE(machine); |
|||
RxGdbSimMachineClass *rxc = RX_GDBSIM_MACHINE_GET_CLASS(machine); |
|||
MemoryRegion *sysmem = get_system_memory(); |
|||
const char *kernel_filename = machine->kernel_filename; |
|||
const char *dtb_filename = machine->dtb; |
|||
|
|||
if (machine->ram_size < mc->default_ram_size) { |
|||
char *sz = size_to_str(mc->default_ram_size); |
|||
error_report("Invalid RAM size, should be more than %s", sz); |
|||
g_free(sz); |
|||
} |
|||
|
|||
/* Allocate memory space */ |
|||
memory_region_add_subregion(sysmem, SDRAM_BASE, machine->ram); |
|||
|
|||
/* Initialize MCU */ |
|||
object_initialize_child(OBJECT(machine), "mcu", &s->mcu, rxc->mcu_name); |
|||
object_property_set_link(OBJECT(&s->mcu), OBJECT(sysmem), |
|||
"main-bus", &error_abort); |
|||
object_property_set_uint(OBJECT(&s->mcu), rxc->xtal_freq_hz, |
|||
"xtal-frequency-hz", &error_abort); |
|||
object_property_set_bool(OBJECT(&s->mcu), kernel_filename != NULL, |
|||
"load-kernel", &error_abort); |
|||
qdev_realize(DEVICE(&s->mcu), NULL, &error_abort); |
|||
|
|||
/* Load kernel and dtb */ |
|||
if (kernel_filename) { |
|||
ram_addr_t kernel_offset; |
|||
|
|||
/*
|
|||
* The kernel image is loaded into |
|||
* the latter half of the SDRAM space. |
|||
*/ |
|||
kernel_offset = machine->ram_size / 2; |
|||
rx_load_image(RXCPU(first_cpu), kernel_filename, |
|||
SDRAM_BASE + kernel_offset, kernel_offset); |
|||
if (dtb_filename) { |
|||
ram_addr_t dtb_offset; |
|||
int dtb_size; |
|||
void *dtb; |
|||
|
|||
dtb = load_device_tree(dtb_filename, &dtb_size); |
|||
if (dtb == NULL) { |
|||
error_report("Couldn't open dtb file %s", dtb_filename); |
|||
exit(1); |
|||
} |
|||
if (machine->kernel_cmdline && |
|||
qemu_fdt_setprop_string(dtb, "/chosen", "bootargs", |
|||
machine->kernel_cmdline) < 0) { |
|||
error_report("Couldn't set /chosen/bootargs"); |
|||
exit(1); |
|||
} |
|||
/* DTB is located at the end of SDRAM space. */ |
|||
dtb_offset = machine->ram_size - dtb_size; |
|||
rom_add_blob_fixed("dtb", dtb, dtb_size, |
|||
SDRAM_BASE + dtb_offset); |
|||
/* Set dtb address to R1 */ |
|||
RXCPU(first_cpu)->env.regs[1] = SDRAM_BASE + dtb_offset; |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void rx_gdbsim_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
MachineClass *mc = MACHINE_CLASS(oc); |
|||
|
|||
mc->init = rx_gdbsim_init; |
|||
mc->default_cpu_type = TYPE_RX62N_CPU; |
|||
mc->default_ram_size = 16 * MiB; |
|||
mc->default_ram_id = "ext-sdram"; |
|||
} |
|||
|
|||
static void rx62n7_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
RxGdbSimMachineClass *rxc = RX_GDBSIM_MACHINE_CLASS(oc); |
|||
MachineClass *mc = MACHINE_CLASS(oc); |
|||
|
|||
rxc->mcu_name = TYPE_R5F562N7_MCU; |
|||
rxc->xtal_freq_hz = 12 * 1000 * 1000; |
|||
mc->desc = "gdb simulator (R5F562N7 MCU and external RAM)"; |
|||
}; |
|||
|
|||
static void rx62n8_class_init(ObjectClass *oc, void *data) |
|||
{ |
|||
RxGdbSimMachineClass *rxc = RX_GDBSIM_MACHINE_CLASS(oc); |
|||
MachineClass *mc = MACHINE_CLASS(oc); |
|||
|
|||
rxc->mcu_name = TYPE_R5F562N8_MCU; |
|||
rxc->xtal_freq_hz = 12 * 1000 * 1000; |
|||
mc->desc = "gdb simulator (R5F562N8 MCU and external RAM)"; |
|||
}; |
|||
|
|||
static const TypeInfo rx_gdbsim_types[] = { |
|||
{ |
|||
.name = MACHINE_TYPE_NAME("gdbsim-r5f562n7"), |
|||
.parent = TYPE_RX_GDBSIM_MACHINE, |
|||
.class_init = rx62n7_class_init, |
|||
}, { |
|||
.name = MACHINE_TYPE_NAME("gdbsim-r5f562n8"), |
|||
.parent = TYPE_RX_GDBSIM_MACHINE, |
|||
.class_init = rx62n8_class_init, |
|||
}, { |
|||
.name = TYPE_RX_GDBSIM_MACHINE, |
|||
.parent = TYPE_MACHINE, |
|||
.instance_size = sizeof(RxGdbSimMachineState), |
|||
.class_size = sizeof(RxGdbSimMachineClass), |
|||
.class_init = rx_gdbsim_class_init, |
|||
.abstract = true, |
|||
} |
|||
}; |
|||
|
|||
DEFINE_TYPES(rx_gdbsim_types) |
|||
Loading…
Reference in new issue