1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#pragma once 8 9#include <config.h> 10#include <arch/object/vcpu.h> 11 12#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 13 14/** Sets the VMID for the current stage 2 address space. 15 * 16 * This will update the current VMID in VTTBR while preserving the 17 * stage 2 translation table base paddr. 18 */ 19static inline void writeContextIDPL2(word_t id) 20{ 21 word_t pd_val, vmid; 22 asm volatile("mrrc p15, 6, %0, %1, c2" : "=r"(pd_val), "=r"(vmid)); 23 asm volatile("mcrr p15, 6, %0, %1, c2" : : "r"(pd_val), "r"(id << (48-32))); 24 isb(); 25} 26 27/** Sets the stage 2 translation table base address and VMID. 28 * 29 * The only difference between this and setCurrentPDPL2() is that 30 * the latter preserves the VMID. 31 */ 32static inline void writeContextIDAndPD(word_t id, word_t pd_val) 33{ 34 asm volatile("mcrr p15, 6, %0, %1, c2" : : "r"(pd_val), "r"(id << (48-32))); 35 isb(); 36} 37 38/** Sets the stage 2 translation table base address. 39 * 40 * "P15, 6, <r0>, <r1>, c2" refers to the VTTBR register. 41 * 42 * VTTBR can only be accessed in hyp mode (or monitor mode with SCR.NS==1). 43 * It sets the physical address of the page tables that the CPU will walk 44 * for stage 2 translation. It also sets the VMID of the current stage 2 45 * address space. 46 */ 47static inline void setCurrentPDPL2(paddr_t addr) 48{ 49 word_t pd_val, vmid; 50 asm volatile("mrrc p15, 6, %0, %1, c2" : "=r"(pd_val), "=r"(vmid)); 51 dsb(); 52 asm volatile("mcrr p15, 6, %0, %1, c2" : : "r"(addr), "r"(vmid)); 53 isb(); 54} 55 56static inline void setCurrentHypPD(paddr_t addr) 57{ 58 word_t zero = 0; 59 dsb(); 60 asm volatile("mcrr p15, 4, %0, %1, c2" : : "r"(addr), "r"(zero)); 61 isb(); 62} 63 64static inline void setVTCR(word_t r) 65{ 66 dsb(); 67 asm volatile("mcr p15, 4, %0, c2, c1, 2" : : "r"(r)); 68 isb(); 69} 70 71static inline void setHCR(word_t r) 72{ 73 dsb(); 74 asm volatile("mcr p15, 4, %0, c1, c1, 0" : : "r"(r)); 75 isb(); 76} 77 78static inline word_t getHCR(void) 79{ 80 word_t HCR; 81 asm volatile("mrc p15, 4, %0, c1, c1, 0" : "=r"(HCR)); 82 return HCR; 83} 84 85static inline void setHCPTR(word_t r) 86{ 87 dsb(); 88 asm volatile("mcr p15, 4, %0, c1, c1, 2" : : "r"(r)); 89 isb(); 90} 91 92static inline word_t PURE getHCPTR(void) 93{ 94 word_t HCPTR; 95 asm volatile("mrc p15, 4, %0, c1, c1, 2" : "=r"(HCPTR)); 96 return HCPTR; 97} 98 99static inline void setHMAIR(word_t hmair0, word_t hmair1) 100{ 101 asm volatile("mcr p15, 4, %0, c10, c2, 0" : : "r"(hmair0)); 102 asm volatile("mcr p15, 4, %0, c10, c2, 1" : : "r"(hmair1)); 103 isb(); 104} 105 106static inline void setMAIR(word_t hmair0, word_t hmair1) 107{ 108 asm volatile("mcr p15, 0, %0, c10, c2, 0" : : "r"(hmair0)); 109 asm volatile("mcr p15, 0, %0, c10, c2, 1" : : "r"(hmair1)); 110 isb(); 111} 112 113static inline void invalidateHypTLB(void) 114{ 115 dsb(); 116 asm volatile("mcr p15, 4, %0, c8, c7, 0" : : "r"(0)); 117 dsb(); 118 isb(); 119} 120 121static inline paddr_t PURE addressTranslateS1CPR(vptr_t vaddr) 122{ 123 uint32_t ipa0, ipa1; 124 asm volatile("mcr p15, 0, %0, c7, c8, 0" :: "r"(vaddr)); 125 isb(); 126 asm volatile("mrrc p15, 0, %0, %1, c7" : "=r"(ipa0), "=r"(ipa1)); 127 128 return ipa0; 129} 130 131static inline word_t PURE getHSR(void) 132{ 133 word_t HSR; 134 asm volatile("mrc p15, 4, %0, c5, c2, 0" : "=r"(HSR)); 135 return HSR; 136} 137 138static inline word_t PURE getHDFAR(void) 139{ 140 word_t HDFAR; 141 asm volatile("mrc p15, 4, %0, c6, c0, 0" : "=r"(HDFAR)); 142 return HDFAR; 143} 144 145static inline word_t PURE getHIFAR(void) 146{ 147 word_t HIFAR; 148 asm volatile("mrc p15, 4, %0, c6, c0, 2" : "=r"(HIFAR)); 149 return HIFAR; 150} 151 152static inline word_t PURE getHPFAR(void) 153{ 154 word_t HPFAR; 155 asm volatile("mrc p15, 4, %0, c6, c0, 4" : "=r"(HPFAR)); 156 return HPFAR; 157} 158 159static inline word_t getSCTLR(void) 160{ 161 word_t SCTLR; 162 asm volatile("mrc p15, 0, %0, c1, c0, 0" : "=r"(SCTLR)); 163 return SCTLR; 164} 165 166static inline void setSCTLR(word_t sctlr) 167{ 168 asm volatile("mcr p15, 0, %0, c1, c0, 0" :: "r"(sctlr)); 169} 170 171static inline void writeHTPIDR(word_t reg) 172{ 173 asm volatile("mcr p15, 4, %0, c13, c0, 2" :: "r"(reg)); 174} 175 176static inline word_t readHTPIDR(void) 177{ 178 word_t reg; 179 asm volatile("mrc p15, 4, %0, c13, c0, 2" : "=r"(reg)); 180 return reg; 181} 182 183#else 184 185/* used in other files without guards */ 186static inline void setCurrentPDPL2(paddr_t pa) {} 187static inline void invalidateHypTLB(void) {} 188static inline void writeContextIDPL2(word_t pd_val) {} 189static inline void writeContextIDAndPD(word_t id, word_t pd_val) {} 190static inline void writeHTPIDR(word_t htpidr) {} 191static inline word_t readHTPIDR(void) 192{ 193 return 0; 194} 195static inline paddr_t addressTranslateS1CPR(vptr_t vaddr) 196{ 197 return vaddr; 198} 199 200#endif /* !CONFIG_ARM_HYPERVISOR_SUPPORT */ 201