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 | */ |