1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Original code:
4  * Copyright (C) 2012 - Virtual Open Systems and Columbia University
5  * Author: Christoffer Dall <c.dall@virtualopensystems.com>
6  *
7  * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.com>
8  */
9 
10 #include <asm/kvm_hyp.h>
11 #include <asm/kvm_mmu.h>
12 
13 /**
14  * Flush per-VMID TLBs
15  *
16  * __kvm_tlb_flush_vmid(struct kvm *kvm);
17  *
18  * We rely on the hardware to broadcast the TLB invalidation to all CPUs
19  * inside the inner-shareable domain (which is the case for all v7
20  * implementations).  If we come across a non-IS SMP implementation, we'll
21  * have to use an IPI based mechanism. Until then, we stick to the simple
22  * hardware assisted version.
23  *
24  * As v7 does not support flushing per IPA, just nuke the whole TLB
25  * instead, ignoring the ipa value.
26  */
__kvm_tlb_flush_vmid(struct kvm * kvm)27 void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
28 {
29 	dsb(ishst);
30 
31 	/* Switch to requested VMID */
32 	kvm = kern_hyp_va(kvm);
33 	write_sysreg(kvm_get_vttbr(kvm), VTTBR);
34 	isb();
35 
36 	write_sysreg(0, TLBIALLIS);
37 	dsb(ish);
38 	isb();
39 
40 	write_sysreg(0, VTTBR);
41 }
42 
__kvm_tlb_flush_vmid_ipa(struct kvm * kvm,phys_addr_t ipa)43 void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
44 {
45 	__kvm_tlb_flush_vmid(kvm);
46 }
47 
__kvm_tlb_flush_local_vmid(struct kvm_vcpu * vcpu)48 void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
49 {
50 	struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
51 
52 	/* Switch to requested VMID */
53 	write_sysreg(kvm_get_vttbr(kvm), VTTBR);
54 	isb();
55 
56 	write_sysreg(0, TLBIALL);
57 	dsb(nsh);
58 	isb();
59 
60 	write_sysreg(0, VTTBR);
61 }
62 
__kvm_flush_vm_context(void)63 void __hyp_text __kvm_flush_vm_context(void)
64 {
65 	write_sysreg(0, TLBIALLNSNHIS);
66 	write_sysreg(0, ICIALLUIS);
67 	dsb(ish);
68 }
69