From patchwork Thu Jun 13 11:07:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 17904 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-vc0-f200.google.com (mail-vc0-f200.google.com [209.85.220.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 5CD1625DF1 for ; Thu, 13 Jun 2013 11:08:29 +0000 (UTC) Received: by mail-vc0-f200.google.com with SMTP id kw10sf4350095vcb.7 for ; Thu, 13 Jun 2013 04:08:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-beenthere:x-forwarded-to:x-forwarded-for :delivered-to:from:to:subject:date:message-id:x-mailer:in-reply-to :references:x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe; bh=ly7TNQbOUqjKv8fJ3a2ZtBz2s0VeN6ZwZ0JK2uKYHXs=; b=bJnXZjSoAKmT0ra4sGgpkLDEKeaf2N3r1Q1FLfMI1p/Os8D3UMzZFVkTeNDGNO7OEs KIRdW/LnOnPfc29UMQ/hQc1u08/SkpYbObUjrmtK0jDvss7vFOsvRzPEalRF29TNcT5R avYxLm0Ad2o3lETxwPQEMKFk+jHm0zDsrKxXNSKoM7bLLOVrsaINgBq64PjzuCasLqUh VeoUXGEaV8l5RnAGrophHqypZmYpz/8R714n5CY907bKB11IBazs9D1dvuZIZBqFThCy L0mMgltnCre0EQ5fnN/IcMuZ/mWchhzy/yODW5WQEsgyY6KuovqGiuk5N0U5TKQ5NscC 3VTA== X-Received: by 10.224.129.196 with SMTP id p4mr1316521qas.6.1371121709147; Thu, 13 Jun 2013 04:08:29 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.127.114 with SMTP id nf18ls3856590qeb.8.gmail; Thu, 13 Jun 2013 04:08:29 -0700 (PDT) X-Received: by 10.52.34.7 with SMTP id v7mr84335vdi.96.1371121709053; Thu, 13 Jun 2013 04:08:29 -0700 (PDT) Received: from mail-vc0-f180.google.com (mail-vc0-f180.google.com [209.85.220.180]) by mx.google.com with ESMTPS id ia10si10210353vdb.51.2013.06.13.04.08.29 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 13 Jun 2013 04:08:29 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.180; Received: by mail-vc0-f180.google.com with SMTP id gf11so5034034vcb.11 for ; Thu, 13 Jun 2013 04:08:29 -0700 (PDT) X-Received: by 10.52.36.115 with SMTP id p19mr126339vdj.8.1371121708905; Thu, 13 Jun 2013 04:08:28 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.191.99 with SMTP id gx3csp17022vec; Thu, 13 Jun 2013 04:08:28 -0700 (PDT) X-Received: by 10.182.66.46 with SMTP id c14mr289390obt.33.1371121708316; Thu, 13 Jun 2013 04:08:28 -0700 (PDT) Received: from mail-oa0-x22b.google.com (mail-oa0-x22b.google.com [2607:f8b0:4003:c02::22b]) by mx.google.com with ESMTPS id zb4si19626874obb.8.2013.06.13.04.08.28 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 13 Jun 2013 04:08:28 -0700 (PDT) Received-SPF: neutral (google.com: 2607:f8b0:4003:c02::22b is neither permitted nor denied by best guess record for domain of andre.przywara@linaro.org) client-ip=2607:f8b0:4003:c02::22b; Received: by mail-oa0-f43.google.com with SMTP id i7so9227645oag.30 for ; Thu, 13 Jun 2013 04:08:27 -0700 (PDT) X-Received: by 10.182.28.98 with SMTP id a2mr290164obh.36.1371121707820; Thu, 13 Jun 2013 04:08:27 -0700 (PDT) Received: from slackpad.drs.calxeda.com (g224198135.adsl.alicedsl.de. [92.224.198.135]) by mx.google.com with ESMTPSA id eq4sm38120532obb.5.2013.06.13.04.08.26 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 13 Jun 2013 04:08:27 -0700 (PDT) From: Andre Przywara To: patches@linaro.org Subject: [PATCH v2 3/7] ARM: add assembly routine to switch to non-secure state Date: Thu, 13 Jun 2013 13:07:39 +0200 Message-Id: <1371121663-18810-4-git-send-email-andre.przywara@linaro.org> X-Mailer: git-send-email 1.7.12.1 In-Reply-To: <1371121663-18810-1-git-send-email-andre.przywara@linaro.org> References: <1371121663-18810-1-git-send-email-andre.przywara@linaro.org> X-Gm-Message-State: ALoCoQl/lUHC1mdBXKbUxZVQnIwFMwDtpEsS4e2ql9yk1DPhFu/L8IhPLp6tNXXrumapWTL7E1iD X-Original-Sender: andre.przywara@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.180 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , While actually switching to non-secure state is one thing, the more important 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. With the GIC accessible, 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) After having switched to non-secure state, we also enable the non-secure GIC CPU interface, since this register is banked. Also we allow access to all coprocessor interfaces from non-secure state by writing the appropriate bits in the NSACR register. 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 disturb the compiler. Signed-off-by: Andre Przywara --- arch/arm/cpu/armv7/nonsec_virt.S | 66 ++++++++++++++++++++++++++++++++++++++++ arch/arm/include/asm/armv7.h | 16 ++++++++++ arch/arm/include/asm/gic.h | 17 +++++++++++ 3 files changed, 99 insertions(+) create mode 100644 arch/arm/include/asm/gic.h diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S index f5572f5..656d99b 100644 --- a/arch/arm/cpu/armv7/nonsec_virt.S +++ b/arch/arm/cpu/armv7/nonsec_virt.S @@ -23,6 +23,8 @@ */ #include +#include +#include /* the vector table for secure state */ _secure_vectors: @@ -52,3 +54,67 @@ _secure_monitor: movs pc, lr @ return to non-secure SVC +#define lo(x) ((x) & 0xFFFF) +#define hi(x) ((x) >> 16) + +/* + * Routine to switch a core to non-secure state. + * Initializes the GIC per-core interface, allows coprocessor access in + * non-secure modes and uses smc #0 to do the non-secure transition. + * To be called by smp_pen for secondary cores and directly for the BSP. + * For those two cases to work we must not use any stack and thus are + * limited to the caller saved registers r0-r3. + * 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. + */ +.globl _nonsec_init +_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 +#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 + bfc r0, #20, #4 @ mask out variant + bfc r0, #0, #4 @ and revision + + movw r1, #lo(MIDR_CORTEX_A7_R0P0 & MIDR_PRIMARY_PART_MASK) + movt r1, #hi(MIDR_CORTEX_A7_R0P0 & MIDR_PRIMARY_PART_MASK) + cmp r0, r1 @ check for Cortex-A7 + + orr r1, #(MIDR_CORTEX_A15_R0P0 & 0xf0) + 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 + + adr r1, _secure_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] @ allow private interrupts + + bx lr diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h index 20caa7c..989bb72 100644 --- a/arch/arm/include/asm/armv7.h +++ b/arch/arm/include/asm/armv7.h @@ -34,6 +34,17 @@ #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_VIRT_SHIFT 12 +#define CPUID_ARM_VIRT_MASK (0xF << CPUID_ARM_VIRT_SHIFT) +#define CPUID_ARM_TIMER_SHIFT 16 +#define CPUID_ARM_TIMER_MASK (0xF << CPUID_ARM_TIMER_SHIFT) + /* CCSIDR */ #define CCSIDR_LINE_SIZE_OFFSET 0 #define CCSIDR_LINE_SIZE_MASK 0x7 @@ -76,6 +87,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_VIRT +/* defined in cpu/armv7/nonsec_virt.S */ +void _nonsec_init(void); +#endif /* CONFIG_ARMV7_VIRT */ + #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