gem5 [DEVELOP-FOR-25.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{
58 warn_if(sys->multiThread,
59 "Base Power Controller does not support multi-threaded systems\n");
60 system.setPowerController(this);
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;
182 regs.ppoffr = data & MPID_MSK;
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);
195 regs.pponr = data & MPID_MSK;
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:209
const char data[]
void invoke(ThreadContext *tc, const StaticInstPtr &inst=nullStaticInstPtr) override
Definition faults.cc:742
Addr pioAddr
Address that the device listens to.
Definition io_device.hh:151
BasicPioDevice(const Params &p, Addr size)
Definition io_device.cc:75
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.
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.
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:246
const Params & params() const
virtual void startup()
startup() is the final initialization call before simulation.
Definition sim_object.cc:96
#define warn(...)
Definition logging.hh:288
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition logging.hh:315
Affinity getAffinity(ArmSystem *arm_sys, ThreadContext *tc)
Retrieves MPIDR_EL1.
Definition utility.cc:222
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 Arm Limited 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
Packet * PacketPtr

Generated on Mon May 26 2025 09:19:09 for gem5 by doxygen 1.13.2