From: Christoffer Dall <christoffer.dall@linaro.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v4 7/8] ARM: extend non-secure switch to also go into HYP mode
Date: Fri, 9 Aug 2013 09:55:13 -0700 [thread overview]
Message-ID: <20130809165513.GD26486@cbox> (raw)
In-Reply-To: <1376060592-10824-8-git-send-email-andre.przywara@linaro.org>
On Fri, Aug 09, 2013 at 05:03:11PM +0200, Andre Przywara wrote:
> For the KVM and XEN hypervisors to be usable, we need to enter the
> kernel in HYP mode. Now that we already are in non-secure state,
> HYP mode switching is within short reach.
>
> While doing the non-secure switch, we have to enable the HVC
> instruction and setup the HYP mode HVBAR (while still secure).
>
> The actual switch is done by dropping back from a HYP mode handler
> without actually leaving HYP mode, so we introduce a new handler
> routine in our new secure exception vector table.
>
> In the assembly switching routine we save and restore the banked LR
> and SP registers around the hypercall to do the actual HYP mode
> switch.
>
> The C routine first checks whether we are in HYP mode already and
> also whether the virtualization extensions are available. It also
> checks whether the HYP mode switch was finally successful.
> The bootm command part only adds and adjusts some error reporting.
>
> Signed-off-by: Andre Przywara <andre.przywara@linaro.org>
> ---
> arch/arm/cpu/armv7/Makefile | 2 +-
> arch/arm/cpu/armv7/nonsec_virt.S | 43 +++++++++++++++++++++++++++++++++++-----
> arch/arm/cpu/armv7/virt-v7.c | 37 ++++++++++++++++++++++++++++++++++
> arch/arm/include/asm/armv7.h | 6 ++++--
> arch/arm/lib/bootm.c | 7 ++++++-
> 5 files changed, 86 insertions(+), 9 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
> index 5813e87..c20df3d 100644
> --- a/arch/arm/cpu/armv7/Makefile
> +++ b/arch/arm/cpu/armv7/Makefile
> @@ -36,7 +36,7 @@ ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONF
> SOBJS += lowlevel_init.o
> endif
>
> -ifneq ($(CONFIG_ARMV7_NONSEC),)
> +ifneq ($(CONFIG_ARMV7_NONSEC)$(CONFIG_ARMV7_VIRT),)
> SOBJS += nonsec_virt.o
> COBJS += virt-v7.o
> endif
> diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
> index a88fa6b..fb1651d 100644
> --- a/arch/arm/cpu/armv7/nonsec_virt.S
> +++ b/arch/arm/cpu/armv7/nonsec_virt.S
> @@ -1,5 +1,5 @@
> /*
> - * code for switching cores into non-secure state
> + * code for switching cores into non-secure state and into HYP mode
> *
> * Copyright (c) 2013 Andre Przywara <andre.przywara@linaro.org>
> *
> @@ -28,15 +28,16 @@
> #include <asm/armv7.h>
>
> .arch_extension sec
> +.arch_extension virt
>
> -/* the vector table for secure state */
> +/* the vector table for secure state and HYP mode */
> _monitor_vectors:
> .word 0 /* reset */
> .word 0 /* undef */
> adr pc, _secure_monitor
> .word 0
> .word 0
> - .word 0
> + adr pc, _hyp_trap
> .word 0
> .word 0
> .word 0 /* pad */
> @@ -54,10 +55,27 @@ _secure_monitor:
> bic r1, r1, #0x4e @ clear IRQ, FIQ, EA, nET bits
> orr r1, r1, #0x31 @ enable NS, AW, FW bits
>
> +#ifdef CONFIG_ARMV7_VIRT
> + mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1
> + and r0, r0, #CPUID_ARM_VIRT_MASK @ mask virtualization bits
> + cmp r0, #(1 << CPUID_ARM_VIRT_SHIFT)
> + orreq r1, r1, #0x100 @ allow HVC instruction
> +#endif
> +
> mcr p15, 0, r1, c1, c1, 0 @ write SCR (with NS bit set)
>
> +#ifdef CONFIG_ARMV7_VIRT
> + mrceq p15, 0, r0, c12, c0, 1 @ get MVBAR value
> + mcreq p15, 4, r0, c12, c0, 0 @ write HVBAR
> +#endif
> +
> movs pc, lr @ return to non-secure SVC
>
> +_hyp_trap:
> + mrs lr, elr_hyp @ for older asm: .byte 0x00, 0xe3, 0x0e, 0xe1
I see you kep this as is, oh well.
> + mov pc, lr @ do no switch modes, but
> + @ return to caller
> +
> /*
> * Secondary CPUs start here and call the code for the core specific parts
> * of the non-secure and HYP mode transition. The GIC distributor specific
> @@ -72,9 +90,13 @@ ENTRY(_smp_pen)
> mcr p15, 0, r1, c12, c0, 0 @ set VBAR
>
> bl _nonsec_init
> + mov r12, r0 @ save GICC address
> +#ifdef CONFIG_ARMV7_VIRT
> + bl _switch_to_hyp
> +#endif
>
> - ldr r1, [r0, #GICC_IAR] @ acknowledge IPI
> - str r1, [r0, #GICC_EOIR] @ signal end of interrupt
> + ldr r1, [r12, #GICC_IAR] @ acknowledge IPI
> + str r1, [r12, #GICC_EOIR] @ signal end of interrupt
>
> adr r0, _smp_pen @ do not use this address again
> b smp_waitloop @ wait for IPIs, board specific
> @@ -161,3 +183,14 @@ ENTRY(_nonsec_init)
>
> bx lr
> ENDPROC(_nonsec_init)
> +
> +ENTRY(_switch_to_hyp)
> + mov r0, lr
> + mov r1, sp @ save SVC copy of LR and SP
> + isb
> + hvc #0 @ for older asm: .byte 0x70, 0x00, 0x40, 0xe1
> + mov sp, r1
> + mov lr, r0 @ restore SVC copy of LR and SP
> +
> + bx lr
> +ENDPROC(_switch_to_hyp)
> diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c
> index 50f0a3a..4dc8c45 100644
> --- a/arch/arm/cpu/armv7/virt-v7.c
> +++ b/arch/arm/cpu/armv7/virt-v7.c
> @@ -3,6 +3,7 @@
> * Andre Przywara, Linaro
> *
> * Routines to transition ARMv7 processors from secure into non-secure state
> + * and from non-secure SVC into HYP mode
> * needed to enable ARMv7 virtualization for current hypervisors
> *
> * See file CREDITS for list of people who contributed to this
> @@ -31,6 +32,14 @@
>
> unsigned long gic_dist_addr;
>
> +static unsigned int read_cpsr(void)
> +{
> + unsigned int reg;
> +
> + asm volatile ("mrs %0, cpsr\n" : "=r" (reg));
> + return reg;
> +}
> +
> static unsigned int read_id_pfr1(void)
> {
> unsigned int reg;
> @@ -90,6 +99,34 @@ void __weak smp_kick_all_cpus(void)
> kick_secondary_cpus_gic(gic_dist_addr);
> }
>
> +int armv7_switch_hyp(void)
> +{
> + unsigned int reg;
> +
> + /* check whether we are in HYP mode already */
> + if ((read_cpsr() & 0x1f) == 0x1a) {
> + debug("CPU already in HYP mode\n");
> + return 0;
> + }
> +
> + /* check whether the CPU supports the virtualization extensions */
> + reg = read_id_pfr1();
> + if ((reg & CPUID_ARM_VIRT_MASK) != 1 << CPUID_ARM_VIRT_SHIFT) {
> + printf("HYP mode: Virtualization extensions not implemented.\n");
> + return -1;
> + }
> +
> + /* call the HYP switching code on this CPU also */
> + _switch_to_hyp();
> +
> + if ((read_cpsr() & 0x1F) != 0x1a) {
> + printf("HYP mode: switch not successful.\n");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> int armv7_switch_nonsec(void)
> {
> unsigned int reg;
> diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
> index 06657fe..1a7b150 100644
> --- a/arch/arm/include/asm/armv7.h
> +++ b/arch/arm/include/asm/armv7.h
> @@ -92,14 +92,16 @@ 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
> +#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
>
> int armv7_switch_nonsec(void);
> +int armv7_switch_hyp(void);
>
> /* defined in assembly file */
> unsigned int _nonsec_init(void);
> void _smp_pen(void);
> -#endif /* CONFIG_ARMV7_NONSEC */
> +void _switch_to_hyp(void);
> +#endif /* CONFIG_ARMV7_NONSEC || CONFIG_ARMV7_VIRT */
>
> #endif /* ! __ASSEMBLY__ */
>
> diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
> index 6470eac..ff36319 100644
> --- a/arch/arm/lib/bootm.c
> +++ b/arch/arm/lib/bootm.c
> @@ -34,7 +34,7 @@
> #include <asm/bootm.h>
> #include <linux/compiler.h>
>
> -#ifdef CONFIG_ARMV7_NONSEC
> +#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
> #include <asm/armv7.h>
> #endif
>
> @@ -201,8 +201,13 @@ static void do_nonsec_virt_switch(void)
> {
> #if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
> if (armv7_switch_nonsec() == 0)
> +#ifdef CONFIG_ARMV7_VIRT
> + if (armv7_switch_hyp() == 0)
> + debug("entered HYP mode\n");
> +#else
> debug("entered non-secure state\n");
> #endif
> +#endif
> }
>
> /* Subcommand: PREP */
> --
> 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
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 [this message]
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=20130809165513.GD26486@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox