1419b0af8Sopenharmony_ci/* 2419b0af8Sopenharmony_ci * Copyright (C) 2022 Huawei Technologies Co., Ltd. 3419b0af8Sopenharmony_ci * Decription: memory operation for gp sharedmem. 4419b0af8Sopenharmony_ci * 5419b0af8Sopenharmony_ci * This software is licensed under the terms of the GNU General Public 6419b0af8Sopenharmony_ci * License version 2, as published by the Free Software Foundation, and 7419b0af8Sopenharmony_ci * may be copied, distributed, and modified under those terms. 8419b0af8Sopenharmony_ci * 9419b0af8Sopenharmony_ci * This program is distributed in the hope that it will be useful, 10419b0af8Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11419b0af8Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12419b0af8Sopenharmony_ci * GNU General Public License for more details. 13419b0af8Sopenharmony_ci */ 14419b0af8Sopenharmony_ci#include "mem.h" 15419b0af8Sopenharmony_ci#include <linux/slab.h> 16419b0af8Sopenharmony_ci#include <linux/uaccess.h> 17419b0af8Sopenharmony_ci#include <linux/sched.h> 18419b0af8Sopenharmony_ci#include <linux/list.h> 19419b0af8Sopenharmony_ci#include <linux/mutex.h> 20419b0af8Sopenharmony_ci#include <linux/freezer.h> 21419b0af8Sopenharmony_ci#include <linux/module.h> 22419b0af8Sopenharmony_ci#include <linux/mempool.h> 23419b0af8Sopenharmony_ci#include <linux/vmalloc.h> 24419b0af8Sopenharmony_ci#include <linux/of_reserved_mem.h> 25419b0af8Sopenharmony_ci#include <securec.h> 26419b0af8Sopenharmony_ci#include "smc_smp.h" 27419b0af8Sopenharmony_ci#include "tc_ns_client.h" 28419b0af8Sopenharmony_ci#include "teek_ns_client.h" 29419b0af8Sopenharmony_ci#include "agent.h" 30419b0af8Sopenharmony_ci#include "tc_ns_log.h" 31419b0af8Sopenharmony_ci#include "mailbox_mempool.h" 32419b0af8Sopenharmony_ci#include "internal_functions.h" 33419b0af8Sopenharmony_ci#include "reserved_mempool.h" 34419b0af8Sopenharmony_ci 35419b0af8Sopenharmony_civoid tc_mem_free(struct tc_ns_shared_mem *shared_mem) 36419b0af8Sopenharmony_ci{ 37419b0af8Sopenharmony_ci if (!shared_mem) 38419b0af8Sopenharmony_ci return; 39419b0af8Sopenharmony_ci if (shared_mem->mem_type == RESERVED_TYPE) { 40419b0af8Sopenharmony_ci reserved_mem_free(shared_mem->kernel_addr); 41419b0af8Sopenharmony_ci kfree(shared_mem); 42419b0af8Sopenharmony_ci return; 43419b0af8Sopenharmony_ci } 44419b0af8Sopenharmony_ci 45419b0af8Sopenharmony_ci if (shared_mem->kernel_addr) { 46419b0af8Sopenharmony_ci#ifndef CONFIG_LIBLINUX 47419b0af8Sopenharmony_ci vfree(shared_mem->kernel_addr); 48419b0af8Sopenharmony_ci#else 49419b0af8Sopenharmony_ci kfree(shared_mem->kernel_addr); 50419b0af8Sopenharmony_ci#endif 51419b0af8Sopenharmony_ci shared_mem->kernel_addr = NULL; 52419b0af8Sopenharmony_ci } 53419b0af8Sopenharmony_ci kfree(shared_mem); 54419b0af8Sopenharmony_ci} 55419b0af8Sopenharmony_ci 56419b0af8Sopenharmony_cistatic void init_shared_mem(struct tc_ns_shared_mem *sh, void *addr, size_t len) 57419b0af8Sopenharmony_ci{ 58419b0af8Sopenharmony_ci sh->kernel_addr = addr; 59419b0af8Sopenharmony_ci sh->len = (uint32_t)len; 60419b0af8Sopenharmony_ci sh->user_addr = INVALID_MAP_ADDR; 61419b0af8Sopenharmony_ci sh->user_addr_ca = INVALID_MAP_ADDR; 62419b0af8Sopenharmony_ci atomic_set(&sh->usage, 0); 63419b0af8Sopenharmony_ci} 64419b0af8Sopenharmony_cistruct tc_ns_shared_mem *tc_mem_allocate(size_t len) 65419b0af8Sopenharmony_ci{ 66419b0af8Sopenharmony_ci struct tc_ns_shared_mem *shared_mem = NULL; 67419b0af8Sopenharmony_ci void *addr = NULL; 68419b0af8Sopenharmony_ci 69419b0af8Sopenharmony_ci shared_mem = kmalloc(sizeof(*shared_mem), GFP_KERNEL | __GFP_ZERO); 70419b0af8Sopenharmony_ci if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)shared_mem)) { 71419b0af8Sopenharmony_ci tloge("shared_mem kmalloc failed\n"); 72419b0af8Sopenharmony_ci return ERR_PTR(-ENOMEM); 73419b0af8Sopenharmony_ci } 74419b0af8Sopenharmony_ci shared_mem->mem_type = VMALLOC_TYPE; 75419b0af8Sopenharmony_ci len = ALIGN(len, SZ_4K); 76419b0af8Sopenharmony_ci if (exist_res_mem()) { 77419b0af8Sopenharmony_ci if (len > get_res_mem_slice_size()) { 78419b0af8Sopenharmony_ci tloge("allocate reserved mem size too large\n"); 79419b0af8Sopenharmony_ci kfree(shared_mem); 80419b0af8Sopenharmony_ci return ERR_PTR(-EINVAL); 81419b0af8Sopenharmony_ci } 82419b0af8Sopenharmony_ci addr = reserved_mem_alloc(len); 83419b0af8Sopenharmony_ci if (addr) { 84419b0af8Sopenharmony_ci shared_mem->mem_type = RESERVED_TYPE; 85419b0af8Sopenharmony_ci init_shared_mem(shared_mem, addr, len); 86419b0af8Sopenharmony_ci return shared_mem; 87419b0af8Sopenharmony_ci } else { 88419b0af8Sopenharmony_ci tlogw("no more reserved memory to alloc so we use system vmalloc.\n"); 89419b0af8Sopenharmony_ci } 90419b0af8Sopenharmony_ci } 91419b0af8Sopenharmony_ci if (len > MAILBOX_POOL_SIZE) { 92419b0af8Sopenharmony_ci tloge("alloc sharemem size %zu is too large\n", len); 93419b0af8Sopenharmony_ci kfree(shared_mem); 94419b0af8Sopenharmony_ci return ERR_PTR(-EINVAL); 95419b0af8Sopenharmony_ci } 96419b0af8Sopenharmony_ci#ifndef CONFIG_LIBLINUX 97419b0af8Sopenharmony_ci addr = vmalloc_user(len); 98419b0af8Sopenharmony_ci#else 99419b0af8Sopenharmony_ci addr = kzalloc(len, GFP_KERNEL); 100419b0af8Sopenharmony_ci#endif 101419b0af8Sopenharmony_ci if (!addr) { 102419b0af8Sopenharmony_ci tloge("alloc mailbox failed\n"); 103419b0af8Sopenharmony_ci kfree(shared_mem); 104419b0af8Sopenharmony_ci return ERR_PTR(-ENOMEM); 105419b0af8Sopenharmony_ci } 106419b0af8Sopenharmony_ci 107419b0af8Sopenharmony_ci init_shared_mem(shared_mem, addr, len); 108419b0af8Sopenharmony_ci return shared_mem; 109419b0af8Sopenharmony_ci} 110