gem5 v24.0.0.0
Loading...
Searching...
No Matches
fvp_base_pwr_ctrl.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 ARM Limited
3 * All rights reserved
4 *
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.
13 *
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.
24 *
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.
36 */
37
39
40#include "arch/arm/faults.hh"
41#include "arch/arm/system.hh"
42#include "arch/arm/utility.hh"
43#include "cpu/base.hh"
44#include "cpu/thread_context.hh"
45#include "debug/FVPBasePwrCtrl.hh"
46#include "mem/packet_access.hh"
47#include "params/FVPBasePwrCtrl.hh"
48#include "sim/system.hh"
49
50namespace gem5
51{
52
53FVPBasePwrCtrl::FVPBasePwrCtrl(const FVPBasePwrCtrlParams &params)
54 : BasicPioDevice(params, 0x1000),
55 regs(),
56 system(*static_cast<ArmSystem *>(sys))
57{
59 "Base Power Controller does not support multi-threaded systems\n");
61}
62
63void
65{
66 // All cores are ON by default (PwrStatus.{l0,l1} = 0b1)
67 corePwrStatus.resize(sys->threads.size(), 0x60000000);
68 for (const auto &tc : sys->threads)
69 poweredCoresPerCluster[tc->socketId()] += 1;
71}
72
73void
75{
76 PwrStatus *pwrs = getCorePwrStatus(tc);
77
78 if (!pwrs->pwfi)
79 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::setStandByWfi: STANDBYWFI "
80 "asserted for core %d\n", tc->contextId());
81 pwrs->pwfi = 1;
82 if (pwrs->l0 && (pwrs->pp || pwrs->pc))
83 powerCoreOff(tc, pwrs);
84}
85
86void
88{
89 PwrStatus *pwrs = getCorePwrStatus(tc);
90
91 if (pwrs->pwfi)
92 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::clearStandByWfi: STANDBYWFI "
93 "deasserted for core %d\n", tc->contextId());
94 pwrs->pwfi = 0;
95}
96
97bool
99{
100 PwrStatus *pwrs = getCorePwrStatus(tc);
101
102 if (!pwrs->pwk)
103 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::setWakeRequest: WakeRequest "
104 "asserted for core %d\n", tc->contextId());
105 pwrs->pwk = 1;
106 if (!pwrs->l0 && pwrs->wen) {
107 pwrs->wk = WK_GICWR;
108 powerCoreOn(tc, pwrs);
109 return true;
110 }
111 return false;
112}
113
114void
116{
117 PwrStatus *pwrs = getCorePwrStatus(tc);
118
119 if (pwrs->pwk)
120 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::clearWakeRequest: "
121 "WakeRequest deasserted for core %d\n", tc->contextId());
122 pwrs->pwk = 0;
123}
124
125Tick
127{
128 const Addr addr = pkt->getAddr() - pioAddr;
129 const size_t size = pkt->getSize();
130 panic_if(size != 4, "FVPBasePwrCtrl::read: Invalid size %i\n", size);
131
132 uint64_t resp = 0;
133 switch (addr) {
134 case PPOFFR:
135 resp = regs.ppoffr;
136 break;
137 case PPONR:
138 resp = regs.pponr;
139 break;
140 case PCOFFR:
141 resp = regs.pcoffr;
142 break;
143 case PWKUPR:
144 resp = regs.pwkupr;
145 break;
146 case PSYSR:
147 resp = regs.psysr;
148 break;
149 default:
150 warn("FVPBasePwrCtrl::read: Unexpected address (0x%x:%i), "
151 "assuming RAZ\n", addr, size);
152 }
153
154 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::read: 0x%x<-0x%x(%i)\n", resp,
155 addr, size);
156
157 pkt->setUintX(resp, ByteOrder::little);
158 pkt->makeResponse();
159 return pioDelay;
160}
161
162Tick
164{
165 const Addr addr = pkt->getAddr() - pioAddr;
166 const size_t size = pkt->getSize();
167 panic_if(size != 4, "FVPBasePwrCtrl::write: Invalid size %i\n", size);
168
169 uint64_t data = pkt->getUintX(ByteOrder::little);
170
171 // Software may use the power controller to check for core presence
172 // If core is not present, return an invalid MPID as notification
174 PwrStatus *pwrs = tc ? getCorePwrStatus(tc) : nullptr;
175 switch (addr) {
176 case PPOFFR:
177 if (!tc) {
178 regs.ppoffr = ~0;
179 } else if (pwrs->l0) {
180 // Set pending power off
181 pwrs->pp = 1;
183 } else {
184 regs.ppoffr = ~0 & MPID_MSK;
185 }
186 break;
187 case PPONR:
188 if (!tc) {
189 regs.pponr = ~0;
190 } else {
191 if (!pwrs->l0) {
192 pwrs->wk = WK_PPONR;
193 powerCoreOn(tc, pwrs);
194 startCoreUp(tc);
196 } else {
197 regs.pponr = ~0 & MPID_MSK;
198 }
199 }
200 break;
201 case PCOFFR:
202 if (!tc) {
203 regs.pcoffr = ~0;
204 } else if (pwrs->l0) {
205 // Power off all cores in the cluster
206 for (const auto &tco : sys->threads) {
207 if (tc->socketId() == tco->socketId()) {
208 PwrStatus *npwrs = getCorePwrStatus(tco);
209 // Set pending cluster power off
210 npwrs->pc = 1;
211 if (npwrs->l0 && npwrs->pwfi)
212 powerCoreOff(tco, npwrs);
213 }
214 }
215 } else {
216 regs.pcoffr = ~0 & MPID_MSK;
217 }
218 break;
219 case PWKUPR:
220 if (!tc) {
221 regs.pwkupr = ~0;
222 } else {
223 // Update WEN value
224 pwrs->wen = bits(data, 31);
225 // Power-on if there is any pending Wakeup Requests
226 if (!pwrs->l0 && pwrs->wen && pwrs->pwk) {
227 pwrs->wk = WK_GICWR;
228 powerCoreOn(tc, pwrs);
229 startCoreUp(tc);
230 }
231 regs.pwkupr = data & (MPID_MSK | (1 << 31));
232 }
233 break;
234 case PSYSR:
235 if (!tc)
236 regs.psysr = ~0;
237 else
238 regs.psysr = (data & MPID_MSK) | (((uint32_t) *pwrs) & ~MPID_MSK);
239 break;
240 default:
241 warn("FVPBasePwrCtrl::write: Unexpected address (0x%x:%i), "
242 "assuming WI\n", addr, size);
243 }
244
245 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::write: 0x%x->0x%x(%i)\n", data,
246 addr, size);
247
248 pkt->makeResponse();
249 return pioDelay;
250}
251
252FVPBasePwrCtrl::PwrStatus *
254{
255 PwrStatus *pwrs = &corePwrStatus[tc->contextId()];
256 pwrs->l1 = poweredCoresPerCluster[tc->socketId()] > 0;
257 return pwrs;
258}
259
262{
263 for (auto &tc : sys->threads) {
264 if (mpid == ArmISA::getAffinity(&system, tc))
265 return tc;
266 }
267 return nullptr;
268}
269
270void
271FVPBasePwrCtrl::powerCoreOn(ThreadContext *const tc, PwrStatus *const pwrs)
272{
273 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::powerCoreOn: Powering ON "
274 "core %d\n", tc->contextId());
275 pwrs->l0 = 1;
277 // Clear pending power-offs to the core
278 pwrs->pp = 0;
279 // Clear pending power-offs to the core's cluster
280 for (const auto &tco : sys->threads) {
281 if (tc->socketId() == tco->socketId()) {
282 PwrStatus *npwrs = getCorePwrStatus(tco);
283 npwrs->pc = 0;
284 }
285 }
286 tc->getCpuPtr()->powerState->set(enums::PwrState::ON);
287}
288
289void
290FVPBasePwrCtrl::powerCoreOff(ThreadContext *const tc, PwrStatus *const pwrs)
291{
292 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::powerCoreOff: Powering OFF "
293 "core %d\n", tc->contextId());
294 pwrs->l0 = 0;
296 // Clear pending power-offs to the core
297 pwrs->pp = 0;
298 pwrs->pc = 0;
299 // Clear power-on reason
300 pwrs->wk = 0;
301 tc->getCpuPtr()->powerState->set(enums::PwrState::OFF);
302}
303
304void
306{
307 DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::startCoreUp: Starting core %d "
308 "from the power controller\n", tc->contextId());
309 clearStandByWfi(tc);
311
312 // InitCPU
313 ArmISA::Reset().invoke(tc);
314 tc->activate();
315}
316
317} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
void invoke(ThreadContext *tc, const StaticInstPtr &inst=nullStaticInstPtr) override
Definition faults.cc:741
void setPowerController(FVPBasePwrCtrl *pwr_ctrl)
Sets the pointer to the Power Controller.
Definition system.hh:171
Addr pioAddr
Address that the device listens to.
Definition io_device.hh:151
Tick pioDelay
Delay that the device experinces on an access.
Definition io_device.hh:157
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
void clearStandByWfi(ThreadContext *const tc)
Triggered when an interrupt is posted to the core.
bool setWakeRequest(ThreadContext *const tc)
Triggered by the GIC when GICR_WAKER.ProcessorSleep is 1 and there are pending interrupts for the cor...
std::vector< PwrStatus > corePwrStatus
Per-core power status.
EndBitUnion(PwrStatus) enum Offset struct gem5::FVPBasePwrCtrl::Registers regs
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
ThreadContext * getThreadContextByMPID(uint32_t mpid) const
Retrieves the thread context reference for a CPU core by MPID.
std::unordered_map< uint32_t, size_t > poweredCoresPerCluster
Number of powered cores per cluster.
void powerCoreOff(ThreadContext *const tc, PwrStatus *const pwrs)
Powers off a core.
PwrStatus * getCorePwrStatus(ThreadContext *const tc)
Retrieves the power status of a certain core and resizes the entries if needed.
void setStandByWfi(ThreadContext *const tc)
Triggered by the ISA when a WFI instruction is executed and (1) there are no pending interrupts and (...
ArmSystem & system
Reference to the arm system.
void startup() override
startup() is the final initialization call before simulation.
FVPBasePwrCtrl(const FVPBasePwrCtrlParams &params)
void powerCoreOn(ThreadContext *const tc, PwrStatus *const pwrs)
Powers on a core.
static constexpr uint32_t MPID_MSK
Mask for extracting the MPID from a 32-bit value.
void clearWakeRequest(ThreadContext *const tc)
Triggered by the GIC when GICR_WAKER.ProcessorSleep becomes 0.
void startCoreUp(ThreadContext *const tc)
Starts a core up.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
void setUintX(uint64_t w, ByteOrder endian)
Set the value in the word w after truncating it to the length of the packet and then byteswapping it ...
Definition packet.cc:361
void makeResponse()
Take a request packet and modify it in place to be suitable for returning as a response to that reque...
Definition packet.hh:1062
unsigned getSize() const
Definition packet.hh:817
uint64_t getUintX(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness and zero-extended to 64 bits.
Definition packet.cc:352
void set(enums::PwrState p)
Change the power state of this object to the power state p.
int size() const
Definition system.hh:210
const bool multiThread
Definition system.hh:312
Threads threads
Definition system.hh:310
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual void activate()=0
Set the status to Active.
virtual uint32_t socketId() const =0
virtual BaseCPU * getCpuPtr()=0
virtual ContextID contextId() const =0
This class implements the base power controller for FVP-based platforms.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition bitfield.hh:79
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
virtual void startup()
startup() is the final initialization call before simulation.
Definition sim_object.cc:96
#define warn(...)
Definition logging.hh:256
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition logging.hh:283
Affinity getAffinity(ArmSystem *arm_sys, ThreadContext *tc)
Retrieves MPIDR_EL1.
Definition utility.cc:221
Bitfield< 15 > system
Definition misc.hh:1032
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
uint64_t Tick
Tick count type.
Definition types.hh:58

Generated on Tue Jun 18 2024 16:24:02 for gem5 by doxygen 1.11.0