gpu_nomali.cc revision 11350
110916Sandreas.sandberg@arm.com/* 211349Sandreas.sandberg@arm.com * Copyright (c) 2014-2016 ARM Limited 310916Sandreas.sandberg@arm.com * All rights reserved 410916Sandreas.sandberg@arm.com * 510916Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall 610916Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual 710916Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating 810916Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software 910916Sandreas.sandberg@arm.com * licensed hereunder. You may use the software subject to the license 1010916Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated 1110916Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 1210916Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form. 1310916Sandreas.sandberg@arm.com * 1410916Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 1510916Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 1610916Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 1710916Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 1810916Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1910916Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 2010916Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 2110916Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 2210916Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 2310916Sandreas.sandberg@arm.com * this software without specific prior written permission. 2410916Sandreas.sandberg@arm.com * 2510916Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610916Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710916Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810916Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910916Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010916Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110916Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210916Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310916Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410916Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510916Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610916Sandreas.sandberg@arm.com * 3710916Sandreas.sandberg@arm.com * Authors: Andreas Sandberg 3810916Sandreas.sandberg@arm.com */ 3910916Sandreas.sandberg@arm.com 4010916Sandreas.sandberg@arm.com#include "dev/arm/gpu_nomali.hh" 4110916Sandreas.sandberg@arm.com 4210916Sandreas.sandberg@arm.com#include "debug/NoMali.hh" 4310916Sandreas.sandberg@arm.com#include "dev/arm/base_gic.hh" 4410916Sandreas.sandberg@arm.com#include "dev/arm/realview.hh" 4510916Sandreas.sandberg@arm.com#include "enums/MemoryMode.hh" 4610916Sandreas.sandberg@arm.com#include "mem/packet_access.hh" 4710916Sandreas.sandberg@arm.com#include "params/NoMaliGpu.hh" 4810916Sandreas.sandberg@arm.com 4911349Sandreas.sandberg@arm.comstatic const std::map<Enums::NoMaliGpuType, nomali_gpu_type_t> gpuTypeMap{ 5011349Sandreas.sandberg@arm.com { Enums::T60x, NOMALI_GPU_T60X }, 5111349Sandreas.sandberg@arm.com { Enums::T62x, NOMALI_GPU_T62X }, 5211349Sandreas.sandberg@arm.com { Enums::T760, NOMALI_GPU_T760 }, 5311349Sandreas.sandberg@arm.com}; 5411349Sandreas.sandberg@arm.com 5510916Sandreas.sandberg@arm.comNoMaliGpu::NoMaliGpu(const NoMaliGpuParams *p) 5610916Sandreas.sandberg@arm.com : PioDevice(p), 5710916Sandreas.sandberg@arm.com pioAddr(p->pio_addr), 5810916Sandreas.sandberg@arm.com platform(p->platform), 5910916Sandreas.sandberg@arm.com interruptMap{ 6010916Sandreas.sandberg@arm.com { NOMALI_INT_GPU, p->int_gpu }, 6110916Sandreas.sandberg@arm.com { NOMALI_INT_JOB, p->int_job }, 6210916Sandreas.sandberg@arm.com { NOMALI_INT_MMU, p->int_mmu }, 6310916Sandreas.sandberg@arm.com } 6410916Sandreas.sandberg@arm.com{ 6510916Sandreas.sandberg@arm.com if (nomali_api_version() != NOMALI_API_VERSION) 6610916Sandreas.sandberg@arm.com panic("NoMali library API mismatch!\n"); 6710916Sandreas.sandberg@arm.com 6810916Sandreas.sandberg@arm.com /* Setup the GPU configuration based on our param struct */ 6910916Sandreas.sandberg@arm.com nomali_config_t cfg; 7010916Sandreas.sandberg@arm.com memset(&cfg, 0, sizeof(cfg)); 7110916Sandreas.sandberg@arm.com 7211349Sandreas.sandberg@arm.com const auto it_gpu(gpuTypeMap.find(p->gpu_type)); 7311349Sandreas.sandberg@arm.com if (it_gpu == gpuTypeMap.end()) { 7411349Sandreas.sandberg@arm.com fatal("Unrecognized GPU type: %s (%i)\n", 7511349Sandreas.sandberg@arm.com Enums::NoMaliGpuTypeStrings[p->gpu_type], p->gpu_type); 7610916Sandreas.sandberg@arm.com } 7711349Sandreas.sandberg@arm.com cfg.type = it_gpu->second; 7810916Sandreas.sandberg@arm.com 7910916Sandreas.sandberg@arm.com cfg.ver_maj = p->ver_maj; 8010916Sandreas.sandberg@arm.com cfg.ver_min = p->ver_min; 8110916Sandreas.sandberg@arm.com cfg.ver_status = p->ver_status; 8210916Sandreas.sandberg@arm.com 8310916Sandreas.sandberg@arm.com panicOnErr( 8410916Sandreas.sandberg@arm.com nomali_create(&nomali, &cfg), 8510916Sandreas.sandberg@arm.com "Failed to instantiate NoMali"); 8610916Sandreas.sandberg@arm.com 8710916Sandreas.sandberg@arm.com 8810916Sandreas.sandberg@arm.com /* Setup an interrupt callback */ 8910916Sandreas.sandberg@arm.com nomali_callback_t cbk_int; 9010916Sandreas.sandberg@arm.com cbk_int.type = NOMALI_CALLBACK_INT; 9110916Sandreas.sandberg@arm.com cbk_int.usr = (void *)this; 9210916Sandreas.sandberg@arm.com cbk_int.func.interrupt = NoMaliGpu::_interrupt; 9311349Sandreas.sandberg@arm.com setCallback(cbk_int); 9410916Sandreas.sandberg@arm.com 9511350Sandreas.sandberg@arm.com /* Setup a reset callback */ 9611350Sandreas.sandberg@arm.com nomali_callback_t cbk_rst; 9711350Sandreas.sandberg@arm.com cbk_rst.type = NOMALI_CALLBACK_RESET; 9811350Sandreas.sandberg@arm.com cbk_rst.usr = (void *)this; 9911350Sandreas.sandberg@arm.com cbk_rst.func.reset = NoMaliGpu::_reset; 10011350Sandreas.sandberg@arm.com setCallback(cbk_rst); 10111350Sandreas.sandberg@arm.com 10210916Sandreas.sandberg@arm.com panicOnErr( 10310916Sandreas.sandberg@arm.com nomali_get_info(nomali, &nomaliInfo), 10410916Sandreas.sandberg@arm.com "Failed to get NoMali information struct"); 10510916Sandreas.sandberg@arm.com} 10610916Sandreas.sandberg@arm.com 10710916Sandreas.sandberg@arm.comNoMaliGpu::~NoMaliGpu() 10810916Sandreas.sandberg@arm.com{ 10910916Sandreas.sandberg@arm.com nomali_destroy(nomali); 11010916Sandreas.sandberg@arm.com} 11110916Sandreas.sandberg@arm.com 11211350Sandreas.sandberg@arm.com 11311350Sandreas.sandberg@arm.comvoid 11411350Sandreas.sandberg@arm.comNoMaliGpu::init() 11511350Sandreas.sandberg@arm.com{ 11611350Sandreas.sandberg@arm.com PioDevice::init(); 11711350Sandreas.sandberg@arm.com 11811350Sandreas.sandberg@arm.com /* Reset the GPU here since the reset callback won't have been 11911350Sandreas.sandberg@arm.com * installed when the GPU was reset at instantiation time. 12011350Sandreas.sandberg@arm.com */ 12111350Sandreas.sandberg@arm.com reset(); 12211350Sandreas.sandberg@arm.com} 12311350Sandreas.sandberg@arm.com 12410916Sandreas.sandberg@arm.comvoid 12510916Sandreas.sandberg@arm.comNoMaliGpu::serialize(CheckpointOut &cp) const 12610916Sandreas.sandberg@arm.com{ 12710916Sandreas.sandberg@arm.com std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2); 12810916Sandreas.sandberg@arm.com 12910916Sandreas.sandberg@arm.com for (int i = 0; i < nomaliInfo.reg_size; i += 4) 13010916Sandreas.sandberg@arm.com regs[i >> 2] = readRegRaw(i); 13110916Sandreas.sandberg@arm.com 13210916Sandreas.sandberg@arm.com SERIALIZE_CONTAINER(regs); 13310916Sandreas.sandberg@arm.com} 13410916Sandreas.sandberg@arm.com 13510916Sandreas.sandberg@arm.comvoid 13610916Sandreas.sandberg@arm.comNoMaliGpu::unserialize(CheckpointIn &cp) 13710916Sandreas.sandberg@arm.com{ 13810916Sandreas.sandberg@arm.com std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2); 13910916Sandreas.sandberg@arm.com 14010916Sandreas.sandberg@arm.com UNSERIALIZE_CONTAINER(regs); 14110916Sandreas.sandberg@arm.com 14210916Sandreas.sandberg@arm.com for (int i = 0; i < nomaliInfo.reg_size; i += 4) 14310916Sandreas.sandberg@arm.com writeRegRaw(i, regs[i >> 2]); 14410916Sandreas.sandberg@arm.com} 14510916Sandreas.sandberg@arm.com 14610916Sandreas.sandberg@arm.comTick 14710916Sandreas.sandberg@arm.comNoMaliGpu::read(PacketPtr pkt) 14810916Sandreas.sandberg@arm.com{ 14910916Sandreas.sandberg@arm.com assert(pkt->getAddr() >= pioAddr); 15010916Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr() - pioAddr); 15110916Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 15210916Sandreas.sandberg@arm.com 15310916Sandreas.sandberg@arm.com if (addr + size >= nomaliInfo.reg_size) 15410916Sandreas.sandberg@arm.com panic("GPU register '0x%x' out of range!\n", addr); 15510916Sandreas.sandberg@arm.com 15610916Sandreas.sandberg@arm.com if (size != 4) 15710916Sandreas.sandberg@arm.com panic("Unexpected GPU register read size: %i\n", size); 15810916Sandreas.sandberg@arm.com else if (addr & 0x3) 15910916Sandreas.sandberg@arm.com panic("Unaligned GPU read: %i\n", size); 16010916Sandreas.sandberg@arm.com 16110916Sandreas.sandberg@arm.com pkt->set<uint32_t>(readReg(addr)); 16210916Sandreas.sandberg@arm.com pkt->makeResponse(); 16310916Sandreas.sandberg@arm.com 16410916Sandreas.sandberg@arm.com return 0; 16510916Sandreas.sandberg@arm.com} 16610916Sandreas.sandberg@arm.com 16710916Sandreas.sandberg@arm.comTick 16810916Sandreas.sandberg@arm.comNoMaliGpu::write(PacketPtr pkt) 16910916Sandreas.sandberg@arm.com{ 17010916Sandreas.sandberg@arm.com assert(pkt->getAddr() >= pioAddr); 17110916Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr() - pioAddr); 17210916Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 17310916Sandreas.sandberg@arm.com 17410916Sandreas.sandberg@arm.com if (addr + size >= nomaliInfo.reg_size) 17510916Sandreas.sandberg@arm.com panic("GPU register '0x%x' out of range!\n", addr); 17610916Sandreas.sandberg@arm.com 17710916Sandreas.sandberg@arm.com if (size != 4) 17810916Sandreas.sandberg@arm.com panic("Unexpected GPU register write size: %i\n", size); 17910916Sandreas.sandberg@arm.com else if (addr & 0x3) 18010916Sandreas.sandberg@arm.com panic("Unaligned GPU write: %i\n", size); 18110916Sandreas.sandberg@arm.com 18210916Sandreas.sandberg@arm.com writeReg(addr, pkt->get<uint32_t>()); 18310916Sandreas.sandberg@arm.com pkt->makeAtomicResponse(); 18410916Sandreas.sandberg@arm.com 18510916Sandreas.sandberg@arm.com return 0; 18610916Sandreas.sandberg@arm.com} 18710916Sandreas.sandberg@arm.com 18810916Sandreas.sandberg@arm.comAddrRangeList 18910916Sandreas.sandberg@arm.comNoMaliGpu::getAddrRanges() const 19010916Sandreas.sandberg@arm.com{ 19110916Sandreas.sandberg@arm.com return AddrRangeList({ RangeSize(pioAddr, nomaliInfo.reg_size) }); 19210916Sandreas.sandberg@arm.com} 19310916Sandreas.sandberg@arm.com 19411349Sandreas.sandberg@arm.comvoid 19511349Sandreas.sandberg@arm.comNoMaliGpu::reset() 19611349Sandreas.sandberg@arm.com{ 19711349Sandreas.sandberg@arm.com DPRINTF(NoMali, "reset()\n"); 19811349Sandreas.sandberg@arm.com 19911349Sandreas.sandberg@arm.com panicOnErr( 20011349Sandreas.sandberg@arm.com nomali_reset(nomali), 20111349Sandreas.sandberg@arm.com "Failed to reset GPU"); 20211349Sandreas.sandberg@arm.com} 20311349Sandreas.sandberg@arm.com 20410916Sandreas.sandberg@arm.comuint32_t 20510916Sandreas.sandberg@arm.comNoMaliGpu::readReg(nomali_addr_t reg) 20610916Sandreas.sandberg@arm.com{ 20710916Sandreas.sandberg@arm.com uint32_t value; 20810916Sandreas.sandberg@arm.com 20910916Sandreas.sandberg@arm.com panicOnErr( 21010916Sandreas.sandberg@arm.com nomali_reg_read(nomali, &value, reg), 21110916Sandreas.sandberg@arm.com "GPU register read failed"); 21210916Sandreas.sandberg@arm.com 21310916Sandreas.sandberg@arm.com DPRINTF(NoMali, "readReg(0x%x): 0x%x\n", 21410916Sandreas.sandberg@arm.com reg, value); 21510916Sandreas.sandberg@arm.com 21610916Sandreas.sandberg@arm.com return value; 21710916Sandreas.sandberg@arm.com} 21810916Sandreas.sandberg@arm.com 21910916Sandreas.sandberg@arm.com 22010916Sandreas.sandberg@arm.comvoid 22110916Sandreas.sandberg@arm.comNoMaliGpu::writeReg(nomali_addr_t reg, uint32_t value) 22210916Sandreas.sandberg@arm.com{ 22310916Sandreas.sandberg@arm.com DPRINTF(NoMali, "writeReg(0x%x, 0x%x)\n", 22410916Sandreas.sandberg@arm.com reg, value); 22510916Sandreas.sandberg@arm.com 22610916Sandreas.sandberg@arm.com panicOnErr( 22710916Sandreas.sandberg@arm.com nomali_reg_write(nomali, reg, value), 22810916Sandreas.sandberg@arm.com "GPU register write failed"); 22910916Sandreas.sandberg@arm.com} 23010916Sandreas.sandberg@arm.com 23110916Sandreas.sandberg@arm.comuint32_t 23210916Sandreas.sandberg@arm.comNoMaliGpu::readRegRaw(nomali_addr_t reg) const 23310916Sandreas.sandberg@arm.com{ 23410916Sandreas.sandberg@arm.com uint32_t value; 23510916Sandreas.sandberg@arm.com 23610916Sandreas.sandberg@arm.com panicOnErr( 23710916Sandreas.sandberg@arm.com nomali_reg_read_raw(nomali, &value, reg), 23810916Sandreas.sandberg@arm.com "GPU raw register read failed"); 23910916Sandreas.sandberg@arm.com 24010916Sandreas.sandberg@arm.com return value; 24110916Sandreas.sandberg@arm.com} 24210916Sandreas.sandberg@arm.com 24310916Sandreas.sandberg@arm.com 24410916Sandreas.sandberg@arm.comvoid 24510916Sandreas.sandberg@arm.comNoMaliGpu::writeRegRaw(nomali_addr_t reg, uint32_t value) 24610916Sandreas.sandberg@arm.com{ 24710916Sandreas.sandberg@arm.com panicOnErr( 24810916Sandreas.sandberg@arm.com nomali_reg_write_raw(nomali, reg, value), 24910916Sandreas.sandberg@arm.com "GPU raw register write failed"); 25010916Sandreas.sandberg@arm.com} 25110916Sandreas.sandberg@arm.com 25211349Sandreas.sandberg@arm.combool 25311349Sandreas.sandberg@arm.comNoMaliGpu::intState(nomali_int_t intno) 25410916Sandreas.sandberg@arm.com{ 25511349Sandreas.sandberg@arm.com int state = 0; 25611349Sandreas.sandberg@arm.com panicOnErr( 25711349Sandreas.sandberg@arm.com nomali_int_state(nomali, &state, intno), 25811349Sandreas.sandberg@arm.com "Failed to get interrupt state"); 25910916Sandreas.sandberg@arm.com 26011349Sandreas.sandberg@arm.com return !!state; 26110916Sandreas.sandberg@arm.com} 26210916Sandreas.sandberg@arm.com 26310916Sandreas.sandberg@arm.comvoid 26411349Sandreas.sandberg@arm.comNoMaliGpu::gpuPanic(nomali_error_t err, const char *msg) 26511349Sandreas.sandberg@arm.com{ 26611349Sandreas.sandberg@arm.com panic("%s: %s\n", msg, nomali_errstr(err)); 26711349Sandreas.sandberg@arm.com} 26811349Sandreas.sandberg@arm.com 26911349Sandreas.sandberg@arm.com 27011349Sandreas.sandberg@arm.comvoid 27111349Sandreas.sandberg@arm.comNoMaliGpu::onInterrupt(nomali_int_t intno, bool set) 27210916Sandreas.sandberg@arm.com{ 27310916Sandreas.sandberg@arm.com const auto it_int(interruptMap.find(intno)); 27410916Sandreas.sandberg@arm.com if (it_int == interruptMap.end()) 27510916Sandreas.sandberg@arm.com panic("Unhandled interrupt from NoMali: %i\n", intno); 27610916Sandreas.sandberg@arm.com 27710916Sandreas.sandberg@arm.com DPRINTF(NoMali, "Interrupt %i->%i: %i\n", 27810916Sandreas.sandberg@arm.com intno, it_int->second, set); 27910916Sandreas.sandberg@arm.com 28010916Sandreas.sandberg@arm.com assert(platform); 28110916Sandreas.sandberg@arm.com assert(platform->gic); 28210916Sandreas.sandberg@arm.com 28310916Sandreas.sandberg@arm.com if (set) 28410916Sandreas.sandberg@arm.com platform->gic->sendInt(it_int->second); 28510916Sandreas.sandberg@arm.com else 28610916Sandreas.sandberg@arm.com platform->gic->clearInt(it_int->second); 28710916Sandreas.sandberg@arm.com} 28810916Sandreas.sandberg@arm.com 28910916Sandreas.sandberg@arm.comvoid 29011350Sandreas.sandberg@arm.comNoMaliGpu::onReset() 29111350Sandreas.sandberg@arm.com{ 29211350Sandreas.sandberg@arm.com DPRINTF(NoMali, "Reset\n"); 29311350Sandreas.sandberg@arm.com} 29411350Sandreas.sandberg@arm.com 29511350Sandreas.sandberg@arm.comvoid 29611349Sandreas.sandberg@arm.comNoMaliGpu::setCallback(const nomali_callback_t &callback) 29710916Sandreas.sandberg@arm.com{ 29811349Sandreas.sandberg@arm.com DPRINTF(NoMali, "Registering callback %i\n", 29911349Sandreas.sandberg@arm.com callback.type); 30011349Sandreas.sandberg@arm.com 30111349Sandreas.sandberg@arm.com panicOnErr( 30211349Sandreas.sandberg@arm.com nomali_set_callback(nomali, &callback), 30311349Sandreas.sandberg@arm.com "Failed to register callback"); 30411349Sandreas.sandberg@arm.com} 30511349Sandreas.sandberg@arm.com 30611349Sandreas.sandberg@arm.comvoid 30711349Sandreas.sandberg@arm.comNoMaliGpu::_interrupt(nomali_handle_t h, void *usr, 30811349Sandreas.sandberg@arm.com nomali_int_t intno, int set) 30911349Sandreas.sandberg@arm.com{ 31011349Sandreas.sandberg@arm.com NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr)); 31111349Sandreas.sandberg@arm.com 31211349Sandreas.sandberg@arm.com _this->onInterrupt(intno, !!set); 31310916Sandreas.sandberg@arm.com} 31410916Sandreas.sandberg@arm.com 31511350Sandreas.sandberg@arm.comvoid 31611350Sandreas.sandberg@arm.comNoMaliGpu::_reset(nomali_handle_t h, void *usr) 31711350Sandreas.sandberg@arm.com{ 31811350Sandreas.sandberg@arm.com NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr)); 31911350Sandreas.sandberg@arm.com 32011350Sandreas.sandberg@arm.com _this->onReset(); 32111350Sandreas.sandberg@arm.com} 32211350Sandreas.sandberg@arm.com 32310916Sandreas.sandberg@arm.comNoMaliGpu * 32410916Sandreas.sandberg@arm.comNoMaliGpuParams::create() 32510916Sandreas.sandberg@arm.com{ 32610916Sandreas.sandberg@arm.com return new NoMaliGpu(this); 32710916Sandreas.sandberg@arm.com} 328