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