Search code examples
clinux-kernelarmsmpsoc

Could you tell me how to replace reset vector for secodary cpus in ARM architecture v7?


I know that arm reset vectors can be low(0x00000000) or high(0xffff0000). But some SoC's codes in linux kernel saying the reset vectors can be changed.

For example, in mach-imx

static int __cpuinit imx_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
        imx_set_cpu_jump(cpu, v7_secondary_startup);
        imx_enable_cpu(cpu, true);
        return 0;
}

void imx_set_cpu_jump(int cpu, void *jump_addr)
{
        cpu = cpu_logical_map(cpu);
        writel_relaxed(virt_to_phys(jump_addr),
                       src_base + SRC_GPR1 + cpu * 8);
}

They say that secondary cpu can jump where you want by jump_addr.

Could you tell me how it works?


Solution

  • On ARMv7 cores implementing the security extensions for TrustZone - which as far as I'm aware is all of them - the "low vectors" address (when SCTLR.V == 0) is not hard-coded to 0, but instead set with the VBAR system register. VBAR is banked between secure and non-secure states, so that their vector tables can each be placed at any 32-byte aligned virtual address without interfering with each other, even with the MMU off in both states.

    Note that whilst that's the question you asked, the code here isn't actually that at all. This is just stashing an entry point address in a non-volatile register in the reset controller (a common alternative is using a variable in some shared memory where the bootloader loaded itself to); the secondary CPU will still come out of reset into the default ROM vector and execute a whole bunch of self-initialisation code - code which will, coincidentally, involve setting the non-secure VBAR if the CPU is going to switch into non-secure state. That startup code will eventually end with reading this entry point address from wherever it was stashed and simply jumping to it.