page_table.cc revision 12536:0a1d2ced2d4c
1/*
2 * Copyright (c) 2014 Advanced Micro Devices, Inc.
3 * Copyright (c) 2003 The Regents of The University of Michigan
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Steve Reinhardt
30 *          Ron Dreslinski
31 *          Ali Saidi
32 */
33
34/**
35 * @file
36 * Definitions of functional page table.
37 */
38#include "mem/page_table.hh"
39
40#include <string>
41
42#include "base/compiler.hh"
43#include "base/trace.hh"
44#include "debug/MMU.hh"
45#include "sim/faults.hh"
46#include "sim/serialize.hh"
47
48using namespace std;
49
50void
51EmulationPageTable::map(Addr vaddr, Addr paddr, int64_t size, uint64_t flags)
52{
53    bool clobber = flags & Clobber;
54    // starting address must be page aligned
55    assert(pageOffset(vaddr) == 0);
56
57    DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr + size);
58
59    while (size > 0) {
60        auto it = pTable.find(vaddr);
61        if (it != pTable.end()) {
62            // already mapped
63            panic_if(!clobber,
64                     "EmulationPageTable::allocate: addr %#x already mapped",
65                     vaddr);
66            it->second = Entry(paddr, flags);
67        } else {
68            pTable.emplace(vaddr, Entry(paddr, flags));
69        }
70
71        size -= pageSize;
72        vaddr += pageSize;
73        paddr += pageSize;
74    }
75}
76
77void
78EmulationPageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
79{
80    assert(pageOffset(vaddr) == 0);
81    assert(pageOffset(new_vaddr) == 0);
82
83    DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr,
84            new_vaddr, size);
85
86    while (size > 0) {
87        auto new_it M5_VAR_USED = pTable.find(new_vaddr);
88        auto old_it = pTable.find(vaddr);
89        assert(old_it != pTable.end() && new_it == pTable.end());
90
91        pTable.emplace(new_vaddr, old_it->second);
92        pTable.erase(old_it);
93        size -= pageSize;
94        vaddr += pageSize;
95        new_vaddr += pageSize;
96    }
97}
98
99void
100EmulationPageTable::getMappings(std::vector<std::pair<Addr, Addr>> *addr_maps)
101{
102    for (auto &iter : pTable)
103        addr_maps->push_back(make_pair(iter.first, iter.second.paddr));
104}
105
106void
107EmulationPageTable::unmap(Addr vaddr, int64_t size)
108{
109    assert(pageOffset(vaddr) == 0);
110
111    DPRINTF(MMU, "Unmapping page: %#x-%#x\n", vaddr, vaddr + size);
112
113    while (size > 0) {
114        auto it = pTable.find(vaddr);
115        assert(it != pTable.end());
116        pTable.erase(it);
117        size -= pageSize;
118        vaddr += pageSize;
119    }
120}
121
122bool
123EmulationPageTable::isUnmapped(Addr vaddr, int64_t size)
124{
125    // starting address must be page aligned
126    assert(pageOffset(vaddr) == 0);
127
128    for (int64_t offset = 0; offset < size; offset += pageSize)
129        if (pTable.find(vaddr + offset) != pTable.end())
130            return false;
131
132    return true;
133}
134
135const EmulationPageTable::Entry *
136EmulationPageTable::lookup(Addr vaddr)
137{
138    Addr page_addr = pageAlign(vaddr);
139    PTableItr iter = pTable.find(page_addr);
140    if (iter == pTable.end())
141        return nullptr;
142    return &(iter->second);
143}
144
145bool
146EmulationPageTable::translate(Addr vaddr, Addr &paddr)
147{
148    const Entry *entry = lookup(vaddr);
149    if (!entry) {
150        DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr);
151        return false;
152    }
153    paddr = pageOffset(vaddr) + entry->paddr;
154    DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr);
155    return true;
156}
157
158Fault
159EmulationPageTable::translate(RequestPtr req)
160{
161    Addr paddr;
162    assert(pageAlign(req->getVaddr() + req->getSize() - 1) ==
163           pageAlign(req->getVaddr()));
164    if (!translate(req->getVaddr(), paddr))
165        return Fault(new GenericPageTableFault(req->getVaddr()));
166    req->setPaddr(paddr);
167    if ((paddr & (pageSize - 1)) + req->getSize() > pageSize) {
168        panic("Request spans page boundaries!\n");
169        return NoFault;
170    }
171    return NoFault;
172}
173
174void
175EmulationPageTable::serialize(CheckpointOut &cp) const
176{
177    paramOut(cp, "ptable.size", pTable.size());
178
179    PTable::size_type count = 0;
180    for (auto &pte : pTable) {
181        ScopedCheckpointSection sec(cp, csprintf("Entry%d", count++));
182
183        paramOut(cp, "vaddr", pte.first);
184        paramOut(cp, "paddr", pte.second.paddr);
185        paramOut(cp, "flags", pte.second.flags);
186    }
187    assert(count == pTable.size());
188}
189
190void
191EmulationPageTable::unserialize(CheckpointIn &cp)
192{
193    int count;
194    paramIn(cp, "ptable.size", count);
195
196    for (int i = 0; i < count; ++i) {
197        ScopedCheckpointSection sec(cp, csprintf("Entry%d", i));
198
199        Addr vaddr;
200        UNSERIALIZE_SCALAR(vaddr);
201        Addr paddr;
202        uint64_t flags;
203        UNSERIALIZE_SCALAR(paddr);
204        UNSERIALIZE_SCALAR(flags);
205
206        pTable.emplace(vaddr, Entry(paddr, flags));
207    }
208}
209
210