translation.hh revision 7049:a06e95c99294
13938Ssaidi@eecs.umich.edu/*
23938Ssaidi@eecs.umich.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan
33938Ssaidi@eecs.umich.edu * Copyright (c) 2009 The University of Edinburgh
43938Ssaidi@eecs.umich.edu * All rights reserved.
53938Ssaidi@eecs.umich.edu *
63938Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
73938Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
83938Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
93938Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
103938Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
113938Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
123938Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution;
133938Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
143938Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
153938Ssaidi@eecs.umich.edu * this software without specific prior written permission.
163938Ssaidi@eecs.umich.edu *
173938Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
183938Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
193938Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
203938Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
213938Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
223938Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
233938Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
243938Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
253938Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
263938Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
273938Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
283938Ssaidi@eecs.umich.edu *
293938Ssaidi@eecs.umich.edu * Authors: Gabe Black
303938Ssaidi@eecs.umich.edu *          Timothy M. Jones
313938Ssaidi@eecs.umich.edu */
323938Ssaidi@eecs.umich.edu
333938Ssaidi@eecs.umich.edu#ifndef __CPU_TRANSLATION_HH__
343938Ssaidi@eecs.umich.edu#define __CPU_TRANSLATION_HH__
353938Ssaidi@eecs.umich.edu
363938Ssaidi@eecs.umich.edu#include "sim/tlb.hh"
373938Ssaidi@eecs.umich.edu
383938Ssaidi@eecs.umich.edu/**
393938Ssaidi@eecs.umich.edu * This class captures the state of an address translation.  A translation
403938Ssaidi@eecs.umich.edu * can be split in two if the ISA supports it and the memory access crosses
413938Ssaidi@eecs.umich.edu * a page boundary.  In this case, this class is shared by two data
423938Ssaidi@eecs.umich.edu * translations (below).  Otherwise it is used by a single data translation
433938Ssaidi@eecs.umich.edu * class.  When each part of the translation is finished, the finish
443938Ssaidi@eecs.umich.edu * function is called which will indicate whether the whole translation is
453938Ssaidi@eecs.umich.edu * completed or not.  There are also functions for accessing parts of the
463938Ssaidi@eecs.umich.edu * translation state which deal with the possible split correctly.
473938Ssaidi@eecs.umich.edu */
483938Ssaidi@eecs.umich.educlass WholeTranslationState
493938Ssaidi@eecs.umich.edu{
503938Ssaidi@eecs.umich.edu  protected:
513938Ssaidi@eecs.umich.edu    int outstanding;
523938Ssaidi@eecs.umich.edu    Fault faults[2];
53
54  public:
55    bool isSplit;
56    RequestPtr mainReq;
57    RequestPtr sreqLow;
58    RequestPtr sreqHigh;
59    uint8_t *data;
60    uint64_t *res;
61    BaseTLB::Mode mode;
62
63    /**
64     * Single translation state.  We set the number of outstanding
65     * translations to one and indicate that it is not split.
66     */
67    WholeTranslationState(RequestPtr _req, uint8_t *_data, uint64_t *_res,
68                          BaseTLB::Mode _mode)
69        : outstanding(1), isSplit(false), mainReq(_req), sreqLow(NULL),
70          sreqHigh(NULL), data(_data), res(_res), mode(_mode)
71    {
72        faults[0] = faults[1] = NoFault;
73        assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
74    }
75
76    /**
77     * Split translation state.  We copy all state into this class, set the
78     * number of outstanding translations to two and then mark this as a
79     * split translation.
80     */
81    WholeTranslationState(RequestPtr _req, RequestPtr _sreqLow,
82                          RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res,
83                          BaseTLB::Mode _mode)
84        : outstanding(2), isSplit(true), mainReq(_req), sreqLow(_sreqLow),
85          sreqHigh(_sreqHigh), data(_data), res(_res), mode(_mode)
86    {
87        faults[0] = faults[1] = NoFault;
88        assert(mode == BaseTLB::Read || mode == BaseTLB::Write);
89    }
90
91    /**
92     * Finish part of a translation.  If there is only one request then this
93     * translation is completed.  If the request has been split in two then
94     * the outstanding count determines whether the translation is complete.
95     * In this case, flags from the split request are copied to the main
96     * request to make it easier to access them later on.
97     */
98    bool
99    finish(Fault fault, int index)
100    {
101        assert(outstanding);
102        faults[index] = fault;
103        outstanding--;
104        if (isSplit && outstanding == 0) {
105
106            // For ease later, we copy some state to the main request.
107            if (faults[0] == NoFault) {
108                mainReq->setPaddr(sreqLow->getPaddr());
109            }
110            mainReq->setFlags(sreqLow->getFlags());
111            mainReq->setFlags(sreqHigh->getFlags());
112        }
113        return outstanding == 0;
114    }
115
116    /**
117     * Determine whether this translation produced a fault.  Both parts of the
118     * translation must be checked if this is a split translation.
119     */
120    Fault
121    getFault() const
122    {
123        if (!isSplit)
124            return faults[0];
125        else if (faults[0] != NoFault)
126            return faults[0];
127        else if (faults[1] != NoFault)
128            return faults[1];
129        else
130            return NoFault;
131    }
132
133    /** Remove all faults from the translation. */
134    void
135    setNoFault()
136    {
137        faults[0] = faults[1] = NoFault;
138    }
139
140    /**
141     * Check if this request is uncacheable.  We only need to check the main
142     * request because the flags will have been copied here on a split
143     * translation.
144     */
145    bool
146    isUncacheable() const
147    {
148        return mainReq->isUncacheable();
149    }
150
151    /**
152     * Check if this request is a prefetch.  We only need to check the main
153     * request because the flags will have been copied here on a split
154     * translation.
155     */
156    bool
157    isPrefetch() const
158    {
159        return mainReq->isPrefetch();
160    }
161
162    /** Get the physical address of this request. */
163    Addr
164    getPaddr() const
165    {
166        return mainReq->getPaddr();
167    }
168
169    /**
170     * Get the flags associated with this request.  We only need to access
171     * the main request because the flags will have been copied here on a
172     * split translation.
173     */
174    unsigned
175    getFlags()
176    {
177        return mainReq->getFlags();
178    }
179
180    /** Delete all requests that make up this translation. */
181    void
182    deleteReqs()
183    {
184        delete mainReq;
185        if (isSplit) {
186            delete sreqLow;
187            delete sreqHigh;
188        }
189    }
190};
191
192
193/**
194 * This class represents part of a data address translation.  All state for
195 * the translation is held in WholeTranslationState (above).  Therefore this
196 * class does not need to know whether the translation is split or not.  The
197 * index variable determines this but is simply passed on to the state class.
198 * When this part of the translation is completed, finish is called.  If the
199 * translation state class indicate that the whole translation is complete
200 * then the execution context is informed.
201 */
202template <class ExecContext>
203class DataTranslation : public BaseTLB::Translation
204{
205  protected:
206    ExecContext *xc;
207    WholeTranslationState *state;
208    int index;
209
210  public:
211    DataTranslation(ExecContext *_xc, WholeTranslationState* _state)
212        : xc(_xc), state(_state), index(0)
213    {
214    }
215
216    DataTranslation(ExecContext *_xc, WholeTranslationState* _state,
217                    int _index)
218        : xc(_xc), state(_state), index(_index)
219    {
220    }
221
222    /**
223     * Finish this part of the translation and indicate that the whole
224     * translation is complete if the state says so.
225     */
226    void
227    finish(Fault fault, RequestPtr req, ThreadContext *tc,
228           BaseTLB::Mode mode)
229    {
230        assert(state);
231        assert(mode == state->mode);
232        if (state->finish(fault, index)) {
233            xc->finishTranslation(state);
234        }
235        delete this;
236    }
237};
238
239#endif // __CPU_TRANSLATION_HH__
240