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