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 : #include "ccu_jetty_ctx_mgr_legacy.h"
12 :
13 : #include "ccu_res_specs_legacy.h"
14 : #include "orion_adapter_hccp.h"
15 : #include "resources_not_exist_exception.h"
16 : #include "hccp_tlv_hdc_manager.h"
17 :
18 : namespace Hccl {
19 :
20 : // 对一个数求以2为底的对数,num已保证不为0
21 28 : inline uint16_t Log2OfPowerOfTwo(uint32_t num)
22 : {
23 28 : uint16_t log2 = 0;
24 140 : while (num > 1) {
25 112 : num >>= 1;
26 112 : log2++;
27 : }
28 28 : return log2;
29 : }
30 :
31 : union DoorbellAddr {
32 : uint64_t dbAddr;
33 : uint16_t dbAddr16[4];
34 : };
35 :
36 : LocalJettyCtxData
37 28 : BuildJettyCtxData(const uint8_t dieId, const uint32_t pfeId, const JettyInfo& jettyInfo, const JettyCfg& jettyCfg)
38 : {
39 28 : LocalJettyCtxData data{};
40 :
41 : DoorbellAddr dbAddr;
42 28 : dbAddr.dbAddr = jettyCfg.dbVa;
43 28 : data.doorbellAddr[0] = dbAddr.dbAddr16[0];
44 28 : data.doorbellAddr[1] = dbAddr.dbAddr16[1];
45 28 : data.doorbellAddr[2] = dbAddr.dbAddr16[2]; // 2: doorbell 地址访问
46 28 : data.doorbellAddr[3] = dbAddr.dbAddr16[3]; // 3: doorbell 地址访问
47 :
48 28 : data.pfeIdx = static_cast<uint8_t>(pfeId);
49 28 : data.ioDieId = dieId;
50 :
51 28 : data.doorbellAddrType = DB_ADDR_TYPE;
52 28 : data.tokenValueIsValid = TOKEN_VALUE_IS_VALIDE;
53 :
54 28 : data.tokenIdLow = jettyCfg.dbTokenId & MASK_TK_ID_LOW;
55 28 : data.tokenIdHigh = (jettyCfg.dbTokenId >> SHIFT_8BITS) & MASK_TK_ID_HIGH; // tokenId右移8位
56 :
57 28 : data.tokenValueLow = jettyCfg.dbTokenValue & MASK_TK_VALUE_LOW;
58 28 : data.tokenValueMiddle = (jettyCfg.dbTokenValue >> SHIFT_4BITS) & MASK_TK_VALUE_MID; // tokenValue右移4位
59 28 : data.tokenValueHigh = (jettyCfg.dbTokenValue >> SHIFT_20BITS) & MASK_TK_VALUE_HIGH; // tokenValue右移20位
60 :
61 28 : const uint16_t wqeBBShift = Log2OfPowerOfTwo(jettyInfo.sqDepth * CCU_WQE_NUM_PER_SQE);
62 28 : data.sqeBasicBlockLeftShifts = wqeBBShift;
63 :
64 28 : const uint16_t wqeBBIdx = jettyInfo.wqeBBStartId;
65 28 : data.startWqeBasicBlockIdxLow = wqeBBIdx & MASK_WQEBB_IDX_LOW;
66 28 : data.startWqeBasicBlockIdxHigh = (wqeBBIdx >> SHIFT_4BITS) & MASK_WQEBB_IDX_HIGH; // 右移4位
67 :
68 28 : data.pi = CCU_HARDWARE_DEFAULT_VALUE;
69 28 : data.ci = CCU_HARDWARE_DEFAULT_VALUE;
70 28 : data.maxCi = CCU_HARDWARE_DEFAULT_VALUE;
71 28 : data.oooCqeCnt = CCU_HARDWARE_DEFAULT_VALUE;
72 28 : data.doorbellSendState = CCU_HARDWARE_DEFAULT_VALUE;
73 :
74 28 : return data;
75 : }
76 :
77 28 : void DumpJettyCtxData(const LocalJettyCtxData& tmp)
78 : {
79 84 : HCCL_RUN_INFO(
80 : "doorbellAddr: [3]0x%04x, [2]0x%04x, [1]0x%04x, [0]0x%04x",
81 : tmp.doorbellAddr[3], // 3: doorbell 地址访问
82 : tmp.doorbellAddr[2], // 2: doorbell 地址访问
83 : tmp.doorbellAddr[1], tmp.doorbellAddr[0]);
84 :
85 : // 安全问题:禁止打印token相关信息
86 84 : HCCL_RUN_INFO(
87 : "pfeIdx: 0x%04x, ioDieId: 0x%04x, doorbellAddrType: 0x%04x, "
88 : "tokenValueIsValid: 0x%04x",
89 : tmp.pfeIdx, tmp.ioDieId, tmp.doorbellAddrType, tmp.tokenValueIsValid);
90 :
91 84 : HCCL_RUN_INFO(
92 : "sqeBasicBlockLeftShifts: 0x%04x, pi: 0x%04x, ci: 0x%04x, "
93 : "maxCi: 0x%04x, oooCqeCnt: 0x%04x, startWqeBasicBlockIdxLow: 0x%04x, "
94 : "startWqeBasicBlockIdxHigh: 0x%04x, doorbellSendState: 0x%04x",
95 : tmp.sqeBasicBlockLeftShifts, tmp.pi, tmp.ci, tmp.maxCi, tmp.oooCqeCnt, tmp.startWqeBasicBlockIdxLow,
96 : tmp.startWqeBasicBlockIdxHigh, tmp.doorbellSendState);
97 28 : }
98 :
99 26 : void ConfigJettyCtxData(
100 : const int32_t devLogicId, const uint8_t dieId, const uint16_t startJettyCtxId,
101 : std::vector<LocalJettyCtxData>& jettyCtxData)
102 : {
103 26 : const uint32_t jettyNum = jettyCtxData.size(); // 分配与配置前校验已保证不为0
104 26 : auto tlvHandle = HccpTlvHdcManager::GetInstance().GetTlvHandle(devLogicId);
105 26 : CHECK_NULLPTR(
106 52 : tlvHandle, StringFormat("[CcuJettyCtxMgr][%s] tlvHandle is nullptr, devLogicId[%d]", __func__, devLogicId));
107 :
108 26 : struct CustomChannelInfoIn inBuff;
109 26 : struct CustomChannelInfoOut outBuff;
110 :
111 26 : inBuff.op = CcuOpcodeType::CCU_U_OP_SET_JETTY_CTX;
112 26 : (void)memset_s(inBuff.data.raw, sizeof(inBuff.data.raw), 0, sizeof(inBuff.data.raw));
113 :
114 26 : inBuff.data.dataInfo.udieIdx = dieId;
115 26 : inBuff.data.dataInfo.dataArraySize = jettyNum;
116 :
117 : // 设置数据长度,目前设备管理最多使用5个JettyCtx,需要长度上限为 32 * 5 = 160B
118 26 : inBuff.data.dataInfo.dataLen = sizeof(struct LocalJettyCtxData) * inBuff.data.dataInfo.dataArraySize;
119 26 : inBuff.offsetStartIdx = startJettyCtxId; // 设置起始Jetty上下文ID,注意应从0开始,非TaJettyId
120 :
121 78 : HCCL_INFO(
122 : "[CcuJettyCtxMgr][%s] iodie[%u], startJettyCtxId[%u], jettyCtxData.size[%u]", __func__, dieId, startJettyCtxId,
123 : jettyNum);
124 :
125 54 : for (size_t i = 0; i < jettyNum; i++) {
126 28 : DumpJettyCtxData(jettyCtxData[i]);
127 :
128 28 : (void)memcpy_s(
129 28 : &inBuff.data.dataInfo.dataArray[i], sizeof(struct LocalJettyCtxData), &jettyCtxData[i],
130 : sizeof(struct LocalJettyCtxData));
131 : }
132 :
133 26 : HrtRaTlvRequestForCustomChannel(
134 : tlvHandle, MSG_TYPE_CCU_DISPATCH_CMD, static_cast<void*>(&inBuff), static_cast<void*>(&outBuff));
135 26 : }
136 :
137 24 : CcuJettyCtxMgr::CcuJettyCtxMgr(const int32_t devLogicId, const uint8_t dieId, const uint32_t devPhyId)
138 24 : : devLogicId(devLogicId),
139 24 : dieId(dieId),
140 24 : devPhyId(devPhyId),
141 24 : wqeBBMgr(devLogicId, dieId)
142 : {
143 : // 获取失败或为0场景,分配将按资源不足操作
144 24 : (void)CcuResSpecifications::GetInstance(devLogicId).GetJettyNum(dieId, jettySpecNum);
145 24 : (void)CcuResSpecifications::GetInstance(devLogicId).GetResourceAddr(dieId, ccuResBaseVa);
146 24 : if (UNLIKELY(ccuResBaseVa == 0)) { // 直接抛异常终止,避免访问非法地址
147 0 : THROW<ResourcesNotExistException>(
148 : "[CcuJettyCtxMgr] init failed, ccu resource base addr is 0, "
149 : "devLogicId[%d] dieId[%u].",
150 : devLogicId, dieId);
151 : }
152 24 : pfeMgr = CcuPfeMgr(devLogicId, dieId, devPhyId);
153 24 : }
154 :
155 34 : static HcclResult GetSqeBuffVa(const uint64_t ccuResBaseVa, const uint32_t jettyCtxId, uint64_t& sqeBuffVa)
156 : {
157 34 : sqeBuffVa = 0;
158 34 : if (UINT32_MAX / CCU_SQ_BUFFER_SIZE < jettyCtxId) {
159 0 : HCCL_ERROR(
160 : "[CcuJettyCtxMgr][%s] jetty context id[%u] is greater "
161 : "than expected, CCU_SQ_UBFFER_SIZE[%u], their product will exceed the "
162 : "range of uint32_t.",
163 : __func__, jettyCtxId, CCU_SQ_BUFFER_SIZE);
164 0 : return HcclResult::HCCL_E_INTERNAL;
165 : }
166 34 : const uint64_t jettyCtxOffset = static_cast<uint64_t>(jettyCtxId) * CCU_SQ_BUFFER_SIZE;
167 :
168 34 : if (UINT64_MAX - CCU_V1_WQE_BASIC_BLOCK_OFFSET - jettyCtxOffset < ccuResBaseVa) {
169 0 : HCCL_ERROR(
170 : "[CcuJettyCtxMgr][%s] ccu resource space base va[%llu] "
171 : "is greater than expected, jettyCtxId[%u], the sqe buff va exceed the "
172 : "range of uint64_t.",
173 : __func__, ccuResBaseVa, jettyCtxId);
174 0 : return HcclResult::HCCL_E_INTERNAL;
175 : }
176 :
177 : // 内部分配保证jettyCtxId 小于 jettyCtx规格数量,地址不应越界
178 34 : sqeBuffVa = ccuResBaseVa + CCU_V1_WQE_BASIC_BLOCK_OFFSET + jettyCtxOffset;
179 34 : return HcclResult::HCCL_SUCCESS;
180 : }
181 :
182 28 : HcclResult CcuJettyCtxMgr::TryAllocWqeBBResource(
183 : const uint32_t sqSize, const uint32_t jettyCtxStartId, const uint32_t taJettyStartId, const CcuJettyType jettyType,
184 : std::vector<JettyInfo>& jettyInfos)
185 : {
186 28 : const uint32_t jettyNum = jettyInfos.size();
187 28 : if (jettyNum == 0) {
188 0 : HCCL_WARNING(
189 : "[CcuJettyCtxMgr][%s] failed, jettyInfos size is 0, "
190 : "devLogicId[%d], dieId[%u].",
191 : __func__, devLogicId, dieId);
192 0 : return HcclResult::HCCL_E_PARA;
193 : }
194 :
195 62 : for (uint32_t i = 0; i < jettyNum; i++) {
196 34 : ResInfo wqeBBInfo(0, 0);
197 34 : HcclResult ret = wqeBBMgr.Alloc(sqSize, wqeBBInfo);
198 34 : if (ret != HcclResult::HCCL_SUCCESS) {
199 0 : HCCL_WARNING(
200 : "[CcuJettyCtxMgr][%s] failed to alloc wqe basic block resource, "
201 : "devLogicId[%d], dieId[%u].",
202 : __func__, devLogicId, dieId);
203 0 : return ret;
204 : }
205 :
206 34 : auto& jettyInfo = jettyInfos[i];
207 34 : jettyInfo.jettyType = jettyType;
208 34 : jettyInfo.jettyCtxId = static_cast<uint16_t>(jettyCtxStartId + i);
209 34 : jettyInfo.taJettyId = static_cast<uint16_t>(taJettyStartId + i);
210 :
211 34 : const uint32_t wqeBBReqNum = wqeBBInfo.num;
212 34 : jettyInfo.sqDepth = wqeBBReqNum / CCU_WQE_NUM_PER_SQE;
213 34 : jettyInfo.wqeBBStartId = wqeBBInfo.startId;
214 34 : if (jettyType == CcuJettyType::CCUM_CACHED_JETTY) {
215 34 : jettyInfo.sqBufSize = wqeBBReqNum * CCU_ONE_WQE_SIZE;
216 34 : CHK_RET(GetSqeBuffVa(
217 : ccuResBaseVa, static_cast<uint32_t>(jettyInfo.jettyCtxId),
218 : jettyInfo.sqBufVa)); // 检查溢出,分配成功的wqeBB资源已经记录
219 : }
220 : }
221 :
222 28 : return HcclResult::HCCL_SUCCESS;
223 : }
224 :
225 2 : HcclResult CcuJettyCtxMgr::ReleaseWqeBBResource(const std::vector<JettyInfo>& jettyInfos)
226 : {
227 6 : for (const auto& jettyInfo : jettyInfos) {
228 4 : if (jettyInfo.sqDepth == 0) {
229 0 : continue; // 该jetty未分配完成,跳过wqeBB资源释放
230 : }
231 :
232 4 : uint32_t wqeBBIdx = static_cast<uint32_t>(jettyInfo.wqeBBStartId);
233 : // jettyInfo 为内部数据,分配保证不会溢出
234 4 : uint32_t wqeBBNum = jettyInfo.sqDepth * CCU_WQE_NUM_PER_SQE;
235 4 : const auto resInfo = ResInfo(wqeBBIdx, wqeBBNum);
236 4 : CHK_RET(wqeBBMgr.Release(resInfo));
237 : }
238 2 : return HcclResult::HCCL_SUCCESS;
239 : }
240 :
241 28 : HcclResult CcuJettyCtxMgr::CheckIfJettyCfgsValid(
242 : const std::vector<JettyInfo>& jettyInfos, const std::vector<JettyCfg>& jettyCfgs) const
243 : {
244 28 : const uint32_t jettyNum = jettyInfos.size();
245 28 : const uint32_t jettyCfgNum = jettyCfgs.size();
246 31 : CHK_PRT_RET(
247 : jettyCfgNum != jettyNum,
248 : HCCL_ERROR(
249 : "[CcuJettyCtxMgr][%s] failed, jettyCfgs size[%u] is not expected, "
250 : "which should be equal to jettyInfo size[%u], devLogicId[%d], dieId[%u].",
251 : __func__, jettyCfgNum, jettyNum, devLogicId, dieId),
252 : HcclResult::HCCL_E_PARA);
253 :
254 57 : for (uint32_t i = 0; i < jettyNum; i++) {
255 31 : if (jettyInfos[i].jettyCtxId != jettyCfgs[i].jettyCtxId) {
256 3 : HCCL_ERROR(
257 : "[CcuJettyCtxMgr][%s] failed, jettyCtxId of jettyInfo[%u] and "
258 : "jettyCfg[%u] are not same, devLogicId[%d], dieId[%u].",
259 : __func__, jettyInfos[i].jettyCtxId, jettyCfgs[i].jettyCtxId, devLogicId, dieId);
260 1 : return HcclResult::HCCL_E_PARA;
261 : }
262 : }
263 26 : return HcclResult::HCCL_SUCCESS;
264 : }
265 :
266 : }; // namespace Hccl
|