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.) |