gem5  v20.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 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->threads.size(), 0x60000000);
65  for (const auto &tc : sys->threads)
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, ByteOrder::little);
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(ByteOrder::little);
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->threads) {
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->threads) {
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->threads) {
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;
298  tc->getCpuPtr()->powerState->set(Enums::PwrState::OFF);
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  ArmISA::Reset().invoke(tc);
311  tc->activate();
312 }
313 
315 FVPBasePwrCtrlParams::create()
316 {
317  return new FVPBasePwrCtrl(this);
318 }
FVPBasePwrCtrl::powerCoreOn
void powerCoreOn(ThreadContext *const tc, PwrStatus *const pwrs)
Powers on a core.
Definition: fvp_base_pwr_ctrl.cc:268
FVPBasePwrCtrl::system
ArmSystem & system
Reference to the arm system.
Definition: fvp_base_pwr_ctrl.hh:180
BasicPioDevice::pioAddr
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
ArmISA::getAffinity
RegVal getAffinity(ArmSystem *arm_sys, ThreadContext *tc)
Retrieves MPIDR_EL1.
Definition: utility.cc:312
warn
#define warn(...)
Definition: logging.hh:239
system.hh
ThreadContext::activate
virtual void activate()=0
Set the status to Active.
data
const char data[]
Definition: circlebuf.test.cc:42
FVPBasePwrCtrl::write
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: fvp_base_pwr_ctrl.cc:160
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
PioDevice::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: io_device.cc:56
FVPBasePwrCtrl::clearWakeRequest
void clearWakeRequest(ThreadContext *const tc)
Triggered by the GIC when GICR_WAKER.ProcessorSleep becomes 0.
Definition: fvp_base_pwr_ctrl.cc:112
FVPBasePwrCtrl::Registers::ppoffr
uint32_t ppoffr
Definition: fvp_base_pwr_ctrl.hh:118
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
FVPBasePwrCtrl::read
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: fvp_base_pwr_ctrl.cc:123
ArmSystem::setPowerController
void setPowerController(FVPBasePwrCtrl *pwr_ctrl)
Sets the pointer to the Power Controller.
Definition: system.hh:188
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
FVPBasePwrCtrl::clearStandByWfi
void clearStandByWfi(ThreadContext *const tc)
Triggered when an interrupt is posted to the core.
Definition: fvp_base_pwr_ctrl.cc:84
system.hh
RiscvISA::OFF
@ OFF
Definition: isa.hh:65
FVPBasePwrCtrl::Registers::pwkupr
uint32_t pwkupr
Definition: fvp_base_pwr_ctrl.hh:121
FVPBasePwrCtrl::setStandByWfi
void setStandByWfi(ThreadContext *const tc)
Triggered by the ISA when a WFI instruction is executed and (1) there are no pending interrupts and (...
Definition: fvp_base_pwr_ctrl.cc:71
PioDevice::sys
System * sys
Definition: io_device.hh:102
X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:997
FVPBasePwrCtrl::MPID_MSK
static constexpr uint32_t MPID_MSK
Mask for extracting the MPID from a 32-bit value.
Definition: fvp_base_pwr_ctrl.hh:126
FVPBasePwrCtrl
Definition: fvp_base_pwr_ctrl.hh:55
FVPBasePwrCtrl::powerCoreOff
void powerCoreOff(ThreadContext *const tc, PwrStatus *const pwrs)
Powers off a core.
Definition: fvp_base_pwr_ctrl.cc:287
ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:88
Packet::getUintX
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:350
System::multiThread
const bool multiThread
Definition: system.hh:311
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
FVPBasePwrCtrl::Registers::pponr
uint32_t pponr
Definition: fvp_base_pwr_ctrl.hh:119
FVPBasePwrCtrl::Registers::pcoffr
uint32_t pcoffr
Definition: fvp_base_pwr_ctrl.hh:120
Packet::setUintX
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:367
System::Threads::size
int size() const
Definition: system.hh:204
ThreadContext::contextId
virtual ContextID contextId() const =0
FVPBasePwrCtrl::WK_PPONR
@ WK_PPONR
Definition: fvp_base_pwr_ctrl.hh:128
faults.hh
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
Packet::makeResponse
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:1004
fvp_base_pwr_ctrl.hh
packet_access.hh
utility.hh
FVPBasePwrCtrl::setWakeRequest
bool setWakeRequest(ThreadContext *const tc)
Triggered by the GIC when GICR_WAKER.ProcessorSleep is 1 and there are pending interrupts for the cor...
Definition: fvp_base_pwr_ctrl.cc:95
FVPBasePwrCtrl::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: fvp_base_pwr_ctrl.cc:61
ArmSystem
Definition: system.hh:59
warn_if
#define warn_if(cond,...)
Conditional warning macro that checks the supplied condition and only prints a warning if the conditi...
Definition: logging.hh:263
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:197
System::threads
Threads threads
Definition: system.hh:309
FVPBasePwrCtrl::poweredCoresPerCluster
std::unordered_map< uint32_t, size_t > poweredCoresPerCluster
Number of powered cores per cluster.
Definition: fvp_base_pwr_ctrl.hh:137
base.hh
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
BasicPioDevice
Definition: io_device.hh:150
addr
ip6_addr_t addr
Definition: inet.hh:423
FVPBasePwrCtrl::getCorePwrStatus
PwrStatus * getCorePwrStatus(ThreadContext *const tc)
Retrieves the power status of a certain core and resizes the entries if needed.
Definition: fvp_base_pwr_ctrl.cc:250
BasicPioDevice::pioDelay
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:160
FVPBasePwrCtrl::getThreadContextByMPID
ThreadContext * getThreadContextByMPID(uint32_t mpid) const
Retrieves the thread context reference for a CPU core by MPID.
Definition: fvp_base_pwr_ctrl.cc:258
FVPBasePwrCtrl::FVPBasePwrCtrl
FVPBasePwrCtrl(FVPBasePwrCtrlParams *const params)
Definition: fvp_base_pwr_ctrl.cc:50
ThreadContext::socketId
virtual uint32_t socketId() const =0
FVPBasePwrCtrl::corePwrStatus
std::vector< PwrStatus > corePwrStatus
Per-core power status.
Definition: fvp_base_pwr_ctrl.hh:134
ThreadContext::getCpuPtr
virtual BaseCPU * getCpuPtr()=0
FVPBasePwrCtrl::Registers::psysr
uint32_t psysr
Definition: fvp_base_pwr_ctrl.hh:122
FVPBasePwrCtrl::WK_GICWR
@ WK_GICWR
Definition: fvp_base_pwr_ctrl.hh:128
Ps2::Reset
@ Reset
Definition: types.hh:63
thread_context.hh
FVPBasePwrCtrl::regs
EndBitUnion(PwrStatus) enum Offset struct FVPBasePwrCtrl::Registers regs
FVPBasePwrCtrl::startCoreUp
void startCoreUp(ThreadContext *const tc)
Starts a core up.
Definition: fvp_base_pwr_ctrl.cc:302
bits
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:75

Generated on Wed Sep 30 2020 14:02:10 for gem5 by doxygen 1.8.17