Hi Andre, There is another approach taken in xen. (xen/arch/arm/mode_switch.S) Which do you think is the better approach Regards -mj On 9/19/13, Andre Przywara <andre.przywara@xxxxxxxxxx> wrote: > While actually switching to non-secure state is one thing, another > part of this process is to make sure that we still have full access > to the interrupt controller (GIC). > The GIC is fully aware of secure vs. non-secure state, some > registers are banked, others may be configured to be accessible from > secure state only. > To be as generic as possible, we get the GIC memory mapped address > based on the PERIPHBASE value in the CBAR register. Since this > register is not architecturally defined, we check the MIDR before to > be from an A15 or A7. > For CPUs not having the CBAR or boards with wrong information herein > we allow providing the base address as a configuration variable. > > Now that we know the GIC address, we: > a) allow private interrupts to be delivered to the core > (GICD_IGROUPR0 = 0xFFFFFFFF) > b) enable the CPU interface (GICC_CTLR[0] = 1) > c) set the priority filter to allow non-secure interrupts > (GICC_PMR = 0xFF) > > Also we allow access to all coprocessor interfaces from non-secure > state by writing the appropriate bits in the NSACR register. > > The generic timer base frequency register is only accessible from > secure state, so we have to program it now. Actually this should be > done from primary firmware before, but some boards seems to omit > this, so if needed we do this here with a board specific value. > The Versatile Express board does not need this, so we remove the > frequency from the configuration file here. > > After having switched to non-secure state, we also enable the > non-secure GIC CPU interface, since this register is banked. > > Since we need to call this routine also directly from the smp_pen > later (where we don't have any stack), we can only use caller saved > registers r0-r3 and r12 to not mess with the compiler. > > Signed-off-by: Andre Przywara <andre.przywara@xxxxxxxxxx> > --- > arch/arm/cpu/armv7/nonsec_virt.S | 86 > +++++++++++++++++++++++++++++++++++++ > arch/arm/include/asm/armv7.h | 21 +++++++++ > arch/arm/include/asm/gic.h | 17 ++++++++ > include/configs/vexpress_ca15_tc2.h | 2 - > 4 files changed, 124 insertions(+), 2 deletions(-) > create mode 100644 arch/arm/include/asm/gic.h > > Changes: > v3..v4: clear reserved bits in CBAR > v4..v5: none > > diff --git a/arch/arm/cpu/armv7/nonsec_virt.S > b/arch/arm/cpu/armv7/nonsec_virt.S > index c21bca3..3dd60b7 100644 > --- a/arch/arm/cpu/armv7/nonsec_virt.S > +++ b/arch/arm/cpu/armv7/nonsec_virt.S > @@ -23,6 +23,11 @@ > */ > > #include <config.h> > +#include <linux/linkage.h> > +#include <asm/gic.h> > +#include <asm/armv7.h> > + > +.arch_extension sec > > /* the vector table for secure state */ > _monitor_vectors: > @@ -52,3 +57,84 @@ _secure_monitor: > > movs pc, lr @ return to non-secure SVC > > +/* > + * Switch a core to non-secure state. > + * > + * 1. initialize the GIC per-core interface > + * 2. allow coprocessor access in non-secure modes > + * 3. switch the cpu mode (by calling "smc #0") > + * > + * Called from smp_pen by secondary cores and directly by the BSP. > + * Do not assume that the stack is available and only use registers > + * r0-r3 and r12. > + * > + * PERIPHBASE is used to get the GIC address. This could be 40 bits long, > + * though, but we check this in C before calling this function. > + */ > +ENTRY(_nonsec_init) > +#ifdef CONFIG_ARM_GIC_BASE_ADDRESS > + ldr r2, =CONFIG_ARM_GIC_BASE_ADDRESS > +#else > + mrc p15, 4, r2, c15, c0, 0 @ read CBAR > + bfc r2, #0, #15 @ clear reserved bits > +#endif > + add r3, r2, #GIC_DIST_OFFSET @ GIC dist i/f offset > + mvn r1, #0 @ all bits to 1 > + str r1, [r3, #GICD_IGROUPRn] @ allow private interrupts > + > + mrc p15, 0, r0, c0, c0, 0 @ read MIDR > + ldr r1, =MIDR_PRIMARY_PART_MASK > + and r0, r0, r1 @ mask out variant and revision > + > + ldr r1, =MIDR_CORTEX_A7_R0P0 & MIDR_PRIMARY_PART_MASK > + cmp r0, r1 @ check for Cortex-A7 > + > + ldr r1, =MIDR_CORTEX_A15_R0P0 & MIDR_PRIMARY_PART_MASK > + cmpne r0, r1 @ check for Cortex-A15 > + > + movne r1, #GIC_CPU_OFFSET_A9 @ GIC CPU offset for A9 > + moveq r1, #GIC_CPU_OFFSET_A15 @ GIC CPU offset for A15/A7 > + add r3, r2, r1 @ r3 = GIC CPU i/f addr > + > + mov r1, #1 @ set GICC_CTLR[enable] > + str r1, [r3, #GICC_CTLR] @ and clear all other bits > + mov r1, #0xff > + str r1, [r3, #GICC_PMR] @ set priority mask register > + > + movw r1, #0x3fff > + movt r1, #0x0006 > + mcr p15, 0, r1, c1, c1, 2 @ NSACR = all copros to non-sec > + > +/* The CNTFRQ register of the generic timer needs to be > + * programmed in secure state. Some primary bootloaders / firmware > + * omit this, so if the frequency is provided in the configuration, > + * we do this here instead. > + * But first check if we have the generic timer. > + */ > +#ifdef CONFIG_SYS_CLK_FREQ > + mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1 > + and r0, r0, #CPUID_ARM_GENTIMER_MASK @ mask arch timer bits > + cmp r0, #(1 << CPUID_ARM_GENTIMER_SHIFT) > + ldreq r1, =CONFIG_SYS_CLK_FREQ > + mcreq p15, 0, r1, c14, c0, 0 @ write CNTFRQ > +#endif > + > + adr r1, _monitor_vectors > + mcr p15, 0, r1, c12, c0, 1 @ set MVBAR to secure vectors > + > + mrc p15, 0, ip, c12, c0, 0 @ save secure copy of VBAR > + > + isb > + smc #0 @ call into MONITOR mode > + > + mcr p15, 0, ip, c12, c0, 0 @ write non-secure copy of VBAR > + > + mov r1, #1 > + str r1, [r3, #GICC_CTLR] @ enable non-secure CPU i/f > + add r2, r2, #GIC_DIST_OFFSET > + str r1, [r2, #GICD_CTLR] @ allow private interrupts > + > + mov r0, r3 @ return GICC address > + > + bx lr > +ENDPROC(_nonsec_init) > diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h > index 0f7cbbf..3dcfc8f 100644 > --- a/arch/arm/include/asm/armv7.h > +++ b/arch/arm/include/asm/armv7.h > @@ -18,6 +18,22 @@ > #define MIDR_CORTEX_A15_R0P0 0x410FC0F0 > #define MIDR_CORTEX_A15_R2P2 0x412FC0F2 > > +/* Cortex-A7 revisions */ > +#define MIDR_CORTEX_A7_R0P0 0x410FC070 > + > +#define MIDR_PRIMARY_PART_MASK 0xFF0FFFF0 > + > +/* ID_PFR1 feature fields */ > +#define CPUID_ARM_SEC_SHIFT 4 > +#define CPUID_ARM_SEC_MASK (0xF << CPUID_ARM_SEC_SHIFT) > +#define CPUID_ARM_VIRT_SHIFT 12 > +#define CPUID_ARM_VIRT_MASK (0xF << CPUID_ARM_VIRT_SHIFT) > +#define CPUID_ARM_GENTIMER_SHIFT 16 > +#define CPUID_ARM_GENTIMER_MASK (0xF << CPUID_ARM_GENTIMER_SHIFT) > + > +/* valid bits in CBAR register / PERIPHBASE value */ > +#define CBAR_MASK 0xFFFF8000 > + > /* CCSIDR */ > #define CCSIDR_LINE_SIZE_OFFSET 0 > #define CCSIDR_LINE_SIZE_MASK 0x7 > @@ -60,6 +76,11 @@ void v7_outer_cache_inval_all(void); > void v7_outer_cache_flush_range(u32 start, u32 end); > void v7_outer_cache_inval_range(u32 start, u32 end); > > +#ifdef CONFIG_ARMV7_NONSEC > +/* defined in assembly file */ > +unsigned int _nonsec_init(void); > +#endif /* CONFIG_ARMV7_NONSEC */ > + > #endif /* ! __ASSEMBLY__ */ > > #endif > diff --git a/arch/arm/include/asm/gic.h b/arch/arm/include/asm/gic.h > new file mode 100644 > index 0000000..c2b1e28 > --- /dev/null > +++ b/arch/arm/include/asm/gic.h > @@ -0,0 +1,17 @@ > +#ifndef __GIC_V2_H__ > +#define __GIC_V2_H__ > + > +/* register offsets for the ARM generic interrupt controller (GIC) */ > + > +#define GIC_DIST_OFFSET 0x1000 > +#define GICD_CTLR 0x0000 > +#define GICD_TYPER 0x0004 > +#define GICD_IGROUPRn 0x0080 > +#define GICD_SGIR 0x0F00 > + > +#define GIC_CPU_OFFSET_A9 0x0100 > +#define GIC_CPU_OFFSET_A15 0x2000 > +#define GICC_CTLR 0x0000 > +#define GICC_PMR 0x0004 > + > +#endif > diff --git a/include/configs/vexpress_ca15_tc2.h > b/include/configs/vexpress_ca15_tc2.h > index d1431e5..89ce1c7 100644 > --- a/include/configs/vexpress_ca15_tc2.h > +++ b/include/configs/vexpress_ca15_tc2.h > @@ -15,6 +15,4 @@ > #include "vexpress_common.h" > #define CONFIG_BOOTP_VCI_STRING "U-boot.armv7.vexpress_ca15x2_tc2" > > -#define CONFIG_SYS_CLK_FREQ 24000000 > - > #endif > -- > 1.7.12.1 > > _______________________________________________ > U-Boot mailing list > U-Boot@xxxxxxxxxxxxx > http://lists.denx.de/mailman/listinfo/u-boot > -- -mj _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm