Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : /*!
12 : * \file stub_base.cpp
13 : * \brief
14 : */
15 : #include <sys/stat.h>
16 : #include <csignal>
17 : #include <ctime>
18 : #include <fcntl.h>
19 : #include <sys/mman.h>
20 : #include <cstdlib>
21 : #include <string>
22 : #include <unistd.h>
23 : #include "securec.h"
24 : #include "stub_def.h"
25 :
26 : int64_t block_idx = 0;
27 : int64_t block_num = 8;
28 : int64_t g_ubBase = 0;
29 : uint64_t g_tilingKey = 0;
30 : int32_t g_coreType = 0; // mix = 0; cube = 1; vec = 2;
31 : int32_t g_matmulCount = 0;
32 236 : std::map<std::string, uint64_t>& GetArgVal()
33 : {
34 236 : static std::map<std::string, uint64_t> instance;
35 236 : return instance;
36 : }
37 :
38 : int32_t g_taskRation = 2;
39 : uint32_t g_threadDimX = 1u;
40 : uint32_t g_threadDimY = 1u;
41 : uint32_t g_threadDimZ = 1u;
42 : thread_local uint32_t g_threadIdxX = 0u;
43 : thread_local uint32_t g_threadIdxY = 0u;
44 : thread_local uint32_t g_threadIdxZ = 0u;
45 : int32_t sub_block_idx = 0;
46 6 : std::string& GetStrCoreType()
47 : {
48 14 : static std::string config = "mix";
49 6 : return config;
50 : }
51 : uint64_t* g_workspaceSharedPtr = nullptr;
52 : uint64_t g_fullSizeOfWorkspace = 0;
53 : KernelMode g_kernelMode = KernelMode::MIX_MODE;
54 : SocVersion g_socVersion = SocVersion::VER_MAX;
55 0 : std::vector<ArgInfoT>& GetArgInfoList()
56 : {
57 0 : static std::vector<ArgInfoT> instance;
58 0 : return instance;
59 : }
60 0 : std::vector<std::string>& GetValidArgTypeList()
61 : {
62 0 : static std::vector<std::string> instance;
63 0 : return instance;
64 : }
65 0 : std::vector<std::string>& GetTmpFileName()
66 : {
67 0 : static std::vector<std::string> instance;
68 0 : return instance;
69 : }
70 0 : std::vector<int32_t>& GetProcessId()
71 : {
72 0 : static std::vector<int32_t> instance;
73 0 : return instance;
74 : }
75 : int32_t g_mainPid = 0;
76 : int32_t g_processNum = 0;
77 : uint64_t g_fixpipeNdNzParam = 0;
78 :
79 : #ifdef TASK_RATION
80 : int32_t g_taskRation = TASK_RATION;
81 : #endif
82 :
83 : namespace AscendC {
84 : const int MIX_TYPE = 0;
85 : const int AIC_TYPE = 1;
86 : const int AIV_TYPE = 2;
87 : const uint64_t ONE_GIGABYTE = 1024 * 1024 * 1024;
88 : uint8_t g_fftsGlobalLock = 0;
89 : uint8_t (*g_syncCounterEachcore)[FLAG_NUM] = nullptr;
90 : uint8_t (*g_syncCounterFfts)[FLAG_NUM] = nullptr;
91 : const uint64_t DOUBLE = 2;
92 : bool g_isVdeq = false;
93 :
94 4 : void SetKernelMode(KernelMode mode)
95 : {
96 4 : g_kernelMode = mode;
97 4 : if (g_kernelMode == KernelMode::MIX_AIC_1_1) {
98 4 : g_taskRation = 1;
99 : }
100 4 : }
101 :
102 204 : void AddNameArg(const char* name, unsigned long val) { GetArgVal().emplace(name, val); }
103 :
104 12 : unsigned long GetNameArg(const char* name) { return static_cast<unsigned long>(GetArgVal().find(name)->second); }
105 :
106 4 : std::string BuildExp(uint64_t val)
107 : {
108 : char buff[256];
109 4 : std::string name = "";
110 4 : uint64_t offset = ARG_STEP;
111 :
112 204 : for (auto it : GetArgVal()) {
113 200 : if (offset > val - it.second) {
114 0 : offset = val - it.second;
115 0 : name = it.first;
116 : }
117 200 : }
118 4 : if (offset != 0) {
119 4 : int ret = snprintf_s(buff, sizeof(buff), sizeof(buff), "(((uint64_t)%s) + 0x%lx)", name.c_str(), offset);
120 4 : if (ret <= 0) {
121 0 : raise(SIGABRT);
122 : }
123 : } else {
124 0 : int ret = snprintf_s(buff, sizeof(buff), sizeof(buff), "%s", name.c_str());
125 0 : if (ret <= 0) {
126 0 : raise(SIGABRT);
127 : }
128 : }
129 8 : return std::string(buff);
130 4 : }
131 :
132 12 : bool FileExists(std::string fileName)
133 : {
134 : struct stat buffer;
135 12 : return stat(fileName.c_str(), &buffer) == 0;
136 : }
137 :
138 12 : uint64_t GetTime()
139 : {
140 12 : struct timespec ts {};
141 12 : (void)clock_gettime(CLOCK_MONOTONIC, &ts);
142 12 : uint64_t milliseconds = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
143 12 : return milliseconds;
144 : }
145 :
146 12 : std::string GetFileName()
147 : {
148 12 : std::string fileName = "/tmp/tmpfile_" + std::to_string(GetTime()) + "_" + std::to_string(getpid());
149 12 : while (FileExists(fileName)) {
150 0 : fileName = "/tmp/tmpfile_" + std::to_string(GetTime()) + "_" + std::to_string(getpid());
151 : }
152 12 : return fileName;
153 0 : }
154 :
155 36 : void HandleError(bool condition, const std::string& message, int fd)
156 : {
157 36 : if (condition) {
158 0 : std::cerr << "GmAlloc Error: " << message << std::endl;
159 0 : close(fd);
160 0 : raise(SIGABRT);
161 : }
162 36 : }
163 :
164 : /**
165 : * GM memory structure:
166 : * protect user tail 4k memory
167 : *
168 : * 0 4K <8K -4K END
169 : * +----------------------+----+----------------------------+----------------------+
170 : * | 4K HEADER READ ONLY |////|<------- USER SIZE -------->| 4K TAIL CANNOT ACCESS|
171 : * +----------------------+----+----------------------------+----------------------+
172 : * ^ ^
173 : * HEADER USER START USER TAIL 4K ALIGN
174 : */
175 :
176 12 : void* GmAlloc(size_t size)
177 : {
178 12 : size_t pageSize = getpagesize();
179 12 : size_t alignedExtraPageSize = pageSize * 2 + pageSize - 1; // 2 pages for header and tail
180 12 : if (size > (SIZE_MAX - alignedExtraPageSize)) {
181 0 : std::cerr << "GmAlloc Error: input size overflow detected." << std::endl;
182 0 : raise(SIGABRT);
183 : }
184 12 : size_t newSize = (size + alignedExtraPageSize) & (~(pageSize - 1)); // align to multiple page size
185 12 : std::string fileName = GetFileName();
186 12 : int fd = open(fileName.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
187 12 : HandleError(fd == -1, "Failed to open file: " + std::string(strerror(errno)), fd);
188 12 : int res = ftruncate(fd, newSize);
189 12 : if (errno == EFBIG) {
190 0 : HandleError(res != 0, "The /tmp directory does not have enough space.", fd);
191 : }
192 12 : auto filePtr = mmap(nullptr, newSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
193 12 : HandleError(filePtr == MAP_FAILED, "Error map file to ptr, error code: " + std::string(strerror(errno)), fd);
194 12 : if (static_cast<int>(reinterpret_cast<intptr_t>(filePtr)) == -1) {
195 0 : std::cout << "Error map file to ptr, error code: " << errno << std::endl;
196 0 : raise(SIGABRT);
197 : }
198 12 : ShmMemT* mem = static_cast<ShmMemT*>(filePtr);
199 12 : mem->fd = fd;
200 12 : mem->size = newSize;
201 12 : mem->magicCode = 0xdeadbeef;
202 12 : errno_t ret = strcpy_s(mem->fileName, sizeof(mem->fileName), fileName.c_str());
203 12 : HandleError(ret != EOK, "strcpy_s failed, ret = " + std::to_string(ret), fd);
204 12 : (void)mprotect(mem, pageSize, PROT_READ);
205 12 : (void)mprotect(reinterpret_cast<uint8_t*>(mem) + newSize - pageSize, pageSize, PROT_NONE);
206 12 : void* userStart = reinterpret_cast<uint8_t*>(mem) + newSize - pageSize - size;
207 12 : void* headerTail = reinterpret_cast<uint8_t*>(mem) + pageSize;
208 12 : if (userStart != headerTail) {
209 12 : size_t emptySize = (uint8_t*)userStart - (uint8_t*)headerTail;
210 12 : if (emptySize > 0) {
211 12 : memset_s(headerTail, emptySize, 0xff, emptySize);
212 : }
213 : }
214 12 : return userStart;
215 12 : }
216 :
217 12 : void* GmGetHeader(void* ptr)
218 : {
219 12 : int pageSize = getpagesize();
220 12 : return (void*)(((uint64_t)ptr & (~(pageSize - 1))) - pageSize);
221 : }
222 :
223 0 : uint64_t GmGetUserSize(uint64_t addr)
224 : {
225 0 : uint64_t pageSize = getpagesize();
226 0 : if (mprotect(reinterpret_cast<void*>(addr & ~(pageSize - 1)), pageSize, PROT_READ | PROT_WRITE) != 0) {
227 0 : return 0;
228 : }
229 0 : ShmMemT* mem = static_cast<AscendC::ShmMemT*>(AscendC::GmGetHeader(reinterpret_cast<void*>(addr)));
230 0 : size_t size = mem->size;
231 0 : uint64_t offset = addr - (addr & ~(pageSize - 1));
232 0 : return size - DOUBLE * pageSize - offset;
233 : }
234 :
235 12 : void CheckEmptyGmValied(void* ptr)
236 : {
237 12 : int pageSize = getpagesize();
238 12 : void* headerTail = (void*)((uint64_t)ptr & (~(pageSize - 1)));
239 12 : if (headerTail != ptr) {
240 36844 : for (uint8_t* tmpPtr = (uint8_t*)headerTail; tmpPtr < (uint8_t*)ptr; tmpPtr++) {
241 36832 : if (*(uint8_t*)tmpPtr != 0xff) {
242 0 : std::cout << "Empty memory is accessed ! or \
243 : this memory has been released more than one time."
244 0 : << std::endl;
245 0 : raise(SIGABRT);
246 : }
247 : }
248 : }
249 12 : }
250 :
251 12 : void GmFree(void* ptr)
252 : {
253 12 : int pageSize = getpagesize();
254 12 : CheckEmptyGmValied(ptr);
255 : int fd;
256 : size_t size;
257 : char file[256];
258 12 : ShmMemT* mem = static_cast<ShmMemT*>(GmGetHeader(ptr));
259 12 : fd = mem->fd;
260 12 : size = mem->size;
261 12 : errno_t ret = strcpy_s(file, sizeof(file), mem->fileName);
262 12 : if (ret != EOK) {
263 0 : std::cout << "strcpy_s failed, ret = " << ret << std::endl;
264 0 : raise(SIGABRT);
265 : }
266 12 : munmap(mem, size);
267 12 : close(fd);
268 12 : remove(file);
269 12 : (void)mprotect(mem, pageSize, PROT_READ | PROT_WRITE | PROT_EXEC);
270 12 : (void)mprotect(reinterpret_cast<uint8_t*>(mem) + size - pageSize, pageSize, PROT_READ | PROT_WRITE | PROT_EXEC);
271 12 : }
272 :
273 4 : void CheckGmValied(int argn, uint64_t* argv)
274 : {
275 8 : for (int i = 0; i < argn; i++) {
276 4 : int ret = mprotect(reinterpret_cast<void*>(argv[i] & 0xfff), 0x1000, PROT_READ | PROT_WRITE);
277 4 : if (ret != 0) {
278 4 : continue;
279 : }
280 0 : ShmMemT* mem = reinterpret_cast<ShmMemT*>(GmGetHeader((void*)argv[i]));
281 0 : if (mem->magicCode != 0xdeadbeef) {
282 0 : std::cout << "The address of args are not allocate by AscendC::GmAlloc!" << std::endl;
283 0 : raise(SIGABRT);
284 : }
285 : }
286 4 : }
287 :
288 0 : void CheckBlockdimForFfts(uint64_t numBlocks)
289 : {
290 : (void)(numBlocks);
291 : #if defined(__NPU_ARCH__) && __NPU_ARCH__ == 2201
292 0 : if ((g_kernelMode == KernelMode::MIX_MODE && numBlocks > MAX_CORE_NUM_V220) ||
293 0 : (g_kernelMode == KernelMode::AIC_MODE && numBlocks > MAX_CORE_NUM_V220) ||
294 0 : (g_kernelMode == KernelMode::AIV_MODE && numBlocks > MAX_CORE_NUM_V220 * AIV_IN_GROUP_CORE_NUM)) {
295 0 : std::cout << "The input numBlocks " << numBlocks << " exceed max core num of ascend910B1!" << std::endl;
296 0 : raise(SIGABRT);
297 : }
298 : #endif
299 0 : }
300 :
301 0 : void CheckNumBlocksForFfts(uint64_t numBlocks) { CheckBlockdimForFfts(numBlocks); }
302 :
303 0 : void SetGCoreType(int type)
304 : {
305 0 : if (type < MIX_TYPE || type > AIV_TYPE) {
306 0 : std::cout << "Error g_coreType!" << std::endl;
307 0 : raise(SIGABRT);
308 : }
309 0 : g_coreType = type;
310 0 : }
311 :
312 0 : void SetArgInfoList(const std::vector<ArgInfoT>& argInfoList) { GetArgInfoList() = argInfoList; }
313 : } // namespace AscendC
|