114039Sstacze01@arm.com/* 214039Sstacze01@arm.com * Copyright (c) 2013, 2018-2019 ARM Limited 314039Sstacze01@arm.com * All rights reserved 414039Sstacze01@arm.com * 514039Sstacze01@arm.com * The license below extends only to copyright in the software and shall 614039Sstacze01@arm.com * not be construed as granting a license to any other intellectual 714039Sstacze01@arm.com * property including but not limited to intellectual property relating 814039Sstacze01@arm.com * to a hardware implementation of the functionality of the software 914039Sstacze01@arm.com * licensed hereunder. You may use the software subject to the license 1014039Sstacze01@arm.com * terms below provided that you ensure that this notice is replicated 1114039Sstacze01@arm.com * unmodified and in its entirety in all distributions of the software, 1214039Sstacze01@arm.com * modified or unmodified, in source code or in binary form. 1314039Sstacze01@arm.com * 1414039Sstacze01@arm.com * Redistribution and use in source and binary forms, with or without 1514039Sstacze01@arm.com * modification, are permitted provided that the following conditions are 1614039Sstacze01@arm.com * met: redistributions of source code must retain the above copyright 1714039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer; 1814039Sstacze01@arm.com * redistributions in binary form must reproduce the above copyright 1914039Sstacze01@arm.com * notice, this list of conditions and the following disclaimer in the 2014039Sstacze01@arm.com * documentation and/or other materials provided with the distribution; 2114039Sstacze01@arm.com * neither the name of the copyright holders nor the names of its 2214039Sstacze01@arm.com * contributors may be used to endorse or promote products derived from 2314039Sstacze01@arm.com * this software without specific prior written permission. 2414039Sstacze01@arm.com * 2514039Sstacze01@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2614039Sstacze01@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2714039Sstacze01@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2814039Sstacze01@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2914039Sstacze01@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3014039Sstacze01@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3114039Sstacze01@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3214039Sstacze01@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3314039Sstacze01@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3414039Sstacze01@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3514039Sstacze01@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3614039Sstacze01@arm.com * 3714039Sstacze01@arm.com * Authors: Stan Czerniawski 3814039Sstacze01@arm.com */ 3914039Sstacze01@arm.com 4014039Sstacze01@arm.com#include "dev/arm/smmu_v3_proc.hh" 4114039Sstacze01@arm.com 4214039Sstacze01@arm.com#include "dev/arm/smmu_v3.hh" 4314039Sstacze01@arm.com#include "sim/system.hh" 4414039Sstacze01@arm.com 4514039Sstacze01@arm.comSMMUProcess::SMMUProcess(const std::string &name, SMMUv3 &_smmu) : 4614039Sstacze01@arm.com coroutine(NULL), 4714039Sstacze01@arm.com myName(name), 4814039Sstacze01@arm.com smmu(_smmu) 4914039Sstacze01@arm.com{} 5014039Sstacze01@arm.com 5114039Sstacze01@arm.comSMMUProcess::~SMMUProcess() 5214039Sstacze01@arm.com{ 5314039Sstacze01@arm.com delete coroutine; 5414039Sstacze01@arm.com} 5514039Sstacze01@arm.com 5614039Sstacze01@arm.comvoid 5714039Sstacze01@arm.comSMMUProcess::wakeup() 5814039Sstacze01@arm.com{ 5914039Sstacze01@arm.com smmu.runProcess(this, NULL); 6014039Sstacze01@arm.com} 6114039Sstacze01@arm.com 6214039Sstacze01@arm.comvoid 6314039Sstacze01@arm.comSMMUProcess::reinit() 6414039Sstacze01@arm.com{ 6514039Sstacze01@arm.com delete coroutine; 6614039Sstacze01@arm.com coroutine = new Coroutine( 6714039Sstacze01@arm.com std::bind(&SMMUProcess::main, this, std::placeholders::_1)); 6814039Sstacze01@arm.com} 6914039Sstacze01@arm.com 7014039Sstacze01@arm.comvoid 7114039Sstacze01@arm.comSMMUProcess::doRead(Yield &yield, Addr addr, void *ptr, size_t size) 7214039Sstacze01@arm.com{ 7314039Sstacze01@arm.com doSemaphoreDown(yield, smmu.masterPortSem); 7414039Sstacze01@arm.com doDelay(yield, Cycles(1)); // request - assume 1 cycle 7514039Sstacze01@arm.com doSemaphoreUp(smmu.masterPortSem); 7614039Sstacze01@arm.com 7714039Sstacze01@arm.com SMMUAction a; 7814039Sstacze01@arm.com a.type = ACTION_SEND_REQ; 7914039Sstacze01@arm.com 8014039Sstacze01@arm.com RequestPtr req = std::make_shared<Request>( 8114039Sstacze01@arm.com addr, size, 0, smmu.masterId); 8214039Sstacze01@arm.com 8314039Sstacze01@arm.com req->taskId(ContextSwitchTaskId::DMA); 8414039Sstacze01@arm.com 8514039Sstacze01@arm.com a.pkt = new Packet(req, MemCmd::ReadReq); 8614039Sstacze01@arm.com a.pkt->dataStatic(ptr); 8714039Sstacze01@arm.com 8814039Sstacze01@arm.com a.delay = 0; 8914039Sstacze01@arm.com 9014039Sstacze01@arm.com PacketPtr pkt = yield(a).get(); 9114039Sstacze01@arm.com 9214039Sstacze01@arm.com assert(pkt); 9314039Sstacze01@arm.com // >= because we may get the whole cache line 9414039Sstacze01@arm.com assert(pkt->getSize() >= size); 9514039Sstacze01@arm.com 9614039Sstacze01@arm.com delete pkt; 9714039Sstacze01@arm.com} 9814039Sstacze01@arm.com 9914039Sstacze01@arm.comvoid 10014039Sstacze01@arm.comSMMUProcess::doWrite(Yield &yield, Addr addr, const void *ptr, size_t size) 10114039Sstacze01@arm.com{ 10214039Sstacze01@arm.com unsigned nbeats = (size + (smmu.masterPortWidth-1)) / smmu.masterPortWidth; 10314039Sstacze01@arm.com 10414039Sstacze01@arm.com doSemaphoreDown(yield, smmu.masterPortSem); 10514039Sstacze01@arm.com doDelay(yield, Cycles(nbeats)); 10614039Sstacze01@arm.com doSemaphoreUp(smmu.masterPortSem); 10714039Sstacze01@arm.com 10814039Sstacze01@arm.com 10914039Sstacze01@arm.com SMMUAction a; 11014039Sstacze01@arm.com a.type = ACTION_SEND_REQ; 11114039Sstacze01@arm.com 11214039Sstacze01@arm.com RequestPtr req = std::make_shared<Request>( 11314039Sstacze01@arm.com addr, size, 0, smmu.masterId); 11414039Sstacze01@arm.com 11514039Sstacze01@arm.com req->taskId(ContextSwitchTaskId::DMA); 11614039Sstacze01@arm.com 11714039Sstacze01@arm.com a.pkt = new Packet(req, MemCmd::WriteReq); 11814039Sstacze01@arm.com a.pkt->dataStatic(ptr); 11914039Sstacze01@arm.com 12014039Sstacze01@arm.com PacketPtr pkt = yield(a).get(); 12114039Sstacze01@arm.com 12214039Sstacze01@arm.com delete pkt; 12314039Sstacze01@arm.com} 12414039Sstacze01@arm.com 12514039Sstacze01@arm.comvoid 12614039Sstacze01@arm.comSMMUProcess::doDelay(Yield &yield, Cycles cycles) 12714039Sstacze01@arm.com{ 12814039Sstacze01@arm.com if (smmu.system.isTimingMode()) 12914039Sstacze01@arm.com scheduleWakeup(smmu.clockEdge(cycles)); 13014039Sstacze01@arm.com 13114039Sstacze01@arm.com SMMUAction a; 13214039Sstacze01@arm.com a.type = ACTION_DELAY; 13314039Sstacze01@arm.com a.delay = cycles * smmu.clockPeriod(); 13414039Sstacze01@arm.com yield(a); 13514039Sstacze01@arm.com} 13614039Sstacze01@arm.com 13714039Sstacze01@arm.comvoid 13814039Sstacze01@arm.comSMMUProcess::doSleep(Yield &yield) 13914039Sstacze01@arm.com{ 14014039Sstacze01@arm.com SMMUAction a; 14114039Sstacze01@arm.com a.type = ACTION_SLEEP; 14214039Sstacze01@arm.com yield(a); 14314039Sstacze01@arm.com} 14414039Sstacze01@arm.com 14514039Sstacze01@arm.comvoid 14614039Sstacze01@arm.comSMMUProcess::doSemaphoreDown(Yield &yield, SMMUSemaphore &sem) 14714039Sstacze01@arm.com{ 14814039Sstacze01@arm.com while (sem.count == 0) { 14914039Sstacze01@arm.com sem.queue.push(this); 15014039Sstacze01@arm.com doSleep(yield); 15114039Sstacze01@arm.com } 15214039Sstacze01@arm.com 15314039Sstacze01@arm.com sem.count--; 15414039Sstacze01@arm.com return; 15514039Sstacze01@arm.com} 15614039Sstacze01@arm.com 15714039Sstacze01@arm.comvoid 15814039Sstacze01@arm.comSMMUProcess::doSemaphoreUp(SMMUSemaphore &sem) 15914039Sstacze01@arm.com{ 16014039Sstacze01@arm.com sem.count++; 16114039Sstacze01@arm.com if (!sem.queue.empty()) { 16214039Sstacze01@arm.com SMMUProcess *next_proc = sem.queue.front(); 16314039Sstacze01@arm.com sem.queue.pop(); 16414039Sstacze01@arm.com 16514039Sstacze01@arm.com // Schedule event in the current tick instead of 16614039Sstacze01@arm.com // calling the function directly to avoid overflowing 16714039Sstacze01@arm.com // the stack in this coroutine. 16814039Sstacze01@arm.com next_proc->scheduleWakeup(curTick()); 16914039Sstacze01@arm.com } 17014039Sstacze01@arm.com} 17114039Sstacze01@arm.com 17214039Sstacze01@arm.comvoid 17314039Sstacze01@arm.comSMMUProcess::doWaitForSignal(Yield &yield, SMMUSignal &sig) 17414039Sstacze01@arm.com{ 17514039Sstacze01@arm.com sig.waiting.push_back(this); 17614039Sstacze01@arm.com doSleep(yield); 17714039Sstacze01@arm.com} 17814039Sstacze01@arm.com 17914039Sstacze01@arm.comvoid 18014039Sstacze01@arm.comSMMUProcess::doBroadcastSignal(SMMUSignal &sig) 18114039Sstacze01@arm.com{ 18214039Sstacze01@arm.com if (!sig.waiting.empty()) { 18314039Sstacze01@arm.com for (auto it : sig.waiting) { 18414039Sstacze01@arm.com // Schedule event in the current tick instead of 18514039Sstacze01@arm.com // calling the function directly to avoid overflowing 18614039Sstacze01@arm.com // the stack in this coroutine. 18714039Sstacze01@arm.com it->scheduleWakeup(curTick()); 18814039Sstacze01@arm.com } 18914039Sstacze01@arm.com 19014039Sstacze01@arm.com sig.waiting.clear(); 19114039Sstacze01@arm.com } 19214039Sstacze01@arm.com} 19314039Sstacze01@arm.com 19414039Sstacze01@arm.comvoid 19514039Sstacze01@arm.comSMMUProcess::scheduleWakeup(Tick when) 19614039Sstacze01@arm.com{ 19714039Sstacze01@arm.com auto *ep = new EventWrapper< 19814039Sstacze01@arm.com SMMUProcess, &SMMUProcess::wakeup> (this, true); 19914039Sstacze01@arm.com 20014039Sstacze01@arm.com smmu.schedule(ep, when); 20114039Sstacze01@arm.com} 20214039Sstacze01@arm.com 20314039Sstacze01@arm.comSMMUAction 20414039Sstacze01@arm.comSMMUProcess::run(PacketPtr pkt) 20514039Sstacze01@arm.com{ 20614039Sstacze01@arm.com assert(coroutine != NULL); 20714039Sstacze01@arm.com assert(*coroutine); 20814039Sstacze01@arm.com return (*coroutine)(pkt).get(); 20914039Sstacze01@arm.com} 210