* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef DEVMM_COMMON_H
#define DEVMM_COMMON_H
#include "ka_base_pub.h"
#include "ka_memory_pub.h"
#include "ka_task_pub.h"
#include "ka_net_pub.h"
#include "ka_common_pub.h"
#include "ka_list_pub.h"
#include "ka_fs_pub.h"
#include "ka_driver_pub.h"
#include "ka_errno_pub.h"
#include "ka_system_pub.h"
#include "ka_kernel_def_pub.h"
#include "ka_compiler_pub.h"
#include "ka_barrier_pub.h"
#include "devmm_proc_info.h"
#include "svm_proc_gfp.h"
#include "devmm_mem_alloc_interface.h"
#ifndef __KA_GFP_ACCOUNT
#ifdef __KA_GFP_KMEMCG
#define __KA_GFP_ACCOUNT __KA_GFP_KMEMCG
#endif
#ifdef __KA_GFP_NOACCOUNT
#define __KA_GFP_ACCOUNT 0
#endif
#endif
#define DEVMM_BITS_PER_CHAR 8
#define DEVMM_PAGENUM_PER_HPAGE (KA_HPAGE_SIZE / KA_MM_PAGE_SIZE)
#define DEVMM_WAKEUP_TIMEINTERVAL 500
#define DEVMM_SVM_MMU_MIN_SLEEP 50
#define DEVMM_SVM_MMU_MAX_SLEEP 60
#define SVM_DEV_INST_MAX_NUM (SVM_MAX_AGENT_NUM * DEVMM_MAX_VF_NUM)
#define SVM_MASTER_HUGE_PAGE_SIZE 0x200000ULL
#define SVM_MASTER_GIANT_PAGE_SIZE 0x40000000ULL
#if KA_MAX_NUMNODES > 256
#define SVM_MASTER_NUMA_MAX 256
#else
#define SVM_MASTER_NUMA_MAX KA_MAX_NUMNODES
#endif
#define DEVMM_S2S_HOST_GLOBAL_BASE_OFFSET 0x800000000000
#define DEVMM_S2S_HOST_NODE_NUM 4
#ifdef EMU_ST
#define DEVMM_S2S_HOST_NODE_MEM_SIZE 0x40000000
#else
#define DEVMM_S2S_HOST_NODE_MEM_SIZE 0xaa80000000
#endif
#define DEVMM_S2S_HOST_SERVER_MEM_SIZE (DEVMM_S2S_HOST_NODE_MEM_SIZE * DEVMM_S2S_HOST_NODE_NUM)
static inline u64 devmm_get_s2s_host_node_start_addr(u32 server_id, u32 node_id)
{
return (DEVMM_S2S_HOST_GLOBAL_BASE_OFFSET +
DEVMM_S2S_HOST_SERVER_MEM_SIZE * server_id + DEVMM_S2S_HOST_NODE_MEM_SIZE * node_id);
}
static inline u64 devmm_get_host_node_local_addr(u32 node_id)
{
u64 mem_node_start[DEVMM_S2S_HOST_NODE_NUM] = {
0x29580000000,
0xa9580000000,
0x129580000000,
0x1a9580000000
};
return mem_node_start[node_id];
}
static inline u32 devmm_get_host_node_id_by_addr(u64 addr)
{
u32 i;
for (i = 0; i < DEVMM_S2S_HOST_NODE_NUM; i++) {
u64 node_local_addr = devmm_get_host_node_local_addr(i);
if ((addr >= node_local_addr) && (addr < (node_local_addr + DEVMM_S2S_HOST_NODE_MEM_SIZE))) {
return i;
}
}
return DEVMM_S2S_HOST_NODE_NUM;
}
static inline int devmm_get_s2s_host_global_addr(u32 server_id, u64 addr, u64 *global_addr)
{
u32 node_id = 0;
#ifndef EMU_ST
node_id = devmm_get_host_node_id_by_addr(addr);
if (node_id >= DEVMM_S2S_HOST_NODE_NUM) {
return -EINVAL;
}
#endif
*global_addr = devmm_get_s2s_host_node_start_addr(server_id, node_id) +
(addr - devmm_get_host_node_local_addr(node_id));
return 0;
}
struct svm_id_inst {
u32 devid;
u32 vfid;
};
static inline void svm_id_inst_pack(struct svm_id_inst *inst, u32 devid, u32 vfid)
{
inst->devid = devid;
inst->vfid = vfid;
}
static inline u32 svm_id_inst_to_dev_inst(struct svm_id_inst *id_inst)
{
return (id_inst->devid * DEVMM_MAX_VF_NUM + id_inst->vfid);
}
static inline bool devmm_heap_subtype_is_matched(u32 heap_subtype, u32 mask)
{
return ((mask & (1ul << heap_subtype)) != 0) ? true : false;
}
#ifndef EMU_ST
static inline bool devmm_pages_is_continue(ka_page_t *pre_page, ka_page_t *post_page)
{
return (ka_mm_page_to_pfn(pre_page) + 1) == ka_mm_page_to_pfn(post_page);
}
#else
static inline bool devmm_pages_is_continue(ka_page_t *pre_page, ka_page_t *post_page)
{
return false;
}
#endif
static inline void devmm_isb(void)
{
#if defined(__arm__) || defined(__aarch64__)
ka_isb();
#endif
}
extern bool g_devmm_true;
extern bool g_devmm_false;
u32 devmm_get_max_page_num_of_per_msg(u32 *bitmap);
void devmm_try_usleep_by_time(u32 *pre_stamp, u32 time);
void devmm_try_cond_resched(u32 *pre_stamp);
void devmm_try_cond_resched_by_time(u32 *pre_stamp, u32 time);
bool devmm_smmu_is_opening(void);
int devmm_pin_user_pages_fast(u64 va, u64 total_num, int write, ka_page_t **pages);
void devmm_unpin_user_pages(ka_page_t **pages, u64 page_num, u64 unpin_num);
void devmm_put_user_pages(ka_page_t **pages, u64 page_num, u64 unpin_num);
void devmm_pin_user_pages(ka_page_t **pages, u64 page_num);
u64 devmm_get_pagecount_by_size(u64 vptr, u64 sizes, u32 page_size);
int devmm_check_va_add_size_by_heap(struct devmm_svm_heap *heap, u64 va, u64 size);
bool devmm_check_input_heap_info(struct devmm_svm_process *svm_pro,
struct devmm_update_heap_para *cmd, u32 devid);
ssize_t devmm_read_file(ka_file_t *fp, char *dst_addr, size_t fsize, loff_t *pos);
char *devmm_read_line(ka_file_t *fp, loff_t *offset, char *buf, u32 buf_len);
void *devmm_kvalloc(u64 size, ka_gfp_t flags);
void *devmm_kvzalloc(u64 size);
void devmm_kvfree(const void *ptr);
void devmm_set_heap_used_status(struct devmm_svm_heap *heap, u64 va, u64 size);
ka_vm_area_struct_t *devmm_find_vma(struct devmm_svm_process *svm_proc, u64 vaddr);
ka_vm_area_struct_t *devmm_find_vma_custom(struct devmm_svm_process *svm_proc, u32 idx, u64 vaddr);
ka_mm_struct_t *devmm_custom_mm_get(ka_pid_t custom_pid);
void devmm_custom_mm_put(ka_mm_struct_t *custom_mm);
int devmm_update_heap_info(struct devmm_svm_process *svm_process, struct devmm_update_heap_para *cmd,
struct devmm_svm_heap *free_heap);
void devmm_free_heap_struct(struct devmm_svm_process *svm_process, u32 heap_idx, u32 heap_num);
void devmm_clear_svm_heap_struct(struct devmm_svm_process *svm_process, u32 heap_idx, u32 heap_num);
bool devmm_wait_svm_heap_unoccupied(struct devmm_svm_process *svm_process, struct devmm_svm_heap *heap);
struct devmm_svm_heap *devmm_get_heap_by_idx(struct devmm_svm_process *svm_proc, u32 heap_idx);
struct devmm_svm_heap *devmm_get_heap_by_va(struct devmm_svm_process *svm_proc, u64 vaddr);
bool devmm_check_heap_is_entity(struct devmm_svm_heap *heap);
int devmm_shm_inform_host_get_pages(struct devmm_svm_process_id *process_id, u64 va, u64 size);
int devmm_shm_inform_host_put_pages(struct devmm_svm_process_id *process_id, u64 va, u64 size);
void devmm_dev_fault_flag_set(u32 *flag, u32 shift, u32 wide, u32 value);
u32 devmm_dev_fault_flag_get(u32 flag, u32 shift, u32 wide);
bool devmm_is_pcie_connect(u32 dev_id);
bool devmm_is_hccs_connect(u32 dev_id);
bool devmm_is_host_agent(u32 agent_id);
bool devmm_is_dma_link_abnormal(u32 dev_id);
const char *devmm_get_chrdev_name(void);
void devmm_set_proc_vma(ka_mm_struct_t *mm, ka_vm_area_struct_t *vma[], u32 vma_num);
int devmm_get_svm_pages(ka_vm_area_struct_t *vma, u64 va, u64 num, ka_page_t **pages);
void devmm_svm_mem_enable(struct devmm_svm_process *svm_proc);
void devmm_svm_mem_disable(struct devmm_svm_process *svm_proc);
bool devmm_svm_mem_is_enable(struct devmm_svm_process *svm_proc);
void devmm_phy_addr_attr_pack(struct devmm_svm_process *svm_proc, u32 pg_type, u32 mem_type, bool is_continuous,
struct devmm_phy_addr_attr *attr);
u64 devmm_get_tgid_start_time(void);
#ifdef EMU_ST
ka_vm_area_struct_t *devmm_find_vma_from_mm(ka_mm_struct_t *mm, u64 vaddr);
#endif
extern u32 uda_get_host_id(void);
bool devmm_palist_is_continuous(u64 *pa, u32 num, u32 page_size);
bool devmm_palist_is_specify_continuous(u64 *pa, u32 page_size, u32 total_num, u32 min_con_num);
void devmm_update_devids(struct devmm_devid *devids, u32 logical_devid, u32 devid, u32 vfid);
#endif