1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Decription: memory operation for gp sharedmem.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
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 #include "mem.h"
15 #include <linux/slab.h>
16 #include <linux/uaccess.h>
17 #include <linux/sched.h>
18 #include <linux/list.h>
19 #include <linux/mutex.h>
20 #include <linux/freezer.h>
21 #include <linux/module.h>
22 #include <linux/mempool.h>
23 #include <linux/vmalloc.h>
24 #include <linux/of_reserved_mem.h>
25 #include <securec.h>
26 #include "smc_smp.h"
27 #include "tc_ns_client.h"
28 #include "teek_ns_client.h"
29 #include "agent.h"
30 #include "tc_ns_log.h"
31 #include "mailbox_mempool.h"
32 #include "internal_functions.h"
33 #include "reserved_mempool.h"
34
tc_mem_free(struct tc_ns_shared_mem *shared_mem)35 void tc_mem_free(struct tc_ns_shared_mem *shared_mem)
36 {
37 if (!shared_mem)
38 return;
39 if (shared_mem->mem_type == RESERVED_TYPE) {
40 reserved_mem_free(shared_mem->kernel_addr);
41 kfree(shared_mem);
42 return;
43 }
44
45 if (shared_mem->kernel_addr) {
46 #ifndef CONFIG_LIBLINUX
47 vfree(shared_mem->kernel_addr);
48 #else
49 kfree(shared_mem->kernel_addr);
50 #endif
51 shared_mem->kernel_addr = NULL;
52 }
53 kfree(shared_mem);
54 }
55
init_shared_mem(struct tc_ns_shared_mem *sh, void *addr, size_t len)56 static void init_shared_mem(struct tc_ns_shared_mem *sh, void *addr, size_t len)
57 {
58 sh->kernel_addr = addr;
59 sh->len = (uint32_t)len;
60 sh->user_addr = INVALID_MAP_ADDR;
61 sh->user_addr_ca = INVALID_MAP_ADDR;
62 atomic_set(&sh->usage, 0);
63 }
tc_mem_allocate(size_t len)64 struct tc_ns_shared_mem *tc_mem_allocate(size_t len)
65 {
66 struct tc_ns_shared_mem *shared_mem = NULL;
67 void *addr = NULL;
68
69 shared_mem = kmalloc(sizeof(*shared_mem), GFP_KERNEL | __GFP_ZERO);
70 if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)shared_mem)) {
71 tloge("shared_mem kmalloc failed\n");
72 return ERR_PTR(-ENOMEM);
73 }
74 shared_mem->mem_type = VMALLOC_TYPE;
75 len = ALIGN(len, SZ_4K);
76 if (exist_res_mem()) {
77 if (len > get_res_mem_slice_size()) {
78 tloge("allocate reserved mem size too large\n");
79 kfree(shared_mem);
80 return ERR_PTR(-EINVAL);
81 }
82 addr = reserved_mem_alloc(len);
83 if (addr) {
84 shared_mem->mem_type = RESERVED_TYPE;
85 init_shared_mem(shared_mem, addr, len);
86 return shared_mem;
87 } else {
88 tlogw("no more reserved memory to alloc so we use system vmalloc.\n");
89 }
90 }
91 if (len > MAILBOX_POOL_SIZE) {
92 tloge("alloc sharemem size %zu is too large\n", len);
93 kfree(shared_mem);
94 return ERR_PTR(-EINVAL);
95 }
96 #ifndef CONFIG_LIBLINUX
97 addr = vmalloc_user(len);
98 #else
99 addr = kzalloc(len, GFP_KERNEL);
100 #endif
101 if (!addr) {
102 tloge("alloc mailbox failed\n");
103 kfree(shared_mem);
104 return ERR_PTR(-ENOMEM);
105 }
106
107 init_shared_mem(shared_mem, addr, len);
108 return shared_mem;
109 }
110