1*37c43753SMarc Zyngier /* 2*37c43753SMarc Zyngier * Copyright (C) 2012,2013 - ARM Ltd 3*37c43753SMarc Zyngier * Author: Marc Zyngier <marc.zyngier@arm.com> 4*37c43753SMarc Zyngier * 5*37c43753SMarc Zyngier * This program is free software; you can redistribute it and/or modify 6*37c43753SMarc Zyngier * it under the terms of the GNU General Public License version 2 as 7*37c43753SMarc Zyngier * published by the Free Software Foundation. 8*37c43753SMarc Zyngier * 9*37c43753SMarc Zyngier * This program is distributed in the hope that it will be useful, 10*37c43753SMarc Zyngier * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*37c43753SMarc Zyngier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*37c43753SMarc Zyngier * GNU General Public License for more details. 13*37c43753SMarc Zyngier * 14*37c43753SMarc Zyngier * You should have received a copy of the GNU General Public License 15*37c43753SMarc Zyngier * along with this program. If not, see <http://www.gnu.org/licenses/>. 16*37c43753SMarc Zyngier */ 17*37c43753SMarc Zyngier 18*37c43753SMarc Zyngier #ifndef __ARM64_KVM_MMU_H__ 19*37c43753SMarc Zyngier #define __ARM64_KVM_MMU_H__ 20*37c43753SMarc Zyngier 21*37c43753SMarc Zyngier #include <asm/page.h> 22*37c43753SMarc Zyngier #include <asm/memory.h> 23*37c43753SMarc Zyngier 24*37c43753SMarc Zyngier /* 25*37c43753SMarc Zyngier * As we only have the TTBR0_EL2 register, we cannot express 26*37c43753SMarc Zyngier * "negative" addresses. This makes it impossible to directly share 27*37c43753SMarc Zyngier * mappings with the kernel. 28*37c43753SMarc Zyngier * 29*37c43753SMarc Zyngier * Instead, give the HYP mode its own VA region at a fixed offset from 30*37c43753SMarc Zyngier * the kernel by just masking the top bits (which are all ones for a 31*37c43753SMarc Zyngier * kernel address). 32*37c43753SMarc Zyngier */ 33*37c43753SMarc Zyngier #define HYP_PAGE_OFFSET_SHIFT VA_BITS 34*37c43753SMarc Zyngier #define HYP_PAGE_OFFSET_MASK ((UL(1) << HYP_PAGE_OFFSET_SHIFT) - 1) 35*37c43753SMarc Zyngier #define HYP_PAGE_OFFSET (PAGE_OFFSET & HYP_PAGE_OFFSET_MASK) 36*37c43753SMarc Zyngier 37*37c43753SMarc Zyngier /* 38*37c43753SMarc Zyngier * Our virtual mapping for the idmap-ed MMU-enable code. Must be 39*37c43753SMarc Zyngier * shared across all the page-tables. Conveniently, we use the last 40*37c43753SMarc Zyngier * possible page, where no kernel mapping will ever exist. 41*37c43753SMarc Zyngier */ 42*37c43753SMarc Zyngier #define TRAMPOLINE_VA (HYP_PAGE_OFFSET_MASK & PAGE_MASK) 43*37c43753SMarc Zyngier 44*37c43753SMarc Zyngier #ifdef __ASSEMBLY__ 45*37c43753SMarc Zyngier 46*37c43753SMarc Zyngier /* 47*37c43753SMarc Zyngier * Convert a kernel VA into a HYP VA. 48*37c43753SMarc Zyngier * reg: VA to be converted. 49*37c43753SMarc Zyngier */ 50*37c43753SMarc Zyngier .macro kern_hyp_va reg 51*37c43753SMarc Zyngier and \reg, \reg, #HYP_PAGE_OFFSET_MASK 52*37c43753SMarc Zyngier .endm 53*37c43753SMarc Zyngier 54*37c43753SMarc Zyngier #else 55*37c43753SMarc Zyngier 56*37c43753SMarc Zyngier #include <asm/cachetype.h> 57*37c43753SMarc Zyngier #include <asm/cacheflush.h> 58*37c43753SMarc Zyngier 59*37c43753SMarc Zyngier #define KERN_TO_HYP(kva) ((unsigned long)kva - PAGE_OFFSET + HYP_PAGE_OFFSET) 60*37c43753SMarc Zyngier 61*37c43753SMarc Zyngier /* 62*37c43753SMarc Zyngier * Align KVM with the kernel's view of physical memory. Should be 63*37c43753SMarc Zyngier * 40bit IPA, with PGD being 8kB aligned in the 4KB page configuration. 64*37c43753SMarc Zyngier */ 65*37c43753SMarc Zyngier #define KVM_PHYS_SHIFT PHYS_MASK_SHIFT 66*37c43753SMarc Zyngier #define KVM_PHYS_SIZE (1UL << KVM_PHYS_SHIFT) 67*37c43753SMarc Zyngier #define KVM_PHYS_MASK (KVM_PHYS_SIZE - 1UL) 68*37c43753SMarc Zyngier 69*37c43753SMarc Zyngier /* Make sure we get the right size, and thus the right alignment */ 70*37c43753SMarc Zyngier #define PTRS_PER_S2_PGD (1 << (KVM_PHYS_SHIFT - PGDIR_SHIFT)) 71*37c43753SMarc Zyngier #define S2_PGD_ORDER get_order(PTRS_PER_S2_PGD * sizeof(pgd_t)) 72*37c43753SMarc Zyngier 73*37c43753SMarc Zyngier int create_hyp_mappings(void *from, void *to); 74*37c43753SMarc Zyngier int create_hyp_io_mappings(void *from, void *to, phys_addr_t); 75*37c43753SMarc Zyngier void free_boot_hyp_pgd(void); 76*37c43753SMarc Zyngier void free_hyp_pgds(void); 77*37c43753SMarc Zyngier 78*37c43753SMarc Zyngier int kvm_alloc_stage2_pgd(struct kvm *kvm); 79*37c43753SMarc Zyngier void kvm_free_stage2_pgd(struct kvm *kvm); 80*37c43753SMarc Zyngier int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa, 81*37c43753SMarc Zyngier phys_addr_t pa, unsigned long size); 82*37c43753SMarc Zyngier 83*37c43753SMarc Zyngier int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run); 84*37c43753SMarc Zyngier 85*37c43753SMarc Zyngier void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu); 86*37c43753SMarc Zyngier 87*37c43753SMarc Zyngier phys_addr_t kvm_mmu_get_httbr(void); 88*37c43753SMarc Zyngier phys_addr_t kvm_mmu_get_boot_httbr(void); 89*37c43753SMarc Zyngier phys_addr_t kvm_get_idmap_vector(void); 90*37c43753SMarc Zyngier int kvm_mmu_init(void); 91*37c43753SMarc Zyngier void kvm_clear_hyp_idmap(void); 92*37c43753SMarc Zyngier 93*37c43753SMarc Zyngier #define kvm_set_pte(ptep, pte) set_pte(ptep, pte) 94*37c43753SMarc Zyngier 95*37c43753SMarc Zyngier static inline bool kvm_is_write_fault(unsigned long esr) 96*37c43753SMarc Zyngier { 97*37c43753SMarc Zyngier unsigned long esr_ec = esr >> ESR_EL2_EC_SHIFT; 98*37c43753SMarc Zyngier 99*37c43753SMarc Zyngier if (esr_ec == ESR_EL2_EC_IABT) 100*37c43753SMarc Zyngier return false; 101*37c43753SMarc Zyngier 102*37c43753SMarc Zyngier if ((esr & ESR_EL2_ISV) && !(esr & ESR_EL2_WNR)) 103*37c43753SMarc Zyngier return false; 104*37c43753SMarc Zyngier 105*37c43753SMarc Zyngier return true; 106*37c43753SMarc Zyngier } 107*37c43753SMarc Zyngier 108*37c43753SMarc Zyngier static inline void kvm_clean_dcache_area(void *addr, size_t size) {} 109*37c43753SMarc Zyngier static inline void kvm_clean_pgd(pgd_t *pgd) {} 110*37c43753SMarc Zyngier static inline void kvm_clean_pmd_entry(pmd_t *pmd) {} 111*37c43753SMarc Zyngier static inline void kvm_clean_pte(pte_t *pte) {} 112*37c43753SMarc Zyngier static inline void kvm_clean_pte_entry(pte_t *pte) {} 113*37c43753SMarc Zyngier 114*37c43753SMarc Zyngier static inline void kvm_set_s2pte_writable(pte_t *pte) 115*37c43753SMarc Zyngier { 116*37c43753SMarc Zyngier pte_val(*pte) |= PTE_S2_RDWR; 117*37c43753SMarc Zyngier } 118*37c43753SMarc Zyngier 119*37c43753SMarc Zyngier struct kvm; 120*37c43753SMarc Zyngier 121*37c43753SMarc Zyngier static inline void coherent_icache_guest_page(struct kvm *kvm, gfn_t gfn) 122*37c43753SMarc Zyngier { 123*37c43753SMarc Zyngier if (!icache_is_aliasing()) { /* PIPT */ 124*37c43753SMarc Zyngier unsigned long hva = gfn_to_hva(kvm, gfn); 125*37c43753SMarc Zyngier flush_icache_range(hva, hva + PAGE_SIZE); 126*37c43753SMarc Zyngier } else if (!icache_is_aivivt()) { /* non ASID-tagged VIVT */ 127*37c43753SMarc Zyngier /* any kind of VIPT cache */ 128*37c43753SMarc Zyngier __flush_icache_all(); 129*37c43753SMarc Zyngier } 130*37c43753SMarc Zyngier } 131*37c43753SMarc Zyngier 132*37c43753SMarc Zyngier #define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l)) 133*37c43753SMarc Zyngier 134*37c43753SMarc Zyngier #endif /* __ASSEMBLY__ */ 135*37c43753SMarc Zyngier #endif /* __ARM64_KVM_MMU_H__ */ 136