linux/arch/arm64/kernel/hyp-stub.S
<<
>>
Prefs
   1/*
   2 * Hypervisor stub
   3 *
   4 * Copyright (C) 2012 ARM Ltd.
   5 * Author:      Marc Zyngier <marc.zyngier@arm.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include <linux/init.h>
  21#include <linux/linkage.h>
  22#include <linux/irqchip/arm-gic-v3.h>
  23
  24#include <asm/assembler.h>
  25#include <asm/ptrace.h>
  26#include <asm/virt.h>
  27
  28        .text
  29        .align 11
  30
  31ENTRY(__hyp_stub_vectors)
  32        ventry  el2_sync_invalid                // Synchronous EL2t
  33        ventry  el2_irq_invalid                 // IRQ EL2t
  34        ventry  el2_fiq_invalid                 // FIQ EL2t
  35        ventry  el2_error_invalid               // Error EL2t
  36
  37        ventry  el2_sync_invalid                // Synchronous EL2h
  38        ventry  el2_irq_invalid                 // IRQ EL2h
  39        ventry  el2_fiq_invalid                 // FIQ EL2h
  40        ventry  el2_error_invalid               // Error EL2h
  41
  42        ventry  el1_sync                        // Synchronous 64-bit EL1
  43        ventry  el1_irq_invalid                 // IRQ 64-bit EL1
  44        ventry  el1_fiq_invalid                 // FIQ 64-bit EL1
  45        ventry  el1_error_invalid               // Error 64-bit EL1
  46
  47        ventry  el1_sync_invalid                // Synchronous 32-bit EL1
  48        ventry  el1_irq_invalid                 // IRQ 32-bit EL1
  49        ventry  el1_fiq_invalid                 // FIQ 32-bit EL1
  50        ventry  el1_error_invalid               // Error 32-bit EL1
  51ENDPROC(__hyp_stub_vectors)
  52
  53        .align 11
  54
  55el1_sync:
  56        mrs     x1, esr_el2
  57        lsr     x1, x1, #26
  58        cmp     x1, #0x16
  59        b.ne    2f                              // Not an HVC trap
  60        cbz     x0, 1f
  61        msr     vbar_el2, x0                    // Set vbar_el2
  62        b       2f
  631:      mrs     x0, vbar_el2                    // Return vbar_el2
  642:      eret
  65ENDPROC(el1_sync)
  66
  67.macro invalid_vector   label
  68\label:
  69        b \label
  70ENDPROC(\label)
  71.endm
  72
  73        invalid_vector  el2_sync_invalid
  74        invalid_vector  el2_irq_invalid
  75        invalid_vector  el2_fiq_invalid
  76        invalid_vector  el2_error_invalid
  77        invalid_vector  el1_sync_invalid
  78        invalid_vector  el1_irq_invalid
  79        invalid_vector  el1_fiq_invalid
  80        invalid_vector  el1_error_invalid
  81
  82/*
  83 * __hyp_set_vectors: Call this after boot to set the initial hypervisor
  84 * vectors as part of hypervisor installation.  On an SMP system, this should
  85 * be called on each CPU.
  86 *
  87 * x0 must be the physical address of the new vector table, and must be
  88 * 2KB aligned.
  89 *
  90 * Before calling this, you must check that the stub hypervisor is installed
  91 * everywhere, by waiting for any secondary CPUs to be brought up and then
  92 * checking that is_hyp_mode_available() is true.
  93 *
  94 * If not, there is a pre-existing hypervisor, some CPUs failed to boot, or
  95 * something else went wrong... in such cases, trying to install a new
  96 * hypervisor is unlikely to work as desired.
  97 *
  98 * When you call into your shiny new hypervisor, sp_el2 will contain junk,
  99 * so you will need to set that to something sensible at the new hypervisor's
 100 * initialisation entry point.
 101 */
 102
 103ENTRY(__hyp_get_vectors)
 104        mov     x0, xzr
 105        // fall through
 106ENTRY(__hyp_set_vectors)
 107        hvc     #0
 108        ret
 109ENDPROC(__hyp_get_vectors)
 110ENDPROC(__hyp_set_vectors)
 111