Rev 1248 | Rev 1306 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1248 | Rev 1288 | ||
|---|---|---|---|
| Line 55... | Line 55... | ||
| 55 | #include <arch/mm/asid.h> |
55 | #include <arch/mm/asid.h> |
| 56 | #include <synch/spinlock.h> |
56 | #include <synch/spinlock.h> |
| 57 | #include <adt/list.h> |
57 | #include <adt/list.h> |
| 58 | #include <adt/btree.h> |
58 | #include <adt/btree.h> |
| 59 | #include <proc/task.h> |
59 | #include <proc/task.h> |
| - | 60 | #include <proc/thread.h> |
|
| 60 | #include <arch/asm.h> |
61 | #include <arch/asm.h> |
| 61 | #include <panic.h> |
62 | #include <panic.h> |
| 62 | #include <debug.h> |
63 | #include <debug.h> |
| 63 | #include <print.h> |
64 | #include <print.h> |
| 64 | #include <memstr.h> |
65 | #include <memstr.h> |
| Line 66... | Line 67... | ||
| 66 | #include <arch.h> |
67 | #include <arch.h> |
| 67 | #include <errno.h> |
68 | #include <errno.h> |
| 68 | #include <config.h> |
69 | #include <config.h> |
| 69 | #include <arch/types.h> |
70 | #include <arch/types.h> |
| 70 | #include <typedefs.h> |
71 | #include <typedefs.h> |
| - | 72 | #include <syscall/copy.h> |
|
| - | 73 | #include <arch/interrupt.h> |
|
| 71 | 74 | ||
| 72 | as_operations_t *as_operations = NULL; |
75 | as_operations_t *as_operations = NULL; |
| 73 | 76 | ||
| 74 | /** Address space lock. It protects inactive_as_with_asid_head. */ |
77 | /** Address space lock. It protects inactive_as_with_asid_head. */ |
| 75 | SPINLOCK_INITIALIZE(as_lock); |
78 | SPINLOCK_INITIALIZE(as_lock); |
| Line 475... | Line 478... | ||
| 475 | * |
478 | * |
| 476 | * This is the high-level page fault handler. |
479 | * This is the high-level page fault handler. |
| 477 | * Interrupts are assumed disabled. |
480 | * Interrupts are assumed disabled. |
| 478 | * |
481 | * |
| 479 | * @param page Faulting page. |
482 | * @param page Faulting page. |
| - | 483 | * @param istate Pointer to interrupted state. |
|
| 480 | * |
484 | * |
| 481 | * @return 0 on page fault, 1 on success. |
485 | * @return 0 on page fault, 1 on success or 2 if the fault was caused by copy_to_uspace() or copy_from_uspace(). |
| 482 | */ |
486 | */ |
| 483 | int as_page_fault(__address page) |
487 | int as_page_fault(__address page, istate_t *istate) |
| 484 | { |
488 | { |
| 485 | pte_t *pte; |
489 | pte_t *pte; |
| 486 | as_area_t *area; |
490 | as_area_t *area; |
| 487 | __address frame; |
491 | __address frame; |
| 488 | 492 | ||
| Line 494... | Line 498... | ||
| 494 | /* |
498 | /* |
| 495 | * No area contained mapping for 'page'. |
499 | * No area contained mapping for 'page'. |
| 496 | * Signal page fault to low-level handler. |
500 | * Signal page fault to low-level handler. |
| 497 | */ |
501 | */ |
| 498 | spinlock_unlock(&AS->lock); |
502 | spinlock_unlock(&AS->lock); |
| 499 | return 0; |
503 | goto page_fault; |
| 500 | } |
504 | } |
| 501 | 505 | ||
| 502 | if (area->attributes & AS_AREA_ATTR_PARTIAL) { |
506 | if (area->attributes & AS_AREA_ATTR_PARTIAL) { |
| 503 | /* |
507 | /* |
| 504 | * The address space area is not fully initialized. |
508 | * The address space area is not fully initialized. |
| 505 | * Avoid possible race by returning error. |
509 | * Avoid possible race by returning error. |
| 506 | */ |
510 | */ |
| 507 | spinlock_unlock(&area->lock); |
511 | spinlock_unlock(&area->lock); |
| 508 | spinlock_unlock(&AS->lock); |
512 | spinlock_unlock(&AS->lock); |
| 509 | return 0; |
513 | goto page_fault; |
| 510 | } |
514 | } |
| 511 | 515 | ||
| 512 | ASSERT(!(area->flags & AS_AREA_DEVICE)); |
516 | ASSERT(!(area->flags & AS_AREA_DEVICE)); |
| 513 | 517 | ||
| 514 | page_table_lock(AS, false); |
518 | page_table_lock(AS, false); |
| Line 552... | Line 556... | ||
| 552 | page_mapping_insert(AS, page, frame, get_area_flags(area)); |
556 | page_mapping_insert(AS, page, frame, get_area_flags(area)); |
| 553 | page_table_unlock(AS, false); |
557 | page_table_unlock(AS, false); |
| 554 | 558 | ||
| 555 | spinlock_unlock(&area->lock); |
559 | spinlock_unlock(&area->lock); |
| 556 | spinlock_unlock(&AS->lock); |
560 | spinlock_unlock(&AS->lock); |
| 557 | return 1; |
561 | return AS_PF_OK; |
| - | 562 | ||
| - | 563 | page_fault: |
|
| - | 564 | if (!THREAD) |
|
| - | 565 | return AS_PF_FAULT; |
|
| - | 566 | ||
| - | 567 | if (THREAD->in_copy_from_uspace) { |
|
| - | 568 | THREAD->in_copy_from_uspace = false; |
|
| - | 569 | istate_set_retaddr(istate, (__address) &memcpy_from_uspace_failover_address); |
|
| - | 570 | } else if (THREAD->in_copy_to_uspace) { |
|
| - | 571 | THREAD->in_copy_to_uspace = false; |
|
| - | 572 | istate_set_retaddr(istate, (__address) &memcpy_to_uspace_failover_address); |
|
| - | 573 | } else { |
|
| - | 574 | return AS_PF_FAULT; |
|
| - | 575 | } |
|
| - | 576 | ||
| - | 577 | return AS_PF_DEFER; |
|
| 558 | } |
578 | } |
| 559 | 579 | ||
| 560 | /** Switch address spaces. |
580 | /** Switch address spaces. |
| 561 | * |
581 | * |
| 562 | * @param old Old address space or NULL. |
582 | * @param old Old address space or NULL. |
| Line 882... | Line 902... | ||
| 882 | * TASK. Otherwise zero is returned. |
902 | * TASK. Otherwise zero is returned. |
| 883 | */ |
903 | */ |
| 884 | __native sys_as_area_accept(as_area_acptsnd_arg_t *uspace_accept_arg) |
904 | __native sys_as_area_accept(as_area_acptsnd_arg_t *uspace_accept_arg) |
| 885 | { |
905 | { |
| 886 | as_area_acptsnd_arg_t arg; |
906 | as_area_acptsnd_arg_t arg; |
| - | 907 | int rc; |
|
| 887 | 908 | ||
| 888 | copy_from_uspace(&arg, uspace_accept_arg, sizeof(as_area_acptsnd_arg_t)); |
909 | rc = copy_from_uspace(&arg, uspace_accept_arg, sizeof(as_area_acptsnd_arg_t)); |
| - | 910 | if (rc != 0) |
|
| - | 911 | return rc; |
|
| 889 | 912 | ||
| 890 | if (!arg.size) |
913 | if (!arg.size) |
| 891 | return (__native) EPERM; |
914 | return (__native) EPERM; |
| 892 | 915 | ||
| 893 | if (arg.task_id == TASK->taskid) { |
916 | if (arg.task_id == TASK->taskid) { |
| Line 904... | Line 927... | ||
| 904 | 927 | ||
| 905 | /** Wrapper for as_area_send. */ |
928 | /** Wrapper for as_area_send. */ |
| 906 | __native sys_as_area_send(as_area_acptsnd_arg_t *uspace_send_arg) |
929 | __native sys_as_area_send(as_area_acptsnd_arg_t *uspace_send_arg) |
| 907 | { |
930 | { |
| 908 | as_area_acptsnd_arg_t arg; |
931 | as_area_acptsnd_arg_t arg; |
| - | 932 | int rc; |
|
| 909 | 933 | ||
| 910 | copy_from_uspace(&arg, uspace_send_arg, sizeof(as_area_acptsnd_arg_t)); |
934 | rc = copy_from_uspace(&arg, uspace_send_arg, sizeof(as_area_acptsnd_arg_t)); |
| - | 935 | if (rc != 0) |
|
| - | 936 | return rc; |
|
| 911 | 937 | ||
| 912 | if (!arg.size) |
938 | if (!arg.size) |
| 913 | return (__native) EPERM; |
939 | return (__native) EPERM; |
| 914 | 940 | ||
| 915 | if (arg.task_id == TASK->taskid) { |
941 | if (arg.task_id == TASK->taskid) { |