how does qemu load elf64 file-CSDN博客
./aarch64-softmmu/qemu-system-aarch64 -machine virt -cpu cortex-a57 -m 1024M -kernel ./vmlinux -nographic
info->kernel_filename: ./vmlinux
static void arm_setup_direct_kernel_boot(ARMCPU *cpu,
struct arm_boot_info *info)
{
hwaddr entry;
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
primary_loader = bootloader_aarch64;
elf_machine = EM_AARCH64;
} else {
primary_loader = bootloader;
if (!info->write_board_setup) {
primary_loader += BOOTLOADER_NO_BOARD_SETUP_OFFSET;
}
elf_machine = EM_ARM;
}
...code...
/* Assume that raw images are linux kernels, and ELF images are not. */
kernel_size = arm_load_elf(info, &elf_entry, &image_low_addr,
&image_high_addr, elf_machine, as);
entry = elf_entry;
...code...
info->entry = entry;
...code...
info->initrd_start = info->loader_start +
MIN(info->ram_size / 2, 128 * MiB);
if (image_high_addr) {
info->initrd_start = MAX(info->initrd_start, image_high_addr);
}
info->initrd_start = TARGET_PAGE_ALIGN(info->initrd_start);
info->is_linux = is_linux;
for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) {
ARM_CPU(cs)->env.boot_info = info;
}
}
#0 arm_cpu_set_pc (cs=<optimized out>, value=1048576) at /root/doctor/qemu/qemu-4.2.0/target/arm/cpu.c:49
#1 0x0000555555976021 in cpu_set_pc (addr=1048576, cpu=0x55555696bc80)
at /root/doctor/qemu/qemu-4.2.0/include/hw/core/cpu.h:924
#2 do_cpu_reset (opaque=0x55555696bc80) at /root/doctor/qemu/qemu-4.2.0/hw/arm/boot.c:718
#3 0x0000555555b415c5 in qemu_devices_reset () at /root/doctor/qemu/qemu-4.2.0/hw/core/reset.c:69
#4 0x0000555555aca5aa in qemu_system_reset (reason=SHUTDOWN_CAUSE_NONE) at /root/doctor/qemu/qemu-4.2.0/vl.c:1553
#5 0x0000555555873913 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>)
at /root/doctor/qemu/qemu-4.2.0/vl.c:4436
\hw\arm\boot.c
static void do_cpu_reset(void *opaque)
{
ARMCPU *cpu = opaque;
CPUState *cs = CPU(cpu);
CPUARMState *env = &cpu->env;
const struct arm_boot_info *info = env->boot_info;
cpu_reset(cs);
if (info) {
if (!info->is_linux) {
int i;
/* Jump to the entry point. */
uint64_t entry = info->entry;
switch (info->endianness) {...}
cpu_set_pc(cs, entry);
qemu-4.2.0\target\arm\cpu.c
static void arm_cpu_set_pc(CPUState *cs, vaddr value)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
if (is_a64(env)) {
env->pc = value;
env->thumb = 0;
} else {
env->regs[15] = value & ~1;
env->thumb = value & 1;
}
}
qemu-4.2.0\target\arm\cpu.c
static void arm_cpu_reset(CPUState *s)
{
ARMCPU *cpu = ARM_CPU(s);
ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu);
CPUARMState *env = &cpu->env;
...code...
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
/* 64 bit CPUs always start in 64 bit mode */
env->aarch64 = 1;
#0 cpu_get_tb_cpu_state
(env=0x555556974db0, pc=pc@entry=0x7fffcbbfb188, cs_base=cs_base@entry=0x7fffcbbfb180, pflags=pflags@entry=0x7fffcbbfb178)
at /root/doctor/qemu/qemu-4.2.0/target/arm/helper.c:11354
#1 0x00005555558f3813 in tb_lookup__cpu_state
(cf_mask=524288, flags=0x7fffcbbfb178, cs_base=0x7fffcbbfb180, pc=0x7fffcbbfb188, cpu=0x112e0be826d694b3)
at /root/doctor/qemu/qemu-4.2.0/include/exec/tb-lookup.h:28
#2 tb_find (cf_mask=524288, tb_exit=0, last_tb=0x0, cpu=0x112e0be826d694b3)
at /root/doctor/qemu/qemu-4.2.0/accel/tcg/cpu-exec.c:403
#3 cpu_exec (cpu=cpu@entry=0x55555696bc80) at /root/doctor/qemu/qemu-4.2.0/accel/tcg/cpu-exec.c:730
#4 0x00005555558bf4f0 in tcg_cpu_exec (cpu=0x55555696bc80) at /root/doctor/qemu/qemu-4.2.0/cpus.c:1473
#5 0x00005555558c17a4 in qemu_tcg_cpu_thread_fn (arg=arg@entry=0x55555696bc80) at /root/doctor/qemu/qemu-4.2.0/cpus.c:1781
#6 0x0000555555e31533 in qemu_thread_start (args=<optimized out>) at /root/doctor/qemu/qemu-4.2.0/util/qemu-thread-posix.c:519
#7 0x00007ffff5b56609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#8 0x00007ffff5a7b353 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags)
{
uint32_t flags = env->hflags;
uint32_t pstate_for_ss;
*cs_base = 0;
if (FIELD_EX32(flags, TBFLAG_ANY, AARCH64_STATE)) {
*pc = env->pc;
\qemu-4.2.0\accel\tcg\cpu-exec.c
static inline TranslationBlock *tb_find(CPUState *cpu,
TranslationBlock *last_tb,
int tb_exit, uint32_t cf_mask)
{
TranslationBlock *tb;
target_ulong cs_base, pc;
uint32_t flags;
tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask);
if (tb == NULL) {
mmap_lock();
tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask);
\qemu-4.2.0\accel\tcg\translate-all.c
/* Called with mmap_lock held for user mode emulation. */
TranslationBlock *tb_gen_code(CPUState *cpu,
target_ulong pc, target_ulong cs_base,
uint32_t flags, int cflags)
{
CPUArchState *env = cpu->env_ptr;
TranslationBlock *tb, *existing_tb;
tb_page_addr_t phys_pc, phys_page2;
phys_pc = get_page_addr_code(env, pc);