Message ID | 1329329763-31508-3-git-send-email-dave.martin@linaro.org |
---|---|
State | Not Applicable |
Headers | show |
Hi Dave, On Wed, Feb 15, 2012 at 06:15:55PM +0000, Dave Martin wrote: > * 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. Guarantee. > * 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 If. > 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). Since the staggered boot of secondary CPUs is out of headsmp.S, does this mean that each platform needs to call the hyp stub explicitly or do you plan to plumb it into secondary_startup? > 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. virtualisations is a cool word :) > 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. > + */ I agree with Nicolas that GPL should be used, but obviously you need to ask the right people about that. > 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 Maybe it's just me, but CONFIG_ARM_VIRT sounds like something to do with virtual memory rather than the virtualisations. CONFIG_ARM_HYP instead? > 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... Is this fall through safe if __hyp_stub_install ends on a halfword boundary (not that it can at the moment)? Or is this code always ARM? > +@ 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 We probably also want to enable EL1 access to the physical timers here too. > + * 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) will. > + */ > + @ 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 This .bss looks out of place - why do you need it here? Will
On Thu, Feb 16, 2012 at 11:09 AM, Will Deacon <will.deacon@arm.com> wrote: > Hi Dave, > > On Wed, Feb 15, 2012 at 06:15:55PM +0000, Dave Martin wrote: >> * 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. > > Guarantee. Uh... > >> * 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 > > If. ...huh. > >> 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). > > Since the staggered boot of secondary CPUs is out of headsmp.S, does this > mean that each platform needs to call the hyp stub explicitly or do you plan > to plumb it into secondary_startup? Yes. That's why I plumbed it into secondary_startup in kernel/head.S. But that was a bit of a hack and I haven't convinced myself that it will really work yet. I'm certainly hoping we don't have to hack it into every board's secondary entry point... but that needs to be confirmed. > >> 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. > > virtualisations is a cool word :) Hmmm, I think that was supposed to say "virtualisation extensions". > >> 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. >> + */ > > I agree with Nicolas that GPL should be used, but obviously you need to ask > the right people about that. Dave R agrees with GPL for this kind of thing... I will switch it. > >> 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 > > Maybe it's just me, but CONFIG_ARM_VIRT sounds like something to do with > virtual memory rather than the virtualisations. CONFIG_ARM_HYP instead? OK, I guess that makes sense. I worried slightly that CONFIG_ARM_HYP was a bit too encrypted, but probably not... hyp mode may be ARM-specific, but the concept of a hypervisor is not. Or I could just call it CONFIG_ARM_HYPERVISOR and be done with it. > >> 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... > > Is this fall through safe if __hyp_stub_install ends on a halfword boundary Why should that make any difference? Last time I checked, Thumb instructions were allowed to fall on a halfword boundary... that includes function entry points. > (not that it can at the moment)? Or is this code always ARM? > >> +@ 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 > > We probably also want to enable EL1 access to the physical timers here too. That wasn't explicit, but yes-- any architectural resources owned by PL2 need to get handed to PL1 here. > >> + * 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) > > will. This comment should be gone from the final post, of course... > >> + */ >> + @ 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 > > This .bss looks out of place - why do you need it here? > > Will That's left over from a previous edit. I'll tidy that up, but this will probably all change again anyway. Thanks for the review. Cheers ---Dave
On Thu, Feb 16, 2012 at 11:21:33AM +0000, Dave Martin wrote: > On Thu, Feb 16, 2012 at 11:09 AM, Will Deacon <will.deacon@arm.com> wrote: > >> +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... > > > > Is this fall through safe if __hyp_stub_install ends on a halfword boundary > > Why should that make any difference? > Last time I checked, Thumb instructions were allowed to fall on a > halfword boundary... that includes function entry points. Sure, but the ENTRY macro for __hyp_stub_install_secondary will emit a .align 0. However, it turns out that throws out a nop (I wrongly assumed '0' was the fill) so you're ok. Will
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
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