Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Generic page table allocator for IOMMUs.
0004  *
0005  * Copyright (C) 2014 ARM Limited
0006  *
0007  * Author: Will Deacon <will.deacon@arm.com>
0008  */
0009 
0010 #include <linux/bug.h>
0011 #include <linux/io-pgtable.h>
0012 #include <linux/kernel.h>
0013 #include <linux/types.h>
0014 
0015 static const struct io_pgtable_init_fns *
0016 io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
0017 #ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE
0018     [ARM_32_LPAE_S1] = &io_pgtable_arm_32_lpae_s1_init_fns,
0019     [ARM_32_LPAE_S2] = &io_pgtable_arm_32_lpae_s2_init_fns,
0020     [ARM_64_LPAE_S1] = &io_pgtable_arm_64_lpae_s1_init_fns,
0021     [ARM_64_LPAE_S2] = &io_pgtable_arm_64_lpae_s2_init_fns,
0022     [ARM_MALI_LPAE] = &io_pgtable_arm_mali_lpae_init_fns,
0023     [APPLE_DART] = &io_pgtable_apple_dart_init_fns,
0024 #endif
0025 #ifdef CONFIG_IOMMU_IO_PGTABLE_ARMV7S
0026     [ARM_V7S] = &io_pgtable_arm_v7s_init_fns,
0027 #endif
0028 #ifdef CONFIG_AMD_IOMMU
0029     [AMD_IOMMU_V1] = &io_pgtable_amd_iommu_v1_init_fns,
0030 #endif
0031 };
0032 
0033 struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
0034                         struct io_pgtable_cfg *cfg,
0035                         void *cookie)
0036 {
0037     struct io_pgtable *iop;
0038     const struct io_pgtable_init_fns *fns;
0039 
0040     if (fmt >= IO_PGTABLE_NUM_FMTS)
0041         return NULL;
0042 
0043     fns = io_pgtable_init_table[fmt];
0044     if (!fns)
0045         return NULL;
0046 
0047     iop = fns->alloc(cfg, cookie);
0048     if (!iop)
0049         return NULL;
0050 
0051     iop->fmt    = fmt;
0052     iop->cookie = cookie;
0053     iop->cfg    = *cfg;
0054 
0055     return &iop->ops;
0056 }
0057 EXPORT_SYMBOL_GPL(alloc_io_pgtable_ops);
0058 
0059 /*
0060  * It is the IOMMU driver's responsibility to ensure that the page table
0061  * is no longer accessible to the walker by this point.
0062  */
0063 void free_io_pgtable_ops(struct io_pgtable_ops *ops)
0064 {
0065     struct io_pgtable *iop;
0066 
0067     if (!ops)
0068         return;
0069 
0070     iop = io_pgtable_ops_to_pgtable(ops);
0071     io_pgtable_tlb_flush_all(iop);
0072     io_pgtable_init_table[iop->fmt]->free(iop);
0073 }
0074 EXPORT_SYMBOL_GPL(free_io_pgtable_ops);