Subversion Repositories HelenOS-historic

Rev

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

Rev 687 Rev 703
Line 28... Line 28...
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/as.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>
Line 90... Line 90...
90
    __address badvaddr;
90
    __address badvaddr;
91
    pte_t *pte;
91
    pte_t *pte;
92
 
92
 
93
    badvaddr = cp0_badvaddr_read();
93
    badvaddr = cp0_badvaddr_read();
94
 
94
 
95
    spinlock_lock(&VM->lock);      
95
    spinlock_lock(&AS->lock);      
96
 
96
 
97
    pte = find_mapping_and_check(badvaddr);
97
    pte = find_mapping_and_check(badvaddr);
98
    if (!pte)
98
    if (!pte)
99
        goto fail;
99
        goto fail;
100
 
100
 
101
    /*
101
    /*
102
     * Record access to PTE.
102
     * Record access to PTE.
103
     */
103
     */
104
    pte->a = 1;
104
    pte->a = 1;
105
 
105
 
106
    prepare_entry_hi(&hi, VM->asid, badvaddr);
106
    prepare_entry_hi(&hi, AS->asid, badvaddr);
107
    prepare_entry_lo(&lo, pte->lo.g, pte->lo.v, pte->lo.d, pte->lo.c, pte->lo.pfn);
107
    prepare_entry_lo(&lo, pte->lo.g, pte->lo.v, pte->lo.d, pte->lo.c, pte->lo.pfn);
108
 
108
 
109
    /*
109
    /*
110
     * New entry is to be inserted into TLB
110
     * New entry is to be inserted into TLB
111
     */
111
     */
Line 119... Line 119...
119
        cp0_entry_lo1_write(lo.value);
119
        cp0_entry_lo1_write(lo.value);
120
    }
120
    }
121
    cp0_pagemask_write(TLB_PAGE_MASK_16K);
121
    cp0_pagemask_write(TLB_PAGE_MASK_16K);
122
    tlbwr();
122
    tlbwr();
123
 
123
 
124
    spinlock_unlock(&VM->lock);
124
    spinlock_unlock(&AS->lock);
125
    return;
125
    return;
126
   
126
   
127
fail:
127
fail:
128
    spinlock_unlock(&VM->lock);
128
    spinlock_unlock(&AS->lock);
129
    tlb_refill_fail(pstate);
129
    tlb_refill_fail(pstate);
130
}
130
}
131
 
131
 
132
/** Process TLB Invalid Exception
132
/** Process TLB Invalid Exception
133
 *
133
 *
Line 152... Line 152...
152
    prepare_entry_hi(&hi, hi.asid, badvaddr);
152
    prepare_entry_hi(&hi, hi.asid, badvaddr);
153
    cp0_entry_hi_write(hi.value);
153
    cp0_entry_hi_write(hi.value);
154
    tlbp();
154
    tlbp();
155
    index.value = cp0_index_read();
155
    index.value = cp0_index_read();
156
   
156
   
157
    spinlock_lock(&VM->lock);  
157
    spinlock_lock(&AS->lock);  
158
   
158
   
159
    /*
159
    /*
160
     * Fail if the entry is not in TLB.
160
     * Fail if the entry is not in TLB.
161
     */
161
     */
162
    if (index.p) {
162
    if (index.p) {
Line 188... Line 188...
188
    else
188
    else
189
        cp0_entry_lo1_write(lo.value);
189
        cp0_entry_lo1_write(lo.value);
190
    cp0_pagemask_write(TLB_PAGE_MASK_16K);
190
    cp0_pagemask_write(TLB_PAGE_MASK_16K);
191
    tlbwi();
191
    tlbwi();
192
 
192
 
193
    spinlock_unlock(&VM->lock);
193
    spinlock_unlock(&AS->lock);
194
    return;
194
    return;
195
   
195
   
196
fail:
196
fail:
197
    spinlock_unlock(&VM->lock);
197
    spinlock_unlock(&AS->lock);
198
    tlb_invalid_fail(pstate);
198
    tlb_invalid_fail(pstate);
199
}
199
}
200
 
200
 
201
/** Process TLB Modified Exception
201
/** Process TLB Modified Exception
202
 *
202
 *
Line 221... Line 221...
221
    prepare_entry_hi(&hi, hi.asid, badvaddr);
221
    prepare_entry_hi(&hi, hi.asid, badvaddr);
222
    cp0_entry_hi_write(hi.value);
222
    cp0_entry_hi_write(hi.value);
223
    tlbp();
223
    tlbp();
224
    index.value = cp0_index_read();
224
    index.value = cp0_index_read();
225
   
225
   
226
    spinlock_lock(&VM->lock);  
226
    spinlock_lock(&AS->lock);  
227
   
227
   
228
    /*
228
    /*
229
     * Fail if the entry is not in TLB.
229
     * Fail if the entry is not in TLB.
230
     */
230
     */
231
    if (index.p) {
231
    if (index.p) {
Line 264... Line 264...
264
    else
264
    else
265
        cp0_entry_lo1_write(lo.value);
265
        cp0_entry_lo1_write(lo.value);
266
    cp0_pagemask_write(TLB_PAGE_MASK_16K);
266
    cp0_pagemask_write(TLB_PAGE_MASK_16K);
267
    tlbwi();
267
    tlbwi();
268
 
268
 
269
    spinlock_unlock(&VM->lock);
269
    spinlock_unlock(&AS->lock);
270
    return;
270
    return;
271
   
271
   
272
fail:
272
fail:
273
    spinlock_unlock(&VM->lock);
273
    spinlock_unlock(&AS->lock);
274
    tlb_modified_fail(pstate);
274
    tlb_modified_fail(pstate);
275
}
275
}
276
 
276
 
277
void tlb_refill_fail(struct exception_regdump *pstate)
277
void tlb_refill_fail(struct exception_regdump *pstate)
278
{
278
{
Line 310... Line 310...
310
}
310
}
311
 
311
 
312
/** Try to find PTE for faulting address
312
/** Try to find PTE for faulting address
313
 *
313
 *
314
 * Try to find PTE for faulting address.
314
 * Try to find PTE for faulting address.
315
 * The VM->lock must be held on entry to this function.
315
 * The AS->lock must be held on entry to this function.
316
 *
316
 *
317
 * @param badvaddr Faulting virtual address.
317
 * @param badvaddr Faulting virtual address.
318
 *
318
 *
319
 * @return PTE on success, NULL otherwise.
319
 * @return PTE on success, NULL otherwise.
320
 */
320
 */
Line 326... Line 326...
326
    hi.value = cp0_entry_hi_read();
326
    hi.value = cp0_entry_hi_read();
327
 
327
 
328
    /*
328
    /*
329
     * Handler cannot succeed if the ASIDs don't match.
329
     * Handler cannot succeed if the ASIDs don't match.
330
     */
330
     */
331
    if (hi.asid != VM->asid) {
331
    if (hi.asid != AS->asid) {
332
        printf("EntryHi.asid=%d, VM->asid=%d\n", hi.asid, VM->asid);
332
        printf("EntryHi.asid=%d, AS->asid=%d\n", hi.asid, AS->asid);
333
        return NULL;
333
        return NULL;
334
    }
334
    }
-
 
335
 
-
 
336
    /*
-
 
337
     * Check if the mapping exists in page tables.
-
 
338
     */
-
 
339
    pte = page_mapping_find(badvaddr, AS->asid, 0);
-
 
340
    if (pte && pte->lo.v) {
-
 
341
        /*
-
 
342
         * Mapping found in page tables.
-
 
343
         * Immediately succeed.
-
 
344
         */
-
 
345
        return pte;
-
 
346
    } else {
-
 
347
        /*
-
 
348
         * Mapping not found in page tables.
-
 
349
         * Resort to higher-level page fault handler.
-
 
350
         */
-
 
351
        if (as_page_fault(badvaddr)) {
-
 
352
            /*
-
 
353
             * The higher-level page fault handler succeeded,
-
 
354
             * The mapping ought to be in place.
-
 
355
             */
-
 
356
            pte = page_mapping_find(badvaddr, AS->asid, 0);
-
 
357
            ASSERT(pte && pte->lo.v);
-
 
358
            return pte;
-
 
359
        }
335
   
360
    }
-
 
361
 
336
    /*
362
    /*
337
     * Handler cannot succeed if badvaddr has no mapping.
363
     * Handler cannot succeed if badvaddr has no mapping.
338
     */
364
     */
339
    pte = page_mapping_find(badvaddr, VM->asid, 0);
-
 
340
    if (!pte) {
365
    if (!pte) {
341
        printf("No such mapping.\n");
366
        printf("No such mapping.\n");
342
        return NULL;
367
        return NULL;
343
    }
368
    }
344
 
369