Rev 1248 | Rev 1306 | Go to most recent revision | Show entire file | Regard 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) { |