Skip to content

Commit 6b5c19c

Browse files
aikmpe
authored andcommitted
powerpc/mmu: Add real mode support for IOMMU preregistered memory
This makes mm_iommu_lookup() able to work in realmode by replacing list_for_each_entry_rcu() (which can do debug stuff which can fail in real mode) with list_for_each_entry_lockless(). This adds realmode version of mm_iommu_ua_to_hpa() which adds explicit vmalloc'd-to-linear address conversion. Unlike mm_iommu_ua_to_hpa(), mm_iommu_ua_to_hpa_rm() can fail. This changes mm_iommu_preregistered() to receive @mm as in real mode @current does not always have a correct pointer. This adds realmode version of mm_iommu_lookup() which receives @mm (for the same reason as for mm_iommu_preregistered()) and uses lockless version of list_for_each_entry_rcu(). Signed-off-by: Alexey Kardashevskiy <[email protected]> Reviewed-by: David Gibson <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 97da385 commit 6b5c19c

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

arch/powerpc/include/asm/mmu_context.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@ extern void mm_iommu_init(struct mm_struct *mm);
2929
extern void mm_iommu_cleanup(struct mm_struct *mm);
3030
extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm,
3131
unsigned long ua, unsigned long size);
32+
extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(
33+
struct mm_struct *mm, unsigned long ua, unsigned long size);
3234
extern struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
3335
unsigned long ua, unsigned long entries);
3436
extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
3537
unsigned long ua, unsigned long *hpa);
38+
extern long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
39+
unsigned long ua, unsigned long *hpa);
3640
extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
3741
extern void mm_iommu_mapped_dec(struct mm_iommu_table_group_mem_t *mem);
3842
#endif

arch/powerpc/mm/mmu_context_iommu.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,25 @@ struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm,
314314
}
315315
EXPORT_SYMBOL_GPL(mm_iommu_lookup);
316316

317+
struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(struct mm_struct *mm,
318+
unsigned long ua, unsigned long size)
319+
{
320+
struct mm_iommu_table_group_mem_t *mem, *ret = NULL;
321+
322+
list_for_each_entry_lockless(mem, &mm->context.iommu_group_mem_list,
323+
next) {
324+
if ((mem->ua <= ua) &&
325+
(ua + size <= mem->ua +
326+
(mem->entries << PAGE_SHIFT))) {
327+
ret = mem;
328+
break;
329+
}
330+
}
331+
332+
return ret;
333+
}
334+
EXPORT_SYMBOL_GPL(mm_iommu_lookup_rm);
335+
317336
struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
318337
unsigned long ua, unsigned long entries)
319338
{
@@ -345,6 +364,26 @@ long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
345364
}
346365
EXPORT_SYMBOL_GPL(mm_iommu_ua_to_hpa);
347366

367+
long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
368+
unsigned long ua, unsigned long *hpa)
369+
{
370+
const long entry = (ua - mem->ua) >> PAGE_SHIFT;
371+
void *va = &mem->hpas[entry];
372+
unsigned long *pa;
373+
374+
if (entry >= mem->entries)
375+
return -EFAULT;
376+
377+
pa = (void *) vmalloc_to_phys(va);
378+
if (!pa)
379+
return -EFAULT;
380+
381+
*hpa = *pa | (ua & ~PAGE_MASK);
382+
383+
return 0;
384+
}
385+
EXPORT_SYMBOL_GPL(mm_iommu_ua_to_hpa_rm);
386+
348387
long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem)
349388
{
350389
if (atomic64_inc_not_zero(&mem->mapped))

0 commit comments

Comments
 (0)