Subversion Repositories HelenOS

Rev

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

Rev 1196 Rev 1288
Line 42... Line 42...
42
 
42
 
43
static void tlb_refill_fail(istate_t *istate);
43
static void tlb_refill_fail(istate_t *istate);
44
static void tlb_invalid_fail(istate_t *istate);
44
static void tlb_invalid_fail(istate_t *istate);
45
static void tlb_modified_fail(istate_t *istate);
45
static void tlb_modified_fail(istate_t *istate);
46
 
46
 
47
static pte_t *find_mapping_and_check(__address badvaddr);
47
static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc);
48
 
48
 
49
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn);
49
static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn);
50
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr);
50
static void prepare_entry_hi(entry_hi_t *hi, asid_t asid, __address addr);
51
 
51
 
52
/** Initialize TLB
52
/** Initialize TLB
Line 89... Line 89...
89
    entry_lo_t lo;
89
    entry_lo_t lo;
90
    entry_hi_t hi;
90
    entry_hi_t hi;
91
    asid_t asid;
91
    asid_t asid;
92
    __address badvaddr;
92
    __address badvaddr;
93
    pte_t *pte;
93
    pte_t *pte;
-
 
94
    int pfrc;
94
 
95
 
95
    badvaddr = cp0_badvaddr_read();
96
    badvaddr = cp0_badvaddr_read();
96
 
97
 
97
    spinlock_lock(&AS->lock);
98
    spinlock_lock(&AS->lock);
98
    asid = AS->asid;
99
    asid = AS->asid;
99
    spinlock_unlock(&AS->lock);
100
    spinlock_unlock(&AS->lock);
100
 
101
 
101
    page_table_lock(AS, true);
102
    page_table_lock(AS, true);
102
 
103
 
103
    pte = find_mapping_and_check(badvaddr);
104
    pte = find_mapping_and_check(badvaddr, istate, &pfrc);
104
    if (!pte)
105
    if (!pte) {
-
 
106
        switch (pfrc) {
-
 
107
        case AS_PF_FAULT:
105
        goto fail;
108
            goto fail;
-
 
109
            break;
-
 
110
        case AS_PF_DEFER:
-
 
111
            /*
-
 
112
             * The page fault came during copy_from_uspace()
-
 
113
             * or copy_to_uspace().
-
 
114
             */
-
 
115
            page_table_unlock(AS, true);
-
 
116
            return;
-
 
117
        default:
-
 
118
            panic("unexpected pfrc (%d)\n", pfrc);
-
 
119
        }
-
 
120
    }
106
 
121
 
107
    /*
122
    /*
108
     * Record access to PTE.
123
     * Record access to PTE.
109
     */
124
     */
110
    pte->a = 1;
125
    pte->a = 1;
Line 146... Line 161...
146
    tlb_index_t index;
161
    tlb_index_t index;
147
    __address badvaddr;
162
    __address badvaddr;
148
    entry_lo_t lo;
163
    entry_lo_t lo;
149
    entry_hi_t hi;
164
    entry_hi_t hi;
150
    pte_t *pte;
165
    pte_t *pte;
-
 
166
    int pfrc;
151
 
167
 
152
    badvaddr = cp0_badvaddr_read();
168
    badvaddr = cp0_badvaddr_read();
153
 
169
 
154
    /*
170
    /*
155
     * Locate the faulting entry in TLB.
171
     * Locate the faulting entry in TLB.
Line 168... Line 184...
168
    if (index.p) {
184
    if (index.p) {
169
        printf("TLB entry not found.\n");
185
        printf("TLB entry not found.\n");
170
        goto fail;
186
        goto fail;
171
    }
187
    }
172
 
188
 
173
    pte = find_mapping_and_check(badvaddr);
189
    pte = find_mapping_and_check(badvaddr, istate, &pfrc);
174
    if (!pte)
190
    if (!pte) {
-
 
191
        switch (pfrc) {
-
 
192
        case AS_PF_FAULT:
175
        goto fail;
193
            goto fail;
-
 
194
            break;
-
 
195
        case AS_PF_DEFER:
-
 
196
            /*
-
 
197
             * The page fault came during copy_from_uspace()
-
 
198
             * or copy_to_uspace().
-
 
199
             */
-
 
200
            page_table_unlock(AS, true);             
-
 
201
            return;
-
 
202
        default:
-
 
203
            panic("unexpected pfrc (%d)\n", pfrc);
-
 
204
        }
-
 
205
    }
176
 
206
 
177
    /*
207
    /*
178
     * Read the faulting TLB entry.
208
     * Read the faulting TLB entry.
179
     */
209
     */
180
    tlbr();
210
    tlbr();
Line 215... Line 245...
215
    tlb_index_t index;
245
    tlb_index_t index;
216
    __address badvaddr;
246
    __address badvaddr;
217
    entry_lo_t lo;
247
    entry_lo_t lo;
218
    entry_hi_t hi;
248
    entry_hi_t hi;
219
    pte_t *pte;
249
    pte_t *pte;
-
 
250
    int pfrc;
220
 
251
 
221
    badvaddr = cp0_badvaddr_read();
252
    badvaddr = cp0_badvaddr_read();
222
 
253
 
223
    /*
254
    /*
224
     * Locate the faulting entry in TLB.
255
     * Locate the faulting entry in TLB.
Line 237... Line 268...
237
    if (index.p) {
268
    if (index.p) {
238
        printf("TLB entry not found.\n");
269
        printf("TLB entry not found.\n");
239
        goto fail;
270
        goto fail;
240
    }
271
    }
241
 
272
 
242
    pte = find_mapping_and_check(badvaddr);
273
    pte = find_mapping_and_check(badvaddr, istate, &pfrc);
243
    if (!pte)
274
    if (!pte) {
-
 
275
        switch (pfrc) {
-
 
276
        case AS_PF_FAULT:
244
        goto fail;
277
            goto fail;
-
 
278
            break;
-
 
279
        case AS_PF_DEFER:
-
 
280
            /*
-
 
281
             * The page fault came during copy_from_uspace()
-
 
282
             * or copy_to_uspace().
-
 
283
             */
-
 
284
            page_table_unlock(AS, true);             
-
 
285
            return;
-
 
286
        default:
-
 
287
            panic("unexpected pfrc (%d)\n", pfrc);
-
 
288
        }
-
 
289
    }
245
 
290
 
246
    /*
291
    /*
247
     * Fail if the page is not writable.
292
     * Fail if the page is not writable.
248
     */
293
     */
249
    if (!pte->w)
294
    if (!pte->w)
Line 319... Line 364...
319
 *
364
 *
320
 * Try to find PTE for faulting address.
365
 * Try to find PTE for faulting address.
321
 * The AS->lock must be held on entry to this function.
366
 * The AS->lock must be held on entry to this function.
322
 *
367
 *
323
 * @param badvaddr Faulting virtual address.
368
 * @param badvaddr Faulting virtual address.
-
 
369
 * @param istate Pointer to interrupted state.
-
 
370
 * @param pfrc Pointer to variable where as_page_fault() return code will be stored.
324
 *
371
 *
325
 * @return PTE on success, NULL otherwise.
372
 * @return PTE on success, NULL otherwise.
326
 */
373
 */
327
pte_t *find_mapping_and_check(__address badvaddr)
374
pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc)
328
{
375
{
329
    entry_hi_t hi;
376
    entry_hi_t hi;
330
    pte_t *pte;
377
    pte_t *pte;
331
 
378
 
332
    hi.value = cp0_entry_hi_read();
379
    hi.value = cp0_entry_hi_read();
Line 348... Line 395...
348
         * Mapping found in page tables.
395
         * Mapping found in page tables.
349
         * Immediately succeed.
396
         * Immediately succeed.
350
         */
397
         */
351
        return pte;
398
        return pte;
352
    } else {
399
    } else {
-
 
400
        int rc;
-
 
401
       
353
        /*
402
        /*
354
         * Mapping not found in page tables.
403
         * Mapping not found in page tables.
355
         * Resort to higher-level page fault handler.
404
         * Resort to higher-level page fault handler.
356
         */
405
         */
357
        page_table_unlock(AS, true);
406
        page_table_unlock(AS, true);
358
        if (as_page_fault(badvaddr)) {
407
        switch (rc = as_page_fault(badvaddr, istate)) {
-
 
408
        case AS_PF_OK:
359
            /*
409
            /*
360
             * The higher-level page fault handler succeeded,
410
             * The higher-level page fault handler succeeded,
361
             * The mapping ought to be in place.
411
             * The mapping ought to be in place.
362
             */
412
             */
363
            page_table_lock(AS, true);
413
            page_table_lock(AS, true);
364
            pte = page_mapping_find(AS, badvaddr);
414
            pte = page_mapping_find(AS, badvaddr);
365
            ASSERT(pte && pte->p);
415
            ASSERT(pte && pte->p);
366
            return pte;
416
            return pte;
-
 
417
            break;
-
 
418
        case AS_PF_DEFER:
-
 
419
            page_table_lock(AS, true);
-
 
420
            *pfrc = AS_PF_DEFER;
-
 
421
            return NULL;
367
        } else {
422
            break;
-
 
423
        case AS_PF_FAULT:
368
            page_table_lock(AS, true);
424
            page_table_lock(AS, true);
369
            printf("Page fault.\n");
425
            printf("Page fault.\n");
-
 
426
            *pfrc = AS_PF_FAULT;
370
            return NULL;
427
            return NULL;
-
 
428
            break;
-
 
429
        default:
-
 
430
            panic("unexpected rc (%d)\n", rc);
371
        }
431
        }
372
       
432
       
373
    }
433
    }
374
}
434
}
375
 
435