gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 FVPBasePwrCtrl::FVPBasePwrCtrl(FVPBasePwrCtrlParams *const params)
51  : BasicPioDevice(params, 0x1000),
52  regs(),
53  system(*static_cast<ArmSystem *>(sys))
54 {
56  "Base Power Controller does not support multi-threaded systems\n");
58 }
59 
60 void
62 {
63  // All cores are ON by default (PwrStatus.{l0,l1} = 0b1)
64  corePwrStatus.resize(sys->numContexts(), 0x60000000);
65  for (const auto &tc : sys->threadContexts)
66  poweredCoresPerCluster[tc->socketId()] += 1;
68 }
69 
70 void
72 {
73  PwrStatus *pwrs = getCorePwrStatus(tc);
74 
75  if (!pwrs->pwfi)
76  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::setStandByWfi: STANDBYWFI "
77  "asserted for core %d\n", tc->contextId());
78  pwrs->pwfi = 1;
79  if (pwrs->l0 && (pwrs->pp || pwrs->pc))
80  powerCoreOff(tc, pwrs);
81 }
82 
83 void
85 {
86  PwrStatus *pwrs = getCorePwrStatus(tc);
87 
88  if (pwrs->pwfi)
89  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::clearStandByWfi: STANDBYWFI "
90  "deasserted for core %d\n", tc->contextId());
91  pwrs->pwfi = 0;
92 }
93 
94 bool
96 {
97  PwrStatus *pwrs = getCorePwrStatus(tc);
98 
99  if (!pwrs->pwk)
100  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::setWakeRequest: WakeRequest "
101  "asserted for core %d\n", tc->contextId());
102  pwrs->pwk = 1;
103  if (!pwrs->l0 && pwrs->wen) {
104  pwrs->wk = WK_GICWR;
105  powerCoreOn(tc, pwrs);
106  return true;
107  }
108  return false;
109 }
110 
111 void
113 {
114  PwrStatus *pwrs = getCorePwrStatus(tc);
115 
116  if (pwrs->pwk)
117  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::clearWakeRequest: "
118  "WakeRequest deasserted for core %d\n", tc->contextId());
119  pwrs->pwk = 0;
120 }
121 
122 Tick
124 {
125  const Addr addr = pkt->getAddr() - pioAddr;
126  const size_t size = pkt->getSize();
127  panic_if(size != 4, "FVPBasePwrCtrl::read: Invalid size %i\n", size);
128 
129  uint64_t resp = 0;
130  switch (addr) {
131  case PPOFFR:
132  resp = regs.ppoffr;
133  break;
134  case PPONR:
135  resp = regs.pponr;
136  break;
137  case PCOFFR:
138  resp = regs.pcoffr;
139  break;
140  case PWKUPR:
141  resp = regs.pwkupr;
142  break;
143  case PSYSR:
144  resp = regs.psysr;
145  break;
146  default:
147  warn("FVPBasePwrCtrl::read: Unexpected address (0x%x:%i), "
148  "assuming RAZ\n", addr, size);
149  }
150 
151  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::read: 0x%x<-0x%x(%i)\n", resp,
152  addr, size);
153 
154  pkt->setUintX(resp, LittleEndianByteOrder);
155  pkt->makeResponse();
156  return pioDelay;
157 }
158 
159 Tick
161 {
162  const Addr addr = pkt->getAddr() - pioAddr;
163  const size_t size = pkt->getSize();
164  panic_if(size != 4, "FVPBasePwrCtrl::write: Invalid size %i\n", size);
165 
166  uint64_t data = pkt->getUintX(LittleEndianByteOrder);
167 
168  // Software may use the power controller to check for core presence
169  // If core is not present, return an invalid MPID as notification
171  PwrStatus *pwrs = tc ? getCorePwrStatus(tc) : nullptr;
172  switch (addr) {
173  case PPOFFR:
174  if (!tc) {
175  regs.ppoffr = ~0;
176  } else if (pwrs->l0) {
177  // Set pending power off
178  pwrs->pp = 1;
179  regs.ppoffr = data & MPID_MSK;
180  } else {
181  regs.ppoffr = ~0 & MPID_MSK;
182  }
183  break;
184  case PPONR:
185  if (!tc) {
186  regs.pponr = ~0;
187  } else {
188  if (!pwrs->l0) {
189  pwrs->wk = WK_PPONR;
190  powerCoreOn(tc, pwrs);
191  startCoreUp(tc);
192  regs.pponr = data & MPID_MSK;
193  } else {
194  regs.pponr = ~0 & MPID_MSK;
195  }
196  }
197  break;
198  case PCOFFR:
199  if (!tc) {
200  regs.pcoffr = ~0;
201  } else if (pwrs->l0) {
202  // Power off all cores in the cluster
203  for (const auto &tco : sys->threadContexts) {
204  if (tc->socketId() == tco->socketId()) {
205  PwrStatus *npwrs = getCorePwrStatus(tco);
206  // Set pending cluster power off
207  npwrs->pc = 1;
208  if (npwrs->l0 && npwrs->pwfi)
209  powerCoreOff(tco, npwrs);
210  }
211  }
212  } else {
213  regs.pcoffr = ~0 & MPID_MSK;
214  }
215  break;
216  case PWKUPR:
217  if (!tc) {
218  regs.pwkupr = ~0;
219  } else {
220  // Update WEN value
221  pwrs->wen = bits(data, 31);
222  // Power-on if there is any pending Wakeup Requests
223  if (!pwrs->l0 && pwrs->wen && pwrs->pwk) {
224  pwrs->wk = WK_GICWR;
225  powerCoreOn(tc, pwrs);
226  startCoreUp(tc);
227  }
228  regs.pwkupr = data & (MPID_MSK | (1 << 31));
229  }
230  break;
231  case PSYSR:
232  if (!tc)
233  regs.psysr = ~0;
234  else
235  regs.psysr = (data & MPID_MSK) | (((uint32_t) *pwrs) & ~MPID_MSK);
236  break;
237  default:
238  warn("FVPBasePwrCtrl::write: Unexpected address (0x%x:%i), "
239  "assuming WI\n", addr, size);
240  }
241 
242  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::write: 0x%x->0x%x(%i)\n", data,
243  addr, size);
244 
245  pkt->makeResponse();
246  return pioDelay;
247 }
248 
249 FVPBasePwrCtrl::PwrStatus *
251 {
252  PwrStatus *pwrs = &corePwrStatus[tc->contextId()];
253  pwrs->l1 = poweredCoresPerCluster[tc->socketId()] > 0;
254  return pwrs;
255 }
256 
259 {
260  for (auto &tc : sys->threadContexts) {
261  if (mpid == ArmISA::getAffinity(&system, tc))
262  return tc;
263  }
264  return nullptr;
265 }
266 
267 void
268 FVPBasePwrCtrl::powerCoreOn(ThreadContext *const tc, PwrStatus *const pwrs)
269 {
270  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::powerCoreOn: Powering ON "
271  "core %d\n", tc->contextId());
272  pwrs->l0 = 1;
274  // Clear pending power-offs to the core
275  pwrs->pp = 0;
276  // Clear pending power-offs to the core's cluster
277  for (const auto &tco : sys->threadContexts) {
278  if (tc->socketId() == tco->socketId()) {
279  PwrStatus *npwrs = getCorePwrStatus(tco);
280  npwrs->pc = 0;
281  }
282  }
283  tc->getCpuPtr()->powerState->set(Enums::PwrState::ON);
284 }
285 
286 void
287 FVPBasePwrCtrl::powerCoreOff(ThreadContext *const tc, PwrStatus *const pwrs)
288 {
289  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::powerCoreOff: Powering OFF "
290  "core %d\n", tc->contextId());
291  pwrs->l0 = 0;
293  // Clear pending power-offs to the core
294  pwrs->pp = 0;
295  pwrs->pc = 0;
296  // Clear power-on reason
297  pwrs->wk = 0;
299 }
300 
301 void
303 {
304  DPRINTF(FVPBasePwrCtrl, "FVPBasePwrCtrl::startCoreUp: Starting core %d "
305  "from the power controller\n", tc->contextId());
306  clearStandByWfi(tc);
307  clearWakeRequest(tc);
308 
309  // InitCPU
310  Reset().invoke(tc);
311  tc->activate();
312 }
313 
315 FVPBasePwrCtrlParams::create()
316 {
317  return new FVPBasePwrCtrl(this);
318 }
#define DPRINTF(x,...)
Definition: trace.hh:222
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:351
RegVal getAffinity(ArmSystem *arm_sys, ThreadContext *tc)
Retrieves MPIDR_EL1.
Definition: utility.cc:280
ThreadContext * getThreadContextByMPID(uint32_t mpid) const
Retrieves the thread context reference for a CPU core by MPID.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
std::vector< PwrStatus > corePwrStatus
Per-core power status.
bool setWakeRequest(ThreadContext *const tc)
Triggered by the GIC when GICR_WAKER.ProcessorSleep is 1 and there are pending interrupts for the cor...
void setPowerController(FVPBasePwrCtrl *pwr_ctrl)
Sets the pointer to the Power Controller.
Definition: system.hh:177
ip6_addr_t addr
Definition: inet.hh:330
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: io_device.cc:56
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
virtual BaseCPU * getCpuPtr()=0
const bool multiThread
Definition: system.hh:191
static constexpr uint32_t MPID_MSK
Mask for extracting the MPID from a 32-bit value.
ThreadContext is the external interface to all thread state for anything outside of the CPU...
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:334
void powerCoreOn(ThreadContext *const tc, PwrStatus *const pwrs)
Powers on a core.
FVPBasePwrCtrl(FVPBasePwrCtrlParams *const params)
unsigned getSize() const
Definition: packet.hh:730
void powerCoreOff(ThreadContext *const tc, PwrStatus *const pwrs)
Powers off a core.
uint64_t Tick
Tick count type.
Definition: types.hh:61
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition: logging.hh:224
std::vector< ThreadContext * > threadContexts
Definition: system.hh:182
Addr getAddr() const
Definition: packet.hh:720
unsigned numContexts() const
Definition: system.hh:198
void startCoreUp(ThreadContext *const tc)
Starts a core up.
void setStandByWfi(ThreadContext *const tc)
Triggered by the ISA when a WFI instruction is executed and (1) there are no pending interrupts and (...
void set(Enums::PwrState p)
Change the power state of this object to the power state p.
Definition: power_state.cc:89
virtual void activate()=0
Set the status to Active.
void clearWakeRequest(ThreadContext *const tc)
Triggered by the GIC when GICR_WAKER.ProcessorSleep becomes 0.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
System * sys
Definition: io_device.hh:102
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
EndBitUnion(PwrStatus) enum Offset struct FVPBasePwrCtrl::Registers regs
Bitfield< 15 > system
Definition: misc.hh:997
void clearStandByWfi(ThreadContext *const tc)
Triggered when an interrupt is posted to the core.
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:931
This class implements the base power controller for FVP-based platforms.
PwrStatus * getCorePwrStatus(ThreadContext *const tc)
Retrieves the power status of a certain core and resizes the entries if needed.
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:160
virtual uint32_t socketId() const =0
virtual ContextID contextId() const =0
PowerState * powerState
ArmSystem & system
Reference to the arm system.
#define warn(...)
Definition: logging.hh:208
std::unordered_map< uint32_t, size_t > poweredCoresPerCluster
Number of powered cores per cluster.
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:71
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:181
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
const char data[]
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.

Generated on Mon Jun 8 2020 15:45:09 for gem5 by doxygen 1.8.13