| /* | |
| * Copyright (c) 2007 The Hewlett-Packard Development Company | |
| * All rights reserved. | |
| * | |
| * The license below extends only to copyright in the software and shall | |
| * not be construed as granting a license to any other intellectual | |
| * property including but not limited to intellectual property relating | |
| * to a hardware implementation of the functionality of the software | |
| * licensed hereunder. You may use the software subject to the license | |
| * terms below provided that you ensure that this notice is replicated | |
| * unmodified and in its entirety in all distributions of the software, | |
| * modified or unmodified, in source code or in binary form. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * Authors: Gabe Black | |
| */ | |
| #ifndef __ARCH_X86_PAGE_TABLE_WALKER_HH__ | |
| #define __ARCH_X86_PAGE_TABLE_WALKER_HH__ | |
| #include <vector> | |
| #include "arch/x86/pagetable.hh" | |
| #include "arch/x86/tlb.hh" | |
| #include "base/types.hh" | |
| #include "mem/packet.hh" | |
| #include "params/X86PagetableWalker.hh" | |
| #include "sim/clocked_object.hh" | |
| #include "sim/faults.hh" | |
| #include "sim/system.hh" | |
| class ThreadContext; | |
| namespace X86ISA | |
| { | |
| class Walker : public ClockedObject | |
| { | |
| protected: | |
| // Port for accessing memory | |
| class WalkerPort : public MasterPort | |
| { | |
| public: | |
| WalkerPort(const std::string &_name, Walker * _walker) : | |
| MasterPort(_name, _walker), walker(_walker) | |
| {} | |
| protected: | |
| Walker *walker; | |
| bool recvTimingResp(PacketPtr pkt); | |
| void recvReqRetry(); | |
| }; | |
| friend class WalkerPort; | |
| WalkerPort port; | |
| // State to track each walk of the page table | |
| class WalkerState | |
| { | |
| friend class Walker; | |
| private: | |
| enum State { | |
| Ready, | |
| Waiting, | |
| // Long mode | |
| LongPML4, LongPDP, LongPD, LongPTE, | |
| // PAE legacy mode | |
| PAEPDP, PAEPD, PAEPTE, | |
| // Non PAE legacy mode with and without PSE | |
| PSEPD, PD, PTE | |
| }; | |
| protected: | |
| Walker *walker; | |
| ThreadContext *tc; | |
| RequestPtr req; | |
| State state; | |
| State nextState; | |
| int dataSize; | |
| bool enableNX; | |
| unsigned inflight; | |
| TlbEntry entry; | |
| PacketPtr read; | |
| std::vector<PacketPtr> writes; | |
| Fault timingFault; | |
| TLB::Translation * translation; | |
| BaseTLB::Mode mode; | |
| bool functional; | |
| bool timing; | |
| bool retrying; | |
| bool started; | |
| bool squashed; | |
| public: | |
| WalkerState(Walker * _walker, BaseTLB::Translation *_translation, | |
| const RequestPtr &_req, bool _isFunctional = false) : | |
| walker(_walker), req(_req), state(Ready), | |
| nextState(Ready), inflight(0), | |
| translation(_translation), | |
| functional(_isFunctional), timing(false), | |
| retrying(false), started(false), squashed(false) | |
| { | |
| } | |
| void initState(ThreadContext * _tc, BaseTLB::Mode _mode, | |
| bool _isTiming = false); | |
| Fault startWalk(); | |
| Fault startFunctional(Addr &addr, unsigned &logBytes); | |
| bool recvPacket(PacketPtr pkt); | |
| unsigned numInflight() const; | |
| bool isRetrying(); | |
| bool wasStarted(); | |
| bool isTiming(); | |
| void retry(); | |
| void squash(); | |
| std::string name() const {return walker->name();} | |
| private: | |
| void setupWalk(Addr vaddr); | |
| Fault stepWalk(PacketPtr &write); | |
| void sendPackets(); | |
| void endWalk(); | |
| Fault pageFault(bool present); | |
| }; | |
| friend class WalkerState; | |
| // State for timing and atomic accesses (need multiple per walker in | |
| // the case of multiple outstanding requests in timing mode) | |
| std::list<WalkerState *> currStates; | |
| // State for functional accesses (only need one of these per walker) | |
| WalkerState funcState; | |
| struct WalkerSenderState : public Packet::SenderState | |
| { | |
| WalkerState * senderWalk; | |
| WalkerSenderState(WalkerState * _senderWalk) : | |
| senderWalk(_senderWalk) {} | |
| }; | |
| public: | |
| // Kick off the state machine. | |
| Fault start(ThreadContext * _tc, BaseTLB::Translation *translation, | |
| const RequestPtr &req, BaseTLB::Mode mode); | |
| Fault startFunctional(ThreadContext * _tc, Addr &addr, | |
| unsigned &logBytes, BaseTLB::Mode mode); | |
| Port &getPort(const std::string &if_name, | |
| PortID idx=InvalidPortID) override; | |
| protected: | |
| // The TLB we're supposed to load. | |
| TLB * tlb; | |
| System * sys; | |
| MasterID masterId; | |
| // The number of outstanding walks that can be squashed per cycle. | |
| unsigned numSquashable; | |
| // Wrapper for checking for squashes before starting a translation. | |
| void startWalkWrapper(); | |
| /** | |
| * Event used to call startWalkWrapper. | |
| **/ | |
| EventFunctionWrapper startWalkWrapperEvent; | |
| // Functions for dealing with packets. | |
| bool recvTimingResp(PacketPtr pkt); | |
| void recvReqRetry(); | |
| bool sendTiming(WalkerState * sendingState, PacketPtr pkt); | |
| public: | |
| void setTLB(TLB * _tlb) | |
| { | |
| tlb = _tlb; | |
| } | |
| typedef X86PagetableWalkerParams Params; | |
| const Params * | |
| params() const | |
| { | |
| return static_cast<const Params *>(_params); | |
| } | |
| Walker(const Params *params) : | |
| ClockedObject(params), port(name() + ".port", this), | |
| funcState(this, NULL, NULL, true), tlb(NULL), sys(params->system), | |
| masterId(sys->getMasterId(this)), | |
| numSquashable(params->num_squash_per_cycle), | |
| startWalkWrapperEvent([this]{ startWalkWrapper(); }, name()) | |
| { | |
| } | |
| }; | |
| } | |
| #endif // __ARCH_X86_PAGE_TABLE_WALKER_HH__ |