![Lennart Sorensen](/assets/img/avatar_default.png)
If the boot loader enables HYP mode on the boot CPU, the secondary CPU also needs to call into the ROM to switch to HYP mode before booting. The firmwares on the omap5 and dra7xx unfortunately do not take care of this, so it has to be handled by the kernel. This patch is based on "[PATCH 2/2] ARM: OMAP5: Add HYP mode entry support for secondary CPUs" by Santosh Shilimkar <santosh.shilimkar@ti.com>, except this version does not require a compile time CONFIG to control if it should enable HYP mode or not, it simply does it based on the mode of the boot CPU, so it works whether the CPU boots in SVC or HYP mode, and should even work as a guest kernel inside kvm if qemu decides to support emulating the omap5 or dra7xx. Cc: stable@vger.kernel.org #v3.16+ Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca> Signed-off-by: Tony Lindgren <tony@atomide.com>
124 lines
3.4 KiB
ArmAsm
124 lines
3.4 KiB
ArmAsm
/*
|
|
* Secondary CPU startup routine source file.
|
|
*
|
|
* Copyright (C) 2009-2014 Texas Instruments, Inc.
|
|
*
|
|
* Author:
|
|
* Santosh Shilimkar <santosh.shilimkar@ti.com>
|
|
*
|
|
* Interface functions needed for the SMP. This file is based on arm
|
|
* realview smp platform.
|
|
* Copyright (c) 2003 ARM Limited.
|
|
*
|
|
* This program is free software,you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <linux/init.h>
|
|
|
|
#include "omap44xx.h"
|
|
|
|
/* Physical address needed since MMU not enabled yet on secondary core */
|
|
#define AUX_CORE_BOOT0_PA 0x48281800
|
|
#define API_HYP_ENTRY 0x102
|
|
|
|
/*
|
|
* OMAP5 specific entry point for secondary CPU to jump from ROM
|
|
* code. This routine also provides a holding flag into which
|
|
* secondary core is held until we're ready for it to initialise.
|
|
* The primary core will update this flag using a hardware
|
|
* register AuxCoreBoot0.
|
|
*/
|
|
ENTRY(omap5_secondary_startup)
|
|
wait: ldr r2, =AUX_CORE_BOOT0_PA @ read from AuxCoreBoot0
|
|
ldr r0, [r2]
|
|
mov r0, r0, lsr #5
|
|
mrc p15, 0, r4, c0, c0, 5
|
|
and r4, r4, #0x0f
|
|
cmp r0, r4
|
|
bne wait
|
|
b secondary_startup
|
|
ENDPROC(omap5_secondary_startup)
|
|
/*
|
|
* Same as omap5_secondary_startup except we call into the ROM to
|
|
* enable HYP mode first. This is called instead of
|
|
* omap5_secondary_startup if the primary CPU was put into HYP mode by
|
|
* the boot loader.
|
|
*/
|
|
ENTRY(omap5_secondary_hyp_startup)
|
|
wait_2: ldr r2, =AUX_CORE_BOOT0_PA @ read from AuxCoreBoot0
|
|
ldr r0, [r2]
|
|
mov r0, r0, lsr #5
|
|
mrc p15, 0, r4, c0, c0, 5
|
|
and r4, r4, #0x0f
|
|
cmp r0, r4
|
|
bne wait_2
|
|
ldr r12, =API_HYP_ENTRY
|
|
adr r0, hyp_boot
|
|
smc #0
|
|
hyp_boot:
|
|
b secondary_startup
|
|
ENDPROC(omap5_secondary_hyp_startup)
|
|
/*
|
|
* OMAP4 specific entry point for secondary CPU to jump from ROM
|
|
* code. This routine also provides a holding flag into which
|
|
* secondary core is held until we're ready for it to initialise.
|
|
* The primary core will update this flag using a hardware
|
|
* register AuxCoreBoot0.
|
|
*/
|
|
ENTRY(omap4_secondary_startup)
|
|
hold: ldr r12,=0x103
|
|
dsb
|
|
smc #0 @ read from AuxCoreBoot0
|
|
mov r0, r0, lsr #9
|
|
mrc p15, 0, r4, c0, c0, 5
|
|
and r4, r4, #0x0f
|
|
cmp r0, r4
|
|
bne hold
|
|
|
|
/*
|
|
* we've been released from the wait loop,secondary_stack
|
|
* should now contain the SVC stack for this core
|
|
*/
|
|
b secondary_startup
|
|
ENDPROC(omap4_secondary_startup)
|
|
|
|
ENTRY(omap4460_secondary_startup)
|
|
hold_2: ldr r12,=0x103
|
|
dsb
|
|
smc #0 @ read from AuxCoreBoot0
|
|
mov r0, r0, lsr #9
|
|
mrc p15, 0, r4, c0, c0, 5
|
|
and r4, r4, #0x0f
|
|
cmp r0, r4
|
|
bne hold_2
|
|
|
|
/*
|
|
* GIC distributor control register has changed between
|
|
* CortexA9 r1pX and r2pX. The Control Register secure
|
|
* banked version is now composed of 2 bits:
|
|
* bit 0 == Secure Enable
|
|
* bit 1 == Non-Secure Enable
|
|
* The Non-Secure banked register has not changed
|
|
* Because the ROM Code is based on the r1pX GIC, the CPU1
|
|
* GIC restoration will cause a problem to CPU0 Non-Secure SW.
|
|
* The workaround must be:
|
|
* 1) Before doing the CPU1 wakeup, CPU0 must disable
|
|
* the GIC distributor
|
|
* 2) CPU1 must re-enable the GIC distributor on
|
|
* it's wakeup path.
|
|
*/
|
|
ldr r1, =OMAP44XX_GIC_DIST_BASE
|
|
ldr r0, [r1]
|
|
orr r0, #1
|
|
str r0, [r1]
|
|
|
|
/*
|
|
* we've been released from the wait loop,secondary_stack
|
|
* should now contain the SVC stack for this core
|
|
*/
|
|
b secondary_startup
|
|
ENDPROC(omap4460_secondary_startup)
|