LCOV - code coverage report
Current view: top level - legacy/ascend950/unified_platform/resource/connection/aicpu - rdma_vendor_base_ops.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 53.7 % 95 51
Test Date: 2026-08-18 17:47:01 Functions: 50.0 % 18 9

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 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              : #ifndef RDMA_BASE_VENDOR_OPS_H
      12              : #define RDMA_BASE_VENDOR_OPS_H
      13              : 
      14              : #include <chrono>
      15              : #include <cstddef>
      16              : #include <cstdint>
      17              : #include <vector>
      18              : #include <securec.h>
      19              : 
      20              : #include "exception_util.h"
      21              : #include "internal_exception.h"
      22              : #include "log.h"
      23              : #include "rma_buf_slice_lite.h"     // RmaBufSliceLite
      24              : #include "rmt_rma_buf_slice_lite.h" // RmtRmaBufSliceLite
      25              : #include "data_type.h"              // DataType
      26              : #include "reduce_op.h"              // ReduceOp
      27              : 
      28              : namespace Hccl {
      29              : 
      30              : struct SqeConfigLite;
      31              : 
      32              : struct RdmaSqContextLite {
      33              :     uint32_t qpn;
      34              :     uint64_t sqVa;
      35              :     uint32_t wqeSize;
      36              :     uint32_t depth;
      37              :     uint64_t headAddr;
      38              :     uint64_t tailAddr;
      39              :     uint64_t dbHwVa;
      40              :     uint64_t dbSwVa;
      41              :     uint8_t sl;
      42              :     uint64_t dbVendorSpecified;
      43              : };
      44              : 
      45              : struct RdmaCqContextLite {
      46              :     uint32_t cqn;
      47              :     uint64_t cqVa;
      48              :     uint32_t cqeSize;
      49              :     uint32_t cqDepth;
      50              :     uint64_t headAddr;
      51              :     uint64_t tailAddr;
      52              :     uint64_t dbHwVa;
      53              :     uint64_t dbSwVa;
      54              :     uint64_t dbVendorSpecified;
      55              : };
      56              : 
      57              : // DbVendorSpecified bitfield layout, matching Roce3DbEntry.dw0.bs:
      58              : //   cos      at bits 24-26 (3 bits)
      59              : //   mtuShift at bits 50-52 (3 bits)
      60              : static constexpr uint32_t UB_DB_VENDOR_COS_SHIFT = 24;
      61              : static constexpr uint32_t UB_DB_VENDOR_MTUSHIFT_SHIFT = 50;
      62              : static constexpr uint32_t UB_DB_VENDOR_FIELD_MASK = 0x7;
      63              : 
      64              : // Necessary helper funcs
      65              : constexpr uint32_t BITS_1BYTE = 8;
      66              : constexpr uint32_t BITS_3BYTE = 24;
      67              : constexpr uint32_t BITS_5BYTE = 40;
      68              : constexpr uint32_t BITS_7BYTE = 56;
      69              : 
      70           33 : inline uint16_t Htons16(uint16_t x) { return (((x & 0xffULL) << BITS_1BYTE) | ((x & 0xff00ULL) >> BITS_1BYTE)); }
      71              : 
      72           86 : inline uint32_t Htonl32(uint32_t x)
      73              : {
      74           86 :     return ((x & 0x000000ffU) << BITS_3BYTE) | ((x & 0x0000ff00U) << BITS_1BYTE) | ((x & 0x00ff0000U) >> BITS_1BYTE)
      75           86 :            | ((x & 0xff000000U) >> BITS_3BYTE);
      76              : }
      77              : 
      78           22 : inline uint64_t Htonll64(uint64_t x)
      79              : {
      80           22 :     return ((x & 0x00000000000000ffULL) << BITS_7BYTE) | ((x & 0x000000000000ff00ULL) << BITS_5BYTE)
      81           22 :            | ((x & 0x0000000000ff0000ULL) << BITS_3BYTE) | ((x & 0x00000000ff000000ULL) << BITS_1BYTE)
      82           22 :            | ((x & 0x000000ff00000000ULL) >> BITS_1BYTE) | ((x & 0x0000ff0000000000ULL) >> BITS_3BYTE)
      83           22 :            | ((x & 0x00ff000000000000ULL) >> BITS_5BYTE) | ((x & 0xff00000000000000ULL) >> BITS_7BYTE);
      84              : }
      85              : 
      86              : enum class CqPollStatus : int32_t {
      87              :     SUCCESS = 0,  /* indicate poll once cqe successfully; */
      88              :     EMPTY = -1,   /* indicate the cq is empty when poll cq; */
      89              :     ERROR = -2,   /* indicate the error when poll cq; */
      90              :     REROLL = -3,  /* 返回到repoll标识 */
      91              :     CONTINUE = 1, /* indicate continue the process */
      92              : };
      93              : 
      94              : class RdmaBaseOps {
      95              : public:
      96           39 :     RdmaBaseOps(RdmaSqContextLite* sqContext, RdmaCqContextLite* cqContext)
      97           39 :         : sqContext_(sqContext),
      98           39 :           cqContext_(cqContext)
      99           39 :     {}
     100           39 :     virtual ~RdmaBaseOps() = default;
     101              : 
     102              :     // 上层接口,不关心具体vendor类型
     103            3 :     HcclResult Read(const RmaBufSliceLite& loc, const RmtRmaBufSliceLite& rmt, const SqeConfigLite& cfg)
     104              :     {
     105              :         // Read需要占用1个wr位置, 确定Sq存在空位
     106            3 :         constexpr int ReadWqeCount = 1;
     107            3 :         CHK_RET(WaitSqFree(ReadWqeCount));
     108              : 
     109              :         // 进入vendor特有wqe组装接口, 组装完wqe直接下发, opCode不支持直接返回HCCL_E_NOT_SUPPORT
     110            3 :         CHK_RET(BuildReadWqe(loc, rmt, cfg));
     111              : 
     112              :         // 更新Sq队列PI值
     113            3 :         CHK_RET(UpdateSqPI());
     114              : 
     115            3 :         return HCCL_SUCCESS;
     116              :     }
     117              : 
     118            6 :     HcclResult Write(const RmaBufSliceLite& loc, const RmtRmaBufSliceLite& rmt, const SqeConfigLite& cfg)
     119              :     {
     120              :         // Write需要占用1个wr位置, 确定Sq存在空位
     121            6 :         constexpr int WriteWqeCount = 1;
     122            6 :         CHK_RET(WaitSqFree(WriteWqeCount));
     123              : 
     124              :         // 进入vendor特有wqe组装接口, 组装完wqe直接下发
     125            6 :         CHK_RET(BuildWriteWqe(loc, rmt, cfg));
     126              : 
     127              :         // 更新Sq队列PI值
     128            6 :         CHK_RET(UpdateSqPI());
     129              : 
     130            6 :         return HCCL_SUCCESS;
     131              :     }
     132              : 
     133            2 :     HcclResult WriteReduce(
     134              :         const RmaBufSliceLite& loc, const RmtRmaBufSliceLite& rmt, const SqeConfigLite& cfg, DataType dataType,
     135              :         ReduceOp reduceOp)
     136              :     {
     137              :         // Inline Reduce Write需要占用1个wr位置, 确定Sq存在空位
     138            2 :         constexpr int WriteReduceWqeCount = 1;
     139            2 :         CHK_RET(WaitSqFree(WriteReduceWqeCount));
     140              : 
     141              :         // 进入vendor特有wqe组装接口, 组装完wqe直接下发
     142            2 :         CHK_RET(BuildWriteReduceWqe(loc, rmt, cfg, dataType, reduceOp));
     143              : 
     144              :         // 更新Sq队列PI值
     145            2 :         CHK_RET(UpdateSqPI());
     146              : 
     147            2 :         return HCCL_SUCCESS;
     148              :     }
     149              : 
     150            3 :     HcclResult PollCq(int32_t numEntries, int32_t timeOut, std::vector<int32_t>& errList)
     151              :     {
     152            3 :         auto timeLimit = std::chrono::milliseconds(timeOut);
     153            3 :         auto startTime = std::chrono::steady_clock::now();
     154              : 
     155            3 :         int32_t totalPollNum = 0;
     156            3 :         int32_t ret = 0;
     157              : 
     158            4 :         while (totalPollNum < numEntries) {
     159              :             // 逐一Poll Cq,并处理cqe
     160            3 :             ret = PollCqImpl(numEntries - totalPollNum, errList);
     161            3 :             if (ret == static_cast<int32_t>(CqPollStatus::ERROR)) {
     162            3 :                 HCCL_ERROR("[RdmaBaseOps::%s][Poll cq] Poll Cq Error.", __func__);
     163            1 :                 return HCCL_E_REMOTE;
     164              :             }
     165              : 
     166            2 :             if (ret > 0) {
     167              :                 // Update cqe in this loop
     168            1 :                 totalPollNum += ret;
     169              : 
     170              :                 // Update Sq Tail
     171            1 :                 sqTail_ += ret;
     172              : 
     173              :                 // continue poll cqe
     174            1 :                 continue;
     175              :             }
     176              : 
     177            1 :             if ((std::chrono::steady_clock::now() - startTime) > timeLimit) {
     178            3 :                 HCCL_ERROR(
     179              :                     "[RdmaBaseOps::%s][Poll cq] Poll Cq timeout, expected[%d], actual[%d], lastRet[%d]", __func__,
     180              :                     numEntries, totalPollNum, ret);
     181            1 :                 return HCCL_E_TIMEOUT;
     182              :             }
     183              :         }
     184              : 
     185            3 :         HCCL_INFO(
     186              :             "[RdmaBaseOps::%s][Poll cq] Poll Cq success, expected[%d], actual[%d]", __func__, numEntries, totalPollNum);
     187            1 :         return HCCL_SUCCESS;
     188              :     }
     189              : 
     190              :     // 准备Doorbell(厂商实现)
     191              :     virtual HcclResult BuildDoorbell(u64& dbAddr, u64& dbValue) = 0;
     192              : 
     193              :     // 准备CqDoorbell(厂商实现)
     194              :     virtual HcclResult BuildCqDoorbell(u64& dbAddr, u64& dbValue) = 0;
     195              : 
     196              : protected:
     197              :     // 软件侧只维护Sq PI,Sq CI由硬件维护
     198              :     u32 sqHead_{0};
     199              :     u32 sqTail_{0};
     200              : 
     201              :     u32 cqHead_{0};
     202              :     u32 cqTail_{0};
     203              :     bool cqDbFlush_ = false;
     204              : 
     205              :     RdmaSqContextLite* sqContext_;
     206              :     RdmaCqContextLite* cqContext_;
     207              : 
     208              :     // 默认超时时间 30 ms
     209              :     const std::chrono::milliseconds timeout_ = std::chrono::milliseconds(30U);
     210              : 
     211              :     // vendor扩展点: 每个原子op一个虚函数
     212              :     // 默认 NOT_SUPPORT, 各个vendor 只重写自己支持的
     213            0 :     virtual HcclResult BuildReadWqe(const RmaBufSliceLite& loc, const RmtRmaBufSliceLite& rmt, const SqeConfigLite& cfg)
     214              :     {
     215              :         (void)loc;
     216              :         (void)rmt;
     217              :         (void)cfg;
     218            0 :         HCCL_ERROR("[RdmaBaseOps::%s] This Backend Not support Read Now.", __func__);
     219            0 :         return HCCL_E_NOT_SUPPORT;
     220              :     }
     221              : 
     222              :     virtual HcclResult
     223            0 :     BuildWriteWqe(const RmaBufSliceLite& loc, const RmtRmaBufSliceLite& rmt, const SqeConfigLite& cfg)
     224              :     {
     225              :         (void)loc;
     226              :         (void)rmt;
     227              :         (void)cfg;
     228            0 :         HCCL_ERROR("[RdmaBaseOps::%s] This Backend Not support Write Now.", __func__);
     229            0 :         return HCCL_E_NOT_SUPPORT;
     230              :     }
     231              : 
     232            0 :     virtual HcclResult BuildWriteReduceWqe(
     233              :         const RmaBufSliceLite& locNotify, const RmtRmaBufSliceLite& notify, const SqeConfigLite& cfg, DataType dataType,
     234              :         ReduceOp reduceOp)
     235              :     {
     236              :         (void)locNotify;
     237              :         (void)notify;
     238              :         (void)cfg;
     239              :         (void)dataType;
     240              :         (void)reduceOp;
     241            0 :         HCCL_ERROR("[RdmaBaseOps::%s] This Backend Not support WriteReduce Now.", __func__);
     242            0 :         return HCCL_E_NOT_SUPPORT;
     243              :     }
     244              : 
     245            0 :     virtual HcclResult WriteInvalidWqebb(uint32_t nextIdx)
     246              :     {
     247              :         (void)nextIdx;
     248            0 :         return HCCL_SUCCESS;
     249              :     }
     250              : 
     251            0 :     virtual int32_t PollCqImpl(int32_t numEntries, [[maybe_unused]] std::vector<int32_t>& errList)
     252              :     {
     253              :         (void)numEntries;
     254            0 :         HCCL_ERROR("[RdmaBaseOps::%s] This Backend Not support PollCq Now.", __func__);
     255            0 :         return HCCL_E_NOT_SUPPORT;
     256              :     }
     257              : 
     258              :     // 搬运wqe(通用实现), 把 Wqe 写到 SQ
     259            0 :     HcclResult CommitWqe(const void* wqe, uint32_t wqeSize)
     260              :     {
     261            0 :         HCCL_INFO("[RdmaBaseOps::%s] Memcpy wqe start, Now SQ PI: [%u]", __func__, sqHead_);
     262              : 
     263              :         // 写wqe到va
     264            0 :         auto sqDepth = sqContext_->depth;
     265            0 :         uint32_t sqPIMask = sqDepth - 1;
     266            0 :         u8* va = reinterpret_cast<u8*>(sqContext_->sqVa + (sqHead_ & sqPIMask) * wqeSize);
     267              : 
     268            0 :         HCCL_INFO(
     269              :             "[RdmaBaseOps][Wqe Write] before copy, sqHead[%u], slot[%u], sqVa[0x%llx], dst[0x%llx], size[%u]", sqHead_,
     270              :             sqHead_ & sqPIMask, static_cast<unsigned long long>(sqContext_->sqVa),
     271              :             reinterpret_cast<unsigned long long>(va), wqeSize);
     272              : 
     273            0 :         auto ret = memcpy_sp(va, wqeSize, wqe, wqeSize);
     274            0 :         if (UNLIKELY(ret != 0)) {
     275            0 :             THROW<InternalException>(StringFormat("[RdmaBaseOps::%s] memcpy_s failed, ret = %d", __func__, ret));
     276              :         }
     277              : 
     278              :         // pi维护用于传入DB Send用于Rtsq 敲door bell
     279            0 :         sqHead_ = sqHead_ + 1;
     280              : 
     281              :         // Write InValid Wqebb
     282            0 :         CHK_RET(WriteInvalidWqebb(sqHead_));
     283              : 
     284            0 :         HCCL_INFO("[RdmaBaseOps::%s] Memcpy wqe end, Now SQ PI: [%u]", __func__, sqHead_);
     285            0 :         return HCCL_SUCCESS;
     286              :     }
     287              : 
     288            0 :     HcclResult WaitSqFree(uint32_t wqeNum)
     289              :     {
     290              :         // wq_overflow
     291            0 :         bool timeOutFlag = false;
     292            0 :         auto startTime = std::chrono::steady_clock::now();
     293              : 
     294            0 :         HCCL_INFO("[RdmaBaseOps::%s] Operate: sqTail = %u", __func__, sqTail_);
     295            0 :         while (!timeOutFlag) {
     296              :             // sq 队列能放下,直接成功返回
     297            0 :             if (static_cast<uint32_t>(sqHead_ - sqTail_ + wqeNum) <= sqContext_->depth) {
     298            0 :                 return HCCL_SUCCESS;
     299              :             }
     300              : 
     301            0 :             timeOutFlag = (std::chrono::steady_clock::now() - startTime) > timeout_;
     302              :         }
     303              : 
     304              :         // 超时处理
     305            0 :         HCCL_ERROR("[RdmaBaseOps::%s] Sq is Full !! Operate: sqTail = %u Failed. ", __func__, sqTail_);
     306            0 :         return HCCL_E_TIMEOUT;
     307              :     }
     308              : 
     309              :     // 将PI更新到硬件可见地址
     310            0 :     HcclResult UpdateSqPI()
     311              :     {
     312              :         // 更新Sq PI指针
     313            0 :         uint32_t sqHeadNum = Htonl32(sqHead_);
     314              : 
     315            0 :         HCCL_INFO(
     316              :             "[RdmaBaseOps][Wqe Write] write soft PI, sqHead host[%u], dbSwVa[0x%llx]", sqHead_,
     317              :             static_cast<unsigned long long>(sqContext_->dbSwVa));
     318              : 
     319              :         auto status
     320            0 :             = memcpy_sp(reinterpret_cast<void*>(sqContext_->dbSwVa), sizeof(uint32_t), &sqHeadNum, sizeof(uint32_t));
     321            0 :         if (UNLIKELY(status != 0)) {
     322            0 :             THROW<InternalException>(StringFormat("[RdmaBaseOps::%s] Ring Sw DB failed, ret = %d", __func__, status));
     323              :         }
     324            0 :         return HCCL_SUCCESS;
     325              :     }
     326              : };
     327              : 
     328              : } // namespace Hccl
     329              : #endif // RDMA_BASE_VENDOR_OPS_H
        

Generated by: LCOV version 2.0-1