translation.hh revision 7678
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * Copyright (c) 2009 The University of Edinburgh
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: Gabe Black
30 *          Timothy M. Jones
31 */
32
33#ifndef __CPU_TRANSLATION_HH__
34#define __CPU_TRANSLATION_HH__
35
36#include "sim/faults.hh"
37#include "sim/tlb.hh"
38
39/**
40 * This class captures the state of an address translation.  A translation
41 * can be split in two if the ISA supports it and the memory access crosses
42 * a page boundary.  In this case, this class is shared by two data
43 * translations (below).  Otherwise it is used by a single data translation
44 * class.  When each part of the translation is finished, the finish
45 * function is called which will indicate whether the whole translation is
46 * completed or not.  There are also functions for accessing parts of the
47 * translation state which deal with the possible split correctly.
48 */
49class WholeTranslationState
50{
51  protected:
52    int outstanding;
53    Fault faults[2];
54
55  public:
56    bool isSplit;
57    RequestPtr mainReq;
58    RequestPtr sreqLow;
59    RequestPtr sreqHigh;
60    uint8_t *data;
61    uint64_t *res;
62    BaseTLB::Mode mode;
63
64    /**
65     * Single translation state.  We set the number of outstanding
66     * translations to one and indicate that it is not split.
67     */
68    WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res,
69                          BaseTLB::Mode _mode)
70        : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL),
71          sreqHigh(NULL), data(_data), res(_res), mode(_mode)
72    {
73        faults[0] = faults[1] = NoFault;
74        assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
75    }
76
77    /**
78     * Split translation state.  We copy all state into this class, set the
79     * number of outstanding translations to two and then mark this as a
80     * split translation.
81     */
82    WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow,
83                          RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res,
84                          BaseTLB::Mode _mode)
85        : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow),
86          sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode)
87    {
88        faults[0] = faults[1] = NoFault;
89        assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
90    }
91
92    /**
93     * Finish part of a translation.  If there is only one request then this
94     * translation is completed.  If the request has been split in two then
95     * the outstanding count determines whether the translation is complete.
96     * In this case, flags from the split request are copied to the main
97     * request to make it easier to access them later on.
98     */
99    bool
100    finish(Fault fault, int index)
101    {
102        assert(outstanding);
103        faults[index] = fault;
104        outstanding--;
105        if (isSplit && outstanding == 0) {
106
107            // For ease later, we copy some state to the main request.
108            if (faults[0] == NoFault) {
109                mainReq->setPaddr(sreqLow->getPaddr());
110            }
111            mainReq->setFlags(sreqLow->getFlags());
112            mainReq->setFlags(sreqHigh->getFlags());
113        }
114        return outstanding == 0;
115    }
116
117    /**
118     * Determine whether this translation produced a fault.  Both parts of the
119     * translation must be checked if this is a split translation.
120     */
121    Fault
122    getFault() const
123    {
124        if (!isSplit)
125            return faults[0];
126        else if (faults[0] != NoFault)
127            return faults[0];
128        else if (faults[1] != NoFault)
129            return faults[1];
130        else
131            return NoFault;
132    }
133
134    /** Remove all faults from the translation. */
135    void
136    setNoFault()
137    {
138        faults[0] = faults[1] = NoFault;
139    }
140
141    /**
142     * Check if this request is uncacheable.  We only need to check the main
143     * request because the flags will have been copied here on a split
144     * translation.
145     */
146    bool
147    isUncacheable() const
148    {
149        return mainReq->isUncacheable();
150    }
151
152    /**
153     * Check if this request is a prefetch.  We only need to check the main
154     * request because the flags will have been copied here on a split
155     * translation.
156     */
157    bool
158    isPrefetch() const
159    {
160        return mainReq->isPrefetch();
161    }
162
163    /** Get the physical address of this request. */
164    Addr
165    getPaddr() const
166    {
167        return mainReq->getPaddr();
168    }
169
170    /**
171     * Get the flags associated with this request.  We only need to access
172     * the main request because the flags will have been copied here on a
173     * split translation.
174     */
175    unsigned
176    getFlags()
177    {
178        return mainReq->getFlags();
179    }
180
181    /** Delete all requests that make up this translation. */
182    void
183    deleteReqs()
184    {
185        delete mainReq;
186        if (isSplit) {
187            delete sreqLow;
188            delete sreqHigh;
189        }
190    }
191};
192
193
194/**
195 * This class represents part of a data address translation.  All state for
196 * the translation is held in WholeTranslationState (above).  Therefore this
197 * class does not need to know whether the translation is split or not.  The
198 * index variable determines this but is simply passed on to the state class.
199 * When this part of the translation is completed, finish is called.  If the
200 * translation state class indicate that the whole translation is complete
201 * then the execution context is informed.
202 */
203template <class ExecContext>
204class DataTranslation : public BaseTLB::Translation
205{
206  protected:
207    ExecContext *xc;
208    WholeTranslationState *state;
209    int index;
210
211  public:
212    DataTranslation(ExecContext *_xc, WholeTranslationState* _state)
213        : xc(_xc), state(_state), index(0)
214    {
215    }
216
217    DataTranslation(ExecContext *_xc, WholeTranslationState* _state,
218                    int _index)
219        : xc(_xc), state(_state), index(_index)
220    {
221    }
222
223    /**
224     * Finish this part of the translation and indicate that the whole
225     * translation is complete if the state says so.
226     */
227    void
228    finish(Fault fault, RequestPtr req, ThreadContext *tc,
229           BaseTLB::Mode mode)
230    {
231        assert(state);
232        assert(mode == state->mode);
233        if (state->finish(fault, index)) {
234            xc->finishTranslation(state);
235        }
236        delete this;
237    }
238};
239
240#endif // __CPU_TRANSLATION_HH__
241