1 /*
2  * xen/drivers/passthrough/arm/iommu_helpers.c
3  *
4  * Contains various helpers to be used by IOMMU drivers.
5  *
6  * Based on Xen's SMMU driver:
7  *    xen/drivers/passthrough/arm/smmu.c
8  *
9  * Copyright (C) 2014 Linaro Limited.
10  *
11  * Copyright (C) 2019 EPAM Systems Inc.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms and conditions of the GNU General Public
15  * License, version 2, as published by the Free Software Foundation.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public
23  * License along with this program; If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include <xen/iommu.h>
27 #include <xen/lib.h>
28 #include <xen/sched.h>
29 
30 #include <asm/device.h>
31 
32 /* Should only be used if P2M Table is shared between the CPU and the IOMMU. */
arm_iommu_map_page(struct domain * d,dfn_t dfn,mfn_t mfn,unsigned int flags,unsigned int * flush_flags)33 int __must_check arm_iommu_map_page(struct domain *d, dfn_t dfn, mfn_t mfn,
34                                     unsigned int flags,
35                                     unsigned int *flush_flags)
36 {
37     p2m_type_t t;
38 
39     /*
40      * Grant mappings can be used for DMA requests. The dev_bus_addr
41      * returned by the hypercall is the MFN (not the IPA). For device
42      * protected by an IOMMU, Xen needs to add a 1:1 mapping in the domain
43      * p2m to allow DMA request to work.
44      * This is only valid when the domain is directed mapped. Hence this
45      * function should only be used by gnttab code with gfn == mfn == dfn.
46      */
47     BUG_ON(!is_domain_direct_mapped(d));
48     BUG_ON(mfn_x(mfn) != dfn_x(dfn));
49 
50     /* We only support readable and writable flags */
51     if ( !(flags & (IOMMUF_readable | IOMMUF_writable)) )
52         return -EINVAL;
53 
54     t = (flags & IOMMUF_writable) ? p2m_iommu_map_rw : p2m_iommu_map_ro;
55 
56     /*
57      * The function guest_physmap_add_entry replaces the current mapping
58      * if there is already one...
59      */
60     return guest_physmap_add_entry(d, _gfn(dfn_x(dfn)), _mfn(dfn_x(dfn)), 0, t);
61 }
62 
63 /* Should only be used if P2M Table is shared between the CPU and the IOMMU. */
arm_iommu_unmap_page(struct domain * d,dfn_t dfn,unsigned int * flush_flags)64 int __must_check arm_iommu_unmap_page(struct domain *d, dfn_t dfn,
65                                       unsigned int *flush_flags)
66 {
67     /*
68      * This function should only be used by gnttab code when the domain
69      * is direct mapped (i.e. gfn == mfn == dfn).
70      */
71     if ( !is_domain_direct_mapped(d) )
72         return -EINVAL;
73 
74     return guest_physmap_remove_page(d, _gfn(dfn_x(dfn)), _mfn(dfn_x(dfn)), 0);
75 }
76 
77 /*
78  * Local variables:
79  * mode: C
80  * c-file-style: "BSD"
81  * c-basic-offset: 4
82  * indent-tabs-mode: nil
83  * End:
84  */
85