diff mbox

[2/2] ARM: virt: Initial Virtualization Extensions support

Message ID 1328901508-22076-2-git-send-email-dave.martin@linaro.org
State Not Applicable
Headers show

Commit Message

Dave Martin Feb. 10, 2012, 7:18 p.m. UTC
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 <dave.martin@linaro.org>
---
 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

Comments

Nicolas Pitre Feb. 13, 2012, 2:29 a.m. UTC | #1
On Fri, 10 Feb 2012, Dave Martin wrote:

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

We'll want this not to be optional, but selected by any architecture 
with possible availability of the virtualization extensions, as we are 
asking for bootloaders to pass control to the kernel in hyp mode.

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

The firmware/bootloader will have to let the kernel gain control of 
secondary CPUs in hyp mode too.

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

No need to be too smart here.  Entry in SVC mode = we're a guest and/or 
the hyp mode is not available.  Entry in hyp mode = we take control 
whether or not another hypervisor was already there.  No need to 
probe/detect anything.  If the system is inconsistent then tough.

[...]
> +/*
> + * 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.
> + */

Is there a reason for not using the GPL for newly created code added to 
the kernel?  None of that is likely to be useful elsewhere anyway.


Nicolas
diff mbox

Patch

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 <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * 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