gpu_nomali.cc revision 13230
16145Snate@binkert.org/* 26145Snate@binkert.org * Copyright (c) 2014-2016 ARM Limited 36145Snate@binkert.org * All rights reserved 46145Snate@binkert.org * 56145Snate@binkert.org * The license below extends only to copyright in the software and shall 66145Snate@binkert.org * not be construed as granting a license to any other intellectual 76145Snate@binkert.org * property including but not limited to intellectual property relating 86145Snate@binkert.org * to a hardware implementation of the functionality of the software 96145Snate@binkert.org * licensed hereunder. You may use the software subject to the license 106145Snate@binkert.org * terms below provided that you ensure that this notice is replicated 116145Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 126145Snate@binkert.org * modified or unmodified, in source code or in binary form. 136145Snate@binkert.org * 146145Snate@binkert.org * Redistribution and use in source and binary forms, with or without 156145Snate@binkert.org * modification, are permitted provided that the following conditions are 166145Snate@binkert.org * met: redistributions of source code must retain the above copyright 176145Snate@binkert.org * notice, this list of conditions and the following disclaimer; 186145Snate@binkert.org * redistributions in binary form must reproduce the above copyright 196145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 206145Snate@binkert.org * documentation and/or other materials provided with the distribution; 216145Snate@binkert.org * neither the name of the copyright holders nor the names of its 226145Snate@binkert.org * contributors may be used to endorse or promote products derived from 236145Snate@binkert.org * this software without specific prior written permission. 246145Snate@binkert.org * 256145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 266145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 276145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 286145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297054Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307054Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 316154Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 326154Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337054Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347054Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 356154Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 366145Snate@binkert.org * 377055Snate@binkert.org * Authors: Andreas Sandberg 387055Snate@binkert.org */ 396145Snate@binkert.org 406145Snate@binkert.org#include "dev/arm/gpu_nomali.hh" 416145Snate@binkert.org 426145Snate@binkert.org#include "debug/NoMali.hh" 436145Snate@binkert.org#include "dev/arm/base_gic.hh" 446145Snate@binkert.org#include "dev/arm/realview.hh" 456145Snate@binkert.org#include "enums/MemoryMode.hh" 466145Snate@binkert.org#include "mem/packet_access.hh" 476145Snate@binkert.org#include "nomali/lib/mali_midg_regmap.h" 487055Snate@binkert.org#include "params/CustomNoMaliGpu.hh" 496145Snate@binkert.org#include "params/NoMaliGpu.hh" 507054Snate@binkert.org 517054Snate@binkert.orgstatic const std::map<Enums::NoMaliGpuType, nomali_gpu_type_t> gpuTypeMap{ 526145Snate@binkert.org { Enums::T60x, NOMALI_GPU_T60X }, 537054Snate@binkert.org { Enums::T62x, NOMALI_GPU_T62X }, 547054Snate@binkert.org { Enums::T760, NOMALI_GPU_T760 }, 556145Snate@binkert.org}; 566145Snate@binkert.org 577054Snate@binkert.orgNoMaliGpu::NoMaliGpu(const NoMaliGpuParams *p) 587054Snate@binkert.org : PioDevice(p), 596145Snate@binkert.org pioAddr(p->pio_addr), 607054Snate@binkert.org platform(p->platform), 617054Snate@binkert.org interruptMap{ 626145Snate@binkert.org { NOMALI_INT_GPU, p->int_gpu }, 636145Snate@binkert.org { NOMALI_INT_JOB, p->int_job }, 647054Snate@binkert.org { NOMALI_INT_MMU, p->int_mmu }, 657054Snate@binkert.org } 666145Snate@binkert.org{ 677054Snate@binkert.org if (nomali_api_version() != NOMALI_API_VERSION) 687054Snate@binkert.org panic("NoMali library API mismatch!\n"); 696145Snate@binkert.org 707054Snate@binkert.org /* Setup the GPU configuration based on our param struct */ 717054Snate@binkert.org nomali_config_t cfg; 727054Snate@binkert.org memset(&cfg, 0, sizeof(cfg)); 736145Snate@binkert.org 747054Snate@binkert.org const auto it_gpu(gpuTypeMap.find(p->gpu_type)); 757054Snate@binkert.org if (it_gpu == gpuTypeMap.end()) { 766145Snate@binkert.org fatal("Unrecognized GPU type: %s (%i)\n", 776145Snate@binkert.org Enums::NoMaliGpuTypeStrings[p->gpu_type], p->gpu_type); 787054Snate@binkert.org } 797054Snate@binkert.org cfg.type = it_gpu->second; 806145Snate@binkert.org 817054Snate@binkert.org cfg.ver_maj = p->ver_maj; 827054Snate@binkert.org cfg.ver_min = p->ver_min; 837054Snate@binkert.org cfg.ver_status = p->ver_status; 847054Snate@binkert.org 856145Snate@binkert.org panicOnErr( 866145Snate@binkert.org nomali_create(&nomali, &cfg), 877054Snate@binkert.org "Failed to instantiate NoMali"); 887054Snate@binkert.org 897054Snate@binkert.org 906145Snate@binkert.org /* Setup an interrupt callback */ 917054Snate@binkert.org nomali_callback_t cbk_int; 927054Snate@binkert.org cbk_int.type = NOMALI_CALLBACK_INT; 937054Snate@binkert.org cbk_int.usr = (void *)this; 947054Snate@binkert.org cbk_int.func.interrupt = NoMaliGpu::_interrupt; 956145Snate@binkert.org setCallback(cbk_int); 967054Snate@binkert.org 977054Snate@binkert.org /* Setup a reset callback */ 987054Snate@binkert.org nomali_callback_t cbk_rst; 997054Snate@binkert.org cbk_rst.type = NOMALI_CALLBACK_RESET; 1007054Snate@binkert.org cbk_rst.usr = (void *)this; 1017054Snate@binkert.org cbk_rst.func.reset = NoMaliGpu::_reset; 1026145Snate@binkert.org setCallback(cbk_rst); 1036145Snate@binkert.org 1046145Snate@binkert.org panicOnErr( 1057054Snate@binkert.org nomali_get_info(nomali, &nomaliInfo), 1067054Snate@binkert.org "Failed to get NoMali information struct"); 1076145Snate@binkert.org} 1087054Snate@binkert.org 1097054Snate@binkert.orgNoMaliGpu::~NoMaliGpu() 1107054Snate@binkert.org{ 1116145Snate@binkert.org nomali_destroy(nomali); 1127054Snate@binkert.org} 1137054Snate@binkert.org 1147054Snate@binkert.org 1157054Snate@binkert.orgvoid 1167054Snate@binkert.orgNoMaliGpu::init() 1177054Snate@binkert.org{ 1186145Snate@binkert.org PioDevice::init(); 1196145Snate@binkert.org 1207054Snate@binkert.org /* Reset the GPU here since the reset callback won't have been 1217054Snate@binkert.org * installed when the GPU was reset at instantiation time. 1226145Snate@binkert.org */ 1237054Snate@binkert.org reset(); 1247054Snate@binkert.org} 1257054Snate@binkert.org 1266145Snate@binkert.orgvoid 1277054Snate@binkert.orgNoMaliGpu::serialize(CheckpointOut &cp) const 1287054Snate@binkert.org{ 1297054Snate@binkert.org std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2); 1307054Snate@binkert.org 1317054Snate@binkert.org for (int i = 0; i < nomaliInfo.reg_size; i += 4) 1327054Snate@binkert.org regs[i >> 2] = readRegRaw(i); 1336145Snate@binkert.org 1347054Snate@binkert.org SERIALIZE_CONTAINER(regs); 1357054Snate@binkert.org} 1367054Snate@binkert.org 1377054Snate@binkert.orgvoid 1387054Snate@binkert.orgNoMaliGpu::unserialize(CheckpointIn &cp) 1397054Snate@binkert.org{ 1406145Snate@binkert.org std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2); 1416145Snate@binkert.org 1427054Snate@binkert.org UNSERIALIZE_CONTAINER(regs); 1437054Snate@binkert.org 1447054Snate@binkert.org for (int i = 0; i < nomaliInfo.reg_size; i += 4) 1457054Snate@binkert.org writeRegRaw(i, regs[i >> 2]); 1467054Snate@binkert.org} 1477054Snate@binkert.org 1487054Snate@binkert.orgTick 1497054Snate@binkert.orgNoMaliGpu::read(PacketPtr pkt) 1507054Snate@binkert.org{ 1517054Snate@binkert.org assert(pkt->getAddr() >= pioAddr); 1527054Snate@binkert.org const Addr addr(pkt->getAddr() - pioAddr); 1537054Snate@binkert.org const unsigned size(pkt->getSize()); 1547054Snate@binkert.org 1557054Snate@binkert.org if (addr + size >= nomaliInfo.reg_size) 1567054Snate@binkert.org panic("GPU register '0x%x' out of range!\n", addr); 1577054Snate@binkert.org 1587054Snate@binkert.org if (size != 4) 1597054Snate@binkert.org panic("Unexpected GPU register read size: %i\n", size); 1607453Snate@binkert.org else if (addr & 0x3) 1617054Snate@binkert.org panic("Unaligned GPU read: %i\n", size); 1627054Snate@binkert.org 1637054Snate@binkert.org pkt->setLE<uint32_t>(readReg(addr)); 1647054Snate@binkert.org pkt->makeResponse(); 1657054Snate@binkert.org 1667054Snate@binkert.org return 0; 1677054Snate@binkert.org} 1687054Snate@binkert.org 1697054Snate@binkert.orgTick 1707054Snate@binkert.orgNoMaliGpu::write(PacketPtr pkt) 1717054Snate@binkert.org{ 1727054Snate@binkert.org assert(pkt->getAddr() >= pioAddr); 1737054Snate@binkert.org const Addr addr(pkt->getAddr() - pioAddr); 1747054Snate@binkert.org const unsigned size(pkt->getSize()); 1757054Snate@binkert.org 1767054Snate@binkert.org if (addr + size >= nomaliInfo.reg_size) 1777054Snate@binkert.org panic("GPU register '0x%x' out of range!\n", addr); 1787054Snate@binkert.org 1797054Snate@binkert.org if (size != 4) 1807054Snate@binkert.org panic("Unexpected GPU register write size: %i\n", size); 1817054Snate@binkert.org else if (addr & 0x3) 1827054Snate@binkert.org panic("Unaligned GPU write: %i\n", size); 1837054Snate@binkert.org 1847054Snate@binkert.org writeReg(addr, pkt->getLE<uint32_t>()); 1857054Snate@binkert.org pkt->makeAtomicResponse(); 1867054Snate@binkert.org 1877054Snate@binkert.org return 0; 1887054Snate@binkert.org} 1897054Snate@binkert.org 1907054Snate@binkert.orgAddrRangeList 1917054Snate@binkert.orgNoMaliGpu::getAddrRanges() const 1927054Snate@binkert.org{ 1937054Snate@binkert.org return AddrRangeList({ RangeSize(pioAddr, nomaliInfo.reg_size) }); 1947054Snate@binkert.org} 1957054Snate@binkert.org 1966145Snate@binkert.orgvoid 1976145Snate@binkert.orgNoMaliGpu::reset() 1987054Snate@binkert.org{ 1997054Snate@binkert.org DPRINTF(NoMali, "reset()\n"); 2007054Snate@binkert.org 2016145Snate@binkert.org panicOnErr( 2027054Snate@binkert.org nomali_reset(nomali), 2037054Snate@binkert.org "Failed to reset GPU"); 2046145Snate@binkert.org} 2057054Snate@binkert.org 2067054Snate@binkert.orguint32_t 2077054Snate@binkert.orgNoMaliGpu::readReg(nomali_addr_t reg) 2087054Snate@binkert.org{ 2097054Snate@binkert.org uint32_t value; 2107054Snate@binkert.org 2117054Snate@binkert.org panicOnErr( 2127054Snate@binkert.org nomali_reg_read(nomali, &value, reg), 2137054Snate@binkert.org "GPU register read failed"); 2147054Snate@binkert.org 2157054Snate@binkert.org DPRINTF(NoMali, "readReg(0x%x): 0x%x\n", 2167054Snate@binkert.org reg, value); 2177054Snate@binkert.org 2187054Snate@binkert.org return value; 2197054Snate@binkert.org} 2207054Snate@binkert.org 2217054Snate@binkert.org 2226145Snate@binkert.orgvoid 2236145Snate@binkert.orgNoMaliGpu::writeReg(nomali_addr_t reg, uint32_t value) 2247054Snate@binkert.org{ 2257054Snate@binkert.org DPRINTF(NoMali, "writeReg(0x%x, 0x%x)\n", 2266145Snate@binkert.org reg, value); 2277054Snate@binkert.org 2286145Snate@binkert.org panicOnErr( 2296145Snate@binkert.org nomali_reg_write(nomali, reg, value), 2307054Snate@binkert.org "GPU register write failed"); 2317054Snate@binkert.org} 2326145Snate@binkert.org 2337054Snate@binkert.orguint32_t 2347054Snate@binkert.orgNoMaliGpu::readRegRaw(nomali_addr_t reg) const 2356145Snate@binkert.org{ 2367054Snate@binkert.org uint32_t value; 2377054Snate@binkert.org 2387054Snate@binkert.org panicOnErr( 2397054Snate@binkert.org nomali_reg_read_raw(nomali, &value, reg), 2406145Snate@binkert.org "GPU raw register read failed"); 2416145Snate@binkert.org 2426145Snate@binkert.org return value; 2437054Snate@binkert.org} 2447054Snate@binkert.org 2456145Snate@binkert.org 2466145Snate@binkert.orgvoid 2476145Snate@binkert.orgNoMaliGpu::writeRegRaw(nomali_addr_t reg, uint32_t value) 2487054Snate@binkert.org{ 2497054Snate@binkert.org panicOnErr( 2506145Snate@binkert.org nomali_reg_write_raw(nomali, reg, value), 2517054Snate@binkert.org "GPU raw register write failed"); 2527054Snate@binkert.org} 2536145Snate@binkert.org 2546145Snate@binkert.orgbool 2557054Snate@binkert.orgNoMaliGpu::intState(nomali_int_t intno) 2567054Snate@binkert.org{ 2576145Snate@binkert.org int state = 0; 2587054Snate@binkert.org panicOnErr( 2597054Snate@binkert.org nomali_int_state(nomali, &state, intno), 2606145Snate@binkert.org "Failed to get interrupt state"); 2616145Snate@binkert.org 2627054Snate@binkert.org return !!state; 2637054Snate@binkert.org} 2647054Snate@binkert.org 2657054Snate@binkert.orgvoid 2666145Snate@binkert.orgNoMaliGpu::gpuPanic(nomali_error_t err, const char *msg) 2677054Snate@binkert.org{ 2687054Snate@binkert.org panic("%s: %s\n", msg, nomali_errstr(err)); 2697054Snate@binkert.org} 2706145Snate@binkert.org 2717054Snate@binkert.org 2727054Snate@binkert.orgvoid 2737054Snate@binkert.orgNoMaliGpu::onInterrupt(nomali_int_t intno, bool set) 2747054Snate@binkert.org{ 2757054Snate@binkert.org const auto it_int(interruptMap.find(intno)); 2766145Snate@binkert.org if (it_int == interruptMap.end()) 277 panic("Unhandled interrupt from NoMali: %i\n", intno); 278 279 DPRINTF(NoMali, "Interrupt %i->%i: %i\n", 280 intno, it_int->second, set); 281 282 assert(platform); 283 assert(platform->gic); 284 285 if (set) 286 platform->gic->sendInt(it_int->second); 287 else 288 platform->gic->clearInt(it_int->second); 289} 290 291void 292NoMaliGpu::onReset() 293{ 294 DPRINTF(NoMali, "Reset\n"); 295} 296 297void 298NoMaliGpu::setCallback(const nomali_callback_t &callback) 299{ 300 DPRINTF(NoMali, "Registering callback %i\n", 301 callback.type); 302 303 panicOnErr( 304 nomali_set_callback(nomali, &callback), 305 "Failed to register callback"); 306} 307 308void 309NoMaliGpu::_interrupt(nomali_handle_t h, void *usr, 310 nomali_int_t intno, int set) 311{ 312 NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr)); 313 314 _this->onInterrupt(intno, !!set); 315} 316 317void 318NoMaliGpu::_reset(nomali_handle_t h, void *usr) 319{ 320 NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr)); 321 322 _this->onReset(); 323} 324 325 326CustomNoMaliGpu::CustomNoMaliGpu(const CustomNoMaliGpuParams *p) 327 : NoMaliGpu(p), 328 idRegs{ 329 { GPU_CONTROL_REG(GPU_ID), p->gpu_id }, 330 { GPU_CONTROL_REG(L2_FEATURES), p->l2_features }, 331 { GPU_CONTROL_REG(TILER_FEATURES), p->tiler_features }, 332 { GPU_CONTROL_REG(MEM_FEATURES), p->mem_features }, 333 { GPU_CONTROL_REG(MMU_FEATURES), p->mmu_features }, 334 { GPU_CONTROL_REG(AS_PRESENT), p->as_present }, 335 { GPU_CONTROL_REG(JS_PRESENT), p->js_present }, 336 337 { GPU_CONTROL_REG(THREAD_MAX_THREADS), p->thread_max_threads }, 338 { GPU_CONTROL_REG(THREAD_MAX_WORKGROUP_SIZE), 339 p->thread_max_workgroup_size }, 340 { GPU_CONTROL_REG(THREAD_MAX_BARRIER_SIZE), 341 p->thread_max_barrier_size }, 342 { GPU_CONTROL_REG(THREAD_FEATURES), p->thread_features }, 343 344 { GPU_CONTROL_REG(SHADER_PRESENT_LO), bits(p->shader_present, 31, 0) }, 345 { GPU_CONTROL_REG(SHADER_PRESENT_HI), bits(p->shader_present, 63, 32) }, 346 { GPU_CONTROL_REG(TILER_PRESENT_LO), bits(p->tiler_present, 31, 0) }, 347 { GPU_CONTROL_REG(TILER_PRESENT_HI), bits(p->tiler_present, 63, 32) }, 348 { GPU_CONTROL_REG(L2_PRESENT_LO), bits(p->l2_present, 31, 0) }, 349 { GPU_CONTROL_REG(L2_PRESENT_HI), bits(p->l2_present, 63, 32) }, 350 } 351{ 352 fatal_if(p->texture_features.size() > 3, 353 "Too many texture feature registers specified (%i)\n", 354 p->texture_features.size()); 355 356 fatal_if(p->js_features.size() > 16, 357 "Too many job slot feature registers specified (%i)\n", 358 p->js_features.size()); 359 360 for (int i = 0; i < p->texture_features.size(); i++) 361 idRegs[TEXTURE_FEATURES_REG(i)] = p->texture_features[i]; 362 363 for (int i = 0; i < p->js_features.size(); i++) 364 idRegs[JS_FEATURES_REG(i)] = p->js_features[i]; 365} 366 367CustomNoMaliGpu::~CustomNoMaliGpu() 368{ 369} 370 371void 372CustomNoMaliGpu::onReset() 373{ 374 NoMaliGpu::onReset(); 375 376 for (const auto ® : idRegs) 377 writeRegRaw(reg.first, reg.second); 378} 379 380 381 382NoMaliGpu * 383NoMaliGpuParams::create() 384{ 385 return new NoMaliGpu(this); 386} 387 388CustomNoMaliGpu * 389CustomNoMaliGpuParams::create() 390{ 391 return new CustomNoMaliGpu(this); 392} 393