linux/arch/arm/kvm/init.S
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
   4 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
   5 */
   6
   7#include <linux/linkage.h>
   8#include <asm/assembler.h>
   9#include <asm/unified.h>
  10#include <asm/asm-offsets.h>
  11#include <asm/kvm_asm.h>
  12#include <asm/kvm_arm.h>
  13#include <asm/kvm_mmu.h>
  14#include <asm/virt.h>
  15
  16/********************************************************************
  17 * Hypervisor initialization
  18 *   - should be called with:
  19 *       r0 = top of Hyp stack (kernel VA)
  20 *       r1 = pointer to hyp vectors
  21 *       r2,r3 = Hypervisor pgd pointer
  22 *
  23 * The init scenario is:
  24 * - We jump in HYP with 3 parameters: runtime HYP pgd, runtime stack,
  25 *   runtime vectors
  26 * - Invalidate TLBs
  27 * - Set stack and vectors
  28 * - Setup the page tables
  29 * - Enable the MMU
  30 * - Profit! (or eret, if you only care about the code).
  31 *
  32 * Another possibility is to get a HYP stub hypercall.
  33 * We discriminate between the two by checking if r0 contains a value
  34 * that is less than HVC_STUB_HCALL_NR.
  35 */
  36
  37        .text
  38        .pushsection    .hyp.idmap.text,"ax"
  39        .align 5
  40__kvm_hyp_init:
  41        .globl __kvm_hyp_init
  42
  43        @ Hyp-mode exception vector
  44        W(b)    .
  45        W(b)    .
  46        W(b)    .
  47        W(b)    .
  48        W(b)    .
  49        W(b)    __do_hyp_init
  50        W(b)    .
  51        W(b)    .
  52
  53__do_hyp_init:
  54        @ Check for a stub hypercall
  55        cmp     r0, #HVC_STUB_HCALL_NR
  56        blo     __kvm_handle_stub_hvc
  57
  58        @ Set stack pointer
  59        mov     sp, r0
  60
  61        @ Set HVBAR to point to the HYP vectors
  62        mcr     p15, 4, r1, c12, c0, 0  @ HVBAR
  63
  64        @ Set the HTTBR to point to the hypervisor PGD pointer passed
  65        mcrr    p15, 4, rr_lo_hi(r2, r3), c2
  66
  67        @ Set the HTCR and VTCR to the same shareability and cacheability
  68        @ settings as the non-secure TTBCR and with T0SZ == 0.
  69        mrc     p15, 4, r0, c2, c0, 2   @ HTCR
  70        ldr     r2, =HTCR_MASK
  71        bic     r0, r0, r2
  72        mrc     p15, 0, r1, c2, c0, 2   @ TTBCR
  73        and     r1, r1, #(HTCR_MASK & ~TTBCR_T0SZ)
  74        orr     r0, r0, r1
  75        mcr     p15, 4, r0, c2, c0, 2   @ HTCR
  76
  77        @ Use the same memory attributes for hyp. accesses as the kernel
  78        @ (copy MAIRx ro HMAIRx).
  79        mrc     p15, 0, r0, c10, c2, 0
  80        mcr     p15, 4, r0, c10, c2, 0
  81        mrc     p15, 0, r0, c10, c2, 1
  82        mcr     p15, 4, r0, c10, c2, 1
  83
  84        @ Invalidate the stale TLBs from Bootloader
  85        mcr     p15, 4, r0, c8, c7, 0   @ TLBIALLH
  86        dsb     ish
  87
  88        @ Set the HSCTLR to:
  89        @  - ARM/THUMB exceptions: Kernel config (Thumb-2 kernel)
  90        @  - Endianness: Kernel config
  91        @  - Fast Interrupt Features: Kernel config
  92        @  - Write permission implies XN: disabled
  93        @  - Instruction cache: enabled
  94        @  - Data/Unified cache: enabled
  95        @  - MMU: enabled (this code must be run from an identity mapping)
  96        mrc     p15, 4, r0, c1, c0, 0   @ HSCR
  97        ldr     r2, =HSCTLR_MASK
  98        bic     r0, r0, r2
  99        mrc     p15, 0, r1, c1, c0, 0   @ SCTLR
 100        ldr     r2, =(HSCTLR_EE | HSCTLR_FI | HSCTLR_I | HSCTLR_C)
 101        and     r1, r1, r2
 102 ARM(   ldr     r2, =(HSCTLR_M)                                 )
 103 THUMB( ldr     r2, =(HSCTLR_M | HSCTLR_TE)                     )
 104        orr     r1, r1, r2
 105        orr     r0, r0, r1
 106        mcr     p15, 4, r0, c1, c0, 0   @ HSCR
 107        isb
 108
 109        eret
 110
 111ENTRY(__kvm_handle_stub_hvc)
 112        cmp     r0, #HVC_SOFT_RESTART
 113        bne     1f
 114
 115        /* The target is expected in r1 */
 116        msr     ELR_hyp, r1
 117        mrs     r0, cpsr
 118        bic     r0, r0, #MODE_MASK
 119        orr     r0, r0, #HYP_MODE
 120THUMB(  orr     r0, r0, #PSR_T_BIT      )
 121        msr     spsr_cxsf, r0
 122        b       reset
 123
 1241:      cmp     r0, #HVC_RESET_VECTORS
 125        bne     1f
 126
 127reset:
 128        /* We're now in idmap, disable MMU */
 129        mrc     p15, 4, r1, c1, c0, 0   @ HSCTLR
 130        ldr     r0, =(HSCTLR_M | HSCTLR_A | HSCTLR_C | HSCTLR_I)
 131        bic     r1, r1, r0
 132        mcr     p15, 4, r1, c1, c0, 0   @ HSCTLR
 133
 134        /*
 135         * Install stub vectors, using ardb's VA->PA trick.
 136         */
 1370:      adr     r0, 0b                                  @ PA(0)
 138        movw    r1, #:lower16:__hyp_stub_vectors - 0b   @ VA(stub) - VA(0)
 139        movt    r1, #:upper16:__hyp_stub_vectors - 0b
 140        add     r1, r1, r0                              @ PA(stub)
 141        mcr     p15, 4, r1, c12, c0, 0  @ HVBAR
 142        b       exit
 143
 1441:      ldr     r0, =HVC_STUB_ERR
 145        eret
 146
 147exit:
 148        mov     r0, #0
 149        eret
 150ENDPROC(__kvm_handle_stub_hvc)
 151
 152        .ltorg
 153
 154        .globl __kvm_hyp_init_end
 155__kvm_hyp_init_end:
 156
 157        .popsection
 158