Saturday, March 4, 2017

rv64 RISC-V booting

This text is based on boot.md from my GitHub repo  riscv-notes

After reset a rv64 RISC-V CPU fetches the first instruction from DEFAULT_RSTVEC = 0x00001000. For example below is QEMU CPU reset emulation from riscv-qemu/target-riscv/cpu.c
static void riscv_cpu_reset(CPUState *s)
{
    RISCVCPU *cpu = RISCV_CPU(s);
    RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
    CPURISCVState *env = &cpu->env;
    CPUState *cs = CPU(cpu);

    mcc->parent_reset(s);
#ifndef CONFIG_USER_ONLY
    tlb_flush(s, 1);
    env->priv = PRV_M;
    env->mtvec = DEFAULT_MTVEC;
#endif
    env->pc = DEFAULT_RSTVEC;
    cs->exception_index = EXCP_NONE;
}
The 0x00001000 address is mapped to ROM with a trampoline code to 0x80000000. AUIPC instruction moves its immediate value 12 bits to the left and adds to the current PC , so t0 = 0(x7ffff<<12)+ 0x1000 = 0x80000000
(gdb) x/2i 0x1000
   0x1000:  auipc   t0,0x7ffff
   0x1004:  jr  t0
For QEMU the above code is defined in riscv-qemu/hw/riscv/riscv_board.c
    uint32_t reset_vec[8] = {
        0x297 + 0x80000000 - 0x1000, /* reset vector */
        0x00028067,                  /* jump to DRAM_BASE */
        0x00000000,                  /* reserved */
        0x0,                         /* config string pointer */
        0, 0, 0, 0                   /* trap vector */
    };
The 0x80000000 address is a start of DRAM where the BBL is loaded. Below are definitions that are the same for the both QEMU and spike simulator.
#define DEFAULT_RSTVEC     0x00001000
#define DRAM_BASE          0x80000000
After jr t0 has been execute the register content is as follows ( t0 and pc are equal )
(gdb) info registers
ra             0x0000000000000000   0
sp             0x0000000000000000   0
gp             0x0000000000000000   0
tp             0x0000000000000000   0
t0             0x0000000080000000   2147483648
t1             0x0000000000000000   0
t2             0x0000000000000000   0
fp             0x0000000000000000   0
s1             0x0000000000000000   0
a0             0x0000000000000000   0
a1             0x0000000000000000   0
a2             0x0000000000000000   0
a3             0x0000000000000000   0
a4             0x0000000000000000   0
a5             0x0000000000000000   0
a6             0x0000000000000000   0
a7             0x0000000000000000   0
s2             0x0000000000000000   0
s3             0x0000000000000000   0
s4             0x0000000000000000   0
s5             0x0000000000000000   0
s6             0x0000000000000000   0
s7             0x0000000000000000   0
s8             0x0000000000000000   0
s9             0x0000000000000000   0
s10            0x0000000000000000   0
s11            0x0000000000000000   0
t3             0x0000000000000000   0
t4             0x0000000000000000   0
t5             0x0000000000000000   0
t6             0x0000000000000000   0
pc             0x0000000080000000   2147483648
BBL assigns 0x80000000 address to reset_vector by placing it in the beginning of the .text.init section which is linked to 0x80000000 .
From riscv-tools/riscv-pk/machine/mentry.S
  .section .text.init,"ax",@progbits
  .globl reset_vector
reset_vector:
  j do_reset
From riscv-tools/riscv-pk/pk/pk.lds
  /* Begining of code and text segment */
  . = 0x80000000;
  _ftext = .;
  PROVIDE( eprol = . );

  .text :
  {
    *(.text.init)
  }

No comments:

Post a Comment