smmu_v3_proc.cc revision 14039:4991b2a345a1
16145Snate@binkert.org/* 26145Snate@binkert.org * Copyright (c) 2013, 2018-2019 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 296145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307039Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 316145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 326145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337039Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347039Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 356145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367055Snate@binkert.org * 377055Snate@binkert.org * Authors: Stan Czerniawski 387039Snate@binkert.org */ 397039Snate@binkert.org 406154Snate@binkert.org#include "dev/arm/smmu_v3_proc.hh" 416882SBrad.Beckmann@amd.com 426145Snate@binkert.org#include "dev/arm/smmu_v3.hh" 436285Snate@binkert.org#include "sim/system.hh" 446285Snate@binkert.org 457039Snate@binkert.orgSMMUProcess::SMMUProcess(const std::string &name, SMMUv3 &_smmu) : 467039Snate@binkert.org coroutine(NULL), 477039Snate@binkert.org myName(name), 487039Snate@binkert.org smmu(_smmu) 497039Snate@binkert.org{} 506145Snate@binkert.org 518086SBrad.Beckmann@amd.comSMMUProcess::~SMMUProcess() 527839Snilay@cs.wisc.edu{ 537839Snilay@cs.wisc.edu delete coroutine; 547039Snate@binkert.org} 557039Snate@binkert.org 567039Snate@binkert.orgvoid 577839Snilay@cs.wisc.eduSMMUProcess::wakeup() 587839Snilay@cs.wisc.edu{ 596145Snate@binkert.org smmu.runProcess(this, NULL); 606145Snate@binkert.org} 617055Snate@binkert.org 627055Snate@binkert.orgvoid 636145Snate@binkert.orgSMMUProcess::reinit() 647039Snate@binkert.org{ 657055Snate@binkert.org delete coroutine; 667039Snate@binkert.org coroutine = new Coroutine( 676145Snate@binkert.org std::bind(&SMMUProcess::main, this, std::placeholders::_1)); 686145Snate@binkert.org} 697039Snate@binkert.org 70void 71SMMUProcess::doRead(Yield &yield, Addr addr, void *ptr, size_t size) 72{ 73 doSemaphoreDown(yield, smmu.masterPortSem); 74 doDelay(yield, Cycles(1)); // request - assume 1 cycle 75 doSemaphoreUp(smmu.masterPortSem); 76 77 SMMUAction a; 78 a.type = ACTION_SEND_REQ; 79 80 RequestPtr req = std::make_shared<Request>( 81 addr, size, 0, smmu.masterId); 82 83 req->taskId(ContextSwitchTaskId::DMA); 84 85 a.pkt = new Packet(req, MemCmd::ReadReq); 86 a.pkt->dataStatic(ptr); 87 88 a.delay = 0; 89 90 PacketPtr pkt = yield(a).get(); 91 92 assert(pkt); 93 // >= because we may get the whole cache line 94 assert(pkt->getSize() >= size); 95 96 delete pkt; 97} 98 99void 100SMMUProcess::doWrite(Yield &yield, Addr addr, const void *ptr, size_t size) 101{ 102 unsigned nbeats = (size + (smmu.masterPortWidth-1)) / smmu.masterPortWidth; 103 104 doSemaphoreDown(yield, smmu.masterPortSem); 105 doDelay(yield, Cycles(nbeats)); 106 doSemaphoreUp(smmu.masterPortSem); 107 108 109 SMMUAction a; 110 a.type = ACTION_SEND_REQ; 111 112 RequestPtr req = std::make_shared<Request>( 113 addr, size, 0, smmu.masterId); 114 115 req->taskId(ContextSwitchTaskId::DMA); 116 117 a.pkt = new Packet(req, MemCmd::WriteReq); 118 a.pkt->dataStatic(ptr); 119 120 PacketPtr pkt = yield(a).get(); 121 122 delete pkt; 123} 124 125void 126SMMUProcess::doDelay(Yield &yield, Cycles cycles) 127{ 128 if (smmu.system.isTimingMode()) 129 scheduleWakeup(smmu.clockEdge(cycles)); 130 131 SMMUAction a; 132 a.type = ACTION_DELAY; 133 a.delay = cycles * smmu.clockPeriod(); 134 yield(a); 135} 136 137void 138SMMUProcess::doSleep(Yield &yield) 139{ 140 SMMUAction a; 141 a.type = ACTION_SLEEP; 142 yield(a); 143} 144 145void 146SMMUProcess::doSemaphoreDown(Yield &yield, SMMUSemaphore &sem) 147{ 148 while (sem.count == 0) { 149 sem.queue.push(this); 150 doSleep(yield); 151 } 152 153 sem.count--; 154 return; 155} 156 157void 158SMMUProcess::doSemaphoreUp(SMMUSemaphore &sem) 159{ 160 sem.count++; 161 if (!sem.queue.empty()) { 162 SMMUProcess *next_proc = sem.queue.front(); 163 sem.queue.pop(); 164 165 // Schedule event in the current tick instead of 166 // calling the function directly to avoid overflowing 167 // the stack in this coroutine. 168 next_proc->scheduleWakeup(curTick()); 169 } 170} 171 172void 173SMMUProcess::doWaitForSignal(Yield &yield, SMMUSignal &sig) 174{ 175 sig.waiting.push_back(this); 176 doSleep(yield); 177} 178 179void 180SMMUProcess::doBroadcastSignal(SMMUSignal &sig) 181{ 182 if (!sig.waiting.empty()) { 183 for (auto it : sig.waiting) { 184 // Schedule event in the current tick instead of 185 // calling the function directly to avoid overflowing 186 // the stack in this coroutine. 187 it->scheduleWakeup(curTick()); 188 } 189 190 sig.waiting.clear(); 191 } 192} 193 194void 195SMMUProcess::scheduleWakeup(Tick when) 196{ 197 auto *ep = new EventWrapper< 198 SMMUProcess, &SMMUProcess::wakeup> (this, true); 199 200 smmu.schedule(ep, when); 201} 202 203SMMUAction 204SMMUProcess::run(PacketPtr pkt) 205{ 206 assert(coroutine != NULL); 207 assert(*coroutine); 208 return (*coroutine)(pkt).get(); 209} 210