mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-18 07:32:06 -06:00
hw/loongarch: Add LoongArch load elf function.
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220606124333.2060567-40-yangxiaojuan@loongson.cn> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
c117f68a46
commit
6a6f26f481
2 changed files with 61 additions and 2 deletions
|
@ -19,6 +19,8 @@
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "hw/irq.h"
|
#include "hw/irq.h"
|
||||||
#include "net/net.h"
|
#include "net/net.h"
|
||||||
|
#include "hw/loader.h"
|
||||||
|
#include "elf.h"
|
||||||
#include "hw/intc/loongarch_ipi.h"
|
#include "hw/intc/loongarch_ipi.h"
|
||||||
#include "hw/intc/loongarch_extioi.h"
|
#include "hw/intc/loongarch_extioi.h"
|
||||||
#include "hw/intc/loongarch_pch_pic.h"
|
#include "hw/intc/loongarch_pch_pic.h"
|
||||||
|
@ -29,6 +31,36 @@
|
||||||
|
|
||||||
#include "target/loongarch/cpu.h"
|
#include "target/loongarch/cpu.h"
|
||||||
|
|
||||||
|
static struct _loaderparams {
|
||||||
|
uint64_t ram_size;
|
||||||
|
const char *kernel_filename;
|
||||||
|
} loaderparams;
|
||||||
|
|
||||||
|
static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
|
||||||
|
{
|
||||||
|
return addr & 0x1fffffffll;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t load_kernel_info(void)
|
||||||
|
{
|
||||||
|
uint64_t kernel_entry, kernel_low, kernel_high;
|
||||||
|
ssize_t kernel_size;
|
||||||
|
|
||||||
|
kernel_size = load_elf(loaderparams.kernel_filename, NULL,
|
||||||
|
cpu_loongarch_virt_to_phys, NULL,
|
||||||
|
&kernel_entry, &kernel_low,
|
||||||
|
&kernel_high, NULL, 0,
|
||||||
|
EM_LOONGARCH, 1, 0);
|
||||||
|
|
||||||
|
if (kernel_size < 0) {
|
||||||
|
error_report("could not load kernel '%s': %s",
|
||||||
|
loaderparams.kernel_filename,
|
||||||
|
load_elf_strerror(kernel_size));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return kernel_entry;
|
||||||
|
}
|
||||||
|
|
||||||
static void loongarch_devices_init(DeviceState *pch_pic)
|
static void loongarch_devices_init(DeviceState *pch_pic)
|
||||||
{
|
{
|
||||||
DeviceState *gpex_dev;
|
DeviceState *gpex_dev;
|
||||||
|
@ -200,15 +232,29 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||||
loongarch_devices_init(pch_pic);
|
loongarch_devices_init(pch_pic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reset_load_elf(void *opaque)
|
||||||
|
{
|
||||||
|
LoongArchCPU *cpu = opaque;
|
||||||
|
CPULoongArchState *env = &cpu->env;
|
||||||
|
|
||||||
|
cpu_reset(CPU(cpu));
|
||||||
|
if (env->load_elf) {
|
||||||
|
cpu_set_pc(CPU(cpu), env->elf_address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void loongarch_init(MachineState *machine)
|
static void loongarch_init(MachineState *machine)
|
||||||
{
|
{
|
||||||
const char *cpu_model = machine->cpu_type;
|
const char *cpu_model = machine->cpu_type;
|
||||||
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
ram_addr_t offset = 0;
|
ram_addr_t offset = 0;
|
||||||
ram_addr_t ram_size = machine->ram_size;
|
ram_addr_t ram_size = machine->ram_size;
|
||||||
uint64_t highram_size = 0;
|
uint64_t highram_size = 0;
|
||||||
MemoryRegion *address_space_mem = get_system_memory();
|
MemoryRegion *address_space_mem = get_system_memory();
|
||||||
LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
|
LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
|
||||||
|
LoongArchCPU *lacpu;
|
||||||
int i;
|
int i;
|
||||||
|
int64_t kernel_addr = 0;
|
||||||
|
|
||||||
if (!cpu_model) {
|
if (!cpu_model) {
|
||||||
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
|
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||||
|
@ -234,17 +280,28 @@ static void loongarch_init(MachineState *machine)
|
||||||
machine->ram, 0, 256 * MiB);
|
machine->ram, 0, 256 * MiB);
|
||||||
memory_region_add_subregion(address_space_mem, offset, &lams->lowmem);
|
memory_region_add_subregion(address_space_mem, offset, &lams->lowmem);
|
||||||
offset += 256 * MiB;
|
offset += 256 * MiB;
|
||||||
|
|
||||||
highram_size = ram_size - 256 * MiB;
|
highram_size = ram_size - 256 * MiB;
|
||||||
memory_region_init_alias(&lams->highmem, NULL, "loongarch.highmem",
|
memory_region_init_alias(&lams->highmem, NULL, "loongarch.highmem",
|
||||||
machine->ram, offset, highram_size);
|
machine->ram, offset, highram_size);
|
||||||
memory_region_add_subregion(address_space_mem, 0x90000000, &lams->highmem);
|
memory_region_add_subregion(address_space_mem, 0x90000000, &lams->highmem);
|
||||||
|
|
||||||
/* Add isa io region */
|
/* Add isa io region */
|
||||||
memory_region_init_alias(&lams->isa_io, NULL, "isa-io",
|
memory_region_init_alias(&lams->isa_io, NULL, "isa-io",
|
||||||
get_system_io(), 0, LOONGARCH_ISA_IO_SIZE);
|
get_system_io(), 0, LOONGARCH_ISA_IO_SIZE);
|
||||||
memory_region_add_subregion(address_space_mem, LOONGARCH_ISA_IO_BASE,
|
memory_region_add_subregion(address_space_mem, LOONGARCH_ISA_IO_BASE,
|
||||||
&lams->isa_io);
|
&lams->isa_io);
|
||||||
|
if (kernel_filename) {
|
||||||
|
loaderparams.ram_size = ram_size;
|
||||||
|
loaderparams.kernel_filename = kernel_filename;
|
||||||
|
kernel_addr = load_kernel_info();
|
||||||
|
if (!machine->firmware) {
|
||||||
|
for (i = 0; i < machine->smp.cpus; i++) {
|
||||||
|
lacpu = LOONGARCH_CPU(qemu_get_cpu(i));
|
||||||
|
lacpu->env.load_elf = true;
|
||||||
|
lacpu->env.elf_address = kernel_addr;
|
||||||
|
qemu_register_reset(reset_load_elf, lacpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Initialize the IO interrupt subsystem */
|
/* Initialize the IO interrupt subsystem */
|
||||||
loongarch_irq_init(lams);
|
loongarch_irq_init(lams);
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,6 +308,8 @@ typedef struct CPUArchState {
|
||||||
AddressSpace address_space_iocsr;
|
AddressSpace address_space_iocsr;
|
||||||
MemoryRegion system_iocsr;
|
MemoryRegion system_iocsr;
|
||||||
MemoryRegion iocsr_mem;
|
MemoryRegion iocsr_mem;
|
||||||
|
bool load_elf;
|
||||||
|
uint64_t elf_address;
|
||||||
} CPULoongArchState;
|
} CPULoongArchState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue