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