1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #ifndef __ARM_MPU_MM_H__
4 #define __ARM_MPU_MM_H__
5 
6 #include <xen/bug.h>
7 #include <xen/macros.h>
8 #include <xen/page-size.h>
9 #include <xen/types.h>
10 #include <asm/mm.h>
11 #include <asm/mpu.h>
12 
13 #define MPUMAP_REGION_OVERLAP      -1
14 #define MPUMAP_REGION_NOTFOUND      0
15 #define MPUMAP_REGION_FOUND         1
16 #define MPUMAP_REGION_INCLUSIVE     2
17 
18 #define INVALID_REGION_IDX     0xFFU
19 
20 extern struct page_info *frame_table;
21 
22 extern uint8_t max_mpu_regions;
23 
24 extern DECLARE_BITMAP(xen_mpumap_mask, MAX_MPU_REGION_NR);
25 
26 extern pr_t xen_mpumap[MAX_MPU_REGION_NR];
27 
28 #define virt_to_maddr(va) ((paddr_t)((vaddr_t)(va) & PADDR_MASK))
29 
30 #ifdef CONFIG_ARM_32
31 #define is_xen_heap_page(page) ({ BUG_ON("unimplemented"); false; })
32 #define is_xen_heap_mfn(mfn) ({ BUG_ON("unimplemented"); false; })
33 #endif
34 
35 /* On MPU systems there is no translation, ma == va. */
maddr_to_virt(paddr_t ma)36 static inline void *maddr_to_virt(paddr_t ma)
37 {
38     return _p(ma);
39 }
40 
41 /* Convert between virtual address to page-info structure. */
virt_to_page(const void * v)42 static inline struct page_info *virt_to_page(const void *v)
43 {
44     mfn_t mfn = _mfn(virt_to_mfn(v));
45 
46     ASSERT(mfn_valid(mfn));
47 
48     return mfn_to_page(mfn);
49 }
50 
51 /* Utility function to be used whenever MPU regions are modified */
context_sync_mpu(void)52 static inline void context_sync_mpu(void)
53 {
54     /*
55      * ARM DDI 0600B.a, C1.7.1
56      * Writes to MPU registers are only guaranteed to be visible following a
57      * Context synchronization event and DSB operation.
58      */
59     dsb(sy);
60     isb();
61 }
62 
63 /*
64  * The following API requires context_sync_mpu() after being used to modify MPU
65  * regions:
66  *  - write_protection_region
67  *  - xen_mpumap_update
68  */
69 
70 /* Reads the MPU region (into @pr_read) with index @sel from the HW */
71 void read_protection_region(pr_t *pr_read, uint8_t sel);
72 
73 /* Writes the MPU region (from @pr_write) with index @sel to the HW */
74 void write_protection_region(const pr_t *pr_write, uint8_t sel);
75 
76 /*
77  * Maps an address range into the MPU data structure and updates the HW.
78  * Equivalent to xen_pt_update in an MMU system.
79  *
80  * @param base      Base address of the range to map (inclusive).
81  * @param limit     Limit address of the range to map (exclusive).
82  * @param flags     Flags for the memory range to map.
83  * @return          0 on success, negative on error.
84  */
85 int xen_mpumap_update(paddr_t base, paddr_t limit, unsigned int flags);
86 
87 /*
88  * Creates a pr_t structure describing a protection region.
89  *
90  * @base: base address as base of the protection region.
91  * @limit: exclusive address as limit of the protection region.
92  * @flags: memory flags for the mapping.
93  * @return: pr_t structure describing a protection region.
94  */
95 pr_t pr_of_addr(paddr_t base, paddr_t limit, unsigned int flags);
96 
97 /*
98  * Checks whether a given memory range is present in the provided table of
99  * MPU protection regions.
100  *
101  * @param table         Array of pr_t protection regions.
102  * @param r_regions     Number of elements in `table`.
103  * @param base          Start of the memory region to be checked (inclusive).
104  * @param limit         End of the memory region to be checked (exclusive).
105  * @param index         Set to the index of the region if an exact or inclusive
106  *                      match is found, and INVALID_REGION otherwise.
107  * @return: Return code indicating the result of the search:
108  *          MPUMAP_REGION_NOTFOUND: no part of the range is present in `table`
109  *          MPUMAP_REGION_FOUND: found an exact match in `table`
110  *          MPUMAP_REGION_INCLUSIVE: found an inclusive match in `table`
111  *          MPUMAP_REGION_OVERLAP: found an overlap with a mapping in `table`
112  *
113  * Note: make sure that the range [`base`, `limit`) refers to the memory region
114  * inclusive of `base` and exclusive of `limit`.
115  */
116 int mpumap_contains_region(pr_t *table, uint8_t nr_regions, paddr_t base,
117                            paddr_t limit, uint8_t *index);
118 
119 #endif /* __ARM_MPU_MM_H__ */
120 
121 /*
122  * Local variables:
123  * mode: C
124  * c-file-style: "BSD"
125  * c-basic-offset: 4
126  * indent-tabs-mode: nil
127  * End:
128  */
129