gem5  v22.1.0.0
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 
50 namespace gem5
51 {
52 
53 FVPBasePwrCtrl::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 
63 void
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 
73 void
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 
86 void
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 
97 bool
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 
114 void
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 
125 Tick
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 
162 Tick
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 
252 FVPBasePwrCtrl::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 
270 void
271 FVPBasePwrCtrl::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 
289 void
290 FVPBasePwrCtrl::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;
302 }
303 
304 void
306 {
307  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::startCoreUp: Starting core %d "
308  "from the power controller\n", tc->contextId());
309  clearStandByWfi(tc);
310  clearWakeRequest(tc);
311 
312  // InitCPU
313  ArmISA::Reset().invoke(tc);
314  tc->activate();
315 }
316 
317 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
void setPowerController(FVPBasePwrCtrl *pwr_ctrl)
Sets the pointer to the Power Controller.
Definition: system.hh:168
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
PowerState * powerState
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:294
Addr getAddr() const
Definition: packet.hh:805
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:1059
unsigned getSize() const
Definition: packet.hh:815
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
System * sys
Definition: io_device.hh:105
void set(enums::PwrState p)
Change the power state of this object to the power state p.
Definition: power_state.cc:96
int size() const
Definition: system.hh:213
const bool multiThread
Definition: system.hh:315
Threads threads
Definition: system.hh:313
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:76
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
virtual void startup()
startup() is the final initialization call before simulation.
Definition: sim_object.cc:99
#define warn(...)
Definition: logging.hh:246
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition: logging.hh:273
Affinity getAffinity(ArmSystem *arm_sys, ThreadContext *tc)
Retrieves MPIDR_EL1.
Definition: utility.cc:214
Bitfield< 15 > system
Definition: misc.hh:1004
Bitfield< 3 > addr
Definition: types.hh:84
@ Reset
Definition: types.hh:70
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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 Wed Dec 21 2022 10:22:32 for gem5 by doxygen 1.9.1