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