2 * Copyright (c) 2012, 2014, 2018 ARM Limited
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.
14 * Copyright (c) 2002-2005 The Regents of The University of Michigan
15 * Copyright (c) 2011 Regents of the University of California
16 * All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 #include <unordered_map>
50 #include "arch/isa_traits.hh"
51 #include "base/loader/memory_image.hh"
52 #include "base/loader/symtab.hh"
53 #include "base/statistics.hh"
54 #include "config/the_isa.hh"
55 #include "cpu/pc_event.hh"
56 #include "enums/MemoryMode.hh"
57 #include "mem/mem_requestor.hh"
58 #include "mem/physical.hh"
59 #include "mem/port.hh"
60 #include "mem/port_proxy.hh"
61 #include "params/System.hh"
62 #include "sim/futex_map.hh"
63 #include "sim/redirect_path.hh"
64 #include "sim/se_signal.hh"
65 #include "sim/sim_object.hh"
66 #include "sim/workload.hh"
72 class System : public SimObject, public PCEventScope
77 * Private class for the system port which is only used as a
78 * requestor for debug access and for non-structural entities that do
79 * not have a port of their own.
81 class SystemPort : public RequestPort
86 * Create a system port with a name and an owner.
88 SystemPort(const std::string &_name, SimObject *_owner)
89 : RequestPort(_name, _owner)
91 bool recvTimingResp(PacketPtr pkt) override
92 { panic("SystemPort does not receive timing!\n"); return false; }
93 void recvReqRetry() override
94 { panic("SystemPort does not expect retry!\n"); }
97 std::list<PCEvent *> liveEvents;
98 SystemPort _systemPort;
100 // Map of memory address ranges for devices with their own backing stores
101 std::unordered_map<RequestorID, AbstractMemory *> deviceMemMap;
110 ThreadContext *context = nullptr;
112 BaseRemoteGDB *gdb = nullptr;
113 Event *resumeEvent = nullptr;
116 std::string name() const;
117 void quiesce() const;
120 std::vector<Thread> threads;
130 thread(ContextID id) const
136 ContextID insert(ThreadContext *tc, ContextID id=InvalidContextID);
137 void replace(ThreadContext *tc, ContextID id);
145 const Threads &threads;
148 friend class Threads;
150 const_iterator(const Threads &_threads, int _pos) :
151 threads(_threads), pos(_pos)
155 const_iterator(const const_iterator &) = default;
156 const_iterator &operator = (const const_iterator &) = default;
158 using iterator_category = std::forward_iterator_tag;
159 using value_type = ThreadContext *;
160 using difference_type = int;
161 using pointer = const value_type *;
162 using reference = const value_type &;
174 return const_iterator(threads, pos++);
177 reference operator * () { return threads.thread(pos).context; }
178 pointer operator -> () { return &threads.thread(pos).context; }
181 operator == (const const_iterator &other) const
183 return &threads == &other.threads && pos == other.pos;
187 operator != (const const_iterator &other) const
189 return !(*this == other);
193 ThreadContext *findFree();
196 operator [](ContextID id) const
198 return thread(id).context;
201 void markActive(ContextID id) { thread(id).active = true; }
203 int size() const { return threads.size(); }
204 bool empty() const { return threads.empty(); }
205 int numRunning() const;
210 for (auto &thread: threads) {
217 void quiesce(ContextID id);
218 void quiesceTick(ContextID id, Tick when);
220 const_iterator begin() const { return const_iterator(*this, 0); }
221 const_iterator end() const { return const_iterator(*this, size()); }
225 * After all objects have been created and all ports are
226 * connected, check that the system port is connected.
228 void init() override;
229 void startup() override;
232 * Get a reference to the system port that can be used by
233 * non-structural simulation objects like processes or threads, or
234 * external entities like loaders and debuggers, etc, to access
237 * @return a reference to the system port we own
239 RequestPort& getSystemPort() { return _systemPort; }
242 * Additional function to return the Port of a memory object.
244 Port &getPort(const std::string &if_name,
245 PortID idx=InvalidPortID) override;
249 * Is the system in atomic mode?
251 * There are currently two different atomic memory modes:
252 * 'atomic', which supports caches; and 'atomic_noncaching', which
253 * bypasses caches. The latter is used by hardware virtualized
254 * CPUs. SimObjects are expected to use Port::sendAtomic() and
255 * Port::recvAtomic() when accessing memory in this mode.
257 bool isAtomicMode() const {
258 return memoryMode == Enums::atomic ||
259 memoryMode == Enums::atomic_noncaching;
263 * Is the system in timing mode?
265 * SimObjects are expected to use Port::sendTiming() and
266 * Port::recvTiming() when accessing memory in this mode.
268 bool isTimingMode() const {
269 return memoryMode == Enums::timing;
273 * Should caches be bypassed?
275 * Some CPUs need to bypass caches to allow direct memory
276 * accesses, which is required for hardware virtualization.
278 bool bypassCaches() const {
279 return memoryMode == Enums::atomic_noncaching;
285 * Get the memory mode of the system.
287 * \warn This should only be used by the Python world. The C++
288 * world should use one of the query functions above
289 * (isAtomicMode(), isTimingMode(), bypassCaches()).
291 Enums::MemoryMode getMemoryMode() const { return memoryMode; }
294 * Change the memory mode of the system.
296 * \warn This should only be called by the Python!
298 * @param mode Mode to change to (atomic/timing/...)
300 void setMemoryMode(Enums::MemoryMode mode);
304 * Get the cache line size of the system.
306 unsigned int cacheLineSize() const { return _cacheLineSize; }
310 const bool multiThread;
312 using SimObject::schedule;
314 bool schedule(PCEvent *event) override;
315 bool remove(PCEvent *event) override;
321 /** Port to physical memory used for writing object files into ram at
326 Workload *workload = nullptr;
330 * Get a pointer to the Kernel Virtual Machine (KVM) SimObject,
337 /** Verify gem5 configuration will support KVM emulation */
338 bool validKvmEnvironment() const;
340 /** Get a pointer to access the physical memory of the system */
341 PhysicalMemory& getPhysMem() { return physmem; }
343 /** Amount of physical memory that is still free */
344 Addr freeMemSize() const;
346 /** Amount of physical memory that exists */
347 Addr memSize() const;
350 * Check if a physical address is within a range of a memory that
351 * is part of the global address map.
353 * @param addr A physical address
354 * @return Whether the address corresponds to a memory
356 bool isMemAddr(Addr addr) const;
359 * Add a physical memory range for a device. The ranges added here will
360 * be considered a non-PIO memory address if the requestorId of the packet
361 * and range match something in the device memory map.
363 void addDeviceMemory(RequestorID requestorId,
364 AbstractMemory *deviceMemory);
367 * Similar to isMemAddr but for devices. Checks if a physical address
368 * of the packet match an address range of a device corresponding to the
369 * RequestorId of the request.
371 bool isDeviceMemAddr(PacketPtr pkt) const;
374 * Return a pointer to the device memory.
376 AbstractMemory *getDeviceMemory(RequestorID _id) const;
379 * Get the architecture.
381 Arch getArch() const { return Arch::TheISA; }
384 * Get the guest byte order.
387 getGuestByteOrder() const
389 return _params->byte_order;
393 * Get the page bytes for the ISA.
395 Addr getPageBytes() const { return TheISA::PageBytes; }
398 * Get the number of bits worth of in-page address for the ISA.
400 Addr getPageShift() const { return TheISA::PageShift; }
403 * The thermal model used for this system (if any).
405 ThermalModel * getThermalModel() const { return thermalModel; }
411 PhysicalMemory physmem;
413 Enums::MemoryMode memoryMode;
415 const unsigned int _cacheLineSize;
417 uint64_t workItemsBegin;
418 uint64_t workItemsEnd;
421 /** This array is a per-system list of all devices capable of issuing a
422 * memory system request and an associated string for each requestor id.
423 * It's used to uniquely id any requestor in the system by name for things
424 * like cache statistics.
426 std::vector<RequestorInfo> requestors;
428 ThermalModel * thermalModel;
432 * Strips off the system name from a requestor name
434 std::string stripSystemName(const std::string& requestor_name) const;
439 * Request an id used to create a request object in the system. All objects
440 * that intend to issues requests into the memory system must request an id
441 * in the init() phase of startup. All requestor ids must be fixed by the
442 * regStats() phase that immediately precedes it. This allows objects in
443 * the memory system to understand how many requestors may exist and
444 * appropriately name the bins of their per-requestor stats before the
445 * stats are finalized.
447 * Registers a RequestorID:
448 * This method takes two parameters, one of which is optional.
449 * The first one is the requestor object, and it is compulsory; in case
450 * a object has multiple (sub)requestors, a second parameter must be
451 * provided and it contains the name of the subrequestor. The method will
452 * create a requestor's name by concatenating the SimObject name with the
453 * eventual subrequestor string, separated by a dot.
456 * For a cpu having two requestors: a data requestor and an
457 * instruction requestor,
458 * the method must be called twice:
460 * instRequestorId = getRequestorId(cpu, "inst");
461 * dataRequestorId = getRequestorId(cpu, "data");
463 * and the requestors' names will be:
467 * @param requestor SimObject related to the requestor
468 * @param subrequestor String containing the subrequestor's name
469 * @return the requestor's ID.
471 RequestorID getRequestorId(const SimObject* requestor,
472 std::string subrequestor = std::string());
475 * Registers a GLOBAL RequestorID, which is a RequestorID not related
476 * to any particular SimObject; since no SimObject is passed,
477 * the requestor gets registered by providing the full requestor name.
479 * @param requestorName full name of the requestor
480 * @return the requestor's ID.
482 RequestorID getGlobalRequestorId(const std::string& requestor_name);
485 * Get the name of an object for a given request id.
487 std::string getRequestorName(RequestorID requestor_id);
490 * Looks up the RequestorID for a given SimObject
491 * returns an invalid RequestorID (invldRequestorId) if not found.
493 RequestorID lookupRequestorId(const SimObject* obj) const;
496 * Looks up the RequestorID for a given object name string
497 * returns an invalid RequestorID (invldRequestorId) if not found.
499 RequestorID lookupRequestorId(const std::string& name) const;
501 /** Get the number of requestors registered in the system */
502 RequestorID maxRequestors() { return requestors.size(); }
505 /** helper function for getRequestorId */
506 RequestorID _getRequestorId(const SimObject* requestor,
507 const std::string& requestor_name);
510 * Helper function for constructing the full (sub)requestor name
511 * by providing the root requestor and the relative subrequestor name.
513 std::string leafRequestorName(const SimObject* requestor,
514 const std::string& subrequestor);
518 void regStats() override;
520 * Called by pseudo_inst to track the number of work items started by this
526 return ++workItemsBegin;
530 * Called by pseudo_inst to track the number of work items completed by
536 return ++workItemsEnd;
540 * Called by pseudo_inst to mark the cpus actively executing work items.
541 * Returns the total number of cpus that have executed work item begin or
545 markWorkItem(int index)
547 threads.markActive(index);
548 return threads.numActive();
551 inline void workItemBegin(uint32_t tid, uint32_t workid)
553 std::pair<uint32_t,uint32_t> p(tid, workid);
554 lastWorkItemStarted[p] = curTick();
557 void workItemEnd(uint32_t tid, uint32_t workid);
563 typedef SystemParams Params;
569 * Range for memory-mapped m5 pseudo ops. The range will be
570 * invalid/empty if disabled.
572 const AddrRange _m5opRange;
578 const Params *params() const { return (const Params *)_params; }
581 * Range used by memory-mapped m5 pseudo-ops if enabled. Returns
582 * an invalid/empty range if disabled.
584 const AddrRange &m5opRange() const { return _m5opRange; }
588 /// Allocate npages contiguous unused physical pages
589 /// @return Starting address of first page
590 Addr allocPhysPages(int npages);
592 ContextID registerThreadContext(
593 ThreadContext *tc, ContextID assigned=InvalidContextID);
594 void replaceThreadContext(ThreadContext *tc, ContextID context_id);
596 void serialize(CheckpointOut &cp) const override;
597 void unserialize(CheckpointIn &cp) override;
599 void drainResume() override;
602 Counter totalNumInsts;
603 std::map<std::pair<uint32_t,uint32_t>, Tick> lastWorkItemStarted;
604 std::map<uint32_t, Stats::Histogram*> workItemStats;
606 ////////////////////////////////////////////
608 // STATIC GLOBAL SYSTEM LIST
610 ////////////////////////////////////////////
612 static std::vector<System *> systemList;
613 static int numSystemsRunning;
615 static void printSystems();
619 static const int maxPID = 32768;
621 /** Process set to track which PIDs have already been allocated */
624 // By convention, all signals are owned by the receiving process. The
625 // receiver will delete the signal upon reception.
626 std::list<BasicSignal> signalList;
628 // Used by syscall-emulation mode. This member contains paths which need
629 // to be redirected to the faux-filesystem (a duplicate filesystem
630 // intended to replace certain files on the host filesystem).
631 std::vector<RedirectPath*> redirectPaths;
636 #endif // __SYSTEM_HH__