• 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 #include "wmalloc.h"
20 #include "securec.h"
21 #include "tde_define.h"
22 #include "tde_adp.h"
23 
24 typedef struct {
25     hi_u32 n_size;
26     hi_u16 n_free;
27     hi_u16 n_first;
28     hi_u16 n_unit_size;
29 #if HI_TDE_MEMCOUNT_SUPPORT
30     hi_u16 n_max_used; /* max used unit number */
31     hi_u16 n_max_num;  /* max unit number */
32 #endif
33     hi_void *start_addr;
34     struct _memory_block *next;
35 } memory_block;
36 
37 typedef enum {
38     UNIT_SIZE_CMD = 0,
39     UNIT_SIZE_JOB,
40     UNIT_SIZE_NODE,
41     UNIT_SIZE_FILTER,
42     UNIT_SIZE_BUTT
43 } unit_size;
44 
45 static memory_block g_stru_mem_block[UNIT_SIZE_BUTT];
46 
47 #ifndef HI_BUILD_IN_BOOT
48 static osal_spinlock_t g_mem_lock;
49 #endif
50 
51 #define print_mem_info()                                                                                              \
52     do {                                                                                                            \
53         tde_info("-----------------------------------------------------\n");                                        \
54         tde_info("\tmem_block info\ttotal\tfree\n");                                                                 \
55         tde_info("\t%d\t%lld\t%d\n", CMD_SIZE, HI_TDE_CMD_NUM, g_stru_mem_block[UNIT_SIZE_CMD].n_free);                \
56         tde_info("\t%d\t%lld\t%d\n", JOB_SIZE, HI_TDE_JOB_NUM, g_stru_mem_block[UNIT_SIZE_JOB].n_free);                \
57         tde_info("\t%ld\t%lld\t%d\n", (hi_ulong)NODE_SIZE, HI_TDE_NODE_NUM, g_stru_mem_block[UNIT_SIZE_NODE].n_free); \
58         tde_info("\t%d\t%d\t%d\n", FILTER_SIZE, HI_TDE_FILTER_NUM, g_stru_mem_block[UNIT_SIZE_FILTER].n_free);         \
59         tde_info("------------------------------------------------------\n");                                       \
60     } while (0)
61 
memory_block_init(unit_size size,hi_u16 n_unit_num,hi_void * addr)62 static hi_s32 memory_block_init(unit_size size, hi_u16 n_unit_num, hi_void *addr)
63 {
64     hi_u16 i;
65 
66     hi_u8 *data = (hi_u8 *)addr;
67 
68     if ((size >= UNIT_SIZE_BUTT) || (addr == HI_NULL) || (n_unit_num == 0)) {
69         return HI_FAILURE;
70     }
71     if (size == UNIT_SIZE_CMD) {
72         g_stru_mem_block[size].n_unit_size = CMD_SIZE;
73     } else if (size == UNIT_SIZE_JOB) {
74         g_stru_mem_block[size].n_unit_size = JOB_SIZE;
75     } else if (size == UNIT_SIZE_NODE) {
76         g_stru_mem_block[size].n_unit_size = NODE_SIZE;
77     } else if (size == UNIT_SIZE_FILTER) {
78         g_stru_mem_block[size].n_unit_size = FILTER_SIZE;
79     }
80     for (i = 1; i < n_unit_num; i++) {
81         /* Don't flag for last unit,for last unit is ready for assigned, which is say no next unit can be assigned */
82         *(hi_u16 *)data = i;
83 
84         data += g_stru_mem_block[size].n_unit_size;
85     }
86 
87     g_stru_mem_block[size].n_first = 0;
88     g_stru_mem_block[size].n_free = n_unit_num;
89     g_stru_mem_block[size].n_size = n_unit_num * g_stru_mem_block[size].n_unit_size;
90     g_stru_mem_block[size].next = HI_NULL;
91     g_stru_mem_block[size].start_addr = addr;
92 
93 #if HI_TDE_MEMCOUNT_SUPPORT
94     g_stru_mem_block[size].n_max_num = n_unit_num;
95     g_stru_mem_block[size].n_max_used = 0;
96 #endif
97 
98     return HI_SUCCESS;
99 }
100 
malloc_unit(unit_size size)101 static hi_void *malloc_unit(unit_size size)
102 {
103     unsigned long lockflags;
104 
105     memory_block *block = HI_NULL;
106     hi_u8 *free = HI_NULL;
107 
108     tde_spin_lock(&g_mem_lock, lockflags);
109     block = &g_stru_mem_block[size];
110     tde_info("eUnitSize %d, malloc units:%d, first malloc unit:%d...\n", block->n_unit_size, block->n_free,
111              block->n_first);
112     if (!block->n_free) {
113         tde_spin_unlock(&g_mem_lock, lockflags);
114         return HI_NULL;
115     }
116 
117     free = (hi_u8 *)block->start_addr + block->n_first * block->n_unit_size;
118 
119     block->n_first = *(hi_u16 *)free;
120     block->n_free--;
121 #if HI_TDE_MEMCOUNT_SUPPORT
122     if ((g_stru_mem_block[size].n_max_num - block->n_free) > g_stru_mem_block[size].n_max_used) {
123         g_stru_mem_block[size].n_max_used = g_stru_mem_block[size].n_max_num - block->n_free;
124     }
125 #endif
126     tde_spin_unlock(&g_mem_lock, lockflags);
127     (hi_void)memset_s(free, block->n_unit_size, 0, block->n_unit_size);
128     return free;
129 }
130 
wmalloc(unsigned long size)131 static hi_void *wmalloc(unsigned long size)
132 {
133     unit_size i;
134     hi_void *malloc = HI_NULL;
135 
136     if ((size > FILTER_SIZE) || (size == 0)) {
137         return HI_NULL;
138     }
139     if (size <= CMD_SIZE) {
140         for (i = UNIT_SIZE_CMD; i < UNIT_SIZE_BUTT; i++) {
141             malloc = malloc_unit(i);
142             if (malloc != HI_NULL) {
143                 return malloc;
144             }
145         }
146         return HI_NULL;
147     } else if (size <= JOB_SIZE) {
148         for (i = UNIT_SIZE_JOB; i < UNIT_SIZE_BUTT; i++) {
149             malloc = malloc_unit(i);
150             if (malloc != HI_NULL) {
151                 return malloc;
152             }
153         }
154         return HI_NULL;
155     } else if (size <= NODE_SIZE) {
156         for (i = UNIT_SIZE_NODE; i < UNIT_SIZE_BUTT; i++) {
157             malloc = malloc_unit(i);
158             if (malloc != HI_NULL) {
159                 return malloc;
160             }
161         }
162         return HI_NULL;
163     } else {
164         return malloc_unit(UNIT_SIZE_FILTER);
165     }
166 }
167 
free_unit(unit_size size,hi_void * ptr)168 static hi_s32 free_unit(unit_size size, hi_void *ptr)
169 {
170     unsigned long lockflags;
171     memory_block *block = HI_NULL;
172     tde_spin_lock(&g_mem_lock, lockflags);
173     block = &g_stru_mem_block[size];
174 
175     if (((hi_u8 *)ptr < (hi_u8 *)block->start_addr) ||
176         ((hi_u8 *)ptr >= ((hi_u8 *)block->start_addr + block->n_size))) {
177         tde_spin_unlock(&g_mem_lock, lockflags);
178         return HI_FAILURE;
179     }
180 
181     block->n_free++;
182     *(hi_u16 *)ptr = block->n_first; /* point to next unit can be assigned */
183 
184     if (block->n_unit_size == 0) {
185         tde_spin_unlock(&g_mem_lock, lockflags);
186         return HI_FAILURE;
187     }
188     block->n_first = (hi_u16)(((hi_u8 *)ptr - (hi_u8 *)(block->start_addr)) / block->n_unit_size);
189 
190     tde_info("eUnitSize:%hu,first free unit:%hu, free units:%hu\n", block->n_unit_size, block->n_first, block->n_free);
191     tde_spin_unlock(&g_mem_lock, lockflags);
192     return HI_SUCCESS;
193 }
194 
wfree(hi_void * ptr)195 static hi_s32 wfree(hi_void *ptr)
196 {
197     unit_size i;
198     for (i = UNIT_SIZE_CMD; i < UNIT_SIZE_BUTT; i++) {
199         if (free_unit(i, ptr) == HI_SUCCESS) {
200             return HI_SUCCESS;
201         }
202     }
203     tde_error("Free mem failed!vir:0x%pK, phy:%llx\n", ptr, wgetphy(ptr));
204     return HI_FAILURE;
205 }
206 
tde_malloc(hi_u32 size)207 hi_void *tde_malloc(hi_u32 size)
208 {
209     hi_void *ptr = HI_NULL;
210     ptr = (hi_void *)wmalloc(size);
211     return ptr;
212 }
213 
tde_free(hi_void * ptr)214 hi_void tde_free(hi_void *ptr)
215 {
216     if (ptr == HI_NULL) {
217         return;
218     }
219     if (wfree(ptr) != HI_SUCCESS) {
220         tde_error("Free mem failed\n");
221     }
222     return;
223 }
224 
225 #define TDE_MIN_BUFFER ((FILTER_SIZE)*HI_TDE_FILTER_NUM + ((CMD_SIZE) + (NODE_SIZE) + (JOB_SIZE)) * 2)
226 #define TDE_MAX_BUFFER (1024 * 1024)
227 static hi_u64 g_mem_poolphy_addr;
228 static hi_void *g_mem_pool_vrt_addr = HI_NULL;
229 static hi_u32 g_tde_buf = 0;
230 
231 #ifdef HI_BUILD_IN_BOOT
232 /* boot Memory optimization */
233 #define HI_TDE_CMD_NUM 20
234 #define HI_TDE_JOB_NUM 1
235 #define HI_TDE_NODE_NUM 20
236 #else
237 #define HI_TDE_CMD_NUM \
238     (hi_u64)((g_tde_buf - (FILTER_SIZE)*HI_TDE_FILTER_NUM) / ((CMD_SIZE) + (NODE_SIZE) + (JOB_SIZE)))
239 #define HI_TDE_JOB_NUM HI_TDE_CMD_NUM
240 #define HI_TDE_NODE_NUM HI_TDE_CMD_NUM
241 #endif
242 
243 #define TDE_CMD_OFFSET 0
244 #define TDE_JOB_OFFSET ((HI_TDE_CMD_NUM)*CMD_SIZE)
245 #define TDE_NODE_OFFSET (TDE_JOB_OFFSET + ((HI_TDE_JOB_NUM)*JOB_SIZE))
246 #define TDE_FILTER_OFFSET (TDE_NODE_OFFSET + ((HI_TDE_NODE_NUM)*NODE_SIZE))
247 #define TDE_MEMPOOL_SIZE                                                                   \
248     ((HI_TDE_CMD_NUM)*CMD_SIZE + (HI_TDE_JOB_NUM)*JOB_SIZE + (HI_TDE_NODE_NUM)*NODE_SIZE + \
249      (HI_TDE_FILTER_NUM)*FILTER_SIZE)
250 #ifdef HI_BUILD_IN_BOOT
251 #if !defined(HI_TDE_BUFFER)
252 #define HI_TDE_BUFFER 0x20000
253 #endif
254 #endif
255 
tde_init_set_buf(hi_u32 temp_buf)256 hi_void tde_init_set_buf(hi_u32 temp_buf)
257 {
258     g_tde_buf = temp_buf;
259 }
260 
wmeminit(void)261 hi_s32 wmeminit(void)
262 {
263     hi_s32 ret;
264     if (g_tde_buf > TDE_MAX_BUFFER) {
265         g_tde_buf = TDE_MAX_BUFFER;
266     } else if (g_tde_buf < TDE_MIN_BUFFER) {
267         g_tde_buf = TDE_MIN_BUFFER;
268     }
269 
270     tde_get_phyaddr_mmb("TDE_MEMPOOL_MMB", TDE_MEMPOOL_SIZE, g_mem_poolphy_addr);
271     if (g_mem_poolphy_addr == 0) {
272         tde_error("malloc mempool buffer failed!\n");
273         return HI_FAILURE;
274     }
275 #ifdef TDE_CACH_STRATEGY
276     g_mem_pool_vrt_addr = (hi_void *)CMPI_Remap_Cached(g_mem_poolphy_addr, TDE_MEMPOOL_SIZE);
277     if (g_mem_pool_vrt_addr == 0) {
278         tde_free_mmb(g_mem_poolphy_addr);
279         return HI_FAILURE;
280     }
281 
282 #else
283     g_mem_pool_vrt_addr = (hi_void *)cmpi_remap_nocache(g_mem_poolphy_addr, TDE_MEMPOOL_SIZE);
284     if (g_mem_pool_vrt_addr == 0) {
285         tde_free_mmb(g_mem_poolphy_addr);
286         return HI_FAILURE;
287     }
288 
289 #endif
290 
291     if (g_mem_pool_vrt_addr == HI_NULL) {
292         tde_free_mmb(g_mem_poolphy_addr);
293         g_mem_poolphy_addr = 0;
294         return HI_FAILURE;
295     }
296     ret = memory_block_init(UNIT_SIZE_CMD, HI_TDE_CMD_NUM, (g_mem_pool_vrt_addr));
297     if (ret != HI_SUCCESS) {
298     }
299     ret = memory_block_init(UNIT_SIZE_JOB, HI_TDE_JOB_NUM, ((hi_u8 *)g_mem_pool_vrt_addr + TDE_JOB_OFFSET));
300     if (ret != HI_SUCCESS) {
301     }
302     ret = memory_block_init(UNIT_SIZE_NODE, HI_TDE_NODE_NUM, ((hi_u8 *)g_mem_pool_vrt_addr + TDE_NODE_OFFSET));
303     if (ret != HI_SUCCESS) {
304     }
305     ret = memory_block_init(UNIT_SIZE_FILTER, HI_TDE_FILTER_NUM, ((hi_u8 *)g_mem_pool_vrt_addr + TDE_FILTER_OFFSET));
306     if (ret != HI_SUCCESS) {
307     }
308     osal_spin_lock_init(&g_mem_lock);
309     print_mem_info();
310 
311     return HI_SUCCESS;
312 }
313 
wmemterm(void)314 hi_void wmemterm(void)
315 {
316     print_mem_info();
317 #ifndef HI_BUILD_IN_BOOT
318     tde_unmap_mmb(g_mem_pool_vrt_addr);
319     tde_free_mmb(g_mem_poolphy_addr);
320 #endif
321     g_mem_poolphy_addr = 0;
322     g_mem_pool_vrt_addr = HI_NULL;
323 #ifndef HI_BUILD_IN_BOOT
324     osal_spin_lock_destroy(&g_mem_lock);
325 #endif
326     return;
327 }
328 
wgetphy(hi_void * ptr)329 hi_u64 wgetphy(hi_void *ptr)
330 {
331     if (ptr == HI_NULL) {
332         return HI_SUCCESS;
333     }
334 
335     if ((ptr < g_mem_pool_vrt_addr) || ((hi_u8 *)ptr >= ((hi_u8 *)g_mem_pool_vrt_addr + TDE_MEMPOOL_SIZE))) {
336         return HI_SUCCESS;
337     }
338 
339     return (g_mem_poolphy_addr + ((hi_u8 *)ptr - (hi_u8 *)g_mem_pool_vrt_addr));
340 }
341 
wgetvrt(hi_u64 phyaddr)342 hi_void *wgetvrt(hi_u64 phyaddr)
343 {
344     if ((phyaddr < g_mem_poolphy_addr) || (phyaddr >= (g_mem_poolphy_addr + TDE_MEMPOOL_SIZE))) {
345         return HI_NULL;
346     }
347 
348     return (hi_void *)((hi_u8 *)g_mem_pool_vrt_addr + (phyaddr - g_mem_poolphy_addr));
349 }
350 
wgetfreenum(hi_void)351 hi_u32 wgetfreenum(hi_void)
352 {
353     unit_size size = 0;
354     hi_u32 free_unit_num = g_stru_mem_block[size].n_free;
355 
356     for (size = UNIT_SIZE_CMD; size < UNIT_SIZE_FILTER; size++) {
357         free_unit_num = (free_unit_num > g_stru_mem_block[size].n_free) ? g_stru_mem_block[size].n_free :
358                          free_unit_num;
359     }
360 
361     return free_unit_num;
362 }
363 
364 #ifndef HI_BUILD_IN_BOOT
365 
366 #ifdef CONFIG_HI_PROC_SHOW_SUPPORT
wprintinfo(osal_proc_entry_t * page)367 osal_proc_entry_t *wprintinfo(osal_proc_entry_t *page)
368 {
369 #if HI_TDE_MEMCOUNT_SUPPORT
370     hi_u32 max_used_cmd, max_used_job, max_used_node, max_used_filter;
371 #else
372     hi_u32 free_cmd, free_job, free_node, free_filter;
373 #endif
374     if (page == HI_NULL) {
375         return HI_SUCCESS;
376     }
377 
378 #if HI_TDE_MEMCOUNT_SUPPORT
379     max_used_cmd = g_stru_mem_block[UNIT_SIZE_CMD].n_max_used;
380     max_used_job = g_stru_mem_block[UNIT_SIZE_JOB].n_max_used;
381     max_used_node = g_stru_mem_block[UNIT_SIZE_NODE].n_max_used;
382     max_used_filter = g_stru_mem_block[UNIT_SIZE_FILTER].n_max_used;
383 #else
384     free_cmd = g_stru_mem_block[UNIT_SIZE_CMD].n_free;
385     free_job = g_stru_mem_block[UNIT_SIZE_JOB].n_free;
386     free_node = g_stru_mem_block[UNIT_SIZE_NODE].n_free;
387     free_filter = g_stru_mem_block[UNIT_SIZE_FILTER].n_free;
388 #endif
389     osal_seq_printf(page, "--------- Hisilicon TDE Memory Pool Info ---------\n");
390 #if HI_TDE_MEMCOUNT_SUPPORT
391     osal_seq_printf(page, "     Type         Total       MaxUsed\n");
392     osal_seq_printf(page, "[Unit %d ]   %8u  %8u\n", CMD_SIZE, HI_TDE_CMD_NUM, max_used_cmd);
393     osal_seq_printf(page, "[Unit %d ]   %8u  %8u\n", JOB_SIZE, HI_TDE_JOB_NUM, max_used_job);
394     osal_seq_printf(page, "[Unit %d]   %8u  %8u\n", NODE_SIZE, HI_TDE_NODE_NUM, max_used_job);
395     osal_seq_printf(page, "[Unit%d]   %8u  %8u\n", FILTER_SIZE, HI_TDE_FILTER_NUM, max_used_filter);
396     osal_seq_printf(page, "[Total   ]   %8uK %8uK\n", TDE_MEMPOOL_SIZE / 1024, /* 1024 Demotion byte */
397                     (CMD_SIZE * max_used_cmd + JOB_SIZE * max_used_job + NODE_SIZE * max_used_node + FILTER_SIZE *
398                      max_used_filter) / 1024); /* 1024 Demotion byte */
399 #else
400     osal_seq_printf(page, "     Type         Total       Used\n");
401     osal_seq_printf(page, "[Unit %d ]   %8lld  %8lld\n", CMD_SIZE, HI_TDE_CMD_NUM, HI_TDE_CMD_NUM - free_cmd);
402     osal_seq_printf(page, "[Unit %d ]   %8lld  %8lld\n", JOB_SIZE, HI_TDE_JOB_NUM, HI_TDE_JOB_NUM - free_job);
403     osal_seq_printf(page, "[Unit %ld]   %8lld  %8lld\n", (unsigned long)NODE_SIZE, HI_TDE_NODE_NUM,
404                     HI_TDE_NODE_NUM - free_node);
405     osal_seq_printf(page, "[Unit%d]   %8d  %8d\n", FILTER_SIZE, HI_TDE_FILTER_NUM, HI_TDE_FILTER_NUM - free_filter);
406     osal_seq_printf(page, "[Total   ]   %8lldK %8lldK\n", TDE_MEMPOOL_SIZE / 1024, /* 1024 Demotion byte */
407                     (TDE_MEMPOOL_SIZE - (CMD_SIZE * free_cmd + JOB_SIZE * free_job + NODE_SIZE * free_node +
408                     FILTER_SIZE * free_filter)) / 1024); /* 1024 Demotion byte */
409 
410 #endif
411     return page;
412 }
413 #endif
414 
415 #endif
416