71888bd8b3af63f83a54378f0edb9d7a6323094f
2 * Copyright (c) 2013, 2018-2019 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 * Authors: Stan Czerniawski
40 #include "dev/arm/smmu_v3_proc.hh"
42 #include "dev/arm/smmu_v3.hh"
43 #include "sim/system.hh"
45 SMMUProcess::SMMUProcess(const std::string
&name
, SMMUv3
&_smmu
) :
51 SMMUProcess::~SMMUProcess()
59 smmu
.runProcess(this, NULL
);
66 coroutine
= new Coroutine(
67 std::bind(&SMMUProcess::main
, this, std::placeholders::_1
));
71 SMMUProcess::doRead(Yield
&yield
, Addr addr
, void *ptr
, size_t size
)
73 doSemaphoreDown(yield
, smmu
.masterPortSem
);
74 doDelay(yield
, Cycles(1)); // request - assume 1 cycle
75 doSemaphoreUp(smmu
.masterPortSem
);
78 a
.type
= ACTION_SEND_REQ
;
80 RequestPtr req
= std::make_shared
<Request
>(
81 addr
, size
, 0, smmu
.masterId
);
83 req
->taskId(ContextSwitchTaskId::DMA
);
85 a
.pkt
= new Packet(req
, MemCmd::ReadReq
);
86 a
.pkt
->dataStatic(ptr
);
90 PacketPtr pkt
= yield(a
).get();
93 // >= because we may get the whole cache line
94 assert(pkt
->getSize() >= size
);
100 SMMUProcess::doWrite(Yield
&yield
, Addr addr
, const void *ptr
, size_t size
)
102 unsigned nbeats
= (size
+ (smmu
.masterPortWidth
-1)) / smmu
.masterPortWidth
;
104 doSemaphoreDown(yield
, smmu
.masterPortSem
);
105 doDelay(yield
, Cycles(nbeats
));
106 doSemaphoreUp(smmu
.masterPortSem
);
110 a
.type
= ACTION_SEND_REQ
;
112 RequestPtr req
= std::make_shared
<Request
>(
113 addr
, size
, 0, smmu
.masterId
);
115 req
->taskId(ContextSwitchTaskId::DMA
);
117 a
.pkt
= new Packet(req
, MemCmd::WriteReq
);
118 a
.pkt
->dataStatic(ptr
);
120 PacketPtr pkt
= yield(a
).get();
126 SMMUProcess::doDelay(Yield
&yield
, Cycles cycles
)
128 if (smmu
.system
.isTimingMode())
129 scheduleWakeup(smmu
.clockEdge(cycles
));
132 a
.type
= ACTION_DELAY
;
133 a
.delay
= cycles
* smmu
.clockPeriod();
138 SMMUProcess::doSleep(Yield
&yield
)
141 a
.type
= ACTION_SLEEP
;
146 SMMUProcess::doSemaphoreDown(Yield
&yield
, SMMUSemaphore
&sem
)
148 while (sem
.count
== 0) {
149 sem
.queue
.push(this);
158 SMMUProcess::doSemaphoreUp(SMMUSemaphore
&sem
)
161 if (!sem
.queue
.empty()) {
162 SMMUProcess
*next_proc
= sem
.queue
.front();
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());
173 SMMUProcess::doWaitForSignal(Yield
&yield
, SMMUSignal
&sig
)
175 sig
.waiting
.push_back(this);
180 SMMUProcess::doBroadcastSignal(SMMUSignal
&sig
)
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());
195 SMMUProcess::scheduleWakeup(Tick when
)
197 auto *ep
= new EventWrapper
<
198 SMMUProcess
, &SMMUProcess::wakeup
> (this, true);
200 smmu
.schedule(ep
, when
);
204 SMMUProcess::run(PacketPtr pkt
)
206 assert(coroutine
!= NULL
);
208 return (*coroutine
)(pkt
).get();