1/*
2 * Copyright (c) 2014 Advanced Micro Devices, Inc.
3 * Copyright (c) 2007 The Hewlett-Packard Development Company
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder.  You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are
17 * met: redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer;
19 * redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution;
22 * neither the name of the copyright holders nor the names of its
23 * contributors may be used to endorse or promote products derived from
24 * this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 * Authors: Gabe Black
39 */
40
41#ifndef __ARCH_X86_PAGETABLE_HH__
42#define __ARCH_X86_PAGETABLE_HH__
43
44#include <iostream>
45#include <string>
46#include <vector>
47
48#include "base/bitunion.hh"
49#include "base/types.hh"
50#include "base/trie.hh"
51#include "arch/x86/system.hh"
52#include "debug/MMU.hh"
53
54class Checkpoint;
55class ThreadContext;
56
57namespace X86ISA
58{
59    struct TlbEntry;
60}
61
62typedef Trie<Addr, X86ISA::TlbEntry> TlbEntryTrie;
63
64namespace X86ISA
65{
66    struct TlbEntry : public Serializable
67    {
68        // The base of the physical page.
69        Addr paddr;
70
71        // The beginning of the virtual page this entry maps.
72        Addr vaddr;
73        // The size of the page this represents, in address bits.
74        unsigned logBytes;
75
76        // Read permission is always available, assuming it isn't blocked by
77        // other mechanisms.
78        bool writable;
79        // Whether this page is accesible without being in supervisor mode.
80        bool user;
81        // Whether to use write through or write back. M5 ignores this and
82        // lets the caches handle the writeback policy.
83        //bool pwt;
84        // Whether the page is cacheable or not.
85        bool uncacheable;
86        // Whether or not to kick this page out on a write to CR3.
87        bool global;
88        // A bit used to form an index into the PAT table.
89        bool patBit;
90        // Whether or not memory on this page can be executed.
91        bool noExec;
92        // A sequence number to keep track of LRU.
93        uint64_t lruSeq;
94
95        TlbEntryTrie::Handle trieHandle;
96
97        TlbEntry(Addr asn, Addr _vaddr, Addr _paddr,
98                 bool uncacheable, bool read_only);
99        TlbEntry();
100
101        void
102        updateVaddr(Addr new_vaddr)
103        {
104            vaddr = new_vaddr;
105        }
106
107        Addr pageStart()
108        {
109            return paddr;
110        }
111
112        // Return the page size in bytes
113        int size()
114        {
115            return (1 << logBytes);
116        }
117
118        void serialize(CheckpointOut &cp) const override;
119        void unserialize(CheckpointIn &cp) override;
120    };
121
122
123    BitUnion64(VAddr)
124        Bitfield<20, 12> longl1;
125        Bitfield<29, 21> longl2;
126        Bitfield<38, 30> longl3;
127        Bitfield<47, 39> longl4;
128
129        Bitfield<20, 12> pael1;
130        Bitfield<29, 21> pael2;
131        Bitfield<31, 30> pael3;
132
133        Bitfield<21, 12> norml1;
134        Bitfield<31, 22> norml2;
135    EndBitUnion(VAddr)
136
137    // Unfortunately, the placement of the base field in a page table entry is
138    // very erratic and would make a mess here. It might be moved here at some
139    // point in the future.
140    BitUnion64(PageTableEntry)
141        Bitfield<63> nx;
142        Bitfield<51, 12> base;
143        Bitfield<11, 9> avl;
144        Bitfield<8> g;
145        Bitfield<7> ps;
146        Bitfield<6> d;
147        Bitfield<5> a;
148        Bitfield<4> pcd;
149        Bitfield<3> pwt;
150        Bitfield<2> u;
151        Bitfield<1> w;
152        Bitfield<0> p;
153    EndBitUnion(PageTableEntry)
154
155    template <int first, int last>
156    class LongModePTE
157    {
158      public:
159        Addr paddr() { return pte.base << PageShift; }
160        void paddr(Addr addr) { pte.base = addr >> PageShift; }
161
162        bool present() { return pte.p; }
163        void present(bool p) { pte.p = p ? 1 : 0; }
164
165        bool uncacheable() { return pte.pcd; }
166        void uncacheable(bool u) { pte.pcd = u ? 1 : 0; }
167
168        bool readonly() { return !pte.w; }
169        void readonly(bool r) { pte.w = r ? 0 : 1; }
170
171        void
172        read(PortProxy &p, Addr table, Addr vaddr)
173        {
174            entryAddr = table;
175            entryAddr += bits(vaddr, first, last) * sizeof(PageTableEntry);
176            pte = p.read<PageTableEntry>(entryAddr);
177        }
178
179        void
180        reset(Addr _paddr, bool _present=true,
181              bool _uncacheable=false, bool _readonly=false)
182        {
183            pte = 0;
184            pte.u = 1;
185            paddr(_paddr);
186            present(_present);
187            uncacheable(_uncacheable);
188            readonly(_readonly);
189        };
190
191        void write(PortProxy &p) { p.write(entryAddr, pte); }
192
193        static int
194        tableSize()
195        {
196            return 1 << ((first - last) + 4 - PageShift);
197        }
198
199      protected:
200        PageTableEntry pte;
201        Addr entryAddr;
202    };
203}
204
205#endif
206