page_table.cc revision 10558:426665ec11a9
15420Sgblack@eecs.umich.edu/*
25081Sgblack@eecs.umich.edu * Copyright (c) 2014 Advanced Micro Devices, Inc.
35081Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan
47087Snate@binkert.org * All rights reserved.
57087Snate@binkert.org *
67087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
77087Snate@binkert.org * modification, are permitted provided that the following conditions are
87087Snate@binkert.org * met: redistributions of source code must retain the above copyright
97087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
107087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
117087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
125081Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
137087Snate@binkert.org * neither the name of the copyright holders nor the names of its
147087Snate@binkert.org * contributors may be used to endorse or promote products derived from
157087Snate@binkert.org * this software without specific prior written permission.
167087Snate@binkert.org *
177087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
187087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
197087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
207087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
215081Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
227087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
235081Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245081Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255081Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265081Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
275081Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285081Sgblack@eecs.umich.edu *
295081Sgblack@eecs.umich.edu * Authors: Steve Reinhardt
305081Sgblack@eecs.umich.edu *          Ron Dreslinski
315081Sgblack@eecs.umich.edu *          Ali Saidi
325081Sgblack@eecs.umich.edu */
335081Sgblack@eecs.umich.edu
345081Sgblack@eecs.umich.edu/**
355081Sgblack@eecs.umich.edu * @file
365081Sgblack@eecs.umich.edu * Definitions of functional page table.
375081Sgblack@eecs.umich.edu */
385081Sgblack@eecs.umich.edu#include <fstream>
395081Sgblack@eecs.umich.edu#include <map>
405081Sgblack@eecs.umich.edu#include <string>
415081Sgblack@eecs.umich.edu
425081Sgblack@eecs.umich.edu#include "base/bitfield.hh"
435081Sgblack@eecs.umich.edu#include "base/intmath.hh"
445081Sgblack@eecs.umich.edu#include "base/trace.hh"
455081Sgblack@eecs.umich.edu#include "config/the_isa.hh"
465081Sgblack@eecs.umich.edu#include "debug/MMU.hh"
476474Sgblack@eecs.umich.edu#include "mem/page_table.hh"
485081Sgblack@eecs.umich.edu#include "sim/faults.hh"
495081Sgblack@eecs.umich.edu#include "sim/sim_object.hh"
505081Sgblack@eecs.umich.edu
515081Sgblack@eecs.umich.eduusing namespace std;
525081Sgblack@eecs.umich.eduusing namespace TheISA;
535081Sgblack@eecs.umich.edu
545081Sgblack@eecs.umich.eduFuncPageTable::FuncPageTable(const std::string &__name,
555081Sgblack@eecs.umich.edu                             uint64_t _pid, Addr _pageSize)
565081Sgblack@eecs.umich.edu        : PageTableBase(__name, _pid, _pageSize)
575081Sgblack@eecs.umich.edu{
585420Sgblack@eecs.umich.edu}
595661Sgblack@eecs.umich.edu
605420Sgblack@eecs.umich.eduFuncPageTable::~FuncPageTable()
615081Sgblack@eecs.umich.edu{
625081Sgblack@eecs.umich.edu}
635081Sgblack@eecs.umich.edu
645081Sgblack@eecs.umich.eduvoid
655081Sgblack@eecs.umich.eduFuncPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags)
665081Sgblack@eecs.umich.edu{
675420Sgblack@eecs.umich.edu    bool clobber = flags & Clobber;
685081Sgblack@eecs.umich.edu    // starting address must be page aligned
696474Sgblack@eecs.umich.edu    assert(pageOffset(vaddr) == 0);
705081Sgblack@eecs.umich.edu
715081Sgblack@eecs.umich.edu    DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size);
725081Sgblack@eecs.umich.edu
735661Sgblack@eecs.umich.edu    for (; size > 0; size -= pageSize, vaddr += pageSize, paddr += pageSize) {
745420Sgblack@eecs.umich.edu        if (!clobber && (pTable.find(vaddr) != pTable.end())) {
755081Sgblack@eecs.umich.edu            // already mapped
765081Sgblack@eecs.umich.edu            fatal("FuncPageTable::allocate: addr 0x%x already mapped", vaddr);
775081Sgblack@eecs.umich.edu        }
785081Sgblack@eecs.umich.edu
795420Sgblack@eecs.umich.edu        pTable[vaddr] = TheISA::TlbEntry(pid, vaddr, paddr,
805661Sgblack@eecs.umich.edu                                         flags & Uncacheable,
815420Sgblack@eecs.umich.edu                                         flags & ReadOnly);
825081Sgblack@eecs.umich.edu        eraseCacheEntry(vaddr);
835081Sgblack@eecs.umich.edu        updateCache(vaddr, pTable[vaddr]);
845081Sgblack@eecs.umich.edu    }
855081Sgblack@eecs.umich.edu}
865081Sgblack@eecs.umich.edu
875081Sgblack@eecs.umich.eduvoid
885420Sgblack@eecs.umich.eduFuncPageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
895081Sgblack@eecs.umich.edu{
906474Sgblack@eecs.umich.edu    assert(pageOffset(vaddr) == 0);
915081Sgblack@eecs.umich.edu    assert(pageOffset(new_vaddr) == 0);
925081Sgblack@eecs.umich.edu
935081Sgblack@eecs.umich.edu    DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr,
945661Sgblack@eecs.umich.edu            new_vaddr, size);
955420Sgblack@eecs.umich.edu
965081Sgblack@eecs.umich.edu    for (; size > 0;
975081Sgblack@eecs.umich.edu         size -= pageSize, vaddr += pageSize, new_vaddr += pageSize)
985081Sgblack@eecs.umich.edu    {
995081Sgblack@eecs.umich.edu        assert(pTable.find(vaddr) != pTable.end());
100
101        pTable[new_vaddr] = pTable[vaddr];
102        pTable.erase(vaddr);
103        eraseCacheEntry(vaddr);
104        pTable[new_vaddr].updateVaddr(new_vaddr);
105        updateCache(new_vaddr, pTable[new_vaddr]);
106    }
107}
108
109void
110FuncPageTable::unmap(Addr vaddr, int64_t size)
111{
112    assert(pageOffset(vaddr) == 0);
113
114    DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr+ size);
115
116    for (; size > 0; size -= pageSize, vaddr += pageSize) {
117        assert(pTable.find(vaddr) != pTable.end());
118        pTable.erase(vaddr);
119        eraseCacheEntry(vaddr);
120    }
121
122}
123
124bool
125FuncPageTable::isUnmapped(Addr vaddr, int64_t size)
126{
127    // starting address must be page aligned
128    assert(pageOffset(vaddr) == 0);
129
130    for (; size > 0; size -= pageSize, vaddr += pageSize) {
131        if (pTable.find(vaddr) != pTable.end()) {
132            return false;
133        }
134    }
135
136    return true;
137}
138
139bool
140FuncPageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry)
141{
142    Addr page_addr = pageAlign(vaddr);
143
144    if (pTableCache[0].valid && pTableCache[0].vaddr == page_addr) {
145        entry = pTableCache[0].entry;
146        return true;
147    }
148    if (pTableCache[1].valid && pTableCache[1].vaddr == page_addr) {
149        entry = pTableCache[1].entry;
150        return true;
151    }
152    if (pTableCache[2].valid && pTableCache[2].vaddr == page_addr) {
153        entry = pTableCache[2].entry;
154        return true;
155    }
156
157    PTableItr iter = pTable.find(page_addr);
158
159    if (iter == pTable.end()) {
160        return false;
161    }
162
163    updateCache(page_addr, iter->second);
164    entry = iter->second;
165    return true;
166}
167
168bool
169PageTableBase::translate(Addr vaddr, Addr &paddr)
170{
171    TheISA::TlbEntry entry;
172    if (!lookup(vaddr, entry)) {
173        DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr);
174        return false;
175    }
176    paddr = pageOffset(vaddr) + entry.pageStart();
177    DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr);
178    return true;
179}
180
181Fault
182PageTableBase::translate(RequestPtr req)
183{
184    Addr paddr;
185    assert(pageAlign(req->getVaddr() + req->getSize() - 1)
186           == pageAlign(req->getVaddr()));
187    if (!translate(req->getVaddr(), paddr)) {
188        return Fault(new GenericPageTableFault(req->getVaddr()));
189    }
190    req->setPaddr(paddr);
191    if ((paddr & (pageSize - 1)) + req->getSize() > pageSize) {
192        panic("Request spans page boundaries!\n");
193        return NoFault;
194    }
195    return NoFault;
196}
197
198void
199FuncPageTable::serialize(std::ostream &os)
200{
201    paramOut(os, "ptable.size", pTable.size());
202
203    PTable::size_type count = 0;
204
205    PTableItr iter = pTable.begin();
206    PTableItr end = pTable.end();
207    while (iter != end) {
208        os << "\n[" << csprintf("%s.Entry%d", name(), count) << "]\n";
209
210        paramOut(os, "vaddr", iter->first);
211        iter->second.serialize(os);
212
213        ++iter;
214        ++count;
215    }
216    assert(count == pTable.size());
217}
218
219void
220FuncPageTable::unserialize(Checkpoint *cp, const std::string &section)
221{
222    int i = 0, count;
223    paramIn(cp, section, "ptable.size", count);
224
225    pTable.clear();
226
227    while (i < count) {
228        TheISA::TlbEntry *entry;
229        Addr vaddr;
230
231        paramIn(cp, csprintf("%s.Entry%d", name(), i), "vaddr", vaddr);
232        entry = new TheISA::TlbEntry();
233        entry->unserialize(cp, csprintf("%s.Entry%d", name(), i));
234        pTable[vaddr] = *entry;
235        delete entry;
236        ++i;
237    }
238}
239
240