GNU Linux-libre 5.4.274-gnu1
[releases.git] / arch / arm / kvm / hyp / tlb.c
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  */
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
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
48 void __hyp_text __kvm_flush_cpu_context(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         write_sysreg(0, ICIALLU);
58         dsb(nsh);
59         isb();
60
61         write_sysreg(0, VTTBR);
62 }
63
64 void __hyp_text __kvm_flush_vm_context(void)
65 {
66         write_sysreg(0, TLBIALLNSNHIS);
67         write_sysreg(0, ICIALLUIS);
68         dsb(ish);
69 }