1 /*
2 * osal_mem.c
3 *
4 * osal driver
5 *
6 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19 #include "osal_mem.h"
20 #include <linux/export.h>
21 #include <linux/slab.h>
22 #include <linux/string.h>
23 #include <linux/vmalloc.h>
24 #include "hdf_log.h"
25 #include "securec.h"
26
27 #define HDF_LOG_TAG osal_mem
28
29 #define KMALLOC_SIZE 0x20000
30
31 struct mem_hdr {
32 uint32_t type;
33 uint32_t offset;
34 };
35
36 struct mem_block {
37 struct mem_hdr hdr;
38 uint8_t mem[0];
39 };
40
41 enum {
42 TYPE_KMALLOC = 0xa5a5a5a1,
43 TYPE_VMALLOC = 0xa5a5a5a2,
44 };
45
osal_mem_alloc(size_t size,uint32_t * type)46 static void *osal_mem_alloc(size_t size, uint32_t *type)
47 {
48 char *base = NULL;
49 const uint32_t mng_size = sizeof(struct mem_block);
50 if (size > (SIZE_MAX - mng_size)) {
51 HDF_LOGE("%s invalid param %d", __func__, size);
52 return NULL;
53 }
54
55 if (size > (KMALLOC_SIZE - mng_size)) {
56 base = (char *)vmalloc(size + mng_size);
57 *type = TYPE_VMALLOC;
58 } else {
59 base = (char *)kmalloc(size + mng_size, GFP_KERNEL);
60 *type = TYPE_KMALLOC;
61 }
62
63 return base;
64 }
65
OsalMemAlloc(size_t size)66 void *OsalMemAlloc(size_t size)
67 {
68 void *buf = NULL;
69 char *base = NULL;
70 struct mem_block *block = NULL;
71 const uint32_t mng_size = sizeof(*block);
72 uint32_t type;
73
74 if (size == 0) {
75 HDF_LOGE("%s invalid param", __func__);
76 return NULL;
77 }
78
79 base = osal_mem_alloc(size, &type);
80 if (base == NULL) {
81 HDF_LOGE("%s malloc fail %d", __func__, size);
82 return NULL;
83 }
84
85 block = (struct mem_block *)base;
86 block->hdr.type = type;
87 block->hdr.offset = 0;
88
89 buf = (void *)(base + mng_size);
90
91 return buf;
92 }
93 EXPORT_SYMBOL(OsalMemAlloc);
94
OsalMemCalloc(size_t size)95 void *OsalMemCalloc(size_t size)
96 {
97 void *buf = NULL;
98
99 if (size == 0) {
100 HDF_LOGE("%s invalid param", __func__);
101 return NULL;
102 }
103
104 buf = OsalMemAlloc(size);
105 if (buf != NULL)
106 (void)memset_s(buf, size, 0, size);
107
108 return buf;
109 }
110 EXPORT_SYMBOL(OsalMemCalloc);
111
OsalMemAllocAlign(size_t alignment,size_t size)112 void *OsalMemAllocAlign(size_t alignment, size_t size)
113 {
114 char *base = NULL;
115 char *buf = NULL;
116 struct mem_block *block = NULL;
117 const uint32_t mng_size = sizeof(*block);
118 uint32_t type;
119 uint32_t offset;
120 char *aligned_ptr = NULL;
121
122 if (size == 0 || (alignment == 0) || ((alignment & (alignment - 1)) != 0) ||
123 ((alignment % sizeof(void *)) != 0) || size > (SIZE_MAX - alignment)) {
124 HDF_LOGE("%s invalid param align:%d,size:%d", __func__, alignment, size);
125 return NULL;
126 }
127
128 base = osal_mem_alloc(size + alignment, &type);
129 if (base == NULL) {
130 HDF_LOGE("%s malloc fail %d", __func__, size);
131 return NULL;
132 }
133
134 buf = base + mng_size;
135 aligned_ptr = (char *)(uintptr_t)(((size_t)(uintptr_t)buf + alignment - 1) & ~(alignment - 1));
136 offset = aligned_ptr - buf;
137 block = (struct mem_block *)(base + offset);
138 block->hdr.type = type;
139 block->hdr.offset = offset;
140
141 return aligned_ptr;
142 }
143 EXPORT_SYMBOL(OsalMemAllocAlign);
144
OsalMemFree(void * buf)145 void OsalMemFree(void *buf)
146 {
147 uint32_t type;
148 char *base = NULL;
149 struct mem_block *block = NULL;
150
151 if (buf == NULL) {
152 return;
153 }
154
155 block = (struct mem_block *)((char *)buf - (char *)&((struct mem_block *)0)->mem);
156 type = block->hdr.type;
157 base = (char *)block - block->hdr.offset;
158
159 if (type == TYPE_KMALLOC)
160 kfree(base);
161 else if (type == TYPE_VMALLOC)
162 vfree(base);
163 else
164 HDF_LOGE("%s block : type %u fail", __func__, type);
165 }
166 EXPORT_SYMBOL(OsalMemFree);
167
168