hw/riscv: spike: Decouple create_fdt() dependency to ELF loading
At present create_fdt() calls htif_uses_elf_symbols() to determine whether to insert a <reg> property for the HTIF. This unfortunately creates a hidden dependency to riscv_load_{firmware,kernel} that create_fdt() must be called after the ELF {firmware,kernel} image has been loaded. Decouple such dependency be adding a new parameter to create_fdt(), whether custom HTIF base address is used. The flag will be set if non ELF {firmware,kernel} image is given by user. Signed-off-by: Bin Meng <bmeng@tinylab.org> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-Id: <20221229091828.1945072-13-bmeng@tinylab.org> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
8f6196266e
commit
71d68c48be
@ -52,20 +52,17 @@
|
|||||||
#define PK_SYS_WRITE 64
|
#define PK_SYS_WRITE 64
|
||||||
|
|
||||||
static uint64_t fromhost_addr, tohost_addr;
|
static uint64_t fromhost_addr, tohost_addr;
|
||||||
static int address_symbol_set;
|
|
||||||
|
|
||||||
void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
|
void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
|
||||||
uint64_t st_size)
|
uint64_t st_size)
|
||||||
{
|
{
|
||||||
if (strcmp("fromhost", st_name) == 0) {
|
if (strcmp("fromhost", st_name) == 0) {
|
||||||
address_symbol_set |= 1;
|
|
||||||
fromhost_addr = st_value;
|
fromhost_addr = st_value;
|
||||||
if (st_size != 8) {
|
if (st_size != 8) {
|
||||||
error_report("HTIF fromhost must be 8 bytes");
|
error_report("HTIF fromhost must be 8 bytes");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else if (strcmp("tohost", st_name) == 0) {
|
} else if (strcmp("tohost", st_name) == 0) {
|
||||||
address_symbol_set |= 2;
|
|
||||||
tohost_addr = st_value;
|
tohost_addr = st_value;
|
||||||
if (st_size != 8) {
|
if (st_size != 8) {
|
||||||
error_report("HTIF tohost must be 8 bytes");
|
error_report("HTIF tohost must be 8 bytes");
|
||||||
@ -275,19 +272,19 @@ static const MemoryRegionOps htif_mm_ops = {
|
|||||||
.write = htif_mm_write,
|
.write = htif_mm_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool htif_uses_elf_symbols(void)
|
|
||||||
{
|
|
||||||
return (address_symbol_set == 3) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HTIFState *htif_mm_init(MemoryRegion *address_space, Chardev *chr,
|
HTIFState *htif_mm_init(MemoryRegion *address_space, Chardev *chr,
|
||||||
uint64_t nonelf_base)
|
uint64_t nonelf_base, bool custom_base)
|
||||||
{
|
{
|
||||||
uint64_t base, size, tohost_offset, fromhost_offset;
|
uint64_t base, size, tohost_offset, fromhost_offset;
|
||||||
|
|
||||||
if (!htif_uses_elf_symbols()) {
|
if (custom_base) {
|
||||||
fromhost_addr = nonelf_base;
|
fromhost_addr = nonelf_base;
|
||||||
tohost_addr = nonelf_base + 8;
|
tohost_addr = nonelf_base + 8;
|
||||||
|
} else {
|
||||||
|
if (!fromhost_addr || !tohost_addr) {
|
||||||
|
error_report("Invalid HTIF fromhost or tohost address");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
base = MIN(tohost_addr, fromhost_addr);
|
base = MIN(tohost_addr, fromhost_addr);
|
||||||
|
@ -49,7 +49,8 @@ static const MemMapEntry spike_memmap[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
|
static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
|
||||||
uint64_t mem_size, const char *cmdline, bool is_32_bit)
|
uint64_t mem_size, const char *cmdline,
|
||||||
|
bool is_32_bit, bool htif_custom_base)
|
||||||
{
|
{
|
||||||
void *fdt;
|
void *fdt;
|
||||||
uint64_t addr, size;
|
uint64_t addr, size;
|
||||||
@ -77,7 +78,7 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
|
|||||||
|
|
||||||
qemu_fdt_add_subnode(fdt, "/htif");
|
qemu_fdt_add_subnode(fdt, "/htif");
|
||||||
qemu_fdt_setprop_string(fdt, "/htif", "compatible", "ucb,htif0");
|
qemu_fdt_setprop_string(fdt, "/htif", "compatible", "ucb,htif0");
|
||||||
if (!htif_uses_elf_symbols()) {
|
if (htif_custom_base) {
|
||||||
qemu_fdt_setprop_cells(fdt, "/htif", "reg",
|
qemu_fdt_setprop_cells(fdt, "/htif", "reg",
|
||||||
0x0, memmap[SPIKE_HTIF].base, 0x0, memmap[SPIKE_HTIF].size);
|
0x0, memmap[SPIKE_HTIF].base, 0x0, memmap[SPIKE_HTIF].size);
|
||||||
}
|
}
|
||||||
@ -183,18 +184,33 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool spike_test_elf_image(char *filename)
|
||||||
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
load_elf_hdr(filename, NULL, NULL, &err);
|
||||||
|
if (err) {
|
||||||
|
error_free(err);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void spike_board_init(MachineState *machine)
|
static void spike_board_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
const MemMapEntry *memmap = spike_memmap;
|
const MemMapEntry *memmap = spike_memmap;
|
||||||
SpikeState *s = SPIKE_MACHINE(machine);
|
SpikeState *s = SPIKE_MACHINE(machine);
|
||||||
MemoryRegion *system_memory = get_system_memory();
|
MemoryRegion *system_memory = get_system_memory();
|
||||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||||
target_ulong firmware_end_addr, kernel_start_addr;
|
target_ulong firmware_end_addr = memmap[SPIKE_DRAM].base;
|
||||||
const char *firmware_name;
|
target_ulong kernel_start_addr;
|
||||||
|
char *firmware_name;
|
||||||
uint32_t fdt_load_addr;
|
uint32_t fdt_load_addr;
|
||||||
uint64_t kernel_entry;
|
uint64_t kernel_entry;
|
||||||
char *soc_name;
|
char *soc_name;
|
||||||
int i, base_hartid, hart_count;
|
int i, base_hartid, hart_count;
|
||||||
|
bool htif_custom_base = false;
|
||||||
|
|
||||||
/* Check socket count limit */
|
/* Check socket count limit */
|
||||||
if (SPIKE_SOCKETS_MAX < riscv_socket_count(machine)) {
|
if (SPIKE_SOCKETS_MAX < riscv_socket_count(machine)) {
|
||||||
@ -256,10 +272,34 @@ static void spike_board_init(MachineState *machine)
|
|||||||
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
|
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
|
||||||
mask_rom);
|
mask_rom);
|
||||||
|
|
||||||
firmware_name = riscv_default_firmware_name(&s->soc[0]);
|
/* Find firmware */
|
||||||
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
|
firmware_name = riscv_find_firmware(machine->firmware,
|
||||||
memmap[SPIKE_DRAM].base,
|
riscv_default_firmware_name(&s->soc[0]));
|
||||||
htif_symbol_callback);
|
|
||||||
|
/*
|
||||||
|
* Test the given firmware or kernel file to see if it is an ELF image.
|
||||||
|
* If it is an ELF, we assume it contains the symbols required for
|
||||||
|
* the HTIF console, otherwise we fall back to use the custom base
|
||||||
|
* passed from device tree for the HTIF console.
|
||||||
|
*/
|
||||||
|
if (!firmware_name && !machine->kernel_filename) {
|
||||||
|
htif_custom_base = true;
|
||||||
|
} else {
|
||||||
|
if (firmware_name) {
|
||||||
|
htif_custom_base = !spike_test_elf_image(firmware_name);
|
||||||
|
}
|
||||||
|
if (!htif_custom_base && machine->kernel_filename) {
|
||||||
|
htif_custom_base = !spike_test_elf_image(machine->kernel_filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load firmware */
|
||||||
|
if (firmware_name) {
|
||||||
|
firmware_end_addr = riscv_load_firmware(firmware_name,
|
||||||
|
memmap[SPIKE_DRAM].base,
|
||||||
|
htif_symbol_callback);
|
||||||
|
g_free(firmware_name);
|
||||||
|
}
|
||||||
|
|
||||||
/* Load kernel */
|
/* Load kernel */
|
||||||
if (machine->kernel_filename) {
|
if (machine->kernel_filename) {
|
||||||
@ -279,7 +319,7 @@ static void spike_board_init(MachineState *machine)
|
|||||||
|
|
||||||
/* Create device tree */
|
/* Create device tree */
|
||||||
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
|
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
|
||||||
riscv_is_32bit(&s->soc[0]));
|
riscv_is_32bit(&s->soc[0]), htif_custom_base);
|
||||||
|
|
||||||
/* Load initrd */
|
/* Load initrd */
|
||||||
if (machine->kernel_filename && machine->initrd_filename) {
|
if (machine->kernel_filename && machine->initrd_filename) {
|
||||||
@ -307,7 +347,8 @@ static void spike_board_init(MachineState *machine)
|
|||||||
fdt_load_addr);
|
fdt_load_addr);
|
||||||
|
|
||||||
/* initialize HTIF using symbols found in load_kernel */
|
/* initialize HTIF using symbols found in load_kernel */
|
||||||
htif_mm_init(system_memory, serial_hd(0), memmap[SPIKE_HTIF].base);
|
htif_mm_init(system_memory, serial_hd(0), memmap[SPIKE_HTIF].base,
|
||||||
|
htif_custom_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spike_machine_instance_init(Object *obj)
|
static void spike_machine_instance_init(Object *obj)
|
||||||
|
@ -44,11 +44,8 @@ typedef struct HTIFState {
|
|||||||
void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
|
void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
|
||||||
uint64_t st_size);
|
uint64_t st_size);
|
||||||
|
|
||||||
/* Check if HTIF uses ELF symbols */
|
|
||||||
bool htif_uses_elf_symbols(void);
|
|
||||||
|
|
||||||
/* legacy pre qom */
|
/* legacy pre qom */
|
||||||
HTIFState *htif_mm_init(MemoryRegion *address_space, Chardev *chr,
|
HTIFState *htif_mm_init(MemoryRegion *address_space, Chardev *chr,
|
||||||
uint64_t nonelf_base);
|
uint64_t nonelf_base, bool custom_base);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user