Subversion Repositories HelenOS-historic

Rev

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

Rev 1026 Rev 1044
Line 171... Line 171...
171
{
171
{
172
    as_area_t *area;
172
    as_area_t *area;
173
    ipl_t ipl;
173
    ipl_t ipl;
174
   
174
   
175
    ipl = interrupts_disable();
175
    ipl = interrupts_disable();
176
    spinlock_lock(&as->lock);
176
    page_table_lock(as, true);
177
   
177
   
178
    area = find_area_and_lock(as, page);
178
    area = find_area_and_lock(as, page);
179
    if (!area) {
179
    if (!area) {
180
        panic("page not part of any as_area\n");
180
        panic("page not part of any as_area\n");
181
    }
181
    }
182
 
182
 
183
    page_mapping_insert(as, page, frame, get_area_flags(area));
183
    page_mapping_insert(as, page, frame, get_area_flags(area));
184
   
184
   
185
    spinlock_unlock(&area->lock);
185
    spinlock_unlock(&area->lock);
186
    spinlock_unlock(&as->lock);
186
    page_table_unlock(as, true);
187
    interrupts_restore(ipl);
187
    interrupts_restore(ipl);
188
}
188
}
189
 
189
 
190
/** Handle page fault within the current address space.
190
/** Handle page fault within the current address space.
191
 *
191
 *
Line 196... Line 196...
196
 *
196
 *
197
 * @return 0 on page fault, 1 on success.
197
 * @return 0 on page fault, 1 on success.
198
 */
198
 */
199
int as_page_fault(__address page)
199
int as_page_fault(__address page)
200
{
200
{
-
 
201
    pte_t *pte;
201
    as_area_t *area;
202
    as_area_t *area;
202
    __address frame;
203
    __address frame;
203
   
204
   
204
    ASSERT(AS);
205
    ASSERT(AS);
-
 
206
 
205
    spinlock_lock(&AS->lock);
207
    spinlock_lock(&AS->lock);
206
   
-
 
207
    area = find_area_and_lock(AS, page);   
208
    area = find_area_and_lock(AS, page);   
208
    if (!area) {
209
    if (!area) {
209
        /*
210
        /*
210
         * No area contained mapping for 'page'.
211
         * No area contained mapping for 'page'.
211
         * Signal page fault to low-level handler.
212
         * Signal page fault to low-level handler.
212
         */
213
         */
213
        spinlock_unlock(&AS->lock);
214
        spinlock_unlock(&AS->lock);
214
        return 0;
215
        return 0;
215
    }
216
    }
216
 
217
 
-
 
218
    page_table_lock(AS, false);
-
 
219
   
-
 
220
    /*
-
 
221
     * To avoid race condition between two page faults
-
 
222
     * on the same address, we need to make sure
-
 
223
     * the mapping has not been already inserted.
-
 
224
     */
-
 
225
    if ((pte = page_mapping_find(AS, page))) {
-
 
226
        if (PTE_PRESENT(pte)) {
-
 
227
            page_table_unlock(AS, false);
-
 
228
            spinlock_unlock(&area->lock);
-
 
229
            spinlock_unlock(&AS->lock);
-
 
230
            return 1;
-
 
231
        }
-
 
232
    }
-
 
233
 
217
    /*
234
    /*
218
     * In general, there can be several reasons that
235
     * In general, there can be several reasons that
219
     * can have caused this fault.
236
     * can have caused this fault.
220
     *
237
     *
221
     * - non-existent mapping: the area is a scratch
238
     * - non-existent mapping: the area is a scratch
Line 235... Line 252...
235
     * Map 'page' to 'frame'.
252
     * Map 'page' to 'frame'.
236
     * Note that TLB shootdown is not attempted as only new information is being
253
     * Note that TLB shootdown is not attempted as only new information is being
237
     * inserted into page tables.
254
     * inserted into page tables.
238
     */
255
     */
239
    page_mapping_insert(AS, page, frame, get_area_flags(area));
256
    page_mapping_insert(AS, page, frame, get_area_flags(area));
-
 
257
    page_table_unlock(AS, false);
240
   
258
   
241
    spinlock_unlock(&area->lock);
259
    spinlock_unlock(&area->lock);
242
    spinlock_unlock(&AS->lock);
260
    spinlock_unlock(&AS->lock);
243
 
-
 
244
    return 1;
261
    return 1;
245
}
262
}
246
 
263
 
247
/** Switch address spaces.
264
/** Switch address spaces.
248
 *
265
 *
Line 355... Line 372...
355
        ASSERT(as_operations->page_table_create);
372
        ASSERT(as_operations->page_table_create);
356
 
373
 
357
        return as_operations->page_table_create(flags);
374
        return as_operations->page_table_create(flags);
358
}
375
}
359
 
376
 
-
 
377
/** Lock page table.
-
 
378
 *
-
 
379
 * This function should be called before any page_mapping_insert(),
-
 
380
 * page_mapping_remove() and page_mapping_find().
-
 
381
 *
-
 
382
 * Locking order is such that address space areas must be locked
-
 
383
 * prior to this call. Address space can be locked prior to this
-
 
384
 * call in which case the lock argument is false.
-
 
385
 *
-
 
386
 * @param as Address space.
-
 
387
 * @param as_locked If false, do not attempt to lock as->lock.
-
 
388
 */
-
 
389
void page_table_lock(as_t *as, bool lock)
-
 
390
{
-
 
391
    ASSERT(as_operations);
-
 
392
    ASSERT(as_operations->page_table_lock);
-
 
393
 
-
 
394
    as_operations->page_table_lock(as, lock);
-
 
395
}
-
 
396
 
-
 
397
/** Unlock page table.
-
 
398
 *
-
 
399
 * @param as Address space.
-
 
400
 * @param as_locked If false, do not attempt to unlock as->lock.
-
 
401
 */
-
 
402
void page_table_unlock(as_t *as, bool unlock)
-
 
403
{
-
 
404
    ASSERT(as_operations);
-
 
405
    ASSERT(as_operations->page_table_unlock);
-
 
406
 
-
 
407
    as_operations->page_table_unlock(as, unlock);
-
 
408
}
-
 
409
 
360
/** Find address space area and change it.
410
/** Find address space area and change it.
361
 *
411
 *
362
 * @param as Address space.
412
 * @param as Address space.
363
 * @param address Virtual address belonging to the area to be changed. Must be page-aligned.
413
 * @param address Virtual address belonging to the area to be changed. Must be page-aligned.
364
 * @param size New size of the virtual memory block starting at address.
414
 * @param size New size of the virtual memory block starting at address.
Line 395... Line 445...
395
            pte_t *pte;
445
            pte_t *pte;
396
           
446
           
397
            /*
447
            /*
398
             * Releasing physical memory.
448
             * Releasing physical memory.
399
             * This depends on the fact that the memory was allocated using frame_alloc().
449
             * This depends on the fact that the memory was allocated using frame_alloc().
400
             */
450
             */
-
 
451
            page_table_lock(as, false);
401
            pte = page_mapping_find(as, area->base + i*PAGE_SIZE);
452
            pte = page_mapping_find(as, area->base + i*PAGE_SIZE);
402
            if (pte && PTE_VALID(pte)) {
453
            if (pte && PTE_VALID(pte)) {
-
 
454
                __address frame;
-
 
455
 
403
                ASSERT(PTE_PRESENT(pte));
456
                ASSERT(PTE_PRESENT(pte));
404
                frame_free(ADDR2PFN(PTE_GET_FRAME(pte)));
457
                frame = PTE_GET_FRAME(pte);
405
                page_mapping_remove(as, area->base + i*PAGE_SIZE);
458
                page_mapping_remove(as, area->base + i*PAGE_SIZE);
-
 
459
                page_table_unlock(as, false);
-
 
460
 
-
 
461
                frame_free(ADDR2PFN(frame));
-
 
462
            } else {
-
 
463
                page_table_unlock(as, false);
406
            }
464
            }
407
        }
465
        }
408
        /*
466
        /*
409
         * Invalidate TLB's.
467
         * Invalidate TLB's.
410
         */
468
         */