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