Subversion Repositories HelenOS

Rev

Rev 397 | Rev 403 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 397 Rev 399
1
/*
1
/*
2
 * Copyright (C) 2003-2004 Jakub Jermar
2
 * Copyright (C) 2003-2004 Jakub Jermar
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
#include <arch/mm/tlb.h>
29
#include <arch/mm/tlb.h>
30
#include <arch/mm/asid.h>
30
#include <arch/mm/asid.h>
31
#include <mm/tlb.h>
31
#include <mm/tlb.h>
32
#include <mm/page.h>
32
#include <mm/page.h>
33
#include <mm/vm.h>
33
#include <mm/vm.h>
34
#include <arch/cp0.h>
34
#include <arch/cp0.h>
35
#include <panic.h>
35
#include <panic.h>
36
#include <arch.h>
36
#include <arch.h>
37
#include <symtab.h>
37
#include <symtab.h>
38
#include <synch/spinlock.h>
38
#include <synch/spinlock.h>
39
#include <print.h>
39
#include <print.h>
40
#include <debug.h>
40
#include <debug.h>
41
 
41
 
42
static void tlb_refill_fail(struct exception_regdump *pstate);
42
static void tlb_refill_fail(struct exception_regdump *pstate);
43
static void tlb_invalid_fail(struct exception_regdump *pstate);
43
static void tlb_invalid_fail(struct exception_regdump *pstate);
44
static void tlb_modified_fail(struct exception_regdump *pstate);
44
static void tlb_modified_fail(struct exception_regdump *pstate);
45
 
45
 
46
static pte_t *find_mapping_and_check(__address badvaddr);
46
static pte_t *find_mapping_and_check(__address badvaddr);
-
 
47
 
47
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, int c, __address pfn);
48
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, int c, __address pfn);
-
 
49
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr);
48
 
50
 
49
/** Initialize TLB
51
/** Initialize TLB
50
 *
52
 *
51
 * Initialize TLB.
53
 * Initialize TLB.
52
 * Invalidate all entries and mark wired entries.
54
 * Invalidate all entries and mark wired entries.
53
 */
55
 */
54
void tlb_init_arch(void)
56
void tlb_init_arch(void)
55
{
57
{
56
    int i;
58
    int i;
57
 
59
 
58
    cp0_pagemask_write(TLB_PAGE_MASK_16K);
60
    cp0_pagemask_write(TLB_PAGE_MASK_16K);
59
    cp0_entry_hi_write(0);
61
    cp0_entry_hi_write(0);
60
    cp0_entry_lo0_write(0);
62
    cp0_entry_lo0_write(0);
61
    cp0_entry_lo1_write(0);
63
    cp0_entry_lo1_write(0);
62
 
64
 
63
    /*
65
    /*
64
     * Invalidate all entries.
66
     * Invalidate all entries.
65
     */
67
     */
66
    for (i = 0; i < TLB_SIZE; i++) {
68
    for (i = 0; i < TLB_SIZE; i++) {
67
        cp0_index_write(i);
69
        cp0_index_write(i);
68
        tlbwi();
70
        tlbwi();
69
    }
71
    }
70
   
72
   
71
    /*
73
    /*
72
     * The kernel is going to make use of some wired
74
     * The kernel is going to make use of some wired
73
     * entries (e.g. mapping kernel stacks in kseg3).
75
     * entries (e.g. mapping kernel stacks in kseg3).
74
     */
76
     */
75
    cp0_wired_write(TLB_WIRED);
77
    cp0_wired_write(TLB_WIRED);
76
}
78
}
77
 
79
 
78
/** Process TLB Refill Exception
80
/** Process TLB Refill Exception
79
 *
81
 *
80
 * Process TLB Refill Exception.
82
 * Process TLB Refill Exception.
81
 *
83
 *
82
 * @param pstate Interrupted register context.
84
 * @param pstate Interrupted register context.
83
 */
85
 */
84
void tlb_refill(struct exception_regdump *pstate)
86
void tlb_refill(struct exception_regdump *pstate)
85
{
87
{
86
    entry_lo_t lo;
88
    entry_lo_t lo;
-
 
89
    entry_hi_t hi; 
87
    __address badvaddr;
90
    __address badvaddr;
88
    pte_t *pte;
91
    pte_t *pte;
89
 
92
 
90
// debug    
-
 
91
    entry_hi_t hi;
-
 
92
 
-
 
93
    badvaddr = cp0_badvaddr_read();
93
    badvaddr = cp0_badvaddr_read();
94
 
94
 
95
// debug
-
 
96
    hi.value = cp0_entry_hi_read();
-
 
97
    printf("TLB Refill: hi.vnp2=%X\n", hi.vpn2);
-
 
98
   
-
 
99
    spinlock_lock(&VM->lock);      
95
    spinlock_lock(&VM->lock);      
-
 
96
 
100
    pte = find_mapping_and_check(badvaddr);
97
    pte = find_mapping_and_check(badvaddr);
101
    if (!pte)
98
    if (!pte)
102
        goto fail;
99
        goto fail;
103
 
100
 
104
    /*
101
    /*
105
     * Record access to PTE.
102
     * Record access to PTE.
106
     */
103
     */
107
    pte->a = 1;
104
    pte->a = 1;
108
 
105
 
-
 
106
    prepare_entry_hi(&hi, VM->asid, badvaddr);
109
    prepare_entry_lo(&lo, pte->g, pte->v, pte->d, pte->c, pte->pfn);
107
    prepare_entry_lo(&lo, pte->g, pte->v, pte->d, pte->c, pte->pfn);
110
 
108
 
111
    /*
109
    /*
112
     * New entry is to be inserted into TLB
110
     * New entry is to be inserted into TLB
113
     */
111
     */
-
 
112
    cp0_entry_hi_write(hi.value);
114
    if ((badvaddr/PAGE_SIZE) % 2 == 0) {
113
    if ((badvaddr/PAGE_SIZE) % 2 == 0) {
115
        cp0_entry_lo0_write(lo.value);
114
        cp0_entry_lo0_write(lo.value);
116
        cp0_entry_lo1_write(0);
115
        cp0_entry_lo1_write(0);
117
    }
116
    }
118
    else {
117
    else {
119
        cp0_entry_lo0_write(0);
118
        cp0_entry_lo0_write(0);
120
        cp0_entry_lo1_write(lo.value);
119
        cp0_entry_lo1_write(lo.value);
121
    }
120
    }
122
    tlbwr();
121
    tlbwr();
123
 
122
 
124
    spinlock_unlock(&VM->lock);
123
    spinlock_unlock(&VM->lock);
125
    return;
124
    return;
126
   
125
   
127
fail:
126
fail:
128
    spinlock_unlock(&VM->lock);
127
    spinlock_unlock(&VM->lock);
129
    tlb_refill_fail(pstate);
128
    tlb_refill_fail(pstate);
130
}
129
}
131
 
130
 
132
/** Process TLB Invalid Exception
131
/** Process TLB Invalid Exception
133
 *
132
 *
134
 * Process TLB Invalid Exception.
133
 * Process TLB Invalid Exception.
135
 *
134
 *
136
 * @param pstate Interrupted register context.
135
 * @param pstate Interrupted register context.
137
 */
136
 */
138
void tlb_invalid(struct exception_regdump *pstate)
137
void tlb_invalid(struct exception_regdump *pstate)
139
{
138
{
140
    tlb_index_t index;
139
    tlb_index_t index;
141
    __address badvaddr;
140
    __address badvaddr;
142
    entry_lo_t lo;
141
    entry_lo_t lo;
-
 
142
    entry_hi_t hi;
143
    pte_t *pte;
143
    pte_t *pte;
144
 
144
 
145
    badvaddr = cp0_badvaddr_read();
145
    badvaddr = cp0_badvaddr_read();
146
 
146
 
147
    /*
147
    /*
148
     * Locate the faulting entry in TLB.
148
     * Locate the faulting entry in TLB.
149
     */
149
     */
-
 
150
    hi.value = cp0_entry_hi_read();
-
 
151
    prepare_entry_hi(&hi, hi.asid, badvaddr);
-
 
152
    cp0_entry_hi_write(hi.value);
150
    tlbp();
153
    tlbp();
151
    index.value = cp0_index_read();
154
    index.value = cp0_index_read();
152
   
155
   
153
    spinlock_lock(&VM->lock);  
156
    spinlock_lock(&VM->lock);  
154
   
157
   
155
    /*
158
    /*
156
     * Fail if the entry is not in TLB.
159
     * Fail if the entry is not in TLB.
157
     */
160
     */
158
    if (index.p) {
161
    if (index.p) {
159
        printf("TLB entry not found.\n");
162
        printf("TLB entry not found.\n");
160
        goto fail;
163
        goto fail;
161
    }
164
    }
162
 
165
 
163
    pte = find_mapping_and_check(badvaddr);
166
    pte = find_mapping_and_check(badvaddr);
164
    if (!pte)
167
    if (!pte)
165
        goto fail;
168
        goto fail;
166
 
169
 
167
    /*
170
    /*
168
     * Read the faulting TLB entry.
171
     * Read the faulting TLB entry.
169
     */
172
     */
170
    tlbr();
173
    tlbr();
171
 
174
 
172
    /*
175
    /*
173
     * Record access to PTE.
176
     * Record access to PTE.
174
     */
177
     */
175
    pte->a = 1;
178
    pte->a = 1;
176
 
179
 
177
    prepare_entry_lo(&lo, pte->g, pte->v, pte->d, pte->c, pte->pfn);
180
    prepare_entry_lo(&lo, pte->g, pte->v, pte->d, pte->c, pte->pfn);
178
 
181
 
179
    /*
182
    /*
180
     * The entry is to be updated in TLB.
183
     * The entry is to be updated in TLB.
181
     */
184
     */
182
    if ((badvaddr/PAGE_SIZE) % 2 == 0)
185
    if ((badvaddr/PAGE_SIZE) % 2 == 0)
183
        cp0_entry_lo0_write(lo.value);
186
        cp0_entry_lo0_write(lo.value);
184
    else
187
    else
185
        cp0_entry_lo1_write(lo.value);
188
        cp0_entry_lo1_write(lo.value);
186
    tlbwi();
189
    tlbwi();
187
 
190
 
188
    spinlock_unlock(&VM->lock);
191
    spinlock_unlock(&VM->lock);
189
    return;
192
    return;
190
   
193
   
191
fail:
194
fail:
192
    spinlock_unlock(&VM->lock);
195
    spinlock_unlock(&VM->lock);
193
    tlb_invalid_fail(pstate);
196
    tlb_invalid_fail(pstate);
194
}
197
}
195
 
198
 
196
/** Process TLB Modified Exception
199
/** Process TLB Modified Exception
197
 *
200
 *
198
 * Process TLB Modified Exception.
201
 * Process TLB Modified Exception.
199
 *
202
 *
200
 * @param pstate Interrupted register context.
203
 * @param pstate Interrupted register context.
201
 */
204
 */
202
void tlb_modified(struct exception_regdump *pstate)
205
void tlb_modified(struct exception_regdump *pstate)
203
{
206
{
204
    tlb_index_t index;
207
    tlb_index_t index;
205
    __address badvaddr;
208
    __address badvaddr;
206
    entry_lo_t lo;
209
    entry_lo_t lo;
-
 
210
    entry_hi_t hi;
207
    pte_t *pte;
211
    pte_t *pte;
208
 
212
 
209
    badvaddr = cp0_badvaddr_read();
213
    badvaddr = cp0_badvaddr_read();
210
 
214
 
211
    /*
215
    /*
212
     * Locate the faulting entry in TLB.
216
     * Locate the faulting entry in TLB.
213
     */
217
     */
-
 
218
    hi.value = cp0_entry_hi_read();
-
 
219
    prepare_entry_hi(&hi, hi.asid, badvaddr);
-
 
220
    cp0_entry_hi_write(hi.value);
214
    tlbp();
221
    tlbp();
215
    index.value = cp0_index_read();
222
    index.value = cp0_index_read();
216
   
223
   
217
    spinlock_lock(&VM->lock);  
224
    spinlock_lock(&VM->lock);  
218
   
225
   
219
    /*
226
    /*
220
     * Fail if the entry is not in TLB.
227
     * Fail if the entry is not in TLB.
221
     */
228
     */
222
    if (index.p) {
229
    if (index.p) {
223
        printf("TLB entry not found.\n");
230
        printf("TLB entry not found.\n");
224
        goto fail;
231
        goto fail;
225
    }
232
    }
226
 
233
 
227
    pte = find_mapping_and_check(badvaddr);
234
    pte = find_mapping_and_check(badvaddr);
228
    if (!pte)
235
    if (!pte)
229
        goto fail;
236
        goto fail;
230
 
237
 
231
    /*
238
    /*
232
     * Fail if the page is not writable.
239
     * Fail if the page is not writable.
233
     */
240
     */
234
    if (!pte->w)
241
    if (!pte->w)
235
        goto fail;
242
        goto fail;
236
 
243
 
237
    /*
244
    /*
238
     * Read the faulting TLB entry.
245
     * Read the faulting TLB entry.
239
     */
246
     */
240
    tlbr();
247
    tlbr();
241
 
248
 
242
    /*
249
    /*
243
     * Record access and write to PTE.
250
     * Record access and write to PTE.
244
     */
251
     */
245
    pte->a = 1;
252
    pte->a = 1;
246
    pte->d = 1;
253
    pte->d = 1;
247
 
254
 
248
    prepare_entry_lo(&lo, pte->g, pte->v, pte->w, pte->c, pte->pfn);
255
    prepare_entry_lo(&lo, pte->g, pte->v, pte->w, pte->c, pte->pfn);
249
 
256
 
250
    /*
257
    /*
251
     * The entry is to be updated in TLB.
258
     * The entry is to be updated in TLB.
252
     */
259
     */
253
    if ((badvaddr/PAGE_SIZE) % 2 == 0)
260
    if ((badvaddr/PAGE_SIZE) % 2 == 0)
254
        cp0_entry_lo0_write(lo.value);
261
        cp0_entry_lo0_write(lo.value);
255
    else
262
    else
256
        cp0_entry_lo1_write(lo.value);
263
        cp0_entry_lo1_write(lo.value);
257
    tlbwi();
264
    tlbwi();
258
 
265
 
259
    spinlock_unlock(&VM->lock);
266
    spinlock_unlock(&VM->lock);
260
    return;
267
    return;
261
   
268
   
262
fail:
269
fail:
263
    spinlock_unlock(&VM->lock);
270
    spinlock_unlock(&VM->lock);
264
    tlb_modified_fail(pstate);
271
    tlb_modified_fail(pstate);
265
}
272
}
266
 
273
 
267
void tlb_refill_fail(struct exception_regdump *pstate)
274
void tlb_refill_fail(struct exception_regdump *pstate)
268
{
275
{
269
    char *symbol = "";
276
    char *symbol = "";
270
    char *sym2 = "";
277
    char *sym2 = "";
271
 
278
 
272
    char *s = get_symtab_entry(pstate->epc);
279
    char *s = get_symtab_entry(pstate->epc);
273
    if (s)
280
    if (s)
274
        symbol = s;
281
        symbol = s;
275
    s = get_symtab_entry(pstate->ra);
282
    s = get_symtab_entry(pstate->ra);
276
    if (s)
283
    if (s)
277
        sym2 = s;
284
        sym2 = s;
278
    panic("%X: TLB Refill Exception at %X(%s<-%s)\n", cp0_badvaddr_read(), pstate->epc, symbol, sym2);
285
    panic("%X: TLB Refill Exception at %X(%s<-%s)\n", cp0_badvaddr_read(), pstate->epc, symbol, sym2);
279
}
286
}
280
 
287
 
281
 
288
 
282
void tlb_invalid_fail(struct exception_regdump *pstate)
289
void tlb_invalid_fail(struct exception_regdump *pstate)
283
{
290
{
284
    char *symbol = "";
291
    char *symbol = "";
285
 
292
 
286
    char *s = get_symtab_entry(pstate->epc);
293
    char *s = get_symtab_entry(pstate->epc);
287
    if (s)
294
    if (s)
288
        symbol = s;
295
        symbol = s;
289
    panic("%X: TLB Invalid Exception at %X(%s)\n", cp0_badvaddr_read(), pstate->epc, symbol);
296
    panic("%X: TLB Invalid Exception at %X(%s)\n", cp0_badvaddr_read(), pstate->epc, symbol);
290
}
297
}
291
 
298
 
292
void tlb_modified_fail(struct exception_regdump *pstate)
299
void tlb_modified_fail(struct exception_regdump *pstate)
293
{
300
{
294
    char *symbol = "";
301
    char *symbol = "";
295
 
302
 
296
    char *s = get_symtab_entry(pstate->epc);
303
    char *s = get_symtab_entry(pstate->epc);
297
    if (s)
304
    if (s)
298
        symbol = s;
305
        symbol = s;
299
    panic("%X: TLB Modified Exception at %X(%s)\n", cp0_badvaddr_read(), pstate->epc, symbol);
306
    panic("%X: TLB Modified Exception at %X(%s)\n", cp0_badvaddr_read(), pstate->epc, symbol);
300
}
307
}
301
 
308
 
302
/** Invalidate TLB entries with specified ASID
309
/** Invalidate TLB entries with specified ASID
303
 *
310
 *
304
 * Invalidate TLB entries with specified ASID.
311
 * Invalidate TLB entries with specified ASID.
305
 *
312
 *
306
 * @param asid ASID.
313
 * @param asid ASID.
307
 */
314
 */
308
void tlb_invalidate(asid_t asid)
315
void tlb_invalidate(asid_t asid)
309
{
316
{
310
    entry_hi_t hi;
317
    entry_hi_t hi;
311
    pri_t pri;
318
    pri_t pri;
312
    int i; 
319
    int i; 
313
   
320
   
314
    ASSERT(asid != ASID_INVALID);
321
    ASSERT(asid != ASID_INVALID);
315
 
322
 
316
    pri = cpu_priority_high();
323
    pri = cpu_priority_high();
317
   
324
   
318
    for (i = 0; i < TLB_SIZE; i++) {
325
    for (i = 0; i < TLB_SIZE; i++) {
319
        cp0_index_write(i);
326
        cp0_index_write(i);
320
        tlbr();
327
        tlbr();
321
       
328
       
322
        hi.value = cp0_entry_hi_read();
329
        hi.value = cp0_entry_hi_read();
323
        if (hi.asid == asid) {
330
        if (hi.asid == asid) {
324
            cp0_pagemask_write(TLB_PAGE_MASK_16K);
331
            cp0_pagemask_write(TLB_PAGE_MASK_16K);
325
            cp0_entry_hi_write(0);
332
            cp0_entry_hi_write(0);
326
            cp0_entry_lo0_write(0);
333
            cp0_entry_lo0_write(0);
327
            cp0_entry_lo1_write(0);
334
            cp0_entry_lo1_write(0);
328
            tlbwi();
335
            tlbwi();
329
        }
336
        }
330
    }
337
    }
331
   
338
   
332
    cpu_priority_restore(pri);
339
    cpu_priority_restore(pri);
333
}
340
}
334
 
341
 
335
/** Try to find PTE for faulting address
342
/** Try to find PTE for faulting address
336
 *
343
 *
337
 * Try to find PTE for faulting address.
344
 * Try to find PTE for faulting address.
338
 * The VM->lock must be held on entry to this function.
345
 * The VM->lock must be held on entry to this function.
339
 *
346
 *
340
 * @param badvaddr Faulting virtual address.
347
 * @param badvaddr Faulting virtual address.
341
 *
348
 *
342
 * @return PTE on success, NULL otherwise.
349
 * @return PTE on success, NULL otherwise.
343
 */
350
 */
344
pte_t *find_mapping_and_check(__address badvaddr)
351
pte_t *find_mapping_and_check(__address badvaddr)
345
{
352
{
346
    entry_hi_t hi;
353
    entry_hi_t hi;
347
    pte_t *pte;
354
    pte_t *pte;
348
 
355
 
349
    hi.value = cp0_entry_hi_read();
356
    hi.value = cp0_entry_hi_read();
350
 
357
 
351
    /*
358
    /*
352
     * Handler cannot succeed if the ASIDs don't match.
359
     * Handler cannot succeed if the ASIDs don't match.
353
     */
360
     */
354
    if (hi.asid != VM->asid) {
361
    if (hi.asid != VM->asid) {
355
        printf("EntryHi.asid=%d, VM->asid=%d\n", hi.asid, VM->asid);
362
        printf("EntryHi.asid=%d, VM->asid=%d\n", hi.asid, VM->asid);
356
        return NULL;
363
        return NULL;
357
    }
364
    }
358
   
365
   
359
    /*
366
    /*
360
     * Handler cannot succeed if badvaddr has no mapping.
367
     * Handler cannot succeed if badvaddr has no mapping.
361
     */
368
     */
362
    pte = find_mapping(badvaddr, 0);
369
    pte = find_mapping(badvaddr, 0);
363
    if (!pte) {
370
    if (!pte) {
364
        printf("No such mapping.\n");
371
        printf("No such mapping.\n");
365
        return NULL;
372
        return NULL;
366
    }
373
    }
367
 
374
 
368
    /*
375
    /*
369
     * Handler cannot succeed if the mapping is marked as invalid.
376
     * Handler cannot succeed if the mapping is marked as invalid.
370
     */
377
     */
371
    if (!pte->v) {
378
    if (!pte->v) {
372
        printf("Invalid mapping.\n");
379
        printf("Invalid mapping.\n");
373
        return NULL;
380
        return NULL;
374
    }
381
    }
375
 
382
 
376
    return pte;
383
    return pte;
377
}
384
}
378
 
385
 
379
void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, int c, __address pfn)
386
void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, int c, __address pfn)
380
{
387
{
-
 
388
    lo->value = 0;
381
    lo->g = g;
389
    lo->g = g;
382
    lo->v = v;
390
    lo->v = v;
383
    lo->d = d;
391
    lo->d = d;
384
    lo->c = c;
392
    lo->c = c;
385
    lo->pfn = pfn;
393
    lo->pfn = pfn;
-
 
394
}
-
 
395
 
-
 
396
void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr)
-
 
397
{
-
 
398
    hi->value = (((addr/PAGE_SIZE)/2)*PAGE_SIZE*2);
386
    lo->zero = 0;
399
    hi->asid = asid;
387
}
400
}
388
 
401