Merge tag 'drm-next-2018-12-27' of git://anongit.freedesktop.org/drm/drm
[sfrench/cifs-2.6.git] / arch / arm64 / kvm / hyp / tlb.c
1 /*
2  * Copyright (C) 2015 - ARM Ltd
3  * Author: Marc Zyngier <marc.zyngier@arm.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <linux/irqflags.h>
19
20 #include <asm/kvm_hyp.h>
21 #include <asm/kvm_mmu.h>
22 #include <asm/tlbflush.h>
23
24 struct tlb_inv_context {
25         unsigned long   flags;
26         u64             tcr;
27         u64             sctlr;
28 };
29
30 static void __hyp_text __tlb_switch_to_guest_vhe(struct kvm *kvm,
31                                                  struct tlb_inv_context *cxt)
32 {
33         u64 val;
34
35         local_irq_save(cxt->flags);
36
37         if (cpus_have_const_cap(ARM64_WORKAROUND_1165522)) {
38                 /*
39                  * For CPUs that are affected by ARM erratum 1165522, we
40                  * cannot trust stage-1 to be in a correct state at that
41                  * point. Since we do not want to force a full load of the
42                  * vcpu state, we prevent the EL1 page-table walker to
43                  * allocate new TLBs. This is done by setting the EPD bits
44                  * in the TCR_EL1 register. We also need to prevent it to
45                  * allocate IPA->PA walks, so we enable the S1 MMU...
46                  */
47                 val = cxt->tcr = read_sysreg_el1(tcr);
48                 val |= TCR_EPD1_MASK | TCR_EPD0_MASK;
49                 write_sysreg_el1(val, tcr);
50                 val = cxt->sctlr = read_sysreg_el1(sctlr);
51                 val |= SCTLR_ELx_M;
52                 write_sysreg_el1(val, sctlr);
53         }
54
55         /*
56          * With VHE enabled, we have HCR_EL2.{E2H,TGE} = {1,1}, and
57          * most TLB operations target EL2/EL0. In order to affect the
58          * guest TLBs (EL1/EL0), we need to change one of these two
59          * bits. Changing E2H is impossible (goodbye TTBR1_EL2), so
60          * let's flip TGE before executing the TLB operation.
61          *
62          * ARM erratum 1165522 requires some special handling (again),
63          * as we need to make sure both stages of translation are in
64          * place before clearing TGE. __load_guest_stage2() already
65          * has an ISB in order to deal with this.
66          */
67         __load_guest_stage2(kvm);
68         val = read_sysreg(hcr_el2);
69         val &= ~HCR_TGE;
70         write_sysreg(val, hcr_el2);
71         isb();
72 }
73
74 static void __hyp_text __tlb_switch_to_guest_nvhe(struct kvm *kvm,
75                                                   struct tlb_inv_context *cxt)
76 {
77         __load_guest_stage2(kvm);
78         isb();
79 }
80
81 static hyp_alternate_select(__tlb_switch_to_guest,
82                             __tlb_switch_to_guest_nvhe,
83                             __tlb_switch_to_guest_vhe,
84                             ARM64_HAS_VIRT_HOST_EXTN);
85
86 static void __hyp_text __tlb_switch_to_host_vhe(struct kvm *kvm,
87                                                 struct tlb_inv_context *cxt)
88 {
89         /*
90          * We're done with the TLB operation, let's restore the host's
91          * view of HCR_EL2.
92          */
93         write_sysreg(0, vttbr_el2);
94         write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
95         isb();
96
97         if (cpus_have_const_cap(ARM64_WORKAROUND_1165522)) {
98                 /* Restore the registers to what they were */
99                 write_sysreg_el1(cxt->tcr, tcr);
100                 write_sysreg_el1(cxt->sctlr, sctlr);
101         }
102
103         local_irq_restore(cxt->flags);
104 }
105
106 static void __hyp_text __tlb_switch_to_host_nvhe(struct kvm *kvm,
107                                                  struct tlb_inv_context *cxt)
108 {
109         write_sysreg(0, vttbr_el2);
110 }
111
112 static hyp_alternate_select(__tlb_switch_to_host,
113                             __tlb_switch_to_host_nvhe,
114                             __tlb_switch_to_host_vhe,
115                             ARM64_HAS_VIRT_HOST_EXTN);
116
117 void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
118 {
119         struct tlb_inv_context cxt;
120
121         dsb(ishst);
122
123         /* Switch to requested VMID */
124         kvm = kern_hyp_va(kvm);
125         __tlb_switch_to_guest()(kvm, &cxt);
126
127         /*
128          * We could do so much better if we had the VA as well.
129          * Instead, we invalidate Stage-2 for this IPA, and the
130          * whole of Stage-1. Weep...
131          */
132         ipa >>= 12;
133         __tlbi(ipas2e1is, ipa);
134
135         /*
136          * We have to ensure completion of the invalidation at Stage-2,
137          * since a table walk on another CPU could refill a TLB with a
138          * complete (S1 + S2) walk based on the old Stage-2 mapping if
139          * the Stage-1 invalidation happened first.
140          */
141         dsb(ish);
142         __tlbi(vmalle1is);
143         dsb(ish);
144         isb();
145
146         /*
147          * If the host is running at EL1 and we have a VPIPT I-cache,
148          * then we must perform I-cache maintenance at EL2 in order for
149          * it to have an effect on the guest. Since the guest cannot hit
150          * I-cache lines allocated with a different VMID, we don't need
151          * to worry about junk out of guest reset (we nuke the I-cache on
152          * VMID rollover), but we do need to be careful when remapping
153          * executable pages for the same guest. This can happen when KSM
154          * takes a CoW fault on an executable page, copies the page into
155          * a page that was previously mapped in the guest and then needs
156          * to invalidate the guest view of the I-cache for that page
157          * from EL1. To solve this, we invalidate the entire I-cache when
158          * unmapping a page from a guest if we have a VPIPT I-cache but
159          * the host is running at EL1. As above, we could do better if
160          * we had the VA.
161          *
162          * The moral of this story is: if you have a VPIPT I-cache, then
163          * you should be running with VHE enabled.
164          */
165         if (!has_vhe() && icache_is_vpipt())
166                 __flush_icache_all();
167
168         __tlb_switch_to_host()(kvm, &cxt);
169 }
170
171 void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
172 {
173         struct tlb_inv_context cxt;
174
175         dsb(ishst);
176
177         /* Switch to requested VMID */
178         kvm = kern_hyp_va(kvm);
179         __tlb_switch_to_guest()(kvm, &cxt);
180
181         __tlbi(vmalls12e1is);
182         dsb(ish);
183         isb();
184
185         __tlb_switch_to_host()(kvm, &cxt);
186 }
187
188 void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
189 {
190         struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
191         struct tlb_inv_context cxt;
192
193         /* Switch to requested VMID */
194         __tlb_switch_to_guest()(kvm, &cxt);
195
196         __tlbi(vmalle1);
197         dsb(nsh);
198         isb();
199
200         __tlb_switch_to_host()(kvm, &cxt);
201 }
202
203 void __hyp_text __kvm_flush_vm_context(void)
204 {
205         dsb(ishst);
206         __tlbi(alle1is);
207         asm volatile("ic ialluis" : : );
208         dsb(ish);
209 }