• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #ifndef _OSAL_MMZ_H
20 #define _OSAL_MMZ_H
21 
22 #include "hi_osal.h"
23 
24 #define CACHE_LINE_SIZE            0x40
25 #define HIL_MMZ_NAME_LEN           32
26 #define HIL_MMB_NAME_LEN           32
27 
28 struct hil_media_memory_zone {
29     char name[HIL_MMZ_NAME_LEN];
30 
31     unsigned long gfp;
32 
33     unsigned long phys_start;
34     unsigned long nbytes;
35 
36     struct osal_list_head list;
37     union {
38         struct device *cma_dev;
39         unsigned char *bitmap;
40     };
41     struct osal_list_head mmb_list;
42 
43     unsigned int alloc_type;
44     unsigned long block_align;
45 
46     void (*destructor)(const void *);
47 };
48 typedef struct hil_media_memory_zone hil_mmz_t;
49 
50 #define HIL_MMZ_FMT_S              "PHYS(0x%08pK, 0x%08pK), GFP=%lu, nBYTES=%luKB,    NAME=\"%s\""
51 #define hil_mmz_fmt_arg(p) (p)->phys_start, (p)->phys_start + (p)->nbytes - 1, (p)->gfp, (p)->nbytes / SZ_1K, (p)->name
52 
53 struct hil_media_memory_block {
54 #ifndef MMZ_V2_SUPPORT
55     unsigned int id;
56 #endif
57     char name[HIL_MMB_NAME_LEN];
58     struct hil_media_memory_zone *zone;
59     struct osal_list_head list;
60 
61     unsigned long phys_addr;
62     void *kvirt;
63     unsigned long length;
64 
65     unsigned long flags;
66 
67     unsigned int order;
68 
69     int phy_ref;
70     int map_ref;
71 };
72 typedef struct hil_media_memory_block hil_mmb_t;
73 
74 #define hil_mmb_kvirt(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->kvirt; })
75 #define hil_mmb_phys(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->phys_addr; })
76 #define hil_mmb_length(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->length; })
77 #define hil_mmb_name(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->name; })
78 #define hil_mmb_zone(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->zone; })
79 
80 #define HIL_MMB_MAP2KERN           (1 << 0)
81 #define HIL_MMB_MAP2KERN_CACHED    (1 << 1)
82 #define HIL_MMB_RELEASED           (1 << 2)
83 
84 #define HIL_MMB_FMT_S              "phys(0x%08pK, 0x%08pK), kvirt=0x%08pK, flags=0x%08pK, length=%luKB,    name=\"%s\""
85 #define hil_mmb_fmt_arg(p) \
86     (p)->phys_addr, mmz_grain_align((p)->phys_addr + (p)->length) - 1, \
87     (unsigned long)(uintptr_t)((p)->kvirt), (p)->flags, (p)->length / SZ_1K, (p)->name
88 
89 #define DEFAULT_ALLOC              0
90 #define SLAB_ALLOC                 1
91 #define EQ_BLOCK_ALLOC             2
92 
93 #define LOW_TO_HIGH                0
94 #define HIGH_TO_LOW                1
95 
96 #define MMZ_DBG_LEVEL              0x0
97 #define MMZ_WARN_LEVEL              4
98 #define MMZ_ERR_LEVEL               1
99 
100 #define mmz_trace(level, s, params...)                                             \
101     do {                                                                           \
102         if (level & MMZ_DBG_LEVEL)                                                 \
103             printk(KERN_INFO "[%s, %d]: " s "\n", __FUNCTION__, __LINE__, params); \
104     } while (0)
105 
106 #define mmz_trace_func() mmz_trace(0x02, "%s", __FILE__)
107 
108 #define MMZ_GRAIN                  PAGE_SIZE
109 #define mmz_bitmap_size(p) (mmz_align2(mmz_length2grain((p)->nbytes), 8) / 8)
110 
111 #define mmz_get_bit(p, n) (((p)->bitmap[(n) / 8] >> ((n) & 0x7)) & 0x1)
112 #define mmz_set_bit(p, n) ((p)->bitmap[(n) / 8] |= 1 << ((n) & 0x7))
113 #define mmz_clr_bit(p, n) ((p)->bitmap[(n) / 8] &= ~(1 << ((n) & 0x7)))
114 
115 #define mmz_pos2phy_addr(p, n) ((p)->phys_start + (n) * MMZ_GRAIN)
116 #define mmz_phy_addr2pos(p, a) (((a) - (p)->phys_start) / MMZ_GRAIN)
117 
118 #define mmz_align2low(x, g) (((g) == 0) ? (0) : (((x) / (g)) * (g)))
119 #define mmz_align2(x, g) (((g) == 0) ? (0) : ((((x) + (g) - 1) / (g)) * (g)))
120 #define mmz_grain_align(x) mmz_align2(x, MMZ_GRAIN)
121 #define mmz_length2grain(len) (mmz_grain_align(len) / MMZ_GRAIN)
122 
123 #define begin_list_for_each_mmz(p, gfp, mmz_name)        \
124     list_for_each_entry(p, &g_mmz_list, list)              \
125     {                                                    \
126         if ((gfp) == 0 ? 0 : (p)->gfp != (gfp)) {        \
127             continue;                                       \
128         }                                                   \
129         if (((mmz_name) == NULL) || (*(mmz_name) == '\0')) { \
130             if (anony == 1) {                            \
131                 if (strcmp("anonymous", (p)->name)) {    \
132                     continue;                            \
133                 }                                        \
134             } else {                                     \
135                 break;                                   \
136             }                                            \
137         } else {                                         \
138             if (strcmp(mmz_name, (p)->name)) {           \
139                 continue;                                \
140             }                                            \
141         }                                                \
142         mmz_trace(1, HIL_MMZ_FMT_S, hil_mmz_fmt_arg(p));
143 #define end_list_for_each_mmz() }
144 
145 #if defined(KERNEL_BIT_64) && defined(USER_BIT_32)
146 #define __phys_addr_type__         unsigned long long
147 #define __phys_len_type__          unsigned long long
148 #define __phys_addr_align__        __attribute__((aligned(8)))
149 #else
150 #define __phys_addr_type__         unsigned long
151 #define __phys_len_type__          unsigned long
152 #define __phys_addr_align__        __attribute__((aligned(sizeof(long))))
153 #endif
154 
155 struct mmb_info {
156     __phys_addr_type__ phys_addr; /* phys-memory address */
157     __phys_addr_type__ __phys_addr_align__ align; /* if you need your phys-memory have special align size */
158     __phys_len_type__ __phys_addr_align__ size; /* length of memory you need, in bytes */
159     unsigned int __phys_addr_align__ order;
160 
161     void *__phys_addr_align__ mapped; /* userspace mapped ptr */
162 
163     union {
164         struct {
165             unsigned long prot : 8; /* PROT_READ or PROT_WRITE */
166             unsigned long flags : 12; /* MAP_SHARED or MAP_PRIVATE */
167 
168 #ifdef __KERNEL__
169             unsigned long reserved : 8; /* reserved, do not use */
170             unsigned long delayed_free : 1;
171             unsigned long map_cached : 1;
172 #endif
173         };
174         unsigned long w32_stuf;
175     } __phys_addr_align__;
176 
177     char mmb_name[HIL_MMB_NAME_LEN];
178     char mmz_name[HIL_MMZ_NAME_LEN];
179     unsigned long __phys_addr_align__ gfp; /* reserved, do set to 0 */
180 
181 #ifdef __KERNEL__
182     int map_ref;
183     int mmb_ref;
184 
185     struct osal_list_head list;
186     hil_mmb_t *mmb;
187 #endif
188 } __attribute__((aligned(8)));
189 
190 struct dirty_area {
191     __phys_addr_type__ dirty_phys_start; /* dirty physical address */
192     void *__phys_addr_align__ dirty_virt_start; /* dirty virtual  address,
193                        must be coherent with dirty_phys_addr */
194     __phys_len_type__ __phys_addr_align__ dirty_size;
195 } __phys_addr_align__;
196 
197 #define IOC_MMB_ALLOC              _IOWR('m', 10, struct mmb_info)
198 #define IOC_MMB_ATTR               _IOR('m', 11, struct mmb_info)
199 #define IOC_MMB_FREE               _IOW('m', 12, struct mmb_info)
200 #define IOC_MMB_ALLOC_V2           _IOWR('m', 13, struct mmb_info)
201 
202 #define IOC_MMB_USER_REMAP         _IOWR('m', 20, struct mmb_info)
203 #define IOC_MMB_USER_REMAP_CACHED  _IOWR('m', 21, struct mmb_info)
204 #define IOC_MMB_USER_UNMAP         _IOWR('m', 22, struct mmb_info)
205 
206 #define IOC_MMB_VIRT_GET_PHYS      _IOWR('m', 23, struct mmb_info)
207 
208 #define IOC_MMB_SYS_FLUSH_CACHE    _IOW('m', 24, struct mmb_info)
209 #define IOC_MMB_BASE_CHECK_ADDR    _IOW('m', 25, struct mmb_info)
210 #define IOC_MMB_INVALID_CACHE      _IOW('m', 26, struct mmb_info)
211 #define IOC_MMB_CHECK_PHY_ALLOC    _IOWR('m', 27, struct mmb_info)
212 #define IOC_MMB_MMF_REMAP          _IOWR('m', 28, struct mmb_info)
213 #define IOC_MMB_MMF_REMAP_CACHED   _IOWR('m', 29, struct mmb_info)
214 #define IOC_MMB_MMF_UNMAP          _IOWR('m', 30, struct mmb_info)
215 
216 #define IOC_MMB_ADD_REF            _IO('r', 30) /* ioctl(file, cmd, arg), arg is mmb_addr */
217 #define IOC_MMB_DEC_REF            _IO('r', 31) /* ioctl(file, cmd, arg), arg is mmb_addr */
218 
219 #define IOC_MMB_FLUSH_DCACHE       _IO('c', 40)
220 
221 #define IOC_MMB_FLUSH_DCACHE_DIRTY _IOW('d', 50, struct dirty_area)
222 #define IOC_MMB_TEST_CACHE         _IOW('t', 11, struct mmb_info)
223 
224 #define MMZ_SETUP_CMDLINE_LEN      256
225 typedef struct hiMMZ_MODULE_PARAMS_S {
226     char mmz[MMZ_SETUP_CMDLINE_LEN];
227     char map_mmz[MMZ_SETUP_CMDLINE_LEN];
228     int anony;
229 } MMZ_MODULE_PARAMS_S;
230 
231 /*
232  * APIs
233  */
234 extern hil_mmz_t *hil_mmz_create(const char *name, unsigned long gfp, unsigned long phys_start,
235                                  unsigned long nbytes);
236 extern hil_mmz_t *hil_mmz_create_v2(const char *name, unsigned long gfp, unsigned long phys_start,
237                                     unsigned long nbytes, unsigned int alloc_type, unsigned long block_align);
238 
239 extern int hil_mmz_destroy(hil_mmz_t *zone);
240 
241 extern int hil_mmz_register(hil_mmz_t *zone);
242 extern int hil_mmz_unregister(hil_mmz_t *zone);
243 extern hil_mmz_t *hil_mmz_find(unsigned long gfp, const char *mmz_name);
244 
245 extern hil_mmb_t *hil_mmb_alloc(const char *name, unsigned long size, unsigned long align,
246                                 unsigned long gfp, const char *mmz_name);
247 extern hil_mmb_t *hil_mmb_alloc_v2(const char *name, unsigned long size, unsigned long align,
248                                    unsigned long gfp, const char *mmz_name, unsigned int order);
249 extern int hil_mmb_free(hil_mmb_t *mmb);
250 extern hil_mmb_t *hil_mmb_getby_phys(unsigned long addr);
251 extern hil_mmb_t *hil_mmb_getby_phys_2(unsigned long addr, unsigned long *out_offset);
252 extern hil_mmb_t *hil_mmb_getby_kvirt(void *virt);
253 extern unsigned long usr_virt_to_phys(unsigned long virt);
254 
255 extern int hil_map_mmz_check_phys(unsigned long addr_start, unsigned long addr_len);
256 extern int hil_is_phys_in_mmz(unsigned long addr_start, unsigned long addr_len);
257 
258 extern int hil_vma_check(unsigned long vm_start, unsigned long vm_end);
259 extern int hil_mmb_flush_dcache_byaddr_safe(void *kvirt, unsigned long phys_addr, unsigned long length);
260 
261 extern unsigned long hil_mmz_get_phys(const char *zone_name);
262 
263 extern hil_mmb_t *hil_mmb_alloc_in(const char *name, unsigned long size, unsigned long align,
264                                    hil_mmz_t *_user_mmz);
265 extern hil_mmb_t *hil_mmb_alloc_in_v2(const char *name, unsigned long size, unsigned long align,
266                                       hil_mmz_t *_user_mmz, unsigned int order);
267 
268 #define hil_mmb_freeby_phys(phys_addr) hil_mmb_free(hil_mmb_getby_phys(phys_addr))
269 #define hil_mmb_freeby_kvirt(kvirt) hil_mmb_free(hil_mmb_getby_kvirt(kvirt))
270 
271 extern void *hil_mmb_map2kern(hil_mmb_t *mmb);
272 extern void *hil_mmb_map2kern_cached(hil_mmb_t *mmb);
273 
274 extern int hil_mmb_flush_dcache_byaddr(void *kvirt, unsigned long phys_addr, unsigned long length);
275 extern int hil_mmb_invalid_cache_byaddr(void *kvirt, unsigned long phys_addr, unsigned long length);
276 
277 extern int hil_mmb_unmap(hil_mmb_t *mmb);
278 extern int hil_mmb_get(hil_mmb_t *mmb);
279 extern int hil_mmb_put(hil_mmb_t *mmb);
280 
281 extern void *hil_mmf_map2kern_nocache(unsigned long phys, int len);
282 extern void *hil_mmf_map2kern_cache(unsigned long phys, int len);
283 extern void hil_mmf_unmap(void *virt);
284 
285 /* for mmz userdev */
286 int mmz_userdev_init(void);
287 void mmz_userdev_exit(void);
288 int mmz_flush_dcache_all(void);
289 
290 #endif /* _OSAL_MMZ_H */
291