From patchwork Fri Feb 10 19:18:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Martin X-Patchwork-Id: 6756 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 4548F23F8D for ; Fri, 10 Feb 2012 19:16:26 +0000 (UTC) Received: from mail-yw0-f52.google.com (mail-yw0-f52.google.com [209.85.213.52]) by fiordland.canonical.com (Postfix) with ESMTP id F1F8FA186E8 for ; Fri, 10 Feb 2012 19:16:25 +0000 (UTC) Received: by yhgm50 with SMTP id m50so2155634yhg.11 for ; Fri, 10 Feb 2012 11:16:25 -0800 (PST) Received: by 10.50.57.234 with SMTP id l10mr13626406igq.12.1328901384376; Fri, 10 Feb 2012 11:16:24 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.12.131 with SMTP id x3cs89851ibx; Fri, 10 Feb 2012 11:16:23 -0800 (PST) Received: by 10.50.10.225 with SMTP id l1mr13935843igb.9.1328901383352; Fri, 10 Feb 2012 11:16:23 -0800 (PST) Received: from mail-iy0-f178.google.com (mail-iy0-f178.google.com [209.85.210.178]) by mx.google.com with ESMTPS id t4si6087841icw.105.2012.02.10.11.16.22 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 10 Feb 2012 11:16:23 -0800 (PST) Received-SPF: neutral (google.com: 209.85.210.178 is neither permitted nor denied by best guess record for domain of dave.martin@linaro.org) client-ip=209.85.210.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.210.178 is neither permitted nor denied by best guess record for domain of dave.martin@linaro.org) smtp.mail=dave.martin@linaro.org Received: by iage36 with SMTP id e36so877607iag.37 for ; Fri, 10 Feb 2012 11:16:22 -0800 (PST) MIME-Version: 1.0 Received: by 10.42.138.193 with SMTP id d1mr11094478icu.0.1328901382581; Fri, 10 Feb 2012 11:16:22 -0800 (PST) Received: from LinaroE102765.static.wiline.com ([108.60.102.133]) by mx.google.com with ESMTPS id wn7sm3769979igc.0.2012.02.10.11.16.21 (version=SSLv3 cipher=OTHER); Fri, 10 Feb 2012 11:16:22 -0800 (PST) From: Dave Martin To: Nicolas Pitre , Christoffer Dall , Marc Zyngier , Will Deacon Cc: patches@linaro.org, Dave Martin Subject: [PATCH 2/2] ARM: virt: Initial Virtualization Extensions support Date: Fri, 10 Feb 2012 11:18:28 -0800 Message-Id: <1328901508-22076-2-git-send-email-dave.martin@linaro.org> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1328901508-22076-1-git-send-email-dave.martin@linaro.org> References: <1328901508-22076-1-git-send-email-dave.martin@linaro.org> X-Gm-Message-State: ALoCoQknzfSiEImJTnd0XWGDnuGvHFcj3MRgncQdC3lIhCj+loZ+K7N2raalv7Suosn/tkQe9uQf This patch adds initial support to the kernel for using the ARM Virtualization Extensions natively. A new config option, CONFIG_ARM_VIRT enables native in-kernel virtualization support, by installing a stub at boot-time which can be used for subsequent installation of a hypervisor, via a call to __hyp_set_vectors(). Issues: * This is a work in progress and is completely untested. * hyp mode entry via the zImage loader is not supported yet -- you will need to boot via vmlinux or Image instead, for now. (The necessary support should be pretty straightforward, though.) * How this should work with SMP boot and suspend/resume is still pretty fuzzy. As-is, there's no guarante that it will work sensibly (or at all) in all situations. * How to probe/detect pre-existing hypervisors is fuzzy. This patch tries to dodge the problem, but asserting that there is no pre-existing hypervisor if all CPUs were booted in hyp mode; there may be a pre-existing hypervisor is all CPUs were not booted in hyp mode; and the system is in some horribly inconsistent state otherwise which we can do nothing about. * The stub hypervisor is not reentrant, and no inter-CPU synchronisation is done. It is expected that calls into the stub on different CPUs will be serialised and coherency ensured externally (which should be satisfied by the normal SMP bringup procedure in the kernel). * No hyp mode initialisation is currently done. Although we should require the bootloader to set things up in a sane state, we should probably avoid trusting the bootloader too much. This applies to the setup of hypervisor mode itself, as well as platform- and CPU-specific issues. We will probably need hooks for system-specific initialisation, though hopefully we can keep most of all of that out of the hyp mode stub, and do it later when the kernel is somewhat booted. Signed-off-by: Dave Martin --- Documentation/arm/Booting | 22 ++++++- arch/arm/include/asm/ptrace.h | 1 + arch/arm/include/asm/virt.h | 37 +++++++++++ arch/arm/kernel/Makefile | 3 + arch/arm/kernel/head.S | 6 ++ arch/arm/kernel/hyp-stub.S | 138 +++++++++++++++++++++++++++++++++++++++++ arch/arm/mm/Kconfig | 17 +++++ 7 files changed, 223 insertions(+), 1 deletions(-) create mode 100644 arch/arm/include/asm/virt.h create mode 100644 arch/arm/kernel/hyp-stub.S diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting index a341d87..0c1f475 100644 --- a/Documentation/arm/Booting +++ b/Documentation/arm/Booting @@ -154,13 +154,33 @@ In either case, the following conditions must be met: - CPU mode All forms of interrupts must be disabled (IRQs and FIQs) - The CPU must be in SVC mode. (A special exception exists for Angel) + + For CPUs which do not include the ARM virtualization extensions, the + CPU must be in SVC mode. (A special exception exists for Angel) + + CPUs which include support for the virtualization extensions can be + entered in HYP mode in order to enable the kernel to make full use of + these extensions. This is the recommended boot method for such CPUs, + unless the virtualisations are already in use by a pre-installed + hypervisor. + + If the kernel is not entered in HYP mode for any reason, it must be + entered in SVC mode. - Caches, MMUs The MMU must be off. Instruction cache may be on or off. Data cache must be off. + If the kernel is entered in HYP mode, the above requirements apply to + the HYP mode configuration in addition to the ordinary PL1 (privileged + kernel modes) configuration. In addition, all traps into the + hypervisor must be disabled, and PL1 access must be granted for all + peripherals and CPU resources for which this is architecturally + possible. Except for entering in HYP mode, the system configuration + should be such that a kernel which does not include support for the + virtualization extensions can boot correctly without extra help. + - The boot loader is expected to call the kernel image by jumping directly to the first instruction of the kernel image. diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 451808b..f48c006 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -44,6 +44,7 @@ #define IRQ_MODE 0x00000012 #define SVC_MODE 0x00000013 #define ABT_MODE 0x00000017 +#define HYP_MODE 0x0000001a #define UND_MODE 0x0000001b #define SYSTEM_MODE 0x0000001f #define MODE32_BIT 0x00000010 diff --git a/arch/arm/include/asm/virt.h b/arch/arm/include/asm/virt.h new file mode 100644 index 0000000..77d7a65 --- /dev/null +++ b/arch/arm/include/asm/virt.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012 Linaro Limited. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the Linaro Limited nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY LINARO LIMITED AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +#ifndef VIRT_H +#define VIRT_H + +extern int __hyp_stub_install_count; + +void __hyp_set_vectors(unsigned long phys_vector_base); + +#endif /* ! VIRT_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 43b740d..9f49f21 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -83,4 +83,7 @@ head-y := head$(MMUEXT).o obj-$(CONFIG_DEBUG_LL) += debug.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_ARM_VIRT) += hyp-stub.o +AFLAGS_hyp-stub.o := -Wa,-march=armv7-a+virt + extra-y := $(head-y) init_task.o vmlinux.lds diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 0ccf042..bafaf99 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -106,6 +106,9 @@ ENTRY(stext) THUMB( .thumb ) @ switch to Thumb now. THUMB(1: ) +#ifdef CONFIG_ARM_VIRT + bl __hyp_stub_install +#endif @ ensure svc mode and all interrupts masked safe_svcmode_maskall r4 @@ -362,6 +365,9 @@ ENTRY(secondary_startup) * the processor type - there is no need to check the machine type * as it has already been validated by the primary processor. */ +#ifdef CONFIG_ARM_VIRT + bl __hyp_stub_install +#endif safe_svcmode_maskall r4 mrc p15, 0, r9, c0, c0 @ get processor id diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S new file mode 100644 index 0000000..ec16e46 --- /dev/null +++ b/arch/arm/kernel/hyp-stub.S @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2012 Linaro Limited. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the Linaro Limited nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY LINARO LIMITED AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +#include +#include +#include + +/* + * Hypervisor stub installation functions. + * + * These must be called with the MMU and D-cache off. + * They are not ABI compliant and are only intended to be called from the kernel + * entry points in head.S. + */ +@ Call this from the primary CPU +ENTRY(__hyp_stub_install) + adr r4, 1f + ldr r5, .L__hyp_stub_install_count_offset + mov r6, #0 + str r6, [r4, r5] @ reset __hyp_stub_install_count to 0 +ENDPROC(__hyp_stub_install) + + @ fall through... + +@ Secondary CPUs should call here +ENTRY(__hyp_stub_install_secondary) + mrs r6, cpsr + and r7, r6, #MODE_MASK + cmp r7, #HYP_MODE + bxne lr @ give up if not in hyp mode + +/* + * BUG: hyp mode init needs to happen here: + * Configure HSCTLR to set correct exception endianness/instruction set + * state etc. + * Turn off all traps + * Eventually, CPU-specific code might be needed -- assume not for now + * + * The boot state is probably right though, and will probably work for + * ARM kernels right now (but not Thumb-2 -- HSCTLR.EE wlil be wrong + * for that) + */ + @ Now install the hypervisor stub: + adr r7, __hyp_stub_vectors + mcr p15, 4, r7, c12, c0, 0 @ set hypervisor vector base (HVBAR) + + adr r4, 1f + ldr r5, .L__hyp_stub_install_count_offset +1: ldr r7, [r4, r5] + add r7, r7, #1 + str r7, [r4, r5] @ increment __hyp_stub_install_count + + bic lr, lr, #1 @ clear thumb bit + @ (SPSR.T used instead) + msr elr_hyp, lr + bic r7, r6, #MODE_MASK + orr r7, r7, #SVC_MODE + msr spsr_cxsf, r7 + + eret @ return, switching to SVC mode +ENDPROC(__hyp_stub_install_secondary) + +__hyp_stub_do_trap: + mcr p15, 4, r0, c12, c0, 0 @ set HVBAR + eret +ENDPROC(__hyp_stub_do_trap) + +/* + * __hyp_set_vectors: Call this after boot to set the initial hypervisor + * vectors as part of hypervisor installation. On an SMP system, this should + * be called on each CPU. + * + * r0 must be the physical address of the new vector table (which must lie in + * the bottom 4GB of physical address space. + * + * r0 must be 32-byte aligned. + * + * Before calling this, you must check that the stub hypervisor is installed + * everywhere, by checking that __hyp_stub_install_count == the number of + * booted CPUs. If not, there is a pre-existing hypervisor, some CPUs failed + * to boot, or something else went wrong... in such cases, trying to install + * a new hypervisor is unlikely to work as desired. + * + * When you call into your shiny new hypervisor, sp_hyp will contain junk, + * so you will need to set that to something sensible when calling into the + * new hypervisor to initialise it. + */ +ENTRY(__hyp_set_vectors) + hvc #0 + bx lr +ENDPROC(__hyp_set_vectors) + +.align 2 +.L__hyp_stub_install_count_offset: + .long __hyp_stub_install_count - 1b + +.align 5 +__hyp_stub_vectors: +__hyp_stub_reset: W(b) . +__hyp_stub_und: W(b) . +__hyp_stub_svc: W(b) . +__hyp_stub_pabort: W(b) . +__hyp_stub_dabort: W(b) . +__hyp_stub_trap: W(b) __hyp_stub_do_trap +__hyp_stub_irq: W(b) . +__hyp_stub_fiq: W(b) . +ENDPROC(__hyp_stub_vectors) + +.bss + +__hyp_stub_install_count: + .long 0 diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 4cefb57..b4b2834 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -667,6 +667,23 @@ config ARM_THUMBEE Say Y here if you have a CPU with the ThumbEE extension and code to make use of it. Say N for code that can run on CPUs without ThumbEE. +config ARM_VIRT + bool "Native support for the ARM Virtualization Extensions" + depends on MMU && CPU_V7 + help + Enable the kernel to make use of the ARM Virtualization + Extensions to install hypervisors without run-time firmware + assistance. + + A compliant bootloader is required in order to make maximum + use of this feature. Refer to Documentation/arm/Booting for + details. + + It is safe to enable this option even if the kernel may not be + booted in HYP mode, may not have support for the + virtualization extensions, or may be booted with a + non-compliant bootloader. + config SWP_EMULATE bool "Emulate SWP/SWPB instructions" depends on !CPU_USE_DOMAINS && CPU_V7