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 35void 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 56static 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} 64struct 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