Subversion Repositories HelenOS-historic

Rev

Rev 900 | Rev 902 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 900 Rev 901
Line 29... Line 29...
29
/*
29
/*
30
 * TLB management.
30
 * TLB management.
31
 */
31
 */
32
 
32
 
33
#include <mm/tlb.h>
33
#include <mm/tlb.h>
-
 
34
#include <mm/asid.h>
34
#include <arch/mm/tlb.h>
35
#include <arch/mm/tlb.h>
-
 
36
#include <arch/mm/page.h>
35
#include <arch/barrier.h>
37
#include <arch/barrier.h>
36
#include <arch/interrupt.h>
38
#include <arch/interrupt.h>
37
#include <typedefs.h>
39
#include <typedefs.h>
38
#include <panic.h>
40
#include <panic.h>
-
 
41
#include <print.h>
39
 
42
 
40
/** Invalidate all TLB entries. */
43
/** Invalidate all TLB entries. */
41
void tlb_invalidate_all(void)
44
void tlb_invalidate_all(void)
42
{
45
{
43
    /* TODO */
46
    /* TODO */
Line 82... Line 85...
82
void tc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtc)
85
void tc_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtc)
83
{
86
{
84
    region_register rr;
87
    region_register rr;
85
    bool restore_rr = false;
88
    bool restore_rr = false;
86
 
89
 
87
    if (!(entry.not_present.p))
90
    if (!(entry.p))
88
        return;
91
        return;
89
 
92
 
90
    rr.word = rr_read(VA_REGION(va));
93
    rr.word = rr_read(VA2VRN(va));
91
    if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA_REGION(va))))) {
94
    if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
92
        /*
95
        /*
93
         * The selected region register does not contain required RID.
96
         * The selected region register does not contain required RID.
94
         * Save the old content of the register and replace the RID.
97
         * Save the old content of the register and replace the RID.
95
         */
98
         */
96
        region_register rr0;
99
        region_register rr0;
97
 
100
 
98
        rr0 = rr;
101
        rr0 = rr;
99
        rr0.map.rid = ASID2RID(asid, VA_REGION(va));
102
        rr0.map.rid = ASID2RID(asid, VA2VRN(va));
100
        rr_write(VA_REGION(va), rr0.word);
103
        rr_write(VA2VRN(va), rr0.word);
101
        srlz_d();
104
        srlz_d();
102
        srlz_i();
105
        srlz_i();
103
    }
106
    }
104
   
107
   
105
    __asm__ volatile (
108
    __asm__ volatile (
Line 118... Line 121...
118
        : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc)
121
        : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc)
119
        : "p6", "p7", "r8"
122
        : "p6", "p7", "r8"
120
    );
123
    );
121
   
124
   
122
    if (restore_rr) {
125
    if (restore_rr) {
123
        rr_write(VA_REGION(va),rr.word);
126
        rr_write(VA2VRN(va), rr.word);
124
        srlz_d();
127
        srlz_d();
125
        srlz_i();
128
        srlz_i();
126
    }
129
    }
127
}
130
}
128
 
131
 
Line 161... Line 164...
161
void tr_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr)
164
void tr_mapping_insert(__address va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr)
162
{
165
{
163
    region_register rr;
166
    region_register rr;
164
    bool restore_rr = false;
167
    bool restore_rr = false;
165
 
168
 
166
    if (!(entry.not_present.p))
169
    if (!(entry.p))
167
        return;
170
        return;
168
 
171
 
169
    rr.word = rr_read(VA_REGION(va));
172
    rr.word = rr_read(VA2VRN(va));
170
    if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA_REGION(va))))) {
173
    if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
171
        /*
174
        /*
172
         * The selected region register does not contain required RID.
175
         * The selected region register does not contain required RID.
173
         * Save the old content of the register and replace the RID.
176
         * Save the old content of the register and replace the RID.
174
         */
177
         */
175
        region_register rr0;
178
        region_register rr0;
176
 
179
 
177
        rr0 = rr;
180
        rr0 = rr;
178
        rr0.map.rid = ASID2RID(asid, VA_REGION(va));
181
        rr0.map.rid = ASID2RID(asid, VA2VRN(va));
179
        rr_write(VA_REGION(va), rr0.word);
182
        rr_write(VA2VRN(va), rr0.word);
180
        srlz_d();
183
        srlz_d();
181
        srlz_i();
184
        srlz_i();
182
    }
185
    }
183
 
186
 
184
    __asm__ volatile (
187
    __asm__ volatile (
Line 197... Line 200...
197
        : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr)
200
        : "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr)
198
        : "p6", "p7", "r8"
201
        : "p6", "p7", "r8"
199
    );
202
    );
200
   
203
   
201
    if (restore_rr) {
204
    if (restore_rr) {
202
        rr_write(VA_REGION(va),rr.word);
205
        rr_write(VA2VRN(va), rr.word);
203
        srlz_d();
206
        srlz_d();
204
        srlz_i();
207
        srlz_i();
205
    }
208
    }
206
}
209
}
207
 
210
 
-
 
211
/** Insert data into DTLB.
-
 
212
 *
-
 
213
 * @param va Virtual page address.
-
 
214
 * @param asid Address space identifier.
-
 
215
 * @param entry The rest of TLB entry as required by TLB insertion format.
-
 
216
 * @param dtr If true, insert into data translation register, use data translation cache otherwise.
-
 
217
 * @param tr Translation register if dtr is true, ignored otherwise.
-
 
218
 */
-
 
219
void dtlb_mapping_insert(__address page, __address frame, bool dtr, index_t tr)
-
 
220
{
-
 
221
    tlb_entry_t entry;
-
 
222
   
-
 
223
    entry.word[0] = 0;
-
 
224
    entry.word[1] = 0;
-
 
225
   
-
 
226
    entry.p = true;         /* present */
-
 
227
    entry.ma = MA_WRITEBACK;
-
 
228
    entry.a = true;         /* already accessed */
-
 
229
    entry.d = true;         /* already dirty */
-
 
230
    entry.pl = PL_KERNEL;
-
 
231
    entry.ar = AR_READ | AR_WRITE;
-
 
232
    entry.ppn = frame >> PPN_SHIFT;
-
 
233
    entry.ps = PAGE_WIDTH;
-
 
234
   
-
 
235
    if (dtr)
-
 
236
        dtr_mapping_insert(page, ASID_KERNEL, entry, tr);
-
 
237
    else
-
 
238
        dtc_mapping_insert(page, ASID_KERNEL, entry);
-
 
239
}
-
 
240
 
208
void alternate_instruction_tlb_fault(__u64 vector, struct exception_regdump *pstate)
241
void alternate_instruction_tlb_fault(__u64 vector, struct exception_regdump *pstate)
209
{
242
{
210
    panic("%s\n", __FUNCTION__);
243
    panic("%s\n", __FUNCTION__);
211
}
244
}
212
 
245
 
-
 
246
/** Data TLB fault with VHPT turned off.
-
 
247
 *
-
 
248
 * @param vector Interruption vector.
-
 
249
 * @param pstate Structure with saved interruption state.
-
 
250
 */
213
void alternate_data_tlb_fault(__u64 vector, struct exception_regdump *pstate)
251
void alternate_data_tlb_fault(__u64 vector, struct exception_regdump *pstate)
214
{
252
{
-
 
253
    region_register rr;
-
 
254
    rid_t rid;
-
 
255
    __address va;
-
 
256
   
-
 
257
    va = pstate->cr_ifa;    /* faulting address */
-
 
258
    rr.word = rr_read(VA2VRN(va));
-
 
259
    rid = rr.map.rid;
-
 
260
    if (RID2ASID(rid) == ASID_KERNEL) {
-
 
261
        if (VA2VRN(va) == VRN_KERNEL) {
-
 
262
            /*
-
 
263
             * Provide KA2PA(identity) mapping for faulting piece of
-
 
264
             * kernel address space.
-
 
265
             */
-
 
266
            dtlb_mapping_insert(va, KA2PA(va), false, 0);
-
 
267
            return;
-
 
268
        }
-
 
269
    }
215
    panic("%s: %P\n", __FUNCTION__, pstate->cr_ifa);
270
    panic("%s: va=%P, rid=%d\n", __FUNCTION__, pstate->cr_ifa, rr.map.rid);
216
}
271
}
217
 
272
 
218
void data_nested_tlb_fault(__u64 vector, struct exception_regdump *pstate)
273
void data_nested_tlb_fault(__u64 vector, struct exception_regdump *pstate)
219
{
274
{
220
    panic("%s\n", __FUNCTION__);
275
    panic("%s\n", __FUNCTION__);