From: Christoffer Dall <christoffer.dall@linaro.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v4 4/8] ARM: add C function to switch to non-secure state
Date: Fri, 9 Aug 2013 09:55:03 -0700 [thread overview]
Message-ID: <20130809165503.GC26486@cbox> (raw)
In-Reply-To: <1376060592-10824-5-git-send-email-andre.przywara@linaro.org>
On Fri, Aug 09, 2013 at 05:03:08PM +0200, Andre Przywara wrote:
> The core specific part of the work is done in the assembly routine
> in nonsec_virt.S, introduced with the previous patch, but for the full
> glory we need to setup the GIC distributor interface once for the
> whole system, which is done in C here.
> The routine is placed in arch/arm/cpu/armv7 to allow easy access from
> other ARMv7 boards.
>
> We check the availability of the security extensions first.
>
> Since we need a safe way to access the GIC, we use the PERIPHBASE
> registers on Cortex-A15 and A7 CPUs and do some sanity checks.
> Boards not implementing the CBAR can override this value via a
> configuration file variable.
>
> Then we actually do the GIC enablement:
> a) enable the GIC distributor, both for non-secure and secure state
> (GICD_CTLR[1:0] = 11b)
> b) allow all interrupts to be handled from non-secure state
> (GICD_IGROUPRn = 0xFFFFFFFF)
>
> The core specific GIC setup is then done in the assembly routine.
>
> Signed-off-by: Andre Przywara <andre.przywara@linaro.org>
> ---
> arch/arm/cpu/armv7/Makefile | 1 +
> arch/arm/cpu/armv7/virt-v7.c | 121 +++++++++++++++++++++++++++++++++++++++++++
> arch/arm/include/asm/armv7.h | 3 ++
> 3 files changed, 125 insertions(+)
> create mode 100644 arch/arm/cpu/armv7/virt-v7.c
>
> diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
> index 11a8ad5..5813e87 100644
> --- a/arch/arm/cpu/armv7/Makefile
> +++ b/arch/arm/cpu/armv7/Makefile
> @@ -38,6 +38,7 @@ endif
>
> ifneq ($(CONFIG_ARMV7_NONSEC),)
> SOBJS += nonsec_virt.o
> +COBJS += virt-v7.o
> endif
>
> SRCS := $(START:.o=.S) $(COBJS:.o=.c)
> diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c
> new file mode 100644
> index 0000000..689023f
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/virt-v7.c
> @@ -0,0 +1,121 @@
> +/*
> + * (C) Copyright 2013
> + * Andre Przywara, Linaro
> + *
> + * Routines to transition ARMv7 processors from secure into non-secure state
> + * needed to enable ARMv7 virtualization for current hypervisors
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <common.h>
> +#include <asm/armv7.h>
> +#include <asm/gic.h>
> +#include <asm/io.h>
> +
> +unsigned long gic_dist_addr;
> +
> +static unsigned int read_id_pfr1(void)
> +{
> + unsigned int reg;
> +
> + asm("mrc p15, 0, %0, c0, c1, 1\n" : "=r"(reg));
> + return reg;
> +}
> +
> +static unsigned long get_gicd_base_address(void)
> +{
> +#ifdef CONFIG_ARM_GIC_BASE_ADDRESS
> + return CONFIG_ARM_GIC_BASE_ADDRESS + GIC_DIST_OFFSET;
> +#else
> + unsigned midr;
> + unsigned periphbase;
> +
> + /* check whether we are an Cortex-A15 or A7.
> + * The actual HYP switch should work with all CPUs supporting
> + * the virtualization extension, but we need the GIC address,
> + * which we know only for sure for those two CPUs.
> + */
> + asm("mrc p15, 0, %0, c0, c0, 0\n" : "=r"(midr));
> + switch (midr & MIDR_PRIMARY_PART_MASK) {
> + case MIDR_CORTEX_A9_R0P1:
> + case MIDR_CORTEX_A15_R0P0:
> + case MIDR_CORTEX_A7_R0P0:
> + break;
> + default:
> + printf("nonsec: could not determine GIC address.\n");
> + return -1;
> + }
> +
> + /* get the GIC base address from the CBAR register */
> + asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase));
> +
> + /* the PERIPHBASE can be mapped above 4 GB (lower 8 bits used to
> + * encode this). Bail out here since we cannot access this without
> + * enabling paging.
> + */
> + if ((periphbase & 0xff) != 0) {
> + printf("nonsec: PERIPHBASE is above 4 GB, no access.\n");
> + return -1;
> + }
> +
> + return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET;
> +#endif
> +}
> +
> +int armv7_switch_nonsec(void)
> +{
> + unsigned int reg;
> + unsigned itlinesnr, i;
> +
> + /* check whether the CPU supports the security extensions */
> + reg = read_id_pfr1();
> + if ((reg & 0xF0) == 0) {
> + printf("nonsec: Security extensions not implemented.\n");
> + return -1;
> + }
> +
> + /* the SCR register will be set directly in the monitor mode handler,
> + * according to the spec one should not tinker with it in secure state
> + * in SVC mode. Do not try to read it once in non-secure state,
> + * any access to it will trap.
> + */
> +
> + gic_dist_addr = get_gicd_base_address();
> + if (gic_dist_addr == -1)
> + return -1;
> +
> + /* enable the GIC distributor */
> + writel(readl(gic_dist_addr + GICD_CTLR) | 0x03,
> + gic_dist_addr + GICD_CTLR);
> +
> + /* TYPER[4:0] contains an encoded number of available interrupts */
> + itlinesnr = readl(gic_dist_addr + GICD_TYPER) & 0x1f;
> +
> + /* set all bits in the GIC group registers to one to allow access
> + * from non-secure state
> + */
> + for (i = 0; i <= itlinesnr; i++)
> + writel((unsigned)-1, gic_dist_addr + GICD_IGROUPRn + 4 * i);
I think Nikolay pointed out that you could start from 1 in this for
loop.
-Christoffer
> +
> + /* call the non-sec switching code on this CPU */
> + _nonsec_init();
> +
> + return 0;
> +}
> diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
> index 3e4b743..10ced11 100644
> --- a/arch/arm/include/asm/armv7.h
> +++ b/arch/arm/include/asm/armv7.h
> @@ -93,6 +93,9 @@ void v7_outer_cache_flush_range(u32 start, u32 end);
> void v7_outer_cache_inval_range(u32 start, u32 end);
>
> #ifdef CONFIG_ARMV7_NONSEC
> +
> +int armv7_switch_nonsec(void);
> +
> /* defined in assembly file */
> unsigned int _nonsec_init(void);
> #endif /* CONFIG_ARMV7_NONSEC */
> --
> 1.7.12.1
>
next prev parent reply other threads:[~2013-08-09 16:55 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-09 15:03 [U-Boot] [PATCH v4 0/8] ARMv7: Add HYP mode switching support Andre Przywara
2013-08-09 15:03 ` [U-Boot] [PATCH v4 1/8] ARM: prepare armv7.h to be included from assembly source Andre Przywara
2013-08-09 15:03 ` [U-Boot] [PATCH v4 2/8] ARM: add secure monitor handler to switch to non-secure state Andre Przywara
2013-08-27 0:23 ` Masahiro Yamada
2013-08-27 9:51 ` Andre Przywara
2013-08-27 12:11 ` Tom Rini
2013-08-09 15:03 ` [U-Boot] [PATCH v4 3/8] ARM: add assembly routine " Andre Przywara
2013-08-09 15:03 ` [U-Boot] [PATCH v4 4/8] ARM: add C function " Andre Przywara
2013-08-09 16:55 ` Christoffer Dall [this message]
2013-08-09 15:03 ` [U-Boot] [PATCH v4 5/8] ARM: trigger non-secure state switch during bootm execution Andre Przywara
2013-08-09 15:03 ` [U-Boot] [PATCH v4 6/8] ARM: add SMP support for non-secure switch Andre Przywara
2013-08-09 15:03 ` [U-Boot] [PATCH v4 7/8] ARM: extend non-secure switch to also go into HYP mode Andre Przywara
2013-08-09 16:55 ` Christoffer Dall
2013-08-09 15:03 ` [U-Boot] [PATCH v4 8/8] ARM: VExpress: enable ARMv7 virt support for VExpress A15 Andre Przywara
2013-09-14 17:00 ` Albert ARIBAUD
2013-08-09 16:55 ` [U-Boot] [PATCH v4 0/8] ARMv7: Add HYP mode switching support Christoffer Dall
2013-08-16 13:53 ` Andre Przywara
2013-08-26 20:51 ` Christoffer Dall
2013-08-26 21:30 ` Tom Rini
2013-08-26 21:46 ` Christoffer Dall
2013-08-26 21:57 ` Tom Rini
2013-08-23 14:45 ` Nikolay Nikolaev
2013-09-14 11:13 ` Albert ARIBAUD
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130809165503.GC26486@cbox \
--to=christoffer.dall@linaro.org \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.