[RFC PATCH] Arm64: introduce __hyp_func_call

Arun Chandran achandran at mvista.com
Sat Aug 30 03:32:29 PDT 2014


Hi Marc,

On Wed, Aug 27, 2014 at 4:22 PM, Marc Zyngier <marc.zyngier at arm.com> wrote:
> On 27/08/14 11:28, Arun Chandran wrote:
>> This adds a mechanism to __hyp_stub_vectors to allow a hypercall to
>> call a function at EL2. It is needed for users who want to
>> run a part of code with EL2 permissions. The current usecase is for
>> KVM and kexec.
>>
>> For kexec we need to move the final CPU up to the mode it started
>> in before we branch to the new kernel. If we don't do that
>>
>> * We loose EL2 in the next boot
>> * Arm64 bootwrapper may not be able to put CPUs at the spin-table
>>   code. It expects the final jump from kernel to cpu-return-addr to be
>>   done in EL2.
>>
>> KVM can use this to set/get VBAR_EL2
>
> Ah, looking at this a bit more, I see what you've done (missed the
> #define trickery below).
>
>> Signed-off-by: Arun Chandran <achandran at mvista.com>
>> ---
>> Idea is from "Mark Rutland <mark.rutland at arm.com>"
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2014-August/280026.html
>> ---
>>  arch/arm64/include/asm/virt.h |   15 +++++++++++++++
>>  arch/arm64/kernel/hyp-stub.S  |   33 +++++++++++++++++++++------------
>>  2 files changed, 36 insertions(+), 12 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
>> index 7a5df52..910a163 100644
>> --- a/arch/arm64/include/asm/virt.h
>> +++ b/arch/arm64/include/asm/virt.h
>> @@ -34,9 +34,24 @@
>>   */
>>  extern u32 __boot_cpu_mode[2];
>>
>> +void *__hyp_func_call(u64 __tmp, phys_addr_t func, ...);
>>  void __hyp_set_vectors(phys_addr_t phys_vector_base);
>>  phys_addr_t __hyp_get_vectors(void);
>>
>> +#define __hyp_set_vectors(__vbase)                                       \
>> +({                                                                       \
>> +     u64 __tmp = 0;                                                      \
>> +     __hyp_func_call(__tmp, virt_to_phys(__hyp_set_vectors), __vbase);   \
>> +})
>> +
>> +#define __hyp_get_vectors()                                              \
>> +({                                                                       \
>> +     u64 __tmp = 0;                                                      \
>> +     phys_addr_t ret = (phys_addr_t) __hyp_func_call(__tmp,              \
>> +                                     virt_to_phys(__hyp_get_vectors));   \
>> +     ret;                                                                \
>> +})
>> +
>
> This is what has thrown me off the wrong path. Don't do that, this is
> horrid. Just rename the assembly entry points, it will make things a lot
> clearer.
>

Ok. I will post another one.

--Arun


> Thanks,
>
>         M.
>
>>  /* Reports the availability of HYP mode */
>>  static inline bool is_hyp_mode_available(void)
>>  {
>> diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
>> index a272f33..2144a3f 100644
>> --- a/arch/arm64/kernel/hyp-stub.S
>> +++ b/arch/arm64/kernel/hyp-stub.S
>> @@ -53,15 +53,14 @@ ENDPROC(__hyp_stub_vectors)
>>       .align 11
>>
>>  el1_sync:
>> -     mrs     x1, esr_el2
>> -     lsr     x1, x1, #26
>> -     cmp     x1, #0x16
>> +     mrs     x0, esr_el2
>> +     lsr     x0, x0, #26
>> +     cmp     x0, #0x16
>>       b.ne    2f                              // Not an HVC trap
>> -     cbz     x0, 1f
>> -     msr     vbar_el2, x0                    // Set vbar_el2
>> -     b       2f
>> -1:   mrs     x0, vbar_el2                    // Return vbar_el2
>> -2:   eret
>> +
>> +1:   blr     x1                              // Jump to the function
>> +2:   mov     x0, xzr                         // esr_el2 not readable <= el2
>> +     eret
>>  ENDPROC(el1_sync)
>>
>>  .macro invalid_vector        label
>> @@ -101,10 +100,20 @@ ENDPROC(\label)
>>   */
>>
>>  ENTRY(__hyp_get_vectors)
>> -     mov     x0, xzr
>> -     // fall through
>> -ENTRY(__hyp_set_vectors)
>> -     hvc     #0
>> +     mrs     x0, vbar_el2                    // Return vbar_el2
>>       ret
>>  ENDPROC(__hyp_get_vectors)
>> +
>> +ENTRY(__hyp_set_vectors)
>> +     msr     vbar_el2, x2
>> +     ret
>>  ENDPROC(__hyp_set_vectors)
>> +
>> +/* Call a function @x1 */
>> +ENTRY(__hyp_func_call)
>> +     /* Save lr here */
>> +     msr     elr_el1, x30
>> +     hvc     #0
>> +     mrs     x30, elr_el1
>> +     ret
>> +ENDPROC(__hyp_func_call)
>>
>
>
> --
> Jazz is not dead. It just smells funny...



More information about the linux-arm-kernel mailing list