Rev 2094 | Rev 2125 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 2094 | Rev 2106 | ||
|---|---|---|---|
| Line 166... | Line 166... | ||
| 166 | as->asid = ASID_INVALID; |
166 | as->asid = ASID_INVALID; |
| 167 | 167 | ||
| 168 | as->refcount = 0; |
168 | as->refcount = 0; |
| 169 | as->cpu_refcount = 0; |
169 | as->cpu_refcount = 0; |
| 170 | #ifdef AS_PAGE_TABLE |
170 | #ifdef AS_PAGE_TABLE |
| 171 | as->page_table = page_table_create(flags); |
171 | as->genarch.page_table = page_table_create(flags); |
| 172 | #else |
172 | #else |
| 173 | page_table_create(flags); |
173 | page_table_create(flags); |
| 174 | #endif |
174 | #endif |
| 175 | 175 | ||
| 176 | return as; |
176 | return as; |
| Line 218... | Line 218... | ||
| 218 | } |
218 | } |
| 219 | } |
219 | } |
| 220 | 220 | ||
| 221 | btree_destroy(&as->as_area_btree); |
221 | btree_destroy(&as->as_area_btree); |
| 222 | #ifdef AS_PAGE_TABLE |
222 | #ifdef AS_PAGE_TABLE |
| 223 | page_table_destroy(as->page_table); |
223 | page_table_destroy(as->genarch.page_table); |
| 224 | #else |
224 | #else |
| 225 | page_table_destroy(NULL); |
225 | page_table_destroy(NULL); |
| 226 | #endif |
226 | #endif |
| 227 | 227 | ||
| 228 | interrupts_restore(ipl); |
228 | interrupts_restore(ipl); |
| Line 861... | Line 861... | ||
| 861 | * scheduling. Sleeping here would lead to deadlock on wakeup. |
861 | * scheduling. Sleeping here would lead to deadlock on wakeup. |
| 862 | * |
862 | * |
| 863 | * @param old Old address space or NULL. |
863 | * @param old Old address space or NULL. |
| 864 | * @param new New address space. |
864 | * @param new New address space. |
| 865 | */ |
865 | */ |
| 866 | void as_switch(as_t *old, as_t *replace) |
866 | void as_switch(as_t *old_as, as_t *new_as) |
| 867 | { |
867 | { |
| 868 | ipl_t ipl; |
868 | ipl_t ipl; |
| 869 | bool needs_asid = false; |
869 | bool needs_asid = false; |
| 870 | 870 | ||
| 871 | ipl = interrupts_disable(); |
871 | ipl = interrupts_disable(); |
| 872 | spinlock_lock(&inactive_as_with_asid_lock); |
872 | spinlock_lock(&inactive_as_with_asid_lock); |
| 873 | 873 | ||
| 874 | /* |
874 | /* |
| 875 | * First, take care of the old address space. |
875 | * First, take care of the old address space. |
| 876 | */ |
876 | */ |
| 877 | if (old) { |
877 | if (old_as) { |
| 878 | mutex_lock_active(&old->lock); |
878 | mutex_lock_active(&old_as->lock); |
| 879 | ASSERT(old->cpu_refcount); |
879 | ASSERT(old_as->cpu_refcount); |
| 880 | if((--old->cpu_refcount == 0) && (old != AS_KERNEL)) { |
880 | if((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) { |
| 881 | /* |
881 | /* |
| 882 | * The old address space is no longer active on |
882 | * The old address space is no longer active on |
| 883 | * any processor. It can be appended to the |
883 | * any processor. It can be appended to the |
| 884 | * list of inactive address spaces with assigned |
884 | * list of inactive address spaces with assigned |
| 885 | * ASID. |
885 | * ASID. |
| 886 | */ |
886 | */ |
| 887 | ASSERT(old->asid != ASID_INVALID); |
887 | ASSERT(old_as->asid != ASID_INVALID); |
| 888 | list_append(&old->inactive_as_with_asid_link, |
888 | list_append(&old_as->inactive_as_with_asid_link, |
| 889 | &inactive_as_with_asid_head); |
889 | &inactive_as_with_asid_head); |
| 890 | } |
890 | } |
| 891 | mutex_unlock(&old->lock); |
891 | mutex_unlock(&old_as->lock); |
| 892 | 892 | ||
| 893 | /* |
893 | /* |
| 894 | * Perform architecture-specific tasks when the address space |
894 | * Perform architecture-specific tasks when the address space |
| 895 | * is being removed from the CPU. |
895 | * is being removed from the CPU. |
| 896 | */ |
896 | */ |
| 897 | as_deinstall_arch(old); |
897 | as_deinstall_arch(old_as); |
| 898 | } |
898 | } |
| 899 | 899 | ||
| 900 | /* |
900 | /* |
| 901 | * Second, prepare the new address space. |
901 | * Second, prepare the new address space. |
| 902 | */ |
902 | */ |
| 903 | mutex_lock_active(&replace->lock); |
903 | mutex_lock_active(&new_as->lock); |
| 904 | if ((replace->cpu_refcount++ == 0) && (replace != AS_KERNEL)) { |
904 | if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) { |
| 905 | if (replace->asid != ASID_INVALID) { |
905 | if (new_as->asid != ASID_INVALID) { |
| 906 | list_remove(&replace->inactive_as_with_asid_link); |
906 | list_remove(&new_as->inactive_as_with_asid_link); |
| 907 | } else { |
907 | } else { |
| 908 | /* |
908 | /* |
| 909 | * Defer call to asid_get() until replace->lock is released. |
909 | * Defer call to asid_get() until new_as->lock is released. |
| 910 | */ |
910 | */ |
| 911 | needs_asid = true; |
911 | needs_asid = true; |
| 912 | } |
912 | } |
| 913 | } |
913 | } |
| - | 914 | #ifdef AS_PAGE_TABLE |
|
| 914 | SET_PTL0_ADDRESS(replace->page_table); |
915 | SET_PTL0_ADDRESS(new_as->genarch.page_table); |
| - | 916 | #endif |
|
| 915 | mutex_unlock(&replace->lock); |
917 | mutex_unlock(&new_as->lock); |
| 916 | 918 | ||
| 917 | if (needs_asid) { |
919 | if (needs_asid) { |
| 918 | /* |
920 | /* |
| 919 | * Allocation of new ASID was deferred |
921 | * Allocation of new ASID was deferred |
| 920 | * until now in order to avoid deadlock. |
922 | * until now in order to avoid deadlock. |
| 921 | */ |
923 | */ |
| 922 | asid_t asid; |
924 | asid_t asid; |
| 923 | 925 | ||
| 924 | asid = asid_get(); |
926 | asid = asid_get(); |
| 925 | mutex_lock_active(&replace->lock); |
927 | mutex_lock_active(&new_as->lock); |
| 926 | replace->asid = asid; |
928 | new_as->asid = asid; |
| 927 | mutex_unlock(&replace->lock); |
929 | mutex_unlock(&new_as->lock); |
| 928 | } |
930 | } |
| 929 | spinlock_unlock(&inactive_as_with_asid_lock); |
931 | spinlock_unlock(&inactive_as_with_asid_lock); |
| 930 | interrupts_restore(ipl); |
932 | interrupts_restore(ipl); |
| 931 | 933 | ||
| 932 | /* |
934 | /* |
| 933 | * Perform architecture-specific steps. |
935 | * Perform architecture-specific steps. |
| 934 | * (e.g. write ASID to hardware register etc.) |
936 | * (e.g. write ASID to hardware register etc.) |
| 935 | */ |
937 | */ |
| 936 | as_install_arch(replace); |
938 | as_install_arch(new_as); |
| 937 | 939 | ||
| 938 | AS = replace; |
940 | AS = new_as; |
| 939 | } |
941 | } |
| 940 | 942 | ||
| 941 | /** Convert address space area flags to page flags. |
943 | /** Convert address space area flags to page flags. |
| 942 | * |
944 | * |
| 943 | * @param aflags Flags of some address space area. |
945 | * @param aflags Flags of some address space area. |