LCOV - code coverage report
Current view: top level - legacy/ascend910/platform/resource/mem - hdc.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.7 % 187 164
Test Date: 2026-08-18 17:47:01 Functions: 100.0 % 15 15

            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 "hdc_pub.h"
      12              : #include "log.h"
      13              : #include "ascend_hal.h"
      14              : #include "adapter_hal.h"
      15              : #include "adapter_rts.h"
      16              : #include <atomic>
      17              : #include <chrono>
      18              : 
      19              : namespace hccl {
      20          978 : HDCommunicate::HDCommunicate(u32 deviceLogicId, u32 flag, u32 buffLen)
      21          978 :     : deviceLogicId_(deviceLogicId),
      22          978 :       flag_(flag),
      23          978 :       buffLen_(buffLen)
      24          978 : {}
      25          198 : HDCommunicate::HDCommunicate() : deviceLogicId_(INVALID_UINT), flag_(0), buffLen_(0) {}
      26              : 
      27         1175 : HDCommunicate::~HDCommunicate()
      28              : {
      29         1175 :     if (isHost_ && devMem_.ptr() && supportDevMemReg_) {
      30          965 :         (void)hrtHalHostUnregister(devMem_.ptr(), deviceLogicId_);
      31              :     }
      32         1174 : }
      33              : 
      34              : // 在device中申请共享内存,其数据格式如下所示:
      35              : //     +---------------------+
      36              : //     |                     |
      37              : //     |      content        |
      38              : //     |                     |
      39              : //     +---------------------+
      40              : //     |    head_cnt[u32]    |
      41              : //     +---------------------+
      42              : //     |    tail_cnt[u32]    |
      43              : //     +---------------------+
      44              : // 发送方更新content前,需要将head_cnt加1,更新数据后需要将tail_cnt加1;
      45              : // 接收方在读取数据前判断共享内存中的tail_cnt和本地cache中的tailcnt是否一致,如不一致则需要更新本地cache;
      46              : //      更新本地cache时,需要确保cache中head_cnt和tail_cnt一致,否则舍弃本次数据,继续更新cache直至一致;
      47              : 
      48              : #define HCCL_SHM_ALIGN 4096
      49              : #define HCCL_HDC_CONTROL_WORDS 2
      50              : #define HCCL_HDC_HEAD_POS 2
      51              : #define HCCL_HDC_TAIL_POS 1
      52              : 
      53    361787528 : inline u32* HcclHdcGetControlWordAddr(void* base, u64 size, u32 pos)
      54              : {
      55    361787528 :     return reinterpret_cast<u32*>(reinterpret_cast<u8*>((base)) + size - pos * sizeof(pos));
      56              : }
      57              : 
      58          966 : HcclResult HDCommunicate::InitHost()
      59              : {
      60          966 :     CHK_RET(VerifyDeviceMemoryRegisterSupport());
      61              : 
      62          966 :     CHK_RET(AllocShm(deviceLogicId_, devMem_, hostMem_));
      63          966 :     CHK_RET(AllocReadCache(flag_, readCacheAddr_));
      64              : 
      65          966 :     headCntAddr_ = HcclHdcGetControlWordAddr(hostMem_.ptr(), hostMem_.size(), HCCL_HDC_HEAD_POS);
      66          966 :     tailCntAddr_ = HcclHdcGetControlWordAddr(hostMem_.ptr(), hostMem_.size(), HCCL_HDC_TAIL_POS);
      67              : 
      68          966 :     devHeadCntAddr_ = HcclHdcGetControlWordAddr(devMem_.ptr(), devMem_.size(), HCCL_HDC_HEAD_POS);
      69          966 :     devTailCntAddr_ = HcclHdcGetControlWordAddr(devMem_.ptr(), devMem_.size(), HCCL_HDC_TAIL_POS);
      70          966 :     return HCCL_SUCCESS;
      71              : }
      72              : 
      73          966 : HcclResult HDCommunicate::VerifyDeviceMemoryRegisterSupport()
      74              : {
      75          966 :     supportDevMemReg_ = false;
      76          966 :     size_t outputLen = 0;
      77          966 :     struct supportFeaturePara input = {};
      78          966 :     struct supportFeaturePara output = {};
      79          966 :     s32 deviceId = 0;
      80          966 :     CHK_RET(hrtGetDevice(&deviceId));
      81          966 :     s32 logicDevId = 0;
      82              :     // 调用驱动接口前需将userDevId转换为logicDevId
      83          966 :     CHK_RET(hrtGetLogicDevIdByUserDevId(deviceId, logicDevId));
      84          966 :     deviceLogicId_ = static_cast<u32>(logicDevId);
      85          966 :     input.support_feature = CTRL_SUPPORT_PCIE_BAR_MEM_MASK;
      86          966 :     input.devid = static_cast<unsigned int>(logicDevId);
      87          966 :     CHK_RET(hrtHalMemCtl(CTRL_TYPE_SUPPORT_FEATURE, &input, sizeof(struct supportFeaturePara), &output, &outputLen));
      88              : 
      89          966 :     if ((output.support_feature & CTRL_SUPPORT_PCIE_BAR_MEM_MASK) != 0) {
      90          966 :         supportDevMemReg_ = true;
      91              :     }
      92          966 :     HCCL_INFO("[HDCommunicate]supportDevMemReg_ %d deviceId %d", supportDevMemReg_, input.devid);
      93          966 :     return HCCL_SUCCESS;
      94              : }
      95              : 
      96          448 : struct HDCommunicateParams HDCommunicate::GetCommunicateParams()
      97              : {
      98          448 :     struct HDCommunicateParams params;
      99          448 :     params.hostAddr = reinterpret_cast<u64>(hostMem_.ptr());
     100          448 :     params.deviceAddr = reinterpret_cast<u64>(devMem_.ptr());
     101          448 :     params.readCacheAddr = reinterpret_cast<u64>(readCacheAddr_);
     102          448 :     params.devMemSize = devMem_.size();
     103          448 :     params.buffLen = buffLen_;
     104          448 :     params.flag = flag_;
     105          448 :     HCCL_DEBUG(
     106              :         "[HDCommunicate][GetCommunicateParams] hostAddr %p deviceAddr %p readCacheAddr %p devMemSize %u "
     107              :         "buffLen %u flag %u",
     108              :         params.hostAddr, params.deviceAddr, params.readCacheAddr, devMem_.size(), buffLen_, flag_);
     109          448 :     return params;
     110              : }
     111              : 
     112          154 : HcclResult HDCommunicate::InitDevice(const struct HDCommunicateParams& params)
     113              : {
     114          154 :     CHK_PRT_RET(
     115              :         (params.devMemSize == 0), HCCL_ERROR("[HDCommunicate][InitDevice]Invalid devMemSize=%u", params.devMemSize),
     116              :         HCCL_E_PARA);
     117          154 :     void* deviceAddr = reinterpret_cast<void*>(params.deviceAddr);
     118          154 :     CHK_PTR_NULL(deviceAddr);
     119          154 :     readCacheAddr_ = reinterpret_cast<void*>(params.readCacheAddr);
     120          154 :     CHK_PTR_NULL(readCacheAddr_);
     121          154 :     devMem_ = DeviceMem::create(deviceAddr, params.devMemSize);
     122          154 :     buffLen_ = params.buffLen;
     123          154 :     flag_ = params.flag;
     124              : 
     125          154 :     headCntAddr_ = HcclHdcGetControlWordAddr(devMem_.ptr(), devMem_.size(), HCCL_HDC_HEAD_POS);
     126          154 :     tailCntAddr_ = HcclHdcGetControlWordAddr(devMem_.ptr(), devMem_.size(), HCCL_HDC_TAIL_POS);
     127          154 :     isHost_ = false;
     128              : 
     129          154 :     HCCL_DEBUG(
     130              :         "[debug HDCommunicate][InitDevice] buffLen_=%u, flag_=%u, readCacheAddr_=%p, headCntAddr_=%p, "
     131              :         "tailCntAddr_=%p, deviceAddr %p",
     132              :         buffLen_, flag_, readCacheAddr_, headCntAddr_, tailCntAddr_, devMem_.ptr());
     133          154 :     return HCCL_SUCCESS;
     134              : }
     135              : 
     136          193 : HcclResult HDCommunicate::Put(u32 offset, u32 length, u8* value)
     137              : {
     138          193 :     if (length == 0) {
     139            0 :         return HCCL_SUCCESS;
     140              :     }
     141          193 :     CHK_PTR_NULL(value);
     142          193 :     if (((flag_ == HCCL_HDC_TYPE_D2H) && isHost_) || ((flag_ == HCCL_HDC_TYPE_H2D) && !isHost_)) {
     143            1 :         HCCL_ERROR("[HDCommunicate][Put]Invalid usage, flag=%u, isHost=%d", flag_, isHost_);
     144            1 :         return HCCL_E_PARA;
     145              :     }
     146          192 :     CHK_PRT_RET(
     147              :         (offset + length > buffLen_),
     148              :         HCCL_ERROR("[HDCommunicate][Put]Invalid length, offset=%u, length=%u", offset, length), HCCL_E_PARA);
     149          192 :     std::unique_lock<std::shared_mutex> lock(lock_);
     150          192 :     HcclResult ret = Write(offset, length, value);
     151          192 :     if (ret != HCCL_SUCCESS) {
     152            0 :         HCCL_ERROR("[HDCommunicate][Put]Write failed, offset=%u, length=%u", offset, length);
     153            0 :         return ret;
     154              :     }
     155          192 :     return HCCL_SUCCESS;
     156          192 : }
     157              : 
     158    361782853 : HcclResult HDCommunicate::Get(u32 offset, u32 length, u8* value)
     159              : {
     160    361782853 :     if (length == 0) {
     161            0 :         return HCCL_SUCCESS;
     162              :     }
     163    361782853 :     CHK_PTR_NULL(value);
     164    361782853 :     CHK_PRT_RET(
     165              :         (offset + length > buffLen_),
     166              :         HCCL_ERROR("[HDCommunicate][Get]Invalid length, offset=%u, length=%u, befferLen=%u", offset, length, buffLen_),
     167              :         HCCL_E_PARA);
     168    361782852 :     std::shared_lock<std::shared_mutex> lock(lock_);
     169    361782850 :     HcclResult ret = Read(offset, length, value);
     170    361782835 :     if (ret != HCCL_SUCCESS) {
     171            0 :         HCCL_ERROR("[HDCommunicate][Get]Read failed, offset=%u, length=%u", offset, length);
     172            0 :         return ret;
     173              :     }
     174    361782835 :     return HCCL_SUCCESS;
     175    361782835 : }
     176              : 
     177              : #pragma GCC push_options
     178              : #pragma GCC optimize("O0")
     179          192 : HcclResult HDCommunicate::Write(u32 offset, u32 length, u8* value)
     180              : {
     181          192 :     if (length == 0) {
     182            0 :         return HCCL_SUCCESS;
     183              :     }
     184          192 :     CHK_PTR_NULL(value);
     185          192 :     u32 head = *headCntAddr_;
     186          192 :     head++;
     187          192 :     *headCntAddr_ = head;
     188          192 :     if (isHost_ && !supportDevMemReg_) {
     189            0 :         CHK_RET(hrtDrvMemCpy(devHeadCntAddr_, sizeof(u32), headCntAddr_, sizeof(u32)));
     190              :     }
     191              : 
     192          192 :     if (isHost_) {
     193          126 :         auto ret = memcpy_s(
     194           42 :             reinterpret_cast<u8*>(hostMem_.ptr()) + offset, hostMem_.size() - HCCL_HDC_CONTROL_WORDS * sizeof(u32),
     195              :             value, length);
     196           42 :         CHK_PRT_RET(ret != EOK, HCCL_ERROR("[HDCommunicate][Write]memcpy_s failed, return[%d].", ret), HCCL_E_INTERNAL);
     197              :     } else {
     198          450 :         auto ret = memcpy_s(
     199          150 :             reinterpret_cast<u8*>(devMem_.ptr()) + offset, devMem_.size() - HCCL_HDC_CONTROL_WORDS * sizeof(u32), value,
     200              :             length);
     201          150 :         CHK_PRT_RET(ret != EOK, HCCL_ERROR("[HDCommunicate][Write]memcpy_s failed, return[%d].", ret), HCCL_E_INTERNAL);
     202              :     }
     203          192 :     if (isHost_ && !supportDevMemReg_) {
     204            0 :         CHK_RET(hrtDrvMemCpy(
     205              :             reinterpret_cast<u8*>(devMem_.ptr()) + offset, hostMem_.size() - HCCL_HDC_CONTROL_WORDS * sizeof(u32),
     206              :             value, length));
     207              :     }
     208              : 
     209              :     std::atomic_thread_fence(std::memory_order_seq_cst);
     210              : 
     211          192 :     u32 tail = *tailCntAddr_;
     212          192 :     tail++;
     213          192 :     *tailCntAddr_ = tail;
     214          192 :     if (isHost_ && !supportDevMemReg_) {
     215            0 :         CHK_RET(hrtDrvMemCpy(devTailCntAddr_, sizeof(u32), tailCntAddr_, sizeof(u32)));
     216              :     }
     217          192 :     return HCCL_SUCCESS;
     218              : }
     219              : 
     220    361782853 : HcclResult HDCommunicate::Read(u32 offset, u32 length, u8* value)
     221              : {
     222    361782853 :     if (length == 0) {
     223            0 :         return HCCL_SUCCESS;
     224              :     }
     225    361782853 :     CHK_PTR_NULL(value);
     226    361782853 :     u32* cachedTailCntAddr = HcclHdcGetControlWordAddr(readCacheAddr_, devMem_.size(), HCCL_HDC_TAIL_POS);
     227    361782840 :     volatile u32 cachedTailCnt = *cachedTailCntAddr;
     228    361782840 :     volatile u32 tailCnt = 0;
     229    361782840 :     if (isHost_ && !supportDevMemReg_) {
     230            0 :         u32 tempTailCnt = 0;
     231            0 :         u32* devSrcTailCntAddr = HcclHdcGetControlWordAddr(devMem_.ptr(), devMem_.size(), HCCL_HDC_TAIL_POS);
     232            0 :         CHK_RET(hrtDrvMemCpy(&tempTailCnt, sizeof(u32), devSrcTailCntAddr, sizeof(u32)));
     233            0 :         tailCnt = tempTailCnt;
     234            0 :     } else {
     235    361782840 :         tailCnt = *tailCntAddr_;
     236              :     }
     237    361782840 :     if (cachedTailCnt != tailCnt) {
     238              :         // 默认HDC超时时间为10s
     239           94 :         CHK_RET(UpdateCache(10));
     240              :     }
     241    361782840 :     auto ret = memcpy_s(value, length, static_cast<u8*>(readCacheAddr_) + offset, length);
     242    361782835 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[HDCommunicate][Read]memcpy_s failed, return[%d].", ret), HCCL_E_INTERNAL);
     243    361782835 :     return HCCL_SUCCESS;
     244              : }
     245              : 
     246           94 : HcclResult HDCommunicate::UpdateCache(u32 timeoutSec)
     247              : {
     248           94 :     void* srcBaseAddr = isHost_ ? hostMem_.ptr() : devMem_.ptr();
     249           94 :     u32* srcHeadCntAddr = HcclHdcGetControlWordAddr(srcBaseAddr, devMem_.size(), HCCL_HDC_HEAD_POS);
     250           94 :     u32* srcTailCntAddr = HcclHdcGetControlWordAddr(srcBaseAddr, devMem_.size(), HCCL_HDC_TAIL_POS);
     251           94 :     u32* devSrcHeadCntAddr = HcclHdcGetControlWordAddr(devMem_.ptr(), devMem_.size(), HCCL_HDC_HEAD_POS);
     252           94 :     u32* devSrcTailCntAddr = HcclHdcGetControlWordAddr(devMem_.ptr(), devMem_.size(), HCCL_HDC_TAIL_POS);
     253           94 :     u32* cachedHeadCntAddr = HcclHdcGetControlWordAddr(readCacheAddr_, devMem_.size(), HCCL_HDC_HEAD_POS);
     254           94 :     u32* cachedTailCntAddr = HcclHdcGetControlWordAddr(readCacheAddr_, devMem_.size(), HCCL_HDC_TAIL_POS);
     255              : 
     256           94 :     s32 ret = 0;
     257           94 :     auto startTime = std::chrono::steady_clock::now();
     258           94 :     auto timeout = std::chrono::seconds(timeoutSec);
     259              :     while (1) {
     260           94 :         if (isHost_ && !supportDevMemReg_) {
     261              :             // step1: cache尾计数
     262            0 :             CHK_RET(hrtDrvMemCpy(cachedTailCntAddr, sizeof(u32), devSrcTailCntAddr, sizeof(u32)));
     263              : 
     264              :             // step2: cache数据
     265            0 :             CHK_RET(hrtDrvMemCpy(
     266              :                 readCacheAddr_, devMem_.size() - HCCL_HDC_CONTROL_WORDS * sizeof(u32), devMem_.ptr(),
     267              :                 devMem_.size() - HCCL_HDC_CONTROL_WORDS * sizeof(u32)));
     268              : 
     269              :             // step3:cache头计数
     270            0 :             CHK_RET(hrtDrvMemCpy(cachedHeadCntAddr, sizeof(u32), devSrcHeadCntAddr, sizeof(u32)));
     271            0 :         } else {
     272              :             // step1: cache尾计数
     273           94 :             ret = memcpy_s(cachedTailCntAddr, sizeof(u32), srcTailCntAddr, sizeof(u32));
     274           94 :             CHK_PRT_RET(
     275              :                 ret != EOK, HCCL_ERROR("[HDCommunicate][UpdateCache]memcpy_s failed, return[%d].", ret),
     276              :                 HCCL_E_INTERNAL);
     277              : 
     278              :             // step2: cache数据
     279          188 :             ret = memcpy_s(
     280           94 :                 readCacheAddr_, devMem_.size() - HCCL_HDC_CONTROL_WORDS * sizeof(u32), srcBaseAddr,
     281           94 :                 devMem_.size() - HCCL_HDC_CONTROL_WORDS * sizeof(u32));
     282           94 :             CHK_PRT_RET(
     283              :                 ret != EOK, HCCL_ERROR("[HDCommunicate][UpdateCache]memcpy_s failed, return[%d].", ret),
     284              :                 HCCL_E_INTERNAL);
     285              : 
     286              :             // step3:cache头计数
     287           94 :             ret = memcpy_s(cachedHeadCntAddr, sizeof(u32), srcHeadCntAddr, sizeof(u32));
     288           94 :             CHK_PRT_RET(
     289              :                 ret != EOK, HCCL_ERROR("[HDCommunicate][UpdateCache]memcpy_s failed, return[%d].", ret),
     290              :                 HCCL_E_INTERNAL);
     291              :         }
     292              : 
     293           94 :         volatile u32 cachedHeadCnt = *cachedHeadCntAddr;
     294           94 :         volatile u32 cachedTailCnt = *cachedTailCntAddr;
     295              : 
     296           94 :         if (cachedHeadCnt == cachedTailCnt) {
     297           94 :             break;
     298              :         }
     299            0 :         CHK_PRT_RET(
     300              :             ((std::chrono::steady_clock::now() - startTime) >= timeout),
     301              :             HCCL_WARNING("[HDCommunicate][UpdateCache]get remote data timeout[%u s].", timeoutSec), HCCL_E_AGAIN);
     302            0 :     }
     303           94 :     return HCCL_SUCCESS;
     304              : }
     305              : #pragma GCC pop_options
     306              : 
     307          966 : HcclResult HDCommunicate::AllocShm(u32 devid, DeviceMem& devShm, HostMem& hostShm)
     308              : {
     309              :     // 共享内存size需要按照4K(4*1024=4096)对齐
     310          966 :     u32 size = (buffLen_ + HCCL_HDC_CONTROL_WORDS * sizeof(u32) + HCCL_SHM_ALIGN - 1) / HCCL_SHM_ALIGN * HCCL_SHM_ALIGN;
     311          966 :     CHK_RET(DeviceMem::alloc(devShm, size));
     312          966 :     CHK_RET(hrtMemSet(devShm.ptr(), size, size));
     313              : 
     314          966 :     if (supportDevMemReg_) {
     315          966 :         void* hostAddr = nullptr;
     316          966 :         CHK_RET(hrtHalHostRegister(devShm.ptr(), devShm.size(), DEV_SVM_MAP_HOST, devid, hostAddr));
     317              : 
     318          966 :         hostShm = HostMem::create(hostAddr, devShm.size());
     319              :     } else {
     320            0 :         hostShm = HostMem::alloc(devShm.size());
     321              :     }
     322          966 :     CHK_PTR_NULL(hostShm.ptr());
     323              : 
     324          966 :     auto ret = memset_s(hostShm.ptr(), hostShm.size(), 0, hostShm.size());
     325          966 :     CHK_PRT_RET(ret != EOK, HCCL_ERROR("[HDCommunicate][AllocShm]memset_s failed, return[%d].", ret), HCCL_E_INTERNAL);
     326              : 
     327          966 :     return HCCL_SUCCESS;
     328              : }
     329              : 
     330          966 : HcclResult HDCommunicate::AllocReadCache(u32 flag, void*& readCacheAddr)
     331              : {
     332          966 :     if (flag == HCCL_HDC_TYPE_D2H) {
     333          483 :         hostCache_ = HostMem::alloc(hostMem_.size());
     334          483 :         CHK_PTR_NULL(hostCache_.ptr());
     335          483 :         auto ret = memset_s(hostCache_.ptr(), hostCache_.size(), 0, hostCache_.size());
     336          483 :         CHK_PRT_RET(
     337              :             ret != EOK, HCCL_ERROR("[HDCommunicate][AllocReadCache]memset_s failed, return[%d].", ret),
     338              :             HCCL_E_INTERNAL);
     339          483 :         readCacheAddr = hostCache_.ptr();
     340              :     } else {
     341          483 :         CHK_RET(DeviceMem::alloc(devCache_, devMem_.size()));
     342          483 :         CHK_RET(hrtMemSet(devCache_.ptr(), devCache_.size(), devCache_.size()));
     343          483 :         readCacheAddr = devCache_.ptr();
     344              :     }
     345          966 :     return HCCL_SUCCESS;
     346              : }
     347              : } // namespace hccl
        

Generated by: LCOV version 2.0-1