| /* |
| * Copyright (c) 2006 The Regents of The University of Michigan |
| * All rights reserved. |
| * |
| * 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. |
| */ |
| |
| #ifndef __ARCH_SPARC_PAGETABLE_HH__ |
| #define __ARCH_SPARC_PAGETABLE_HH__ |
| |
| #include <cassert> |
| |
| #include "arch/sparc/isa_traits.hh" |
| #include "base/bitfield.hh" |
| #include "base/logging.hh" |
| |
| class Checkpoint; |
| |
| namespace SparcISA { |
| |
| struct VAddr |
| { |
| VAddr(Addr a) { panic("not implemented yet."); } |
| }; |
| |
| class TteTag |
| { |
| private: |
| uint64_t entry; |
| bool populated; |
| |
| public: |
| TteTag() : entry(0), populated(false) {} |
| TteTag(uint64_t e) : entry(e), populated(true) {} |
| |
| const TteTag & |
| operator=(uint64_t e) |
| { |
| populated = true; |
| entry = e; |
| return *this; |
| } |
| |
| bool valid() const { assert(populated); return !bits(entry,62,62); } |
| Addr va() const { assert(populated); return bits(entry,41,0); } |
| }; |
| |
| |
| class PageTableEntry |
| { |
| public: |
| enum EntryType { |
| sun4v, |
| sun4u, |
| invalid |
| }; |
| |
| private: |
| uint64_t entry; |
| EntryType type; |
| uint64_t entry4u; |
| bool populated; |
| |
| public: |
| PageTableEntry() : entry(0), type(invalid), populated(false) |
| {} |
| |
| PageTableEntry(uint64_t e, EntryType t = sun4u) |
| : entry(e), type(t), populated(true) |
| { |
| populate(entry, type); |
| } |
| |
| void |
| populate(uint64_t e, EntryType t = sun4u) |
| { |
| entry = e; |
| type = t; |
| populated = true; |
| |
| // If we get a sun4v format TTE, turn it into a sun4u |
| if (type == sun4u) |
| entry4u = entry; |
| else { |
| entry4u = 0; |
| entry4u |= mbits(entry,63,63); // valid |
| entry4u |= bits(entry,1,0) << 61; // size[1:0] |
| entry4u |= bits(entry,62,62) << 60; // nfo |
| entry4u |= bits(entry,12,12) << 59; // ie |
| entry4u |= bits(entry,2,2) << 48; // size[2] |
| entry4u |= mbits(entry,39,13); // paddr |
| entry4u |= bits(entry,61,61) << 6;; // locked |
| entry4u |= bits(entry,10,10) << 5; // cp |
| entry4u |= bits(entry,9,9) << 4; // cv |
| entry4u |= bits(entry,11,11) << 3; // e |
| entry4u |= bits(entry,8,8) << 2; // p |
| entry4u |= bits(entry,6,6) << 1; // w |
| } |
| } |
| |
| void |
| clear() |
| { |
| populated = false; |
| } |
| |
| static int pageSizes[6]; |
| |
| uint64_t operator()() const { assert(populated); return entry4u; } |
| |
| const PageTableEntry & |
| operator=(uint64_t e) |
| { |
| populated = true; |
| entry4u = e; |
| return *this; |
| } |
| |
| const PageTableEntry & |
| operator=(const PageTableEntry &e) |
| { |
| populated = true; |
| entry4u = e.entry4u; |
| type = e.type; |
| return *this; |
| } |
| |
| bool valid() const { return bits(entry4u,63,63) && populated; } |
| |
| uint8_t |
| _size() const |
| { |
| assert(populated); |
| return bits(entry4u, 62,61) | bits(entry4u, 48,48) << 2; |
| } |
| |
| Addr size() const { assert(_size() < 6); return pageSizes[_size()]; } |
| Addr sizeMask() const { return size() - 1; } |
| bool ie() const { return bits(entry4u, 59,59); } |
| Addr pfn() const { assert(populated); return bits(entry4u,39,13); } |
| Addr paddr() const { assert(populated); return mbits(entry4u, 39,13);} |
| bool locked() const { assert(populated); return bits(entry4u,6,6); } |
| bool cv() const { assert(populated); return bits(entry4u,4,4); } |
| bool cp() const { assert(populated); return bits(entry4u,5,5); } |
| bool priv() const { assert(populated); return bits(entry4u,2,2); } |
| bool writable() const { assert(populated); return bits(entry4u,1,1); } |
| bool nofault() const { assert(populated); return bits(entry4u,60,60); } |
| bool sideffect() const { assert(populated); return bits(entry4u,3,3); } |
| Addr paddrMask() const { assert(populated); return paddr() & ~sizeMask(); } |
| |
| Addr |
| translate(Addr vaddr) const |
| { |
| assert(populated); |
| Addr mask = sizeMask(); |
| return (paddr() & ~mask) | (vaddr & mask); |
| } |
| }; |
| |
| struct TlbRange |
| { |
| Addr va; |
| Addr size; |
| int contextId; |
| int partitionId; |
| bool real; |
| |
| inline bool |
| operator<(const TlbRange &r2) const |
| { |
| if (real && !r2.real) |
| return true; |
| if (!real && r2.real) |
| return false; |
| |
| if (!real && !r2.real) { |
| if (contextId < r2.contextId) |
| return true; |
| else if (contextId > r2.contextId) |
| return false; |
| } |
| |
| if (partitionId < r2.partitionId) |
| return true; |
| else if (partitionId > r2.partitionId) |
| return false; |
| |
| if (va < r2.va) |
| return true; |
| return false; |
| } |
| |
| inline bool |
| operator==(const TlbRange &r2) const |
| { |
| return va == r2.va && |
| size == r2.size && |
| contextId == r2.contextId && |
| partitionId == r2.partitionId && |
| real == r2.real; |
| } |
| }; |
| |
| |
| struct TlbEntry |
| { |
| TlbEntry() |
| {} |
| |
| TlbEntry(Addr asn, Addr vaddr, Addr paddr, |
| bool uncacheable, bool read_only) |
| { |
| uint64_t entry = 0; |
| if (!read_only) |
| entry |= 1ULL << 1; // Writable |
| entry |= 0ULL << 2; // Available in nonpriveleged mode |
| entry |= 0ULL << 3; // No side effects |
| if (!uncacheable) { |
| entry |= 1ULL << 4; // Virtually cachable |
| entry |= 1ULL << 5; // Physically cachable |
| } |
| entry |= 0ULL << 6; // Not locked |
| entry |= mbits(paddr, 39, 13); // Physical address |
| entry |= 0ULL << 48; // size = 8k |
| entry |= 0uLL << 59; // Endianness not inverted |
| entry |= 0ULL << 60; // Not no fault only |
| entry |= 0ULL << 61; // size = 8k |
| entry |= 1ULL << 63; // valid |
| pte = PageTableEntry(entry); |
| |
| range.va = vaddr; |
| range.size = 8*(1<<10); |
| range.contextId = asn; |
| range.partitionId = 0; |
| range.real = false; |
| |
| valid = true; |
| } |
| |
| TlbRange range; |
| PageTableEntry pte; |
| bool used; |
| bool valid; |
| |
| Addr |
| pageStart() |
| { |
| return pte.paddr(); |
| } |
| |
| void |
| updateVaddr(Addr new_vaddr) |
| { |
| range.va = new_vaddr; |
| } |
| |
| void serialize(CheckpointOut &cp) const; |
| void unserialize(CheckpointIn &cp); |
| }; |
| |
| } // namespace SparcISA |
| |
| #endif // __ARCH_SPARC_PAGE_TABLE_HH__ |
| |