.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | | - * This program is free software; you can redistribute it and/or modify |
---|
3 | | - * it under the terms of the GNU General Public License, version 2, as |
---|
4 | | - * published by the Free Software Foundation. |
---|
5 | | - * |
---|
6 | | - * This program is distributed in the hope that it will be useful, |
---|
7 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
8 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
9 | | - * GNU General Public License for more details. |
---|
10 | | - * |
---|
11 | | - * You should have received a copy of the GNU General Public License |
---|
12 | | - * along with this program; if not, write to the Free Software |
---|
13 | | - * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
---|
14 | 3 | * |
---|
15 | 4 | * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> |
---|
16 | 5 | * Copyright 2011 David Gibson, IBM Corporation <dwg@au1.ibm.com> |
---|
.. | .. |
---|
35 | 24 | #include <asm/hvcall.h> |
---|
36 | 25 | #include <asm/synch.h> |
---|
37 | 26 | #include <asm/ppc-opcode.h> |
---|
38 | | -#include <asm/kvm_host.h> |
---|
39 | 27 | #include <asm/udbg.h> |
---|
40 | 28 | #include <asm/iommu.h> |
---|
41 | 29 | #include <asm/tce.h> |
---|
.. | .. |
---|
44 | 32 | #ifdef CONFIG_BUG |
---|
45 | 33 | |
---|
46 | 34 | #define WARN_ON_ONCE_RM(condition) ({ \ |
---|
47 | | - static bool __section(.data.unlikely) __warned; \ |
---|
| 35 | + static bool __section(".data.unlikely") __warned; \ |
---|
48 | 36 | int __ret_warn_once = !!(condition); \ |
---|
49 | 37 | \ |
---|
50 | 38 | if (unlikely(__ret_warn_once && !__warned)) { \ |
---|
.. | .. |
---|
66 | 54 | |
---|
67 | 55 | #endif |
---|
68 | 56 | |
---|
69 | | -#define TCES_PER_PAGE (PAGE_SIZE / sizeof(u64)) |
---|
70 | | - |
---|
71 | 57 | /* |
---|
72 | 58 | * Finds a TCE table descriptor by LIOBN. |
---|
73 | 59 | * |
---|
.. | .. |
---|
87 | 73 | } |
---|
88 | 74 | EXPORT_SYMBOL_GPL(kvmppc_find_table); |
---|
89 | 75 | |
---|
| 76 | +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
---|
| 77 | +static long kvmppc_rm_tce_to_ua(struct kvm *kvm, |
---|
| 78 | + unsigned long tce, unsigned long *ua) |
---|
| 79 | +{ |
---|
| 80 | + unsigned long gfn = tce >> PAGE_SHIFT; |
---|
| 81 | + struct kvm_memory_slot *memslot; |
---|
| 82 | + |
---|
| 83 | + memslot = search_memslots(kvm_memslots_raw(kvm), gfn); |
---|
| 84 | + if (!memslot) |
---|
| 85 | + return -EINVAL; |
---|
| 86 | + |
---|
| 87 | + *ua = __gfn_to_hva_memslot(memslot, gfn) | |
---|
| 88 | + (tce & ~(PAGE_MASK | TCE_PCI_READ | TCE_PCI_WRITE)); |
---|
| 89 | + |
---|
| 90 | + return 0; |
---|
| 91 | +} |
---|
| 92 | + |
---|
90 | 93 | /* |
---|
91 | 94 | * Validates TCE address. |
---|
92 | 95 | * At the moment flags and page mask are validated. |
---|
.. | .. |
---|
94 | 97 | * to the table and user space is supposed to process them), we can skip |
---|
95 | 98 | * checking other things (such as TCE is a guest RAM address or the page |
---|
96 | 99 | * was actually allocated). |
---|
97 | | - * |
---|
98 | | - * WARNING: This will be called in real-mode on HV KVM and virtual |
---|
99 | | - * mode on PR KVM |
---|
100 | 100 | */ |
---|
101 | | -long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt, unsigned long tce) |
---|
| 101 | +static long kvmppc_rm_tce_validate(struct kvmppc_spapr_tce_table *stt, |
---|
| 102 | + unsigned long tce) |
---|
102 | 103 | { |
---|
103 | 104 | unsigned long gpa = tce & ~(TCE_PCI_READ | TCE_PCI_WRITE); |
---|
104 | 105 | enum dma_data_direction dir = iommu_tce_direction(tce); |
---|
| 106 | + struct kvmppc_spapr_tce_iommu_table *stit; |
---|
| 107 | + unsigned long ua = 0; |
---|
105 | 108 | |
---|
106 | 109 | /* Allow userspace to poison TCE table */ |
---|
107 | 110 | if (dir == DMA_NONE) |
---|
.. | .. |
---|
110 | 113 | if (iommu_tce_check_gpa(stt->page_shift, gpa)) |
---|
111 | 114 | return H_PARAMETER; |
---|
112 | 115 | |
---|
| 116 | + if (kvmppc_rm_tce_to_ua(stt->kvm, tce, &ua)) |
---|
| 117 | + return H_TOO_HARD; |
---|
| 118 | + |
---|
| 119 | + list_for_each_entry_lockless(stit, &stt->iommu_tables, next) { |
---|
| 120 | + unsigned long hpa = 0; |
---|
| 121 | + struct mm_iommu_table_group_mem_t *mem; |
---|
| 122 | + long shift = stit->tbl->it_page_shift; |
---|
| 123 | + |
---|
| 124 | + mem = mm_iommu_lookup_rm(stt->kvm->mm, ua, 1ULL << shift); |
---|
| 125 | + if (!mem) |
---|
| 126 | + return H_TOO_HARD; |
---|
| 127 | + |
---|
| 128 | + if (mm_iommu_ua_to_hpa_rm(mem, ua, shift, &hpa)) |
---|
| 129 | + return H_TOO_HARD; |
---|
| 130 | + } |
---|
| 131 | + |
---|
113 | 132 | return H_SUCCESS; |
---|
114 | 133 | } |
---|
115 | | -EXPORT_SYMBOL_GPL(kvmppc_tce_validate); |
---|
116 | 134 | |
---|
117 | 135 | /* Note on the use of page_address() in real mode, |
---|
118 | 136 | * |
---|
.. | .. |
---|
144 | 162 | /* |
---|
145 | 163 | * Handles TCE requests for emulated devices. |
---|
146 | 164 | * Puts guest TCE values to the table and expects user space to convert them. |
---|
147 | | - * Called in both real and virtual modes. |
---|
148 | | - * Cannot fail so kvmppc_tce_validate must be called before it. |
---|
149 | | - * |
---|
150 | | - * WARNING: This will be called in real-mode on HV KVM and virtual |
---|
151 | | - * mode on PR KVM |
---|
| 165 | + * Cannot fail so kvmppc_rm_tce_validate must be called before it. |
---|
152 | 166 | */ |
---|
153 | | -void kvmppc_tce_put(struct kvmppc_spapr_tce_table *stt, |
---|
| 167 | +static void kvmppc_rm_tce_put(struct kvmppc_spapr_tce_table *stt, |
---|
154 | 168 | unsigned long idx, unsigned long tce) |
---|
155 | 169 | { |
---|
156 | 170 | struct page *page; |
---|
.. | .. |
---|
158 | 172 | |
---|
159 | 173 | idx -= stt->offset; |
---|
160 | 174 | page = stt->pages[idx / TCES_PER_PAGE]; |
---|
| 175 | + /* |
---|
| 176 | + * kvmppc_rm_ioba_validate() allows pages not be allocated if TCE is |
---|
| 177 | + * being cleared, otherwise it returns H_TOO_HARD and we skip this. |
---|
| 178 | + */ |
---|
| 179 | + if (!page) { |
---|
| 180 | + WARN_ON_ONCE_RM(tce != 0); |
---|
| 181 | + return; |
---|
| 182 | + } |
---|
161 | 183 | tbl = kvmppc_page_address(page); |
---|
162 | 184 | |
---|
163 | 185 | tbl[idx % TCES_PER_PAGE] = tce; |
---|
164 | 186 | } |
---|
165 | | -EXPORT_SYMBOL_GPL(kvmppc_tce_put); |
---|
166 | 187 | |
---|
167 | | -long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa, |
---|
168 | | - unsigned long *ua, unsigned long **prmap) |
---|
| 188 | +/* |
---|
| 189 | + * TCEs pages are allocated in kvmppc_rm_tce_put() which won't be able to do so |
---|
| 190 | + * in real mode. |
---|
| 191 | + * Check if kvmppc_rm_tce_put() can succeed in real mode, i.e. a TCEs page is |
---|
| 192 | + * allocated or not required (when clearing a tce entry). |
---|
| 193 | + */ |
---|
| 194 | +static long kvmppc_rm_ioba_validate(struct kvmppc_spapr_tce_table *stt, |
---|
| 195 | + unsigned long ioba, unsigned long npages, bool clearing) |
---|
169 | 196 | { |
---|
170 | | - unsigned long gfn = gpa >> PAGE_SHIFT; |
---|
171 | | - struct kvm_memory_slot *memslot; |
---|
| 197 | + unsigned long i, idx, sttpage, sttpages; |
---|
| 198 | + unsigned long ret = kvmppc_ioba_validate(stt, ioba, npages); |
---|
172 | 199 | |
---|
173 | | - memslot = search_memslots(kvm_memslots(kvm), gfn); |
---|
174 | | - if (!memslot) |
---|
175 | | - return -EINVAL; |
---|
| 200 | + if (ret) |
---|
| 201 | + return ret; |
---|
| 202 | + /* |
---|
| 203 | + * clearing==true says kvmppc_rm_tce_put won't be allocating pages |
---|
| 204 | + * for empty tces. |
---|
| 205 | + */ |
---|
| 206 | + if (clearing) |
---|
| 207 | + return H_SUCCESS; |
---|
176 | 208 | |
---|
177 | | - *ua = __gfn_to_hva_memslot(memslot, gfn) | |
---|
178 | | - (gpa & ~(PAGE_MASK | TCE_PCI_READ | TCE_PCI_WRITE)); |
---|
| 209 | + idx = (ioba >> stt->page_shift) - stt->offset; |
---|
| 210 | + sttpage = idx / TCES_PER_PAGE; |
---|
| 211 | + sttpages = ALIGN(idx % TCES_PER_PAGE + npages, TCES_PER_PAGE) / |
---|
| 212 | + TCES_PER_PAGE; |
---|
| 213 | + for (i = sttpage; i < sttpage + sttpages; ++i) |
---|
| 214 | + if (!stt->pages[i]) |
---|
| 215 | + return H_TOO_HARD; |
---|
179 | 216 | |
---|
180 | | -#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
---|
181 | | - if (prmap) |
---|
182 | | - *prmap = &memslot->arch.rmap[gfn - memslot->base_gfn]; |
---|
183 | | -#endif |
---|
184 | | - |
---|
185 | | - return 0; |
---|
| 217 | + return H_SUCCESS; |
---|
186 | 218 | } |
---|
187 | | -EXPORT_SYMBOL_GPL(kvmppc_gpa_to_ua); |
---|
188 | 219 | |
---|
189 | | -#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
---|
190 | | -static long iommu_tce_xchg_rm(struct mm_struct *mm, struct iommu_table *tbl, |
---|
| 220 | +static long iommu_tce_xchg_no_kill_rm(struct mm_struct *mm, |
---|
| 221 | + struct iommu_table *tbl, |
---|
191 | 222 | unsigned long entry, unsigned long *hpa, |
---|
192 | 223 | enum dma_data_direction *direction) |
---|
193 | 224 | { |
---|
194 | 225 | long ret; |
---|
195 | 226 | |
---|
196 | | - ret = tbl->it_ops->exchange_rm(tbl, entry, hpa, direction); |
---|
| 227 | + ret = tbl->it_ops->xchg_no_kill(tbl, entry, hpa, direction, true); |
---|
197 | 228 | |
---|
198 | 229 | if (!ret && ((*direction == DMA_FROM_DEVICE) || |
---|
199 | 230 | (*direction == DMA_BIDIRECTIONAL))) { |
---|
200 | | - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RM(tbl, entry); |
---|
| 231 | + __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); |
---|
201 | 232 | /* |
---|
202 | 233 | * kvmppc_rm_tce_iommu_do_map() updates the UA cache after |
---|
203 | 234 | * calling this so we still get here a valid UA. |
---|
.. | .. |
---|
209 | 240 | return ret; |
---|
210 | 241 | } |
---|
211 | 242 | |
---|
212 | | -static void kvmppc_rm_clear_tce(struct kvm *kvm, struct iommu_table *tbl, |
---|
213 | | - unsigned long entry) |
---|
| 243 | +static void iommu_tce_kill_rm(struct iommu_table *tbl, |
---|
| 244 | + unsigned long entry, unsigned long pages) |
---|
214 | 245 | { |
---|
215 | | - unsigned long hpa = 0; |
---|
216 | | - enum dma_data_direction dir = DMA_NONE; |
---|
| 246 | + if (tbl->it_ops->tce_kill) |
---|
| 247 | + tbl->it_ops->tce_kill(tbl, entry, pages, true); |
---|
| 248 | +} |
---|
217 | 249 | |
---|
218 | | - iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir); |
---|
| 250 | +static void kvmppc_rm_clear_tce(struct kvm *kvm, struct kvmppc_spapr_tce_table *stt, |
---|
| 251 | + struct iommu_table *tbl, unsigned long entry) |
---|
| 252 | +{ |
---|
| 253 | + unsigned long i; |
---|
| 254 | + unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift); |
---|
| 255 | + unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift); |
---|
| 256 | + |
---|
| 257 | + for (i = 0; i < subpages; ++i) { |
---|
| 258 | + unsigned long hpa = 0; |
---|
| 259 | + enum dma_data_direction dir = DMA_NONE; |
---|
| 260 | + |
---|
| 261 | + iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, io_entry + i, &hpa, &dir); |
---|
| 262 | + } |
---|
219 | 263 | } |
---|
220 | 264 | |
---|
221 | 265 | static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm, |
---|
.. | .. |
---|
223 | 267 | { |
---|
224 | 268 | struct mm_iommu_table_group_mem_t *mem = NULL; |
---|
225 | 269 | const unsigned long pgsize = 1ULL << tbl->it_page_shift; |
---|
226 | | - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RM(tbl, entry); |
---|
| 270 | + __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); |
---|
227 | 271 | |
---|
228 | 272 | if (!pua) |
---|
229 | 273 | /* it_userspace allocation might be delayed */ |
---|
.. | .. |
---|
247 | 291 | unsigned long hpa = 0; |
---|
248 | 292 | long ret; |
---|
249 | 293 | |
---|
250 | | - if (iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir)) |
---|
| 294 | + if (iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir)) |
---|
251 | 295 | /* |
---|
252 | 296 | * real mode xchg can fail if struct page crosses |
---|
253 | 297 | * a page boundary |
---|
.. | .. |
---|
259 | 303 | |
---|
260 | 304 | ret = kvmppc_rm_tce_iommu_mapped_dec(kvm, tbl, entry); |
---|
261 | 305 | if (ret) |
---|
262 | | - iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir); |
---|
| 306 | + iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir); |
---|
263 | 307 | |
---|
264 | 308 | return ret; |
---|
265 | 309 | } |
---|
.. | .. |
---|
278 | 322 | break; |
---|
279 | 323 | } |
---|
280 | 324 | |
---|
| 325 | + iommu_tce_kill_rm(tbl, io_entry, subpages); |
---|
| 326 | + |
---|
281 | 327 | return ret; |
---|
282 | 328 | } |
---|
283 | 329 | |
---|
.. | .. |
---|
287 | 333 | { |
---|
288 | 334 | long ret; |
---|
289 | 335 | unsigned long hpa = 0; |
---|
290 | | - __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RM(tbl, entry); |
---|
| 336 | + __be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RO(tbl, entry); |
---|
291 | 337 | struct mm_iommu_table_group_mem_t *mem; |
---|
292 | 338 | |
---|
293 | 339 | if (!pua) |
---|
.. | .. |
---|
305 | 351 | if (WARN_ON_ONCE_RM(mm_iommu_mapped_inc(mem))) |
---|
306 | 352 | return H_TOO_HARD; |
---|
307 | 353 | |
---|
308 | | - ret = iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir); |
---|
| 354 | + ret = iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir); |
---|
309 | 355 | if (ret) { |
---|
310 | 356 | mm_iommu_mapped_dec(mem); |
---|
311 | 357 | /* |
---|
.. | .. |
---|
341 | 387 | break; |
---|
342 | 388 | } |
---|
343 | 389 | |
---|
| 390 | + iommu_tce_kill_rm(tbl, io_entry, subpages); |
---|
| 391 | + |
---|
344 | 392 | return ret; |
---|
345 | 393 | } |
---|
346 | 394 | |
---|
.. | .. |
---|
364 | 412 | if (!stt) |
---|
365 | 413 | return H_TOO_HARD; |
---|
366 | 414 | |
---|
367 | | - ret = kvmppc_ioba_validate(stt, ioba, 1); |
---|
| 415 | + ret = kvmppc_rm_ioba_validate(stt, ioba, 1, tce == 0); |
---|
368 | 416 | if (ret != H_SUCCESS) |
---|
369 | 417 | return ret; |
---|
370 | 418 | |
---|
371 | | - ret = kvmppc_tce_validate(stt, tce); |
---|
| 419 | + ret = kvmppc_rm_tce_validate(stt, tce); |
---|
372 | 420 | if (ret != H_SUCCESS) |
---|
373 | 421 | return ret; |
---|
374 | 422 | |
---|
375 | 423 | dir = iommu_tce_direction(tce); |
---|
376 | | - if ((dir != DMA_NONE) && kvmppc_gpa_to_ua(vcpu->kvm, |
---|
377 | | - tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), &ua, NULL)) |
---|
| 424 | + if ((dir != DMA_NONE) && kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua)) |
---|
378 | 425 | return H_PARAMETER; |
---|
379 | 426 | |
---|
380 | 427 | entry = ioba >> stt->page_shift; |
---|
.. | .. |
---|
387 | 434 | ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt, |
---|
388 | 435 | stit->tbl, entry, ua, dir); |
---|
389 | 436 | |
---|
390 | | - if (ret == H_SUCCESS) |
---|
391 | | - continue; |
---|
392 | | - |
---|
393 | | - if (ret == H_TOO_HARD) |
---|
| 437 | + if (ret != H_SUCCESS) { |
---|
| 438 | + kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry); |
---|
394 | 439 | return ret; |
---|
395 | | - |
---|
396 | | - WARN_ON_ONCE_RM(1); |
---|
397 | | - kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); |
---|
| 440 | + } |
---|
398 | 441 | } |
---|
399 | 442 | |
---|
400 | | - kvmppc_tce_put(stt, entry, tce); |
---|
| 443 | + kvmppc_rm_tce_put(stt, entry, tce); |
---|
401 | 444 | |
---|
402 | 445 | return H_SUCCESS; |
---|
403 | 446 | } |
---|
404 | 447 | |
---|
405 | | -static long kvmppc_rm_ua_to_hpa(struct kvm_vcpu *vcpu, |
---|
406 | | - unsigned long ua, unsigned long *phpa) |
---|
| 448 | +static long kvmppc_rm_ua_to_hpa(struct kvm_vcpu *vcpu, unsigned long mmu_seq, |
---|
| 449 | + unsigned long ua, unsigned long *phpa) |
---|
407 | 450 | { |
---|
408 | 451 | pte_t *ptep, pte; |
---|
409 | 452 | unsigned shift = 0; |
---|
.. | .. |
---|
417 | 460 | * to exit which will agains result in the below page table walk |
---|
418 | 461 | * to finish. |
---|
419 | 462 | */ |
---|
420 | | - ptep = __find_linux_pte(vcpu->arch.pgdir, ua, NULL, &shift); |
---|
421 | | - if (!ptep || !pte_present(*ptep)) |
---|
| 463 | + /* an rmap lock won't make it safe. because that just ensure hash |
---|
| 464 | + * page table entries are removed with rmap lock held. After that |
---|
| 465 | + * mmu notifier returns and we go ahead and removing ptes from Qemu page table. |
---|
| 466 | + */ |
---|
| 467 | + ptep = find_kvm_host_pte(vcpu->kvm, mmu_seq, ua, &shift); |
---|
| 468 | + if (!ptep) |
---|
422 | 469 | return -ENXIO; |
---|
423 | | - pte = *ptep; |
---|
| 470 | + |
---|
| 471 | + pte = READ_ONCE(*ptep); |
---|
| 472 | + if (!pte_present(pte)) |
---|
| 473 | + return -ENXIO; |
---|
424 | 474 | |
---|
425 | 475 | if (!shift) |
---|
426 | 476 | shift = PAGE_SHIFT; |
---|
.. | .. |
---|
442 | 492 | unsigned long liobn, unsigned long ioba, |
---|
443 | 493 | unsigned long tce_list, unsigned long npages) |
---|
444 | 494 | { |
---|
| 495 | + struct kvm *kvm = vcpu->kvm; |
---|
445 | 496 | struct kvmppc_spapr_tce_table *stt; |
---|
446 | 497 | long i, ret = H_SUCCESS; |
---|
447 | 498 | unsigned long tces, entry, ua = 0; |
---|
448 | | - unsigned long *rmap = NULL; |
---|
| 499 | + unsigned long mmu_seq; |
---|
449 | 500 | bool prereg = false; |
---|
450 | 501 | struct kvmppc_spapr_tce_iommu_table *stit; |
---|
451 | 502 | |
---|
452 | 503 | /* For radix, we might be in virtual mode, so punt */ |
---|
453 | 504 | if (kvm_is_radix(vcpu->kvm)) |
---|
454 | 505 | return H_TOO_HARD; |
---|
| 506 | + |
---|
| 507 | + /* |
---|
| 508 | + * used to check for invalidations in progress |
---|
| 509 | + */ |
---|
| 510 | + mmu_seq = kvm->mmu_notifier_seq; |
---|
| 511 | + smp_rmb(); |
---|
455 | 512 | |
---|
456 | 513 | stt = kvmppc_find_table(vcpu->kvm, liobn); |
---|
457 | 514 | if (!stt) |
---|
.. | .. |
---|
468 | 525 | if (tce_list & (SZ_4K - 1)) |
---|
469 | 526 | return H_PARAMETER; |
---|
470 | 527 | |
---|
471 | | - ret = kvmppc_ioba_validate(stt, ioba, npages); |
---|
| 528 | + ret = kvmppc_rm_ioba_validate(stt, ioba, npages, false); |
---|
472 | 529 | if (ret != H_SUCCESS) |
---|
473 | 530 | return ret; |
---|
474 | 531 | |
---|
.. | .. |
---|
480 | 537 | */ |
---|
481 | 538 | struct mm_iommu_table_group_mem_t *mem; |
---|
482 | 539 | |
---|
483 | | - if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, NULL)) |
---|
| 540 | + if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce_list, &ua)) |
---|
484 | 541 | return H_TOO_HARD; |
---|
485 | 542 | |
---|
486 | 543 | mem = mm_iommu_lookup_rm(vcpu->kvm->mm, ua, IOMMU_PAGE_SIZE_4K); |
---|
.. | .. |
---|
496 | 553 | * We do not require memory to be preregistered in this case |
---|
497 | 554 | * so lock rmap and do __find_linux_pte_or_hugepte(). |
---|
498 | 555 | */ |
---|
499 | | - if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, &rmap)) |
---|
| 556 | + if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce_list, &ua)) |
---|
500 | 557 | return H_TOO_HARD; |
---|
501 | 558 | |
---|
502 | | - rmap = (void *) vmalloc_to_phys(rmap); |
---|
503 | | - if (WARN_ON_ONCE_RM(!rmap)) |
---|
504 | | - return H_TOO_HARD; |
---|
505 | | - |
---|
506 | | - /* |
---|
507 | | - * Synchronize with the MMU notifier callbacks in |
---|
508 | | - * book3s_64_mmu_hv.c (kvm_unmap_hva_range_hv etc.). |
---|
509 | | - * While we have the rmap lock, code running on other CPUs |
---|
510 | | - * cannot finish unmapping the host real page that backs |
---|
511 | | - * this guest real page, so we are OK to access the host |
---|
512 | | - * real page. |
---|
513 | | - */ |
---|
514 | | - lock_rmap(rmap); |
---|
515 | | - if (kvmppc_rm_ua_to_hpa(vcpu, ua, &tces)) { |
---|
| 559 | + arch_spin_lock(&kvm->mmu_lock.rlock.raw_lock); |
---|
| 560 | + if (kvmppc_rm_ua_to_hpa(vcpu, mmu_seq, ua, &tces)) { |
---|
516 | 561 | ret = H_TOO_HARD; |
---|
517 | 562 | goto unlock_exit; |
---|
518 | 563 | } |
---|
.. | .. |
---|
521 | 566 | for (i = 0; i < npages; ++i) { |
---|
522 | 567 | unsigned long tce = be64_to_cpu(((u64 *)tces)[i]); |
---|
523 | 568 | |
---|
524 | | - ret = kvmppc_tce_validate(stt, tce); |
---|
| 569 | + ret = kvmppc_rm_tce_validate(stt, tce); |
---|
525 | 570 | if (ret != H_SUCCESS) |
---|
526 | 571 | goto unlock_exit; |
---|
| 572 | + } |
---|
| 573 | + |
---|
| 574 | + for (i = 0; i < npages; ++i) { |
---|
| 575 | + unsigned long tce = be64_to_cpu(((u64 *)tces)[i]); |
---|
527 | 576 | |
---|
528 | 577 | ua = 0; |
---|
529 | | - if (kvmppc_gpa_to_ua(vcpu->kvm, |
---|
530 | | - tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), |
---|
531 | | - &ua, NULL)) { |
---|
| 578 | + if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua)) { |
---|
532 | 579 | ret = H_PARAMETER; |
---|
533 | 580 | goto unlock_exit; |
---|
534 | 581 | } |
---|
.. | .. |
---|
538 | 585 | stit->tbl, entry + i, ua, |
---|
539 | 586 | iommu_tce_direction(tce)); |
---|
540 | 587 | |
---|
541 | | - if (ret == H_SUCCESS) |
---|
542 | | - continue; |
---|
543 | | - |
---|
544 | | - if (ret == H_TOO_HARD) |
---|
| 588 | + if (ret != H_SUCCESS) { |
---|
| 589 | + kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, |
---|
| 590 | + entry + i); |
---|
545 | 591 | goto unlock_exit; |
---|
546 | | - |
---|
547 | | - WARN_ON_ONCE_RM(1); |
---|
548 | | - kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); |
---|
| 592 | + } |
---|
549 | 593 | } |
---|
550 | 594 | |
---|
551 | | - kvmppc_tce_put(stt, entry + i, tce); |
---|
| 595 | + kvmppc_rm_tce_put(stt, entry + i, tce); |
---|
552 | 596 | } |
---|
553 | 597 | |
---|
554 | 598 | unlock_exit: |
---|
555 | | - if (rmap) |
---|
556 | | - unlock_rmap(rmap); |
---|
557 | | - |
---|
| 599 | + if (!prereg) |
---|
| 600 | + arch_spin_unlock(&kvm->mmu_lock.rlock.raw_lock); |
---|
558 | 601 | return ret; |
---|
559 | 602 | } |
---|
560 | 603 | |
---|
.. | .. |
---|
574 | 617 | if (!stt) |
---|
575 | 618 | return H_TOO_HARD; |
---|
576 | 619 | |
---|
577 | | - ret = kvmppc_ioba_validate(stt, ioba, npages); |
---|
| 620 | + ret = kvmppc_rm_ioba_validate(stt, ioba, npages, tce_value == 0); |
---|
578 | 621 | if (ret != H_SUCCESS) |
---|
579 | 622 | return ret; |
---|
580 | 623 | |
---|
.. | .. |
---|
596 | 639 | return ret; |
---|
597 | 640 | |
---|
598 | 641 | WARN_ON_ONCE_RM(1); |
---|
599 | | - kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry); |
---|
| 642 | + kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry + i); |
---|
600 | 643 | } |
---|
601 | 644 | } |
---|
602 | 645 | |
---|
603 | 646 | for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift)) |
---|
604 | | - kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value); |
---|
| 647 | + kvmppc_rm_tce_put(stt, ioba >> stt->page_shift, tce_value); |
---|
605 | 648 | |
---|
606 | | - return H_SUCCESS; |
---|
| 649 | + return ret; |
---|
607 | 650 | } |
---|
608 | 651 | |
---|
609 | 652 | /* This can be called in either virtual mode or real mode */ |
---|
.. | .. |
---|
626 | 669 | |
---|
627 | 670 | idx = (ioba >> stt->page_shift) - stt->offset; |
---|
628 | 671 | page = stt->pages[idx / TCES_PER_PAGE]; |
---|
| 672 | + if (!page) { |
---|
| 673 | + vcpu->arch.regs.gpr[4] = 0; |
---|
| 674 | + return H_SUCCESS; |
---|
| 675 | + } |
---|
629 | 676 | tbl = (u64 *)page_address(page); |
---|
630 | 677 | |
---|
631 | 678 | vcpu->arch.regs.gpr[4] = tbl[idx % TCES_PER_PAGE]; |
---|