diff mbox

[02/10] ARM: virt: Initial Virtualization Extensions support

Message ID 1329329763-31508-3-git-send-email-dave.martin@linaro.org
State Not Applicable
Headers show

Commit Message

Dave Martin Feb. 15, 2012, 6:15 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

Will Deacon Feb. 16, 2012, 11:09 a.m. UTC | #1
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
Dave Martin Feb. 16, 2012, 11:21 a.m. UTC | #2
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
Will Deacon Feb. 16, 2012, 11:55 a.m. UTC | #3
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 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