On 9/14/20 1:25 AM, Bin Meng wrote: > On Tue, Sep 8, 2020 at 2:17 AM Sean Anderson <sean...@gmail.com> wrote: >> >> This allows code to use a construct like `if (gd & gd->...) { ... }` when >> accessing the global data pointer. Without this change, it was possible for >> a very early trap to cause _exit_trap to read arbitrary memory. This could >> cause a second trap, preventing show_regs from being printed. >> >> Fixes: 7c6ca03eaed0035ca6676e9bc7f5f1dfcaae7e8f > > nits: wrong fixes tag format > >> Signed-off-by: Sean Anderson <sean...@gmail.com> >> --- >> >> arch/riscv/cpu/start.S | 20 +++++++++++++++++--- >> arch/riscv/lib/interrupts.c | 3 ++- >> 2 files changed, 19 insertions(+), 4 deletions(-) >> >> diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S >> index ad18e746b6..59d3d7bbf4 100644 >> --- a/arch/riscv/cpu/start.S >> +++ b/arch/riscv/cpu/start.S >> @@ -47,6 +47,13 @@ _start: >> mv tp, a0 >> mv s1, a1 >> >> + /* >> + * Set the global data pointer to a known value in case we get a very >> + * early trap. The global data pointer will be set its actual value >> only >> + * after it has been initialized. >> + */ >> + mv gp, zero >> + >> la t0, trap_entry >> csrw MODE_PREFIX(tvec), t0 >> >> @@ -85,10 +92,10 @@ call_board_init_f_0: >> jal board_init_f_alloc_reserve >> >> /* >> - * Set global data pointer here for all harts, uninitialized at this >> - * point. >> + * Save global data pointer for later. We don't set it here because >> it >> + * is not initialized yet. >> */ >> - mv gp, a0 >> + mv s0, a0 >> >> /* setup stack */ >> #if CONFIG_IS_ENABLED(SMP) >> @@ -135,6 +142,13 @@ wait_for_gd_init: >> fence r, rw >> bnez t1, 1b >> >> + /* >> + * Set the global data pointer only when gd_t has been initialized. >> + * This was already set by arch_setup_gd on the boot hart, but all >> other >> + * harts' global data pointers gets set here. >> + */ >> + mv gp, s0 > > This is currently in the #ifndef CONFIG_XIP block. Should consider the > #else branch?
gp is set by arch_setup_gd in board_init_f_init_reserve on the boot hart. Setting it here is only necessary for secondary harts. > >> + >> /* register available harts in the available_harts mask */ >> li t1, 1 >> sll t1, t1, tp >> diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c >> index cd47e64487..ad870e98d8 100644 >> --- a/arch/riscv/lib/interrupts.c >> +++ b/arch/riscv/lib/interrupts.c >> @@ -78,7 +78,8 @@ static void _exit_trap(ulong code, ulong epc, ulong tval, >> struct pt_regs *regs) >> >> printf("EPC: " REG_FMT " RA: " REG_FMT " TVAL: " REG_FMT "\n", >> epc, regs->ra, tval); >> - if (gd->flags & GD_FLG_RELOC) >> + /* Print relocation adjustments, but only if gd is initialized */ >> + if (gd && gd->flags & GD_FLG_RELOC) >> printf("EPC: " REG_FMT " RA: " REG_FMT " reloc adjusted\n\n", >> epc - gd->reloc_off, regs->ra - gd->reloc_off); >> >> -- > > Regards, > Bin >