From patchwork Fri Aug 9 15:03:11 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 18925 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qe0-f70.google.com (mail-qe0-f70.google.com [209.85.128.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 394B72391D for ; Fri, 9 Aug 2013 15:04:48 +0000 (UTC) Received: by mail-qe0-f70.google.com with SMTP id 6sf5256364qeb.1 for ; Fri, 09 Aug 2013 08:04:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-gm-message-state:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=roHskLUh6X7HitSel9AV7uOTSeGMet1joxxM6kA6a4w=; b=ER/Q8ZukEZ6XXfDhJfKM/5qngp9ga1KKzwbZeGeQsjrWswuaNBMIqk/wbB4R2Ans3j ReGb1mp1HL5bfUnlstlOuO3OKhLdsLVqADfOvBzUxySgR7kb2rzXiErNZtdwLaiuF1Qx b99zHgRSU+Dhkpk5UkX9gELDIrrYAOwoTc0awp2yeZIl67NpfpQlZoVOAHM+gSiNaY+G sgoPK1evPUoeITnAHJSdCw13lq98fJjJIM6YnjRfx+zUu0o58OEROIDOET0O1/A7llZb ekEvc3Ms2dqnKp/Lbyn6JNoHlQZhaYne/KXFXPuhQyPmvaBsEm5sLWPvz0ZZPyw9EbrD SRig== X-Received: by 10.58.220.131 with SMTP id pw3mr1173479vec.21.1376060687969; Fri, 09 Aug 2013 08:04:47 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.106.195 with SMTP id gw3ls1425724qeb.64.gmail; Fri, 09 Aug 2013 08:04:47 -0700 (PDT) X-Received: by 10.58.2.137 with SMTP id 9mr6220570veu.50.1376060687810; Fri, 09 Aug 2013 08:04:47 -0700 (PDT) Received: from mail-vb0-f47.google.com (mail-vb0-f47.google.com [209.85.212.47]) by mx.google.com with ESMTPS id ur15si4731522veb.108.2013.08.09.08.04.47 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 09 Aug 2013 08:04:47 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.47 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.47; Received: by mail-vb0-f47.google.com with SMTP id h10so4196189vbh.34 for ; Fri, 09 Aug 2013 08:04:47 -0700 (PDT) X-Gm-Message-State: ALoCoQlqsYsLrpkiLGjNsuAdVr3qtkGOW955vIECNBKYBscgHJby7wHSjG51M7gsbUwgewO6ImIL X-Received: by 10.52.164.16 with SMTP id ym16mr567721vdb.32.1376060687697; Fri, 09 Aug 2013 08:04:47 -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.220.174.196 with SMTP id u4csp78366vcz; Fri, 9 Aug 2013 08:04:47 -0700 (PDT) X-Received: by 10.60.76.72 with SMTP id i8mr898353oew.11.1376060687022; Fri, 09 Aug 2013 08:04:47 -0700 (PDT) Received: from mail-ob0-f171.google.com (mail-ob0-f171.google.com [209.85.214.171]) by mx.google.com with ESMTPS id l9si9632738obv.135.2013.08.09.08.04.46 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 09 Aug 2013 08:04:46 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.214.171 is neither permitted nor denied by best guess record for domain of andre.przywara@linaro.org) client-ip=209.85.214.171; Received: by mail-ob0-f171.google.com with SMTP id tb18so6533531obb.16 for ; Fri, 09 Aug 2013 08:04:46 -0700 (PDT) X-Received: by 10.182.106.4 with SMTP id gq4mr3695702obb.4.1376060686739; Fri, 09 Aug 2013 08:04:46 -0700 (PDT) Received: from slackpad.drs.calxeda.com (f053081188.adsl.alicedsl.de. [78.53.81.188]) by mx.google.com with ESMTPSA id hm1sm19249781obb.9.2013.08.09.08.04.43 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 09 Aug 2013 08:04:46 -0700 (PDT) From: Andre Przywara To: trini@ti.com, albert.u.boot@aribaud.net, christoffer.dall@linaro.org Cc: u-boot@lists.denx.de, marc.zyngier@arm.com, peter.maydell@linaro.org, geoff.levand@linaro.org, agraf@suse.de, kvmarm@lists.cs.columbia.edu, yamada.m@jp.panasonic.com, nicknickolaev@gmail.com, patches@linaro.org, Andre Przywara Subject: [PATCH v4 7/8] ARM: extend non-secure switch to also go into HYP mode Date: Fri, 9 Aug 2013 17:03:11 +0200 Message-Id: <1376060592-10824-8-git-send-email-andre.przywara@linaro.org> X-Mailer: git-send-email 1.7.12.1 In-Reply-To: <1376060592-10824-1-git-send-email-andre.przywara@linaro.org> References: <1376060592-10824-1-git-send-email-andre.przywara@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: andre.przywara@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.47 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: , 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 --- 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 * @@ -28,15 +28,16 @@ #include .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 + 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 #include -#ifdef CONFIG_ARMV7_NONSEC +#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT) #include #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 */