/* * Copyright © 2014 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including * the next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include "libhsakmt.h" #include "inc/wddm/device.h" #include "inc/wddm/queue.h" #include "hsa-runtime/inc/amd_hsa_signal.h" uint32_t get_vgpr_size_per_cu(HSA_ENGINE_ID id) { uint32_t vgpr_size = 0x40000; if (id.ui32.Major >= 11) { vgpr_size = 0x60000; } return vgpr_size; } HSAKMT_STATUS HSAKMTAPI hsaKmtCreateQueue(HSAuint32 NodeId, HSA_QUEUE_TYPE Type, HSAuint32 QueuePercentage, HSA_QUEUE_PRIORITY Priority, void *QueueAddress, HSAuint64 QueueSizeInBytes, HsaEvent *Event, HsaQueueResource *QueueResource) { if (Type == HSA_QUEUE_SDMA_BY_ENG_ID) return HSAKMT_STATUS_ERROR; return hsaKmtCreateQueueExt(NodeId, Type, QueuePercentage, Priority, 0, QueueAddress, QueueSizeInBytes, Event, QueueResource); } HSAKMT_STATUS HSAKMTAPI hsaKmtCreateQueueExt(HSAuint32 NodeId, HSA_QUEUE_TYPE Type, HSAuint32 QueuePercentage, HSA_QUEUE_PRIORITY Priority, HSAuint32 SdmaEngineId, void *QueueAddress, HSAuint64 QueueSizeInBytes, HsaEvent *Event, HsaQueueResource *QueueResource) { HSAKMT_STATUS result; CHECK_DXG_OPEN(); assert(Event == nullptr); if (Priority < HSA_QUEUE_PRIORITY_MINIMUM || Priority > HSA_QUEUE_PRIORITY_MAXIMUM) return HSAKMT_STATUS_INVALID_PARAMETER; wsl::thunk::WDDMDevice *device_ = get_wddmdev(NodeId); assert(device_); switch (Type) { case HSA_QUEUE_COMPUTE_AQL: { assert(QueueResource->ErrorReason == nullptr); uint64_t pkg_num = QueueSizeInBytes / 64; uint32_t cmdbuf_size = device_->GetCmdbufSize(); uint32_t queue_engine = device_->GetComputeEngine(); bool use_hws = device_->IsHwsEnabled(queue_engine); auto queue_ = new wsl::thunk::ComputeQueue( device_, QueueAddress, pkg_num, reinterpret_cast *>( QueueResource->Queue_write_ptr_aql), reinterpret_cast *>( QueueResource->Queue_read_ptr_aql), QueueResource->ErrorReason, cmdbuf_size, queue_engine, use_hws); QueueResource->QueueId = reinterpret_cast(queue_); // for doorbell_signal.hardware_doorbell_ptr QueueResource->Queue_DoorBell_aql = queue_->GetDoorbellPtr(); } break; case HSA_QUEUE_SDMA: case HSA_QUEUE_SDMA_BY_ENG_ID: { pr_debug("create sdma queue in engine %d\n", SdmaEngineId); uint32_t queue_engine = device_->GetSdmaEngine(0); // TODO: SdmaEngineId bool use_hws = device_->IsHwsEnabled(queue_engine); auto queue_ = new wsl::thunk::SDMAQueue( device_, QueueAddress, QueueSizeInBytes, queue_engine, use_hws); QueueResource->QueueId = reinterpret_cast(queue_); QueueResource->Queue_DoorBell_aql = queue_->GetDoorbellPtr(); QueueResource->Queue_write_ptr_aql = queue_->GetRingWptr(); QueueResource->Queue_read_ptr_aql = queue_->GetRingRptr(); } break; default: assert(false); QueueResource->QueueId = 0; QueueResource->Queue_DoorBell = nullptr; break; } return HSAKMT_STATUS_SUCCESS; } HSAKMT_STATUS HSAKMTAPI hsaKmtUpdateQueue( HSA_QUEUEID QueueId, HSAuint32 QueuePercentage, HSA_QUEUE_PRIORITY Priority, void *QueueAddress, HSAuint64 QueueSize, HsaEvent *Event) { CHECK_DXG_OPEN(); if (Priority < HSA_QUEUE_PRIORITY_MINIMUM || Priority > HSA_QUEUE_PRIORITY_MAXIMUM) return HSAKMT_STATUS_INVALID_PARAMETER; auto queue_ = reinterpret_cast(QueueId); if (!queue_) return HSAKMT_STATUS_INVALID_PARAMETER; return HSAKMT_STATUS_SUCCESS; } HSAKMT_STATUS HSAKMTAPI hsaKmtDestroyQueue(HSA_QUEUEID QueueId) { CHECK_DXG_OPEN(); auto queue_ = reinterpret_cast(QueueId); if (!queue_) return HSAKMT_STATUS_INVALID_PARAMETER; delete queue_; return HSAKMT_STATUS_SUCCESS; } HSAKMT_STATUS HSAKMTAPI hsaKmtSetQueueCUMask(HSA_QUEUEID QueueId, HSAuint32 CUMaskCount, HSAuint32 *QueueCUMask) { CHECK_DXG_OPEN(); auto queue_ = reinterpret_cast(QueueId); if (!queue_) return HSAKMT_STATUS_INVALID_PARAMETER; if (CUMaskCount == 0 || !QueueCUMask || ((CUMaskCount % 32) != 0)) return HSAKMT_STATUS_INVALID_PARAMETER; pr_debug("%s not implemented\n", __func__); return HSAKMT_STATUS_SUCCESS; } HSAKMT_STATUS HSAKMTAPI hsaKmtGetQueueInfo(HSA_QUEUEID QueueId, HsaQueueInfo *QueueInfo) { CHECK_DXG_OPEN(); if (QueueInfo == NULL) return HSAKMT_STATUS_INVALID_PARAMETER; memset(QueueInfo, 0, sizeof(*QueueInfo)); assert(false); return HSAKMT_STATUS_SUCCESS; } HSAKMT_STATUS HSAKMTAPI hsaKmtSetTrapHandler(HSAuint32 Node, void *TrapHandlerBaseAddress, HSAuint64 TrapHandlerSizeInBytes, void *TrapBufferBaseAddress, HSAuint64 TrapBufferSizeInBytes) { CHECK_DXG_OPEN(); pr_debug("%s not implemented\n", __func__); return HSAKMT_STATUS_SUCCESS; } HSAKMT_STATUS HSAKMTAPI hsaKmtAllocQueueGWS(HSA_QUEUEID QueueId, HSAuint32 nGWS, HSAuint32 *firstGWS) { CHECK_DXG_OPEN(); auto queue_ = reinterpret_cast(QueueId); if (!queue_) return HSAKMT_STATUS_INVALID_PARAMETER; assert(false); return HSAKMT_STATUS_SUCCESS; } HSAKMT_STATUS HSAKMTAPI hsaKmtQueueRingDoorbell(HSA_QUEUEID QueueId) { CHECK_DXG_OPEN(); auto queue_ = reinterpret_cast(QueueId); if (!queue_) return HSAKMT_STATUS_INVALID_PARAMETER; queue_->RingDoorbell(); return HSAKMT_STATUS_SUCCESS; }