All of lore.kernel.org
 help / color / mirror / Atom feed
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
> 

  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 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.