111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2012-2015 Advanced Micro Devices, Inc. 311308Santhony.gutierrez@amd.com * All rights reserved. 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only 611308Santhony.gutierrez@amd.com * 711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met: 911308Santhony.gutierrez@amd.com * 1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice, 1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer. 1211308Santhony.gutierrez@amd.com * 1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice, 1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation 1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution. 1611308Santhony.gutierrez@amd.com * 1711308Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its contributors 1811308Santhony.gutierrez@amd.com * may be used to endorse or promote products derived from this software 1911308Santhony.gutierrez@amd.com * without specific prior written permission. 2011308Santhony.gutierrez@amd.com * 2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE. 3211308Santhony.gutierrez@amd.com * 3311308Santhony.gutierrez@amd.com * Author: Anthony Gutierrez 3411308Santhony.gutierrez@amd.com */ 3511308Santhony.gutierrez@amd.com 3611308Santhony.gutierrez@amd.com#include "gpu-compute/cl_driver.hh" 3711308Santhony.gutierrez@amd.com 3811856Sbrandon.potter@amd.com#include <memory> 3911856Sbrandon.potter@amd.com 4011308Santhony.gutierrez@amd.com#include "base/intmath.hh" 4111308Santhony.gutierrez@amd.com#include "cpu/thread_context.hh" 4211308Santhony.gutierrez@amd.com#include "gpu-compute/dispatcher.hh" 4311308Santhony.gutierrez@amd.com#include "gpu-compute/hsa_code.hh" 4411308Santhony.gutierrez@amd.com#include "gpu-compute/hsa_kernel_info.hh" 4511308Santhony.gutierrez@amd.com#include "gpu-compute/hsa_object.hh" 4611308Santhony.gutierrez@amd.com#include "params/ClDriver.hh" 4711308Santhony.gutierrez@amd.com#include "sim/process.hh" 4811308Santhony.gutierrez@amd.com#include "sim/syscall_emul_buf.hh" 4911308Santhony.gutierrez@amd.com 5011308Santhony.gutierrez@amd.comClDriver::ClDriver(ClDriverParams *p) 5111308Santhony.gutierrez@amd.com : EmulatedDriver(p), hsaCode(0) 5211308Santhony.gutierrez@amd.com{ 5311308Santhony.gutierrez@amd.com for (const auto &codeFile : p->codefile) 5411308Santhony.gutierrez@amd.com codeFiles.push_back(&codeFile); 5511308Santhony.gutierrez@amd.com 5611308Santhony.gutierrez@amd.com maxFuncArgsSize = 0; 5711308Santhony.gutierrez@amd.com 5811308Santhony.gutierrez@amd.com for (int i = 0; i < codeFiles.size(); ++i) { 5911308Santhony.gutierrez@amd.com HsaObject *obj = HsaObject::createHsaObject(*codeFiles[i]); 6011308Santhony.gutierrez@amd.com 6111308Santhony.gutierrez@amd.com for (int k = 0; k < obj->numKernels(); ++k) { 6211308Santhony.gutierrez@amd.com assert(obj->getKernel(k)); 6311308Santhony.gutierrez@amd.com kernels.push_back(obj->getKernel(k)); 6411308Santhony.gutierrez@amd.com kernels.back()->setReadonlyData((uint8_t*)obj->readonlyData); 6511308Santhony.gutierrez@amd.com int kern_funcargs_size = kernels.back()->funcarg_size; 6611308Santhony.gutierrez@amd.com maxFuncArgsSize = maxFuncArgsSize < kern_funcargs_size ? 6711308Santhony.gutierrez@amd.com kern_funcargs_size : maxFuncArgsSize; 6811308Santhony.gutierrez@amd.com } 6911308Santhony.gutierrez@amd.com } 7011308Santhony.gutierrez@amd.com 7111308Santhony.gutierrez@amd.com int name_offs = 0; 7211308Santhony.gutierrez@amd.com int code_offs = 0; 7311308Santhony.gutierrez@amd.com 7411308Santhony.gutierrez@amd.com for (int i = 0; i < kernels.size(); ++i) { 7511308Santhony.gutierrez@amd.com kernelInfo.push_back(HsaKernelInfo()); 7611308Santhony.gutierrez@amd.com HsaCode *k = kernels[i]; 7711308Santhony.gutierrez@amd.com 7811308Santhony.gutierrez@amd.com k->generateHsaKernelInfo(&kernelInfo[i]); 7911308Santhony.gutierrez@amd.com 8011308Santhony.gutierrez@amd.com kernelInfo[i].name_offs = name_offs; 8111308Santhony.gutierrez@amd.com kernelInfo[i].code_offs = code_offs; 8211308Santhony.gutierrez@amd.com 8311308Santhony.gutierrez@amd.com name_offs += k->name().size() + 1; 8411697Santhony.gutierrez@amd.com code_offs += k->numInsts() * sizeof(TheGpuISA::RawMachInst); 8511308Santhony.gutierrez@amd.com } 8611308Santhony.gutierrez@amd.com} 8711308Santhony.gutierrez@amd.com 8811308Santhony.gutierrez@amd.comvoid 8911308Santhony.gutierrez@amd.comClDriver::handshake(GpuDispatcher *_dispatcher) 9011308Santhony.gutierrez@amd.com{ 9111308Santhony.gutierrez@amd.com dispatcher = _dispatcher; 9211308Santhony.gutierrez@amd.com dispatcher->setFuncargsSize(maxFuncArgsSize); 9311308Santhony.gutierrez@amd.com} 9411308Santhony.gutierrez@amd.com 9511308Santhony.gutierrez@amd.comint 9613995Sbrandon.potter@amd.comClDriver::open(ThreadContext *tc, int mode, int flags) 9711308Santhony.gutierrez@amd.com{ 9813995Sbrandon.potter@amd.com auto p = tc->getProcessPtr(); 9911856Sbrandon.potter@amd.com std::shared_ptr<DeviceFDEntry> fdp; 10011856Sbrandon.potter@amd.com fdp = std::make_shared<DeviceFDEntry>(this, filename); 10111856Sbrandon.potter@amd.com int tgt_fd = p->fds->allocFD(fdp); 10211856Sbrandon.potter@amd.com return tgt_fd; 10311308Santhony.gutierrez@amd.com} 10411308Santhony.gutierrez@amd.com 10511308Santhony.gutierrez@amd.comint 10613995Sbrandon.potter@amd.comClDriver::ioctl(ThreadContext *tc, unsigned req) 10711308Santhony.gutierrez@amd.com{ 10811308Santhony.gutierrez@amd.com int index = 2; 10913995Sbrandon.potter@amd.com auto process = tc->getProcessPtr(); 11011308Santhony.gutierrez@amd.com Addr buf_addr = process->getSyscallArg(tc, index); 11111308Santhony.gutierrez@amd.com 11211308Santhony.gutierrez@amd.com switch (req) { 11311308Santhony.gutierrez@amd.com case HSA_GET_SIZES: 11411308Santhony.gutierrez@amd.com { 11511308Santhony.gutierrez@amd.com TypedBufferArg<HsaDriverSizes> sizes(buf_addr); 11611308Santhony.gutierrez@amd.com sizes->num_kernels = kernels.size(); 11711308Santhony.gutierrez@amd.com sizes->string_table_size = 0; 11811308Santhony.gutierrez@amd.com sizes->code_size = 0; 11911308Santhony.gutierrez@amd.com sizes->readonly_size = 0; 12011308Santhony.gutierrez@amd.com 12111308Santhony.gutierrez@amd.com if (kernels.size() > 0) { 12211308Santhony.gutierrez@amd.com // all kernels will share the same read-only memory 12311308Santhony.gutierrez@amd.com sizes->readonly_size = 12411308Santhony.gutierrez@amd.com kernels[0]->getSize(HsaCode::MemorySegment::READONLY); 12511308Santhony.gutierrez@amd.com // check our assumption 12611308Santhony.gutierrez@amd.com for (int i = 1; i<kernels.size(); ++i) { 12711308Santhony.gutierrez@amd.com assert(sizes->readonly_size == 12811308Santhony.gutierrez@amd.com kernels[i]->getSize(HsaCode::MemorySegment::READONLY)); 12911308Santhony.gutierrez@amd.com } 13011308Santhony.gutierrez@amd.com } 13111308Santhony.gutierrez@amd.com 13211308Santhony.gutierrez@amd.com for (int i = 0; i < kernels.size(); ++i) { 13311308Santhony.gutierrez@amd.com HsaCode *k = kernels[i]; 13411308Santhony.gutierrez@amd.com // add one for terminating '\0' 13511308Santhony.gutierrez@amd.com sizes->string_table_size += k->name().size() + 1; 13611697Santhony.gutierrez@amd.com sizes->code_size += 13711697Santhony.gutierrez@amd.com k->numInsts() * sizeof(TheGpuISA::RawMachInst); 13811308Santhony.gutierrez@amd.com } 13911308Santhony.gutierrez@amd.com 14014024Sgabeblack@google.com sizes.copyOut(tc->getVirtProxy()); 14111308Santhony.gutierrez@amd.com } 14211308Santhony.gutierrez@amd.com break; 14311308Santhony.gutierrez@amd.com 14411308Santhony.gutierrez@amd.com case HSA_GET_KINFO: 14511308Santhony.gutierrez@amd.com { 14611308Santhony.gutierrez@amd.com TypedBufferArg<HsaKernelInfo> 14711308Santhony.gutierrez@amd.com kinfo(buf_addr, sizeof(HsaKernelInfo) * kernels.size()); 14811308Santhony.gutierrez@amd.com 14911308Santhony.gutierrez@amd.com for (int i = 0; i < kernels.size(); ++i) { 15011308Santhony.gutierrez@amd.com HsaKernelInfo *ki = &kinfo[i]; 15111308Santhony.gutierrez@amd.com ki->name_offs = kernelInfo[i].name_offs; 15211308Santhony.gutierrez@amd.com ki->code_offs = kernelInfo[i].code_offs; 15311308Santhony.gutierrez@amd.com ki->sRegCount = kernelInfo[i].sRegCount; 15411308Santhony.gutierrez@amd.com ki->dRegCount = kernelInfo[i].dRegCount; 15511308Santhony.gutierrez@amd.com ki->cRegCount = kernelInfo[i].cRegCount; 15611308Santhony.gutierrez@amd.com ki->static_lds_size = kernelInfo[i].static_lds_size; 15711308Santhony.gutierrez@amd.com ki->private_mem_size = kernelInfo[i].private_mem_size; 15811308Santhony.gutierrez@amd.com ki->spill_mem_size = kernelInfo[i].spill_mem_size; 15911308Santhony.gutierrez@amd.com } 16011308Santhony.gutierrez@amd.com 16114024Sgabeblack@google.com kinfo.copyOut(tc->getVirtProxy()); 16211308Santhony.gutierrez@amd.com } 16311308Santhony.gutierrez@amd.com break; 16411308Santhony.gutierrez@amd.com 16511308Santhony.gutierrez@amd.com case HSA_GET_STRINGS: 16611308Santhony.gutierrez@amd.com { 16711308Santhony.gutierrez@amd.com int string_table_size = 0; 16811308Santhony.gutierrez@amd.com for (int i = 0; i < kernels.size(); ++i) { 16911308Santhony.gutierrez@amd.com HsaCode *k = kernels[i]; 17011308Santhony.gutierrez@amd.com string_table_size += k->name().size() + 1; 17111308Santhony.gutierrez@amd.com } 17211308Santhony.gutierrez@amd.com 17311308Santhony.gutierrez@amd.com BufferArg buf(buf_addr, string_table_size); 17411308Santhony.gutierrez@amd.com char *bufp = (char*)buf.bufferPtr(); 17511308Santhony.gutierrez@amd.com 17611308Santhony.gutierrez@amd.com for (int i = 0; i < kernels.size(); ++i) { 17711308Santhony.gutierrez@amd.com HsaCode *k = kernels[i]; 17811308Santhony.gutierrez@amd.com const char *n = k->name().c_str(); 17911308Santhony.gutierrez@amd.com 18011308Santhony.gutierrez@amd.com // idiomatic string copy 18111308Santhony.gutierrez@amd.com while ((*bufp++ = *n++)); 18211308Santhony.gutierrez@amd.com } 18311308Santhony.gutierrez@amd.com 18411308Santhony.gutierrez@amd.com assert(bufp - (char *)buf.bufferPtr() == string_table_size); 18511308Santhony.gutierrez@amd.com 18614024Sgabeblack@google.com buf.copyOut(tc->getVirtProxy()); 18711308Santhony.gutierrez@amd.com } 18811308Santhony.gutierrez@amd.com break; 18911308Santhony.gutierrez@amd.com 19011308Santhony.gutierrez@amd.com case HSA_GET_READONLY_DATA: 19111308Santhony.gutierrez@amd.com { 19211308Santhony.gutierrez@amd.com // we can pick any kernel --- they share the same 19311308Santhony.gutierrez@amd.com // readonly segment (this assumption is checked in GET_SIZES) 19411308Santhony.gutierrez@amd.com uint64_t size = 19511308Santhony.gutierrez@amd.com kernels.back()->getSize(HsaCode::MemorySegment::READONLY); 19611308Santhony.gutierrez@amd.com BufferArg data(buf_addr, size); 19711308Santhony.gutierrez@amd.com char *datap = (char *)data.bufferPtr(); 19811308Santhony.gutierrez@amd.com memcpy(datap, 19911308Santhony.gutierrez@amd.com kernels.back()->readonly_data, 20011308Santhony.gutierrez@amd.com size); 20114024Sgabeblack@google.com data.copyOut(tc->getVirtProxy()); 20211308Santhony.gutierrez@amd.com } 20311308Santhony.gutierrez@amd.com break; 20411308Santhony.gutierrez@amd.com 20511308Santhony.gutierrez@amd.com case HSA_GET_CODE: 20611308Santhony.gutierrez@amd.com { 20711308Santhony.gutierrez@amd.com // set hsaCode pointer 20811308Santhony.gutierrez@amd.com hsaCode = buf_addr; 20911308Santhony.gutierrez@amd.com int code_size = 0; 21011308Santhony.gutierrez@amd.com 21111308Santhony.gutierrez@amd.com for (int i = 0; i < kernels.size(); ++i) { 21211308Santhony.gutierrez@amd.com HsaCode *k = kernels[i]; 21311308Santhony.gutierrez@amd.com code_size += k->numInsts() * sizeof(TheGpuISA::RawMachInst); 21411308Santhony.gutierrez@amd.com } 21511308Santhony.gutierrez@amd.com 21611308Santhony.gutierrez@amd.com TypedBufferArg<TheGpuISA::RawMachInst> buf(buf_addr, code_size); 21711308Santhony.gutierrez@amd.com TheGpuISA::RawMachInst *bufp = buf; 21811308Santhony.gutierrez@amd.com 21911308Santhony.gutierrez@amd.com int buf_idx = 0; 22011308Santhony.gutierrez@amd.com 22111308Santhony.gutierrez@amd.com for (int i = 0; i < kernels.size(); ++i) { 22211308Santhony.gutierrez@amd.com HsaCode *k = kernels[i]; 22311308Santhony.gutierrez@amd.com 22411308Santhony.gutierrez@amd.com for (int j = 0; j < k->numInsts(); ++j) { 22511308Santhony.gutierrez@amd.com bufp[buf_idx] = k->insts()->at(j); 22611308Santhony.gutierrez@amd.com ++buf_idx; 22711308Santhony.gutierrez@amd.com } 22811308Santhony.gutierrez@amd.com } 22911308Santhony.gutierrez@amd.com 23014024Sgabeblack@google.com buf.copyOut(tc->getVirtProxy()); 23111308Santhony.gutierrez@amd.com } 23211308Santhony.gutierrez@amd.com break; 23311308Santhony.gutierrez@amd.com 23411308Santhony.gutierrez@amd.com case HSA_GET_CU_CNT: 23511308Santhony.gutierrez@amd.com { 23611308Santhony.gutierrez@amd.com BufferArg buf(buf_addr, sizeof(uint32_t)); 23711308Santhony.gutierrez@amd.com *((uint32_t*)buf.bufferPtr()) = dispatcher->getNumCUs(); 23814024Sgabeblack@google.com buf.copyOut(tc->getVirtProxy()); 23911308Santhony.gutierrez@amd.com } 24011308Santhony.gutierrez@amd.com break; 24111308Santhony.gutierrez@amd.com 24211308Santhony.gutierrez@amd.com case HSA_GET_VSZ: 24311308Santhony.gutierrez@amd.com { 24411308Santhony.gutierrez@amd.com BufferArg buf(buf_addr, sizeof(uint32_t)); 24511534Sjohn.kalamatianos@amd.com *((uint32_t*)buf.bufferPtr()) = dispatcher->wfSize(); 24614024Sgabeblack@google.com buf.copyOut(tc->getVirtProxy()); 24711308Santhony.gutierrez@amd.com } 24811308Santhony.gutierrez@amd.com break; 24911640Salexandru.dutu@amd.com case HSA_GET_HW_STATIC_CONTEXT_SIZE: 25011640Salexandru.dutu@amd.com { 25111640Salexandru.dutu@amd.com BufferArg buf(buf_addr, sizeof(uint32_t)); 25211640Salexandru.dutu@amd.com *((uint32_t*)buf.bufferPtr()) = dispatcher->getStaticContextSize(); 25314024Sgabeblack@google.com buf.copyOut(tc->getVirtProxy()); 25411640Salexandru.dutu@amd.com } 25511640Salexandru.dutu@amd.com break; 25611308Santhony.gutierrez@amd.com 25711308Santhony.gutierrez@amd.com default: 25811308Santhony.gutierrez@amd.com fatal("ClDriver: bad ioctl %d\n", req); 25911308Santhony.gutierrez@amd.com } 26011308Santhony.gutierrez@amd.com 26111308Santhony.gutierrez@amd.com return 0; 26211308Santhony.gutierrez@amd.com} 26311308Santhony.gutierrez@amd.com 26411308Santhony.gutierrez@amd.comconst char* 26511308Santhony.gutierrez@amd.comClDriver::codeOffToKernelName(uint64_t code_ptr) 26611308Santhony.gutierrez@amd.com{ 26711308Santhony.gutierrez@amd.com assert(hsaCode); 26811308Santhony.gutierrez@amd.com uint32_t code_offs = code_ptr - hsaCode; 26911308Santhony.gutierrez@amd.com 27011308Santhony.gutierrez@amd.com for (int i = 0; i < kernels.size(); ++i) { 27111308Santhony.gutierrez@amd.com if (code_offs == kernelInfo[i].code_offs) { 27211308Santhony.gutierrez@amd.com return kernels[i]->name().c_str(); 27311308Santhony.gutierrez@amd.com } 27411308Santhony.gutierrez@amd.com } 27511308Santhony.gutierrez@amd.com 27611308Santhony.gutierrez@amd.com return nullptr; 27711308Santhony.gutierrez@amd.com} 27811308Santhony.gutierrez@amd.com 27911308Santhony.gutierrez@amd.comClDriver* 28011308Santhony.gutierrez@amd.comClDriverParams::create() 28111308Santhony.gutierrez@amd.com{ 28211308Santhony.gutierrez@amd.com return new ClDriver(this); 28311308Santhony.gutierrez@amd.com} 284