12379SN/A/*
210298Salexandru.dutu@amd.com * Copyright (c) 2014 Advanced Micro Devices, Inc.
32379SN/A * Copyright (c) 2003 The Regents of The University of Michigan
42379SN/A * All rights reserved.
52379SN/A *
62379SN/A * Redistribution and use in source and binary forms, with or without
72379SN/A * modification, are permitted provided that the following conditions are
82379SN/A * met: redistributions of source code must retain the above copyright
92379SN/A * notice, this list of conditions and the following disclaimer;
102379SN/A * redistributions in binary form must reproduce the above copyright
112379SN/A * notice, this list of conditions and the following disclaimer in the
122379SN/A * documentation and/or other materials provided with the distribution;
132379SN/A * neither the name of the copyright holders nor the names of its
142379SN/A * contributors may be used to endorse or promote products derived from
152379SN/A * this software without specific prior written permission.
162379SN/A *
172379SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182379SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192379SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202379SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
212379SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
222379SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
232379SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242379SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252379SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262379SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
272379SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282665Ssaidi@eecs.umich.edu *
292665Ssaidi@eecs.umich.edu * Authors: Steve Reinhardt
302665Ssaidi@eecs.umich.edu *          Ron Dreslinski
313311Ssaidi@eecs.umich.edu *          Ali Saidi
322379SN/A */
332379SN/A
342379SN/A/**
352379SN/A * @file
3610298Salexandru.dutu@amd.com * Definitions of functional page table.
372379SN/A */
3811793Sbrandon.potter@amd.com#include "mem/page_table.hh"
3911793Sbrandon.potter@amd.com
402379SN/A#include <string>
412379SN/A
4212536Sbrandon.potter@amd.com#include "base/compiler.hh"
432379SN/A#include "base/trace.hh"
448232Snate@binkert.org#include "debug/MMU.hh"
457678Sgblack@eecs.umich.edu#include "sim/faults.hh"
4611800Sbrandon.potter@amd.com#include "sim/serialize.hh"
472379SN/A
482399SN/Avoid
4912448Sgabeblack@google.comEmulationPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags)
502399SN/A{
5110558Salexandru.dutu@amd.com    bool clobber = flags & Clobber;
522399SN/A    // starting address must be page aligned
532399SN/A    assert(pageOffset(vaddr) == 0);
542399SN/A
5512448Sgabeblack@google.com    DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr + size);
563311Ssaidi@eecs.umich.edu
5712448Sgabeblack@google.com    while (size > 0) {
5812442Sgabeblack@google.com        auto it = pTable.find(vaddr);
5912442Sgabeblack@google.com        if (it != pTable.end()) {
6012461Sgabeblack@google.com            // already mapped
6112461Sgabeblack@google.com            panic_if(!clobber,
6212461Sgabeblack@google.com                     "EmulationPageTable::allocate: addr %#x already mapped",
6312461Sgabeblack@google.com                     vaddr);
6412461Sgabeblack@google.com            it->second = Entry(paddr, flags);
6512442Sgabeblack@google.com        } else {
6612461Sgabeblack@google.com            pTable.emplace(vaddr, Entry(paddr, flags));
672399SN/A        }
682399SN/A
6912448Sgabeblack@google.com        size -= pageSize;
7012448Sgabeblack@google.com        vaddr += pageSize;
7112448Sgabeblack@google.com        paddr += pageSize;
722399SN/A    }
732399SN/A}
742399SN/A
755877Shsul@eecs.umich.eduvoid
7612448Sgabeblack@google.comEmulationPageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
775877Shsul@eecs.umich.edu{
785877Shsul@eecs.umich.edu    assert(pageOffset(vaddr) == 0);
795877Shsul@eecs.umich.edu    assert(pageOffset(new_vaddr) == 0);
805877Shsul@eecs.umich.edu
815877Shsul@eecs.umich.edu    DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr,
825877Shsul@eecs.umich.edu            new_vaddr, size);
835877Shsul@eecs.umich.edu
8412448Sgabeblack@google.com    while (size > 0) {
8512536Sbrandon.potter@amd.com        auto new_it M5_VAR_USED = pTable.find(new_vaddr);
8612442Sgabeblack@google.com        auto old_it = pTable.find(vaddr);
8712442Sgabeblack@google.com        assert(old_it != pTable.end() && new_it == pTable.end());
885877Shsul@eecs.umich.edu
8912519Srico.amslinger@informatik.uni-augsburg.de        pTable.emplace(new_vaddr, old_it->second);
9012442Sgabeblack@google.com        pTable.erase(old_it);
9112448Sgabeblack@google.com        size -= pageSize;
9212448Sgabeblack@google.com        vaddr += pageSize;
9312448Sgabeblack@google.com        new_vaddr += pageSize;
945877Shsul@eecs.umich.edu    }
955877Shsul@eecs.umich.edu}
965877Shsul@eecs.umich.edu
975877Shsul@eecs.umich.eduvoid
9812448Sgabeblack@google.comEmulationPageTable::getMappings(std::vector<std::pair<Addr, Addr>> *addr_maps)
9911886Sbrandon.potter@amd.com{
10011886Sbrandon.potter@amd.com    for (auto &iter : pTable)
10112637Sodanrc@yahoo.com.br        addr_maps->push_back(std::make_pair(iter.first, iter.second.paddr));
10211886Sbrandon.potter@amd.com}
10311886Sbrandon.potter@amd.com
10411886Sbrandon.potter@amd.comvoid
10512448Sgabeblack@google.comEmulationPageTable::unmap(Addr vaddr, int64_t size)
1065877Shsul@eecs.umich.edu{
1075877Shsul@eecs.umich.edu    assert(pageOffset(vaddr) == 0);
1085877Shsul@eecs.umich.edu
10912461Sgabeblack@google.com    DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr + size);
1105877Shsul@eecs.umich.edu
11112448Sgabeblack@google.com    while (size > 0) {
11212442Sgabeblack@google.com        auto it = pTable.find(vaddr);
11312442Sgabeblack@google.com        assert(it != pTable.end());
11412442Sgabeblack@google.com        pTable.erase(it);
11512448Sgabeblack@google.com        size -= pageSize;
11612448Sgabeblack@google.com        vaddr += pageSize;
1175877Shsul@eecs.umich.edu    }
1185877Shsul@eecs.umich.edu}
1195877Shsul@eecs.umich.edu
1202399SN/Abool
12112448Sgabeblack@google.comEmulationPageTable::isUnmapped(Addr vaddr, int64_t size)
1228600Ssteve.reinhardt@amd.com{
1238600Ssteve.reinhardt@amd.com    // starting address must be page aligned
1248600Ssteve.reinhardt@amd.com    assert(pageOffset(vaddr) == 0);
1258600Ssteve.reinhardt@amd.com
12612448Sgabeblack@google.com    for (int64_t offset = 0; offset < size; offset += pageSize)
12712448Sgabeblack@google.com        if (pTable.find(vaddr + offset) != pTable.end())
1288600Ssteve.reinhardt@amd.com            return false;
1298600Ssteve.reinhardt@amd.com
1308600Ssteve.reinhardt@amd.com    return true;
1318600Ssteve.reinhardt@amd.com}
1328600Ssteve.reinhardt@amd.com
13312461Sgabeblack@google.comconst EmulationPageTable::Entry *
13412455Sgabeblack@google.comEmulationPageTable::lookup(Addr vaddr)
1352399SN/A{
1362399SN/A    Addr page_addr = pageAlign(vaddr);
1375004Sgblack@eecs.umich.edu    PTableItr iter = pTable.find(page_addr);
13812448Sgabeblack@google.com    if (iter == pTable.end())
13912455Sgabeblack@google.com        return nullptr;
14012461Sgabeblack@google.com    return &(iter->second);
1412399SN/A}
1422399SN/A
1435004Sgblack@eecs.umich.edubool
14412448Sgabeblack@google.comEmulationPageTable::translate(Addr vaddr, Addr &paddr)
1455004Sgblack@eecs.umich.edu{
14612461Sgabeblack@google.com    const Entry *entry = lookup(vaddr);
14712455Sgabeblack@google.com    if (!entry) {
1485183Ssaidi@eecs.umich.edu        DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr);
1495004Sgblack@eecs.umich.edu        return false;
1505183Ssaidi@eecs.umich.edu    }
15112461Sgabeblack@google.com    paddr = pageOffset(vaddr) + entry->paddr;
1525183Ssaidi@eecs.umich.edu    DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr);
1535004Sgblack@eecs.umich.edu    return true;
1545004Sgblack@eecs.umich.edu}
1552399SN/A
1562394SN/AFault
15712749Sgiacomo.travaglini@arm.comEmulationPageTable::translate(const RequestPtr &req)
1582394SN/A{
1592532SN/A    Addr paddr;
16012448Sgabeblack@google.com    assert(pageAlign(req->getVaddr() + req->getSize() - 1) ==
16112448Sgabeblack@google.com           pageAlign(req->getVaddr()));
16212448Sgabeblack@google.com    if (!translate(req->getVaddr(), paddr))
1635004Sgblack@eecs.umich.edu        return Fault(new GenericPageTableFault(req->getVaddr()));
1642532SN/A    req->setPaddr(paddr);
1655004Sgblack@eecs.umich.edu    if ((paddr & (pageSize - 1)) + req->getSize() > pageSize) {
1665004Sgblack@eecs.umich.edu        panic("Request spans page boundaries!\n");
1675004Sgblack@eecs.umich.edu        return NoFault;
1685004Sgblack@eecs.umich.edu    }
1695004Sgblack@eecs.umich.edu    return NoFault;
1702394SN/A}
1713311Ssaidi@eecs.umich.edu
1723311Ssaidi@eecs.umich.eduvoid
17312448Sgabeblack@google.comEmulationPageTable::serialize(CheckpointOut &cp) const
1743311Ssaidi@eecs.umich.edu{
17510905Sandreas.sandberg@arm.com    paramOut(cp, "ptable.size", pTable.size());
1763320Shsul@eecs.umich.edu
1776227Snate@binkert.org    PTable::size_type count = 0;
17810905Sandreas.sandberg@arm.com    for (auto &pte : pTable) {
17910905Sandreas.sandberg@arm.com        ScopedCheckpointSection sec(cp, csprintf("Entry%d", count++));
1803311Ssaidi@eecs.umich.edu
18110905Sandreas.sandberg@arm.com        paramOut(cp, "vaddr", pte.first);
18212461Sgabeblack@google.com        paramOut(cp, "paddr", pte.second.paddr);
18312461Sgabeblack@google.com        paramOut(cp, "flags", pte.second.flags);
1843311Ssaidi@eecs.umich.edu    }
1853311Ssaidi@eecs.umich.edu    assert(count == pTable.size());
1863311Ssaidi@eecs.umich.edu}
1873311Ssaidi@eecs.umich.edu
1883311Ssaidi@eecs.umich.eduvoid
18912448Sgabeblack@google.comEmulationPageTable::unserialize(CheckpointIn &cp)
1903311Ssaidi@eecs.umich.edu{
19110905Sandreas.sandberg@arm.com    int count;
19210905Sandreas.sandberg@arm.com    paramIn(cp, "ptable.size", count);
1933311Ssaidi@eecs.umich.edu
19410905Sandreas.sandberg@arm.com    for (int i = 0; i < count; ++i) {
19510905Sandreas.sandberg@arm.com        ScopedCheckpointSection sec(cp, csprintf("Entry%d", i));
1963311Ssaidi@eecs.umich.edu
19712461Sgabeblack@google.com        Addr vaddr;
19812461Sgabeblack@google.com        UNSERIALIZE_SCALAR(vaddr);
19912461Sgabeblack@google.com        Addr paddr;
20012461Sgabeblack@google.com        uint64_t flags;
20112461Sgabeblack@google.com        UNSERIALIZE_SCALAR(paddr);
20212461Sgabeblack@google.com        UNSERIALIZE_SCALAR(flags);
20310905Sandreas.sandberg@arm.com
20412461Sgabeblack@google.com        pTable.emplace(vaddr, Entry(paddr, flags));
2056818SLisa.Hsu@amd.com    }
2063311Ssaidi@eecs.umich.edu}
2073311Ssaidi@eecs.umich.edu
208