habanalabs: replace WARN/WARN_ON with dev_crit in driver
[linux-block.git] / drivers / misc / habanalabs / common / mmu.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4  * Copyright 2016-2020 HabanaLabs, Ltd.
5  * All Rights Reserved.
6  */
7
8 #include <linux/slab.h>
9
10 #include "habanalabs.h"
11
12 bool hl_is_dram_va(struct hl_device *hdev, u64 virt_addr)
13 {
14         struct asic_fixed_properties *prop = &hdev->asic_prop;
15
16         return hl_mem_area_inside_range(virt_addr, prop->dmmu.page_size,
17                                         prop->dmmu.start_addr,
18                                         prop->dmmu.end_addr);
19 }
20
21 /**
22  * hl_mmu_init() - initialize the MMU module.
23  * @hdev: habanalabs device structure.
24  *
25  * Return: 0 for success, non-zero for failure.
26  */
27 int hl_mmu_init(struct hl_device *hdev)
28 {
29         int rc = -EOPNOTSUPP;
30
31         if (!hdev->mmu_enable)
32                 return 0;
33
34         if (hdev->mmu_func[MMU_DR_PGT].init != NULL) {
35                 rc = hdev->mmu_func[MMU_DR_PGT].init(hdev);
36                 if (rc)
37                         return rc;
38         }
39
40         if (hdev->mmu_func[MMU_HR_PGT].init != NULL)
41                 rc = hdev->mmu_func[MMU_HR_PGT].init(hdev);
42
43         return rc;
44 }
45
46 /**
47  * hl_mmu_fini() - release the MMU module.
48  * @hdev: habanalabs device structure.
49  *
50  * This function does the following:
51  * - Disable MMU in H/W.
52  * - Free the pgt_infos pool.
53  *
54  * All contexts should be freed before calling this function.
55  */
56 void hl_mmu_fini(struct hl_device *hdev)
57 {
58         if (!hdev->mmu_enable)
59                 return;
60
61         if (hdev->mmu_func[MMU_DR_PGT].fini != NULL)
62                 hdev->mmu_func[MMU_DR_PGT].fini(hdev);
63
64         if (hdev->mmu_func[MMU_HR_PGT].fini != NULL)
65                 hdev->mmu_func[MMU_HR_PGT].fini(hdev);
66 }
67
68 /**
69  * hl_mmu_ctx_init() - initialize a context for using the MMU module.
70  * @ctx: pointer to the context structure to initialize.
71  *
72  * Initialize a mutex to protect the concurrent mapping flow, a hash to hold all
73  * page tables hops related to this context.
74  * Return: 0 on success, non-zero otherwise.
75  */
76 int hl_mmu_ctx_init(struct hl_ctx *ctx)
77 {
78         struct hl_device *hdev = ctx->hdev;
79         int rc = -EOPNOTSUPP;
80
81         if (!hdev->mmu_enable)
82                 return 0;
83
84         mutex_init(&ctx->mmu_lock);
85
86         if (hdev->mmu_func[MMU_DR_PGT].ctx_init != NULL) {
87                 rc = hdev->mmu_func[MMU_DR_PGT].ctx_init(ctx);
88                 if (rc)
89                         return rc;
90         }
91
92         if (hdev->mmu_func[MMU_HR_PGT].ctx_init != NULL)
93                 rc = hdev->mmu_func[MMU_HR_PGT].ctx_init(ctx);
94
95         return rc;
96 }
97
98 /*
99  * hl_mmu_ctx_fini - disable a ctx from using the mmu module
100  *
101  * @ctx: pointer to the context structure
102  *
103  * This function does the following:
104  * - Free any pgts which were not freed yet
105  * - Free the mutex
106  * - Free DRAM default page mapping hops
107  */
108 void hl_mmu_ctx_fini(struct hl_ctx *ctx)
109 {
110         struct hl_device *hdev = ctx->hdev;
111
112         if (!hdev->mmu_enable)
113                 return;
114
115         if (hdev->mmu_func[MMU_DR_PGT].ctx_fini != NULL)
116                 hdev->mmu_func[MMU_DR_PGT].ctx_fini(ctx);
117
118         if (hdev->mmu_func[MMU_HR_PGT].ctx_fini != NULL)
119                 hdev->mmu_func[MMU_HR_PGT].ctx_fini(ctx);
120
121         mutex_destroy(&ctx->mmu_lock);
122 }
123
124 /*
125  * hl_mmu_unmap_page - unmaps a virtual addr
126  *
127  * @ctx: pointer to the context structure
128  * @virt_addr: virt addr to map from
129  * @page_size: size of the page to unmap
130  * @flush_pte: whether to do a PCI flush
131  *
132  * This function does the following:
133  * - Check that the virt addr is mapped
134  * - Unmap the virt addr and frees pgts if possible
135  * - Returns 0 on success, -EINVAL if the given addr is not mapped
136  *
137  * Because this function changes the page tables in the device and because it
138  * changes the MMU hash, it must be protected by a lock.
139  * However, because it maps only a single page, the lock should be implemented
140  * in a higher level in order to protect the entire mapping of the memory area
141  *
142  * For optimization reasons PCI flush may be requested once after unmapping of
143  * large area.
144  */
145 int hl_mmu_unmap_page(struct hl_ctx *ctx, u64 virt_addr, u32 page_size,
146                 bool flush_pte)
147 {
148         struct hl_device *hdev = ctx->hdev;
149         struct asic_fixed_properties *prop = &hdev->asic_prop;
150         struct hl_mmu_properties *mmu_prop;
151         u64 real_virt_addr;
152         u32 real_page_size, npages;
153         int i, rc = 0, pgt_residency;
154         bool is_dram_addr;
155
156         if (!hdev->mmu_enable)
157                 return 0;
158
159         is_dram_addr = hl_is_dram_va(hdev, virt_addr);
160
161         if (is_dram_addr)
162                 mmu_prop = &prop->dmmu;
163         else if ((page_size % prop->pmmu_huge.page_size) == 0)
164                 mmu_prop = &prop->pmmu_huge;
165         else
166                 mmu_prop = &prop->pmmu;
167
168         pgt_residency = mmu_prop->host_resident ? MMU_HR_PGT : MMU_DR_PGT;
169
170         /*
171          * The H/W handles mapping of specific page sizes. Hence if the page
172          * size is bigger, we break it to sub-pages and unmap them separately.
173          */
174         if ((page_size % mmu_prop->page_size) == 0) {
175                 real_page_size = mmu_prop->page_size;
176         } else {
177                 dev_err(hdev->dev,
178                         "page size of %u is not %uKB aligned, can't unmap\n",
179                         page_size, mmu_prop->page_size >> 10);
180
181                 return -EFAULT;
182         }
183
184         npages = page_size / real_page_size;
185         real_virt_addr = virt_addr;
186
187         for (i = 0 ; i < npages ; i++) {
188                 rc = hdev->mmu_func[pgt_residency].unmap(ctx,
189                                                 real_virt_addr, is_dram_addr);
190                 if (rc)
191                         break;
192
193                 real_virt_addr += real_page_size;
194         }
195
196         if (flush_pte)
197                 hdev->mmu_func[pgt_residency].flush(ctx);
198
199         return rc;
200 }
201
202 /*
203  * hl_mmu_map_page - maps a virtual addr to physical addr
204  *
205  * @ctx: pointer to the context structure
206  * @virt_addr: virt addr to map from
207  * @phys_addr: phys addr to map to
208  * @page_size: physical page size
209  * @flush_pte: whether to do a PCI flush
210  *
211  * This function does the following:
212  * - Check that the virt addr is not mapped
213  * - Allocate pgts as necessary in order to map the virt addr to the phys
214  * - Returns 0 on success, -EINVAL if addr is already mapped, or -ENOMEM.
215  *
216  * Because this function changes the page tables in the device and because it
217  * changes the MMU hash, it must be protected by a lock.
218  * However, because it maps only a single page, the lock should be implemented
219  * in a higher level in order to protect the entire mapping of the memory area
220  *
221  * For optimization reasons PCI flush may be requested once after mapping of
222  * large area.
223  */
224 int hl_mmu_map_page(struct hl_ctx *ctx, u64 virt_addr, u64 phys_addr,
225                 u32 page_size, bool flush_pte)
226 {
227         struct hl_device *hdev = ctx->hdev;
228         struct asic_fixed_properties *prop = &hdev->asic_prop;
229         struct hl_mmu_properties *mmu_prop;
230         u64 real_virt_addr, real_phys_addr;
231         u32 real_page_size, npages;
232         int i, rc, pgt_residency, mapped_cnt = 0;
233         bool is_dram_addr;
234
235
236         if (!hdev->mmu_enable)
237                 return 0;
238
239         is_dram_addr = hl_is_dram_va(hdev, virt_addr);
240
241         if (is_dram_addr)
242                 mmu_prop = &prop->dmmu;
243         else if ((page_size % prop->pmmu_huge.page_size) == 0)
244                 mmu_prop = &prop->pmmu_huge;
245         else
246                 mmu_prop = &prop->pmmu;
247
248         pgt_residency = mmu_prop->host_resident ? MMU_HR_PGT : MMU_DR_PGT;
249
250         /*
251          * The H/W handles mapping of specific page sizes. Hence if the page
252          * size is bigger, we break it to sub-pages and map them separately.
253          */
254         if ((page_size % mmu_prop->page_size) == 0) {
255                 real_page_size = mmu_prop->page_size;
256         } else {
257                 dev_err(hdev->dev,
258                         "page size of %u is not %uKB aligned, can't map\n",
259                         page_size, mmu_prop->page_size >> 10);
260
261                 return -EFAULT;
262         }
263
264         if (phys_addr & (real_page_size - 1))
265                 dev_crit(hdev->dev,
266                         "Mapping 0x%llx with page size of 0x%x is erroneous! Address must be divisible by page size",
267                         phys_addr, real_page_size);
268
269         npages = page_size / real_page_size;
270         real_virt_addr = virt_addr;
271         real_phys_addr = phys_addr;
272
273         for (i = 0 ; i < npages ; i++) {
274                 rc = hdev->mmu_func[pgt_residency].map(ctx,
275                                                 real_virt_addr, real_phys_addr,
276                                                 real_page_size, is_dram_addr);
277                 if (rc)
278                         goto err;
279
280                 real_virt_addr += real_page_size;
281                 real_phys_addr += real_page_size;
282                 mapped_cnt++;
283         }
284
285         if (flush_pte)
286                 hdev->mmu_func[pgt_residency].flush(ctx);
287
288         return 0;
289
290 err:
291         real_virt_addr = virt_addr;
292         for (i = 0 ; i < mapped_cnt ; i++) {
293                 if (hdev->mmu_func[pgt_residency].unmap(ctx,
294                                                 real_virt_addr, is_dram_addr))
295                         dev_warn_ratelimited(hdev->dev,
296                                 "failed to unmap va: 0x%llx\n", real_virt_addr);
297
298                 real_virt_addr += real_page_size;
299         }
300
301         hdev->mmu_func[pgt_residency].flush(ctx);
302
303         return rc;
304 }
305
306 /*
307  * hl_mmu_map_contiguous - implements a wrapper for hl_mmu_map_page
308  *                         for mapping contiguous physical memory
309  *
310  * @ctx: pointer to the context structure
311  * @virt_addr: virt addr to map from
312  * @phys_addr: phys addr to map to
313  * @size: size to map
314  *
315  */
316 int hl_mmu_map_contiguous(struct hl_ctx *ctx, u64 virt_addr,
317                                         u64 phys_addr, u32 size)
318 {
319         struct hl_device *hdev = ctx->hdev;
320         struct asic_fixed_properties *prop = &hdev->asic_prop;
321         u64 curr_va, curr_pa;
322         u32 page_size;
323         bool flush_pte;
324         int rc = 0, off;
325
326         if (hl_mem_area_inside_range(virt_addr, size,
327                         prop->dmmu.start_addr, prop->dmmu.end_addr))
328                 page_size = prop->dmmu.page_size;
329         else if (hl_mem_area_inside_range(virt_addr, size,
330                         prop->pmmu.start_addr, prop->pmmu.end_addr))
331                 page_size = prop->pmmu.page_size;
332         else if (hl_mem_area_inside_range(virt_addr, size,
333                         prop->pmmu_huge.start_addr, prop->pmmu_huge.end_addr))
334                 page_size = prop->pmmu_huge.page_size;
335         else
336                 return -EINVAL;
337
338         for (off = 0 ; off < size ; off += page_size) {
339                 curr_va = virt_addr + off;
340                 curr_pa = phys_addr + off;
341                 flush_pte = (off + page_size) >= size;
342                 rc = hl_mmu_map_page(ctx, curr_va, curr_pa, page_size,
343                                                                 flush_pte);
344                 if (rc) {
345                         dev_err(hdev->dev,
346                                 "Map failed for va 0x%llx to pa 0x%llx\n",
347                                 curr_va, curr_pa);
348                         goto unmap;
349                 }
350         }
351
352         return rc;
353
354 unmap:
355         for (; off >= 0 ; off -= page_size) {
356                 curr_va = virt_addr + off;
357                 flush_pte = (off - (s32) page_size) < 0;
358                 if (hl_mmu_unmap_page(ctx, curr_va, page_size, flush_pte))
359                         dev_warn_ratelimited(hdev->dev,
360                                 "failed to unmap va 0x%llx\n", curr_va);
361         }
362
363         return rc;
364 }
365
366 /*
367  * hl_mmu_unmap_contiguous - implements a wrapper for hl_mmu_unmap_page
368  *                           for unmapping contiguous physical memory
369  *
370  * @ctx: pointer to the context structure
371  * @virt_addr: virt addr to unmap
372  * @size: size to unmap
373  *
374  */
375 int hl_mmu_unmap_contiguous(struct hl_ctx *ctx, u64 virt_addr, u32 size)
376 {
377         struct hl_device *hdev = ctx->hdev;
378         struct asic_fixed_properties *prop = &hdev->asic_prop;
379         u64 curr_va;
380         u32 page_size;
381         bool flush_pte;
382         int rc = 0, off;
383
384         if (hl_mem_area_inside_range(virt_addr, size,
385                         prop->dmmu.start_addr, prop->dmmu.end_addr))
386                 page_size = prop->dmmu.page_size;
387         else if (hl_mem_area_inside_range(virt_addr, size,
388                         prop->pmmu.start_addr, prop->pmmu.end_addr))
389                 page_size = prop->pmmu.page_size;
390         else if (hl_mem_area_inside_range(virt_addr, size,
391                         prop->pmmu_huge.start_addr, prop->pmmu_huge.end_addr))
392                 page_size = prop->pmmu_huge.page_size;
393         else
394                 return -EINVAL;
395
396         for (off = 0 ; off < size ; off += page_size) {
397                 curr_va = virt_addr + off;
398                 flush_pte = (off + page_size) >= size;
399                 rc = hl_mmu_unmap_page(ctx, curr_va, page_size, flush_pte);
400                 if (rc)
401                         dev_warn_ratelimited(hdev->dev,
402                                 "Unmap failed for va 0x%llx\n", curr_va);
403         }
404
405         return rc;
406 }
407
408 /*
409  * hl_mmu_swap_out - marks all mapping of the given ctx as swapped out
410  *
411  * @ctx: pointer to the context structure
412  *
413  */
414 void hl_mmu_swap_out(struct hl_ctx *ctx)
415 {
416         struct hl_device *hdev = ctx->hdev;
417
418         if (!hdev->mmu_enable)
419                 return;
420
421         if (hdev->mmu_func[MMU_DR_PGT].swap_out != NULL)
422                 hdev->mmu_func[MMU_DR_PGT].swap_out(ctx);
423
424         if (hdev->mmu_func[MMU_HR_PGT].swap_out != NULL)
425                 hdev->mmu_func[MMU_HR_PGT].swap_out(ctx);
426 }
427
428 /*
429  * hl_mmu_swap_in - marks all mapping of the given ctx as swapped in
430  *
431  * @ctx: pointer to the context structure
432  *
433  */
434 void hl_mmu_swap_in(struct hl_ctx *ctx)
435 {
436         struct hl_device *hdev = ctx->hdev;
437
438         if (!hdev->mmu_enable)
439                 return;
440
441         if (hdev->mmu_func[MMU_DR_PGT].swap_in != NULL)
442                 hdev->mmu_func[MMU_DR_PGT].swap_in(ctx);
443
444         if (hdev->mmu_func[MMU_HR_PGT].swap_in != NULL)
445                 hdev->mmu_func[MMU_HR_PGT].swap_in(ctx);
446 }
447
448 int hl_mmu_va_to_pa(struct hl_ctx *ctx, u64 virt_addr, u64 *phys_addr)
449 {
450         struct hl_mmu_hop_info hops;
451         u64 tmp_addr;
452         int rc;
453
454         rc = hl_mmu_get_tlb_info(ctx, virt_addr, &hops);
455         if (rc)
456                 return rc;
457
458         /* last hop holds the phys address and flags */
459         tmp_addr = hops.hop_info[hops.used_hops - 1].hop_pte_val;
460         *phys_addr = (tmp_addr & HOP_PHYS_ADDR_MASK) | (virt_addr & FLAGS_MASK);
461
462         return 0;
463 }
464
465 int hl_mmu_get_tlb_info(struct hl_ctx *ctx, u64 virt_addr,
466                         struct hl_mmu_hop_info *hops)
467 {
468         struct hl_device *hdev = ctx->hdev;
469         struct asic_fixed_properties *prop = &hdev->asic_prop;
470         struct hl_mmu_properties *mmu_prop;
471         int rc;
472         bool is_dram_addr;
473
474         if (!hdev->mmu_enable)
475                 return -EOPNOTSUPP;
476
477         is_dram_addr = hl_mem_area_inside_range(virt_addr, prop->dmmu.page_size,
478                                                 prop->dmmu.start_addr,
479                                                 prop->dmmu.end_addr);
480
481         /* host-residency is the same in PMMU and HPMMU, use one of them */
482         mmu_prop = is_dram_addr ? &prop->dmmu : &prop->pmmu;
483
484         mutex_lock(&ctx->mmu_lock);
485
486         if (mmu_prop->host_resident)
487                 rc = hdev->mmu_func[MMU_HR_PGT].get_tlb_info(ctx,
488                                                         virt_addr, hops);
489         else
490                 rc = hdev->mmu_func[MMU_DR_PGT].get_tlb_info(ctx,
491                                                         virt_addr, hops);
492
493         mutex_unlock(&ctx->mmu_lock);
494
495         return rc;
496 }
497
498 int hl_mmu_if_set_funcs(struct hl_device *hdev)
499 {
500         if (!hdev->mmu_enable)
501                 return 0;
502
503         switch (hdev->asic_type) {
504         case ASIC_GOYA:
505         case ASIC_GAUDI:
506                 hl_mmu_v1_set_funcs(hdev, &hdev->mmu_func[MMU_DR_PGT]);
507                 break;
508         default:
509                 dev_err(hdev->dev, "Unrecognized ASIC type %d\n",
510                         hdev->asic_type);
511                 return -EOPNOTSUPP;
512         }
513
514         return 0;
515 }