Rev 1413 | Rev 1417 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1413 | Rev 1415 | ||
|---|---|---|---|
| Line 81... | Line 81... | ||
| 81 | btree_t pagemap; /**< B+tree containing complete map of anonymous pages of the shared area. */ |
81 | btree_t pagemap; /**< B+tree containing complete map of anonymous pages of the shared area. */ |
| 82 | }; |
82 | }; |
| 83 | 83 | ||
| 84 | as_operations_t *as_operations = NULL; |
84 | as_operations_t *as_operations = NULL; |
| 85 | 85 | ||
| 86 | /** Address space lock. It protects inactive_as_with_asid_head. Must be acquired before as_t mutex. */ |
86 | /** This lock protects inactive_as_with_asid_head list. It must be acquired before as_t mutex. */ |
| 87 | SPINLOCK_INITIALIZE(as_lock); |
87 | SPINLOCK_INITIALIZE(inactive_as_with_asid_lock); |
| 88 | 88 | ||
| 89 | /** |
89 | /** |
| 90 | * This list contains address spaces that are not active on any |
90 | * This list contains address spaces that are not active on any |
| 91 | * processor and that have valid ASID. |
91 | * processor and that have valid ASID. |
| 92 | */ |
92 | */ |
| Line 126... | Line 126... | ||
| 126 | if (flags & FLAG_AS_KERNEL) |
126 | if (flags & FLAG_AS_KERNEL) |
| 127 | as->asid = ASID_KERNEL; |
127 | as->asid = ASID_KERNEL; |
| 128 | else |
128 | else |
| 129 | as->asid = ASID_INVALID; |
129 | as->asid = ASID_INVALID; |
| 130 | 130 | ||
| 131 | as->refcount = 0; |
131 | as->cpu_refcount = 0; |
| 132 | as->page_table = page_table_create(flags); |
132 | as->page_table = page_table_create(flags); |
| 133 | 133 | ||
| 134 | return as; |
134 | return as; |
| 135 | } |
135 | } |
| 136 | 136 | ||
| 137 | /** Free Adress space */ |
137 | /** Free Adress space */ |
| 138 | void as_free(as_t *as) |
138 | void as_free(as_t *as) |
| 139 | { |
139 | { |
| 140 | ASSERT(as->refcount == 0); |
140 | ASSERT(as->cpu_refcount == 0); |
| 141 | 141 | ||
| 142 | /* TODO: free as_areas and other resources held by as */ |
142 | /* TODO: free as_areas and other resources held by as */ |
| 143 | /* TODO: free page table */ |
143 | /* TODO: free page table */ |
| 144 | free(as); |
144 | free(as); |
| 145 | } |
145 | } |
| Line 731... | Line 731... | ||
| 731 | } |
731 | } |
| 732 | 732 | ||
| 733 | /** Switch address spaces. |
733 | /** Switch address spaces. |
| 734 | * |
734 | * |
| 735 | * Note that this function cannot sleep as it is essentially a part of |
735 | * Note that this function cannot sleep as it is essentially a part of |
| 736 | * the scheduling. Sleeping here would lead to deadlock on wakeup. |
736 | * scheduling. Sleeping here would lead to deadlock on wakeup. |
| 737 | * |
737 | * |
| 738 | * @param old Old address space or NULL. |
738 | * @param old Old address space or NULL. |
| 739 | * @param new New address space. |
739 | * @param new New address space. |
| 740 | */ |
740 | */ |
| 741 | void as_switch(as_t *old, as_t *new) |
741 | void as_switch(as_t *old, as_t *new) |
| 742 | { |
742 | { |
| 743 | ipl_t ipl; |
743 | ipl_t ipl; |
| 744 | bool needs_asid = false; |
744 | bool needs_asid = false; |
| 745 | 745 | ||
| 746 | ipl = interrupts_disable(); |
746 | ipl = interrupts_disable(); |
| 747 | spinlock_lock(&as_lock); |
747 | spinlock_lock(&inactive_as_with_asid_lock); |
| 748 | 748 | ||
| 749 | /* |
749 | /* |
| 750 | * First, take care of the old address space. |
750 | * First, take care of the old address space. |
| 751 | */ |
751 | */ |
| 752 | if (old) { |
752 | if (old) { |
| 753 | mutex_lock_active(&old->lock); |
753 | mutex_lock_active(&old->lock); |
| 754 | ASSERT(old->refcount); |
754 | ASSERT(old->cpu_refcount); |
| 755 | if((--old->refcount == 0) && (old != AS_KERNEL)) { |
755 | if((--old->cpu_refcount == 0) && (old != AS_KERNEL)) { |
| 756 | /* |
756 | /* |
| 757 | * The old address space is no longer active on |
757 | * The old address space is no longer active on |
| 758 | * any processor. It can be appended to the |
758 | * any processor. It can be appended to the |
| 759 | * list of inactive address spaces with assigned |
759 | * list of inactive address spaces with assigned |
| 760 | * ASID. |
760 | * ASID. |
| Line 767... | Line 767... | ||
| 767 | 767 | ||
| 768 | /* |
768 | /* |
| 769 | * Second, prepare the new address space. |
769 | * Second, prepare the new address space. |
| 770 | */ |
770 | */ |
| 771 | mutex_lock_active(&new->lock); |
771 | mutex_lock_active(&new->lock); |
| 772 | if ((new->refcount++ == 0) && (new != AS_KERNEL)) { |
772 | if ((new->cpu_refcount++ == 0) && (new != AS_KERNEL)) { |
| 773 | if (new->asid != ASID_INVALID) |
773 | if (new->asid != ASID_INVALID) |
| 774 | list_remove(&new->inactive_as_with_asid_link); |
774 | list_remove(&new->inactive_as_with_asid_link); |
| 775 | else |
775 | else |
| 776 | needs_asid = true; /* defer call to asid_get() until new->lock is released */ |
776 | needs_asid = true; /* defer call to asid_get() until new->lock is released */ |
| 777 | } |
777 | } |
| Line 788... | Line 788... | ||
| 788 | asid = asid_get(); |
788 | asid = asid_get(); |
| 789 | mutex_lock_active(&new->lock); |
789 | mutex_lock_active(&new->lock); |
| 790 | new->asid = asid; |
790 | new->asid = asid; |
| 791 | mutex_unlock(&new->lock); |
791 | mutex_unlock(&new->lock); |
| 792 | } |
792 | } |
| 793 | spinlock_unlock(&as_lock); |
793 | spinlock_unlock(&inactive_as_with_asid_lock); |
| 794 | interrupts_restore(ipl); |
794 | interrupts_restore(ipl); |
| 795 | 795 | ||
| 796 | /* |
796 | /* |
| 797 | * Perform architecture-specific steps. |
797 | * Perform architecture-specific steps. |
| 798 | * (e.g. write ASID to hardware register etc.) |
798 | * (e.g. write ASID to hardware register etc.) |