page_table.cc revision 6658:f4de76601762
112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * Copyright (c) 2003 The Regents of The University of Michigan
312027Sjungma@eit.uni-kl.de * All rights reserved.
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without
612027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are
712027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright
812027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer;
912027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright
1012027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the
1112027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution;
1212027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its
1312027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from
1412027Sjungma@eit.uni-kl.de * this software without specific prior written permission.
1512027Sjungma@eit.uni-kl.de *
1612027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712027Sjungma@eit.uni-kl.de *
2812027Sjungma@eit.uni-kl.de * Authors: Steve Reinhardt
2912027Sjungma@eit.uni-kl.de *          Ron Dreslinski
3012027Sjungma@eit.uni-kl.de *          Ali Saidi
3112027Sjungma@eit.uni-kl.de */
3212027Sjungma@eit.uni-kl.de
3312027Sjungma@eit.uni-kl.de/**
3412027Sjungma@eit.uni-kl.de * @file
3512027Sjungma@eit.uni-kl.de * Definitions of page table.
3612027Sjungma@eit.uni-kl.de */
3712027Sjungma@eit.uni-kl.de#include <string>
3812027Sjungma@eit.uni-kl.de#include <map>
3912027Sjungma@eit.uni-kl.de#include <fstream>
4012027Sjungma@eit.uni-kl.de
4112027Sjungma@eit.uni-kl.de#include "arch/faults.hh"
4212027Sjungma@eit.uni-kl.de#include "base/bitfield.hh"
4312027Sjungma@eit.uni-kl.de#include "base/intmath.hh"
4412027Sjungma@eit.uni-kl.de#include "base/trace.hh"
4512027Sjungma@eit.uni-kl.de#include "config/the_isa.hh"
4612027Sjungma@eit.uni-kl.de#include "mem/page_table.hh"
4712027Sjungma@eit.uni-kl.de#include "sim/process.hh"
4812027Sjungma@eit.uni-kl.de#include "sim/sim_object.hh"
4912027Sjungma@eit.uni-kl.de#include "sim/system.hh"
5012027Sjungma@eit.uni-kl.de
5112027Sjungma@eit.uni-kl.deusing namespace std;
5212027Sjungma@eit.uni-kl.deusing namespace TheISA;
5312027Sjungma@eit.uni-kl.de
5412027Sjungma@eit.uni-kl.dePageTable::PageTable(Process *_process, Addr _pageSize)
5512027Sjungma@eit.uni-kl.de    : pageSize(_pageSize), offsetMask(mask(floorLog2(_pageSize))),
5612027Sjungma@eit.uni-kl.de      process(_process)
5712027Sjungma@eit.uni-kl.de{
5812027Sjungma@eit.uni-kl.de    assert(isPowerOf2(pageSize));
5912027Sjungma@eit.uni-kl.de    pTableCache[0].vaddr = 0;
6012027Sjungma@eit.uni-kl.de    pTableCache[1].vaddr = 0;
6112027Sjungma@eit.uni-kl.de    pTableCache[2].vaddr = 0;
6212027Sjungma@eit.uni-kl.de}
6312027Sjungma@eit.uni-kl.de
6412027Sjungma@eit.uni-kl.dePageTable::~PageTable()
6512027Sjungma@eit.uni-kl.de{
6612027Sjungma@eit.uni-kl.de}
6712027Sjungma@eit.uni-kl.de
6812027Sjungma@eit.uni-kl.devoid
6912027Sjungma@eit.uni-kl.dePageTable::allocate(Addr vaddr, int64_t size)
7012027Sjungma@eit.uni-kl.de{
7112027Sjungma@eit.uni-kl.de    // starting address must be page aligned
7212027Sjungma@eit.uni-kl.de    assert(pageOffset(vaddr) == 0);
7312027Sjungma@eit.uni-kl.de
7412027Sjungma@eit.uni-kl.de    DPRINTF(MMU, "Allocating Page: %#x-%#x\n", vaddr, vaddr+ size);
7512027Sjungma@eit.uni-kl.de
7612027Sjungma@eit.uni-kl.de    for (; size > 0; size -= pageSize, vaddr += pageSize) {
7712027Sjungma@eit.uni-kl.de        PTableItr iter = pTable.find(vaddr);
7812027Sjungma@eit.uni-kl.de
7912027Sjungma@eit.uni-kl.de        if (iter != pTable.end()) {
8012027Sjungma@eit.uni-kl.de            // already mapped
8112027Sjungma@eit.uni-kl.de            fatal("PageTable::allocate: address 0x%x already mapped",
8212027Sjungma@eit.uni-kl.de                    vaddr);
8312027Sjungma@eit.uni-kl.de        }
8412027Sjungma@eit.uni-kl.de
8512027Sjungma@eit.uni-kl.de        pTable[vaddr] = TheISA::TlbEntry(process->M5_pid, vaddr,
8612027Sjungma@eit.uni-kl.de                process->system->new_page());
8712027Sjungma@eit.uni-kl.de        updateCache(vaddr, pTable[vaddr]);
8812027Sjungma@eit.uni-kl.de    }
8912027Sjungma@eit.uni-kl.de}
9012027Sjungma@eit.uni-kl.de
9112027Sjungma@eit.uni-kl.devoid
9212027Sjungma@eit.uni-kl.dePageTable::remap(Addr vaddr, int64_t size, Addr new_vaddr)
9312027Sjungma@eit.uni-kl.de{
9412027Sjungma@eit.uni-kl.de    assert(pageOffset(vaddr) == 0);
9512027Sjungma@eit.uni-kl.de    assert(pageOffset(new_vaddr) == 0);
9612027Sjungma@eit.uni-kl.de
9712027Sjungma@eit.uni-kl.de    DPRINTF(MMU, "moving pages from vaddr %08p to %08p, size = %d\n", vaddr,
9812027Sjungma@eit.uni-kl.de            new_vaddr, size);
9912027Sjungma@eit.uni-kl.de
10012027Sjungma@eit.uni-kl.de    for (; size > 0; size -= pageSize, vaddr += pageSize, new_vaddr += pageSize) {
10112027Sjungma@eit.uni-kl.de        PTableItr iter = pTable.find(vaddr);
10212027Sjungma@eit.uni-kl.de
10312027Sjungma@eit.uni-kl.de        assert(iter != pTable.end());
10412027Sjungma@eit.uni-kl.de
10512027Sjungma@eit.uni-kl.de        pTable[new_vaddr] = pTable[vaddr];
10612027Sjungma@eit.uni-kl.de        pTable.erase(vaddr);
10712027Sjungma@eit.uni-kl.de        pTable[new_vaddr].updateVaddr(new_vaddr);
10812027Sjungma@eit.uni-kl.de        updateCache(new_vaddr, pTable[new_vaddr]);
10912027Sjungma@eit.uni-kl.de    }
11012027Sjungma@eit.uni-kl.de}
11112027Sjungma@eit.uni-kl.de
11212027Sjungma@eit.uni-kl.devoid
11312027Sjungma@eit.uni-kl.dePageTable::deallocate(Addr vaddr, int64_t size)
11412027Sjungma@eit.uni-kl.de{
11512027Sjungma@eit.uni-kl.de    assert(pageOffset(vaddr) == 0);
11612027Sjungma@eit.uni-kl.de
11712027Sjungma@eit.uni-kl.de    DPRINTF(MMU, "Deallocating page: %#x-%#x\n", vaddr, vaddr+ size);
11812027Sjungma@eit.uni-kl.de
11912027Sjungma@eit.uni-kl.de    for (; size > 0; size -= pageSize, vaddr += pageSize) {
12012027Sjungma@eit.uni-kl.de        PTableItr iter = pTable.find(vaddr);
12112027Sjungma@eit.uni-kl.de
12212027Sjungma@eit.uni-kl.de        assert(iter != pTable.end());
12312027Sjungma@eit.uni-kl.de
12412027Sjungma@eit.uni-kl.de        pTable.erase(vaddr);
12512027Sjungma@eit.uni-kl.de    }
12612027Sjungma@eit.uni-kl.de
12712027Sjungma@eit.uni-kl.de}
12812027Sjungma@eit.uni-kl.de
12912027Sjungma@eit.uni-kl.debool
13012027Sjungma@eit.uni-kl.dePageTable::lookup(Addr vaddr, TheISA::TlbEntry &entry)
13112027Sjungma@eit.uni-kl.de{
13212027Sjungma@eit.uni-kl.de    Addr page_addr = pageAlign(vaddr);
13312027Sjungma@eit.uni-kl.de
13412027Sjungma@eit.uni-kl.de    if (pTableCache[0].vaddr == page_addr) {
13512027Sjungma@eit.uni-kl.de        entry = pTableCache[0].entry;
13612027Sjungma@eit.uni-kl.de        return true;
13712027Sjungma@eit.uni-kl.de    }
13812027Sjungma@eit.uni-kl.de    if (pTableCache[1].vaddr == page_addr) {
13912027Sjungma@eit.uni-kl.de        entry = pTableCache[1].entry;
14012027Sjungma@eit.uni-kl.de        return true;
14112027Sjungma@eit.uni-kl.de    }
14212027Sjungma@eit.uni-kl.de    if (pTableCache[2].vaddr == page_addr) {
14312027Sjungma@eit.uni-kl.de        entry = pTableCache[2].entry;
14412027Sjungma@eit.uni-kl.de        return true;
14512027Sjungma@eit.uni-kl.de    }
14612027Sjungma@eit.uni-kl.de
14712027Sjungma@eit.uni-kl.de    PTableItr iter = pTable.find(page_addr);
14812027Sjungma@eit.uni-kl.de
14912027Sjungma@eit.uni-kl.de    if (iter == pTable.end()) {
15012027Sjungma@eit.uni-kl.de        return false;
15112027Sjungma@eit.uni-kl.de    }
15212027Sjungma@eit.uni-kl.de
15312027Sjungma@eit.uni-kl.de    updateCache(page_addr, iter->second);
15412027Sjungma@eit.uni-kl.de    entry = iter->second;
15512027Sjungma@eit.uni-kl.de    return true;
15612027Sjungma@eit.uni-kl.de}
15712027Sjungma@eit.uni-kl.de
15812027Sjungma@eit.uni-kl.debool
15912027Sjungma@eit.uni-kl.dePageTable::translate(Addr vaddr, Addr &paddr)
16012027Sjungma@eit.uni-kl.de{
16112027Sjungma@eit.uni-kl.de    TheISA::TlbEntry entry;
16212027Sjungma@eit.uni-kl.de    if (!lookup(vaddr, entry)) {
16312027Sjungma@eit.uni-kl.de        DPRINTF(MMU, "Couldn't Translate: %#x\n", vaddr);
16412027Sjungma@eit.uni-kl.de        return false;
16512027Sjungma@eit.uni-kl.de    }
16612027Sjungma@eit.uni-kl.de    paddr = pageOffset(vaddr) + entry.pageStart();
16712027Sjungma@eit.uni-kl.de    DPRINTF(MMU, "Translating: %#x->%#x\n", vaddr, paddr);
16812027Sjungma@eit.uni-kl.de    return true;
16912027Sjungma@eit.uni-kl.de}
17012027Sjungma@eit.uni-kl.de
17112027Sjungma@eit.uni-kl.deFault
17212027Sjungma@eit.uni-kl.dePageTable::translate(RequestPtr req)
17312027Sjungma@eit.uni-kl.de{
17412027Sjungma@eit.uni-kl.de    Addr paddr;
17512027Sjungma@eit.uni-kl.de    assert(pageAlign(req->getVaddr() + req->getSize() - 1)
17612027Sjungma@eit.uni-kl.de           == pageAlign(req->getVaddr()));
17712027Sjungma@eit.uni-kl.de    if (!translate(req->getVaddr(), paddr)) {
17812027Sjungma@eit.uni-kl.de        return Fault(new GenericPageTableFault(req->getVaddr()));
17912027Sjungma@eit.uni-kl.de    }
18012027Sjungma@eit.uni-kl.de    req->setPaddr(paddr);
18112027Sjungma@eit.uni-kl.de    if ((paddr & (pageSize - 1)) + req->getSize() > pageSize) {
18212027Sjungma@eit.uni-kl.de        panic("Request spans page boundaries!\n");
18312027Sjungma@eit.uni-kl.de        return NoFault;
18412027Sjungma@eit.uni-kl.de    }
18512027Sjungma@eit.uni-kl.de    return NoFault;
18612027Sjungma@eit.uni-kl.de}
18712027Sjungma@eit.uni-kl.de
18812027Sjungma@eit.uni-kl.devoid
18912027Sjungma@eit.uni-kl.dePageTable::serialize(std::ostream &os)
19012027Sjungma@eit.uni-kl.de{
19112027Sjungma@eit.uni-kl.de    paramOut(os, "ptable.size", pTable.size());
19212027Sjungma@eit.uni-kl.de
19312027Sjungma@eit.uni-kl.de    PTable::size_type count = 0;
19412027Sjungma@eit.uni-kl.de
19512027Sjungma@eit.uni-kl.de    PTableItr iter = pTable.begin();
19612027Sjungma@eit.uni-kl.de    PTableItr end = pTable.end();
19712027Sjungma@eit.uni-kl.de    while (iter != end) {
19812027Sjungma@eit.uni-kl.de        os << "\n[" << csprintf("%s.Entry%d", process->name(), count) << "]\n";
19912027Sjungma@eit.uni-kl.de
20012027Sjungma@eit.uni-kl.de        paramOut(os, "vaddr", iter->first);
20112027Sjungma@eit.uni-kl.de        iter->second.serialize(os);
20212027Sjungma@eit.uni-kl.de
20312027Sjungma@eit.uni-kl.de        ++iter;
20412027Sjungma@eit.uni-kl.de        ++count;
20512027Sjungma@eit.uni-kl.de    }
20612027Sjungma@eit.uni-kl.de    assert(count == pTable.size());
20712027Sjungma@eit.uni-kl.de}
20812027Sjungma@eit.uni-kl.de
20912027Sjungma@eit.uni-kl.devoid
21012027Sjungma@eit.uni-kl.dePageTable::unserialize(Checkpoint *cp, const std::string &section)
21112027Sjungma@eit.uni-kl.de{
21212027Sjungma@eit.uni-kl.de    int i = 0, count;
21312027Sjungma@eit.uni-kl.de    paramIn(cp, section, "ptable.size", count);
21412027Sjungma@eit.uni-kl.de    Addr vaddr;
21512027Sjungma@eit.uni-kl.de    TheISA::TlbEntry *entry;
21612027Sjungma@eit.uni-kl.de
21712027Sjungma@eit.uni-kl.de    pTable.clear();
21812027Sjungma@eit.uni-kl.de
21912027Sjungma@eit.uni-kl.de    while(i < count) {
22012027Sjungma@eit.uni-kl.de        paramIn(cp, csprintf("%s.Entry%d", process->name(), i), "vaddr", vaddr);
22112027Sjungma@eit.uni-kl.de        entry = new TheISA::TlbEntry();
22212027Sjungma@eit.uni-kl.de        entry->unserialize(cp, csprintf("%s.Entry%d", process->name(), i));
22312027Sjungma@eit.uni-kl.de        pTable[vaddr] = *entry;
22412027Sjungma@eit.uni-kl.de        ++i;
22512027Sjungma@eit.uni-kl.de   }
22612027Sjungma@eit.uni-kl.de}
22712027Sjungma@eit.uni-kl.de
22812027Sjungma@eit.uni-kl.de