Rev 3191 | Rev 3448 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3191 | Rev 3403 | ||
---|---|---|---|
Line 80... | Line 80... | ||
80 | 80 | ||
81 | #ifdef CONFIG_VIRT_IDX_DCACHE |
81 | #ifdef CONFIG_VIRT_IDX_DCACHE |
82 | #include <arch/mm/cache.h> |
82 | #include <arch/mm/cache.h> |
83 | #endif /* CONFIG_VIRT_IDX_DCACHE */ |
83 | #endif /* CONFIG_VIRT_IDX_DCACHE */ |
84 | 84 | ||
85 | #ifndef __OBJC__ |
- | |
86 | /** |
85 | /** |
87 | * Each architecture decides what functions will be used to carry out |
86 | * Each architecture decides what functions will be used to carry out |
88 | * address space operations such as creating or locking page tables. |
87 | * address space operations such as creating or locking page tables. |
89 | */ |
88 | */ |
90 | as_operations_t *as_operations = NULL; |
89 | as_operations_t *as_operations = NULL; |
91 | 90 | ||
92 | /** |
91 | /** |
93 | * Slab for as_t objects. |
92 | * Slab for as_t objects. |
94 | */ |
93 | */ |
95 | static slab_cache_t *as_slab; |
94 | static slab_cache_t *as_slab; |
96 | #endif |
- | |
97 | 95 | ||
98 | /** |
96 | /** |
99 | * This lock serializes access to the ASID subsystem. |
97 | * This lock serializes access to the ASID subsystem. |
100 | * It protects: |
98 | * It protects: |
101 | * - inactive_as_with_asid_head list |
99 | * - inactive_as_with_asid_head list |
Line 111... | Line 109... | ||
111 | LIST_INITIALIZE(inactive_as_with_asid_head); |
109 | LIST_INITIALIZE(inactive_as_with_asid_head); |
112 | 110 | ||
113 | /** Kernel address space. */ |
111 | /** Kernel address space. */ |
114 | as_t *AS_KERNEL = NULL; |
112 | as_t *AS_KERNEL = NULL; |
115 | 113 | ||
116 | static int area_flags_to_page_flags(int aflags); |
114 | static int area_flags_to_page_flags(int); |
117 | static as_area_t *find_area_and_lock(as_t *as, uintptr_t va); |
115 | static as_area_t *find_area_and_lock(as_t *, uintptr_t); |
118 | static bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, |
116 | static bool check_area_conflicts(as_t *, uintptr_t, size_t, as_area_t *); |
119 | as_area_t *avoid_area); |
- | |
120 | static void sh_info_remove_reference(share_info_t *sh_info); |
117 | static void sh_info_remove_reference(share_info_t *); |
121 | 118 | ||
122 | #ifndef __OBJC__ |
- | |
123 | static int as_constructor(void *obj, int flags) |
119 | static int as_constructor(void *obj, int flags) |
124 | { |
120 | { |
125 | as_t *as = (as_t *) obj; |
121 | as_t *as = (as_t *) obj; |
126 | int rc; |
122 | int rc; |
127 | 123 | ||
Line 137... | Line 133... | ||
137 | { |
133 | { |
138 | as_t *as = (as_t *) obj; |
134 | as_t *as = (as_t *) obj; |
139 | 135 | ||
140 | return as_destructor_arch(as); |
136 | return as_destructor_arch(as); |
141 | } |
137 | } |
142 | #endif |
- | |
143 | 138 | ||
144 | /** Initialize address space subsystem. */ |
139 | /** Initialize address space subsystem. */ |
145 | void as_init(void) |
140 | void as_init(void) |
146 | { |
141 | { |
147 | as_arch_init(); |
142 | as_arch_init(); |
148 | 143 | ||
149 | #ifndef __OBJC__ |
- | |
150 | as_slab = slab_cache_create("as_slab", sizeof(as_t), 0, |
144 | as_slab = slab_cache_create("as_slab", sizeof(as_t), 0, |
151 | as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED); |
145 | as_constructor, as_destructor, SLAB_CACHE_MAGDEFERRED); |
152 | #endif |
- | |
153 | 146 | ||
154 | AS_KERNEL = as_create(FLAG_AS_KERNEL); |
147 | AS_KERNEL = as_create(FLAG_AS_KERNEL); |
155 | if (!AS_KERNEL) |
148 | if (!AS_KERNEL) |
156 | panic("can't create kernel address space\n"); |
149 | panic("can't create kernel address space\n"); |
157 | 150 | ||
158 | } |
151 | } |
159 | 152 | ||
160 | /** Create address space. |
153 | /** Create address space. |
161 | * |
154 | * |
162 | * @param flags Flags that influence way in wich the address space is created. |
155 | * @param flags Flags that influence the way in wich the address space |
- | 156 | * is created. |
|
163 | */ |
157 | */ |
164 | as_t *as_create(int flags) |
158 | as_t *as_create(int flags) |
165 | { |
159 | { |
166 | as_t *as; |
160 | as_t *as; |
167 | 161 | ||
168 | #ifdef __OBJC__ |
- | |
169 | as = [as_t new]; |
- | |
170 | link_initialize(&as->inactive_as_with_asid_link); |
- | |
171 | mutex_initialize(&as->lock, MUTEX_PASSIVE); |
- | |
172 | (void) as_constructor_arch(as, flags); |
- | |
173 | #else |
- | |
174 | as = (as_t *) slab_alloc(as_slab, 0); |
162 | as = (as_t *) slab_alloc(as_slab, 0); |
175 | #endif |
- | |
176 | (void) as_create_arch(as, 0); |
163 | (void) as_create_arch(as, 0); |
177 | 164 | ||
178 | btree_create(&as->as_area_btree); |
165 | btree_create(&as->as_area_btree); |
179 | 166 | ||
180 | if (flags & FLAG_AS_KERNEL) |
167 | if (flags & FLAG_AS_KERNEL) |
Line 197... | Line 184... | ||
197 | * |
184 | * |
198 | * When there are no tasks referencing this address space (i.e. its refcount is |
185 | * When there are no tasks referencing this address space (i.e. its refcount is |
199 | * zero), the address space can be destroyed. |
186 | * zero), the address space can be destroyed. |
200 | * |
187 | * |
201 | * We know that we don't hold any spinlock. |
188 | * We know that we don't hold any spinlock. |
- | 189 | * |
|
- | 190 | * @param as Address space to be destroyed. |
|
202 | */ |
191 | */ |
203 | void as_destroy(as_t *as) |
192 | void as_destroy(as_t *as) |
204 | { |
193 | { |
205 | ipl_t ipl; |
194 | ipl_t ipl; |
206 | bool cond; |
195 | bool cond; |
Line 261... | Line 250... | ||
261 | page_table_destroy(NULL); |
250 | page_table_destroy(NULL); |
262 | #endif |
251 | #endif |
263 | 252 | ||
264 | interrupts_restore(ipl); |
253 | interrupts_restore(ipl); |
265 | 254 | ||
266 | #ifdef __OBJC__ |
- | |
267 | [as free]; |
- | |
268 | #else |
- | |
269 | slab_free(as_slab, as); |
255 | slab_free(as_slab, as); |
270 | #endif |
- | |
271 | } |
256 | } |
272 | 257 | ||
273 | /** Create address space area of common attributes. |
258 | /** Create address space area of common attributes. |
274 | * |
259 | * |
275 | * The created address space area is added to the target address space. |
260 | * The created address space area is added to the target address space. |
276 | * |
261 | * |
277 | * @param as Target address space. |
262 | * @param as Target address space. |
278 | * @param flags Flags of the area memory. |
263 | * @param flags Flags of the area memory. |
279 | * @param size Size of area. |
264 | * @param size Size of area. |
280 | * @param base Base address of area. |
265 | * @param base Base address of area. |
281 | * @param attrs Attributes of the area. |
266 | * @param attrs Attributes of the area. |
282 | * @param backend Address space area backend. NULL if no backend is used. |
267 | * @param backend Address space area backend. NULL if no backend is used. |
283 | * @param backend_data NULL or a pointer to an array holding two void *. |
268 | * @param backend_data NULL or a pointer to an array holding two void *. |
284 | * |
269 | * |
285 | * @return Address space area on success or NULL on failure. |
270 | * @return Address space area on success or NULL on failure. |
286 | */ |
271 | */ |
287 | as_area_t * |
272 | as_area_t * |
288 | as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs, |
273 | as_area_create(as_t *as, int flags, size_t size, uintptr_t base, int attrs, |
289 | mem_backend_t *backend, mem_backend_data_t *backend_data) |
274 | mem_backend_t *backend, mem_backend_data_t *backend_data) |
290 | { |
275 | { |
291 | ipl_t ipl; |
276 | ipl_t ipl; |
292 | as_area_t *a; |
277 | as_area_t *a; |
293 | 278 | ||
294 | if (base % PAGE_SIZE) |
279 | if (base % PAGE_SIZE) |
Line 336... | Line 321... | ||
336 | return a; |
321 | return a; |
337 | } |
322 | } |
338 | 323 | ||
339 | /** Find address space area and change it. |
324 | /** Find address space area and change it. |
340 | * |
325 | * |
341 | * @param as Address space. |
326 | * @param as Address space. |
342 | * @param address Virtual address belonging to the area to be changed. Must be |
327 | * @param address Virtual address belonging to the area to be changed. |
343 | * page-aligned. |
328 | * Must be page-aligned. |
344 | * @param size New size of the virtual memory block starting at address. |
329 | * @param size New size of the virtual memory block starting at |
- | 330 | * address. |
|
345 | * @param flags Flags influencing the remap operation. Currently unused. |
331 | * @param flags Flags influencing the remap operation. Currently unused. |
346 | * |
332 | * |
347 | * @return Zero on success or a value from @ref errno.h otherwise. |
333 | * @return Zero on success or a value from @ref errno.h otherwise. |
348 | */ |
334 | */ |
349 | int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags) |
335 | int as_area_resize(as_t *as, uintptr_t address, size_t size, int flags) |
350 | { |
336 | { |
351 | as_area_t *area; |
337 | as_area_t *area; |
352 | ipl_t ipl; |
338 | ipl_t ipl; |
Line 450... | Line 436... | ||
450 | * address space area. |
436 | * address space area. |
451 | */ |
437 | */ |
452 | 438 | ||
453 | cond = false; /* we are almost done */ |
439 | cond = false; /* we are almost done */ |
454 | i = (start_free - b) >> PAGE_WIDTH; |
440 | i = (start_free - b) >> PAGE_WIDTH; |
455 | if (!used_space_remove(area, start_free, c - i)) |
441 | if (!used_space_remove(area, start_free, |
- | 442 | c - i)) |
|
456 | panic("Could not remove used space.\n"); |
443 | panic("Could not remove used " |
- | 444 | "space.\n"); |
|
457 | } else { |
445 | } else { |
458 | /* |
446 | /* |
459 | * The interval of used space can be |
447 | * The interval of used space can be |
460 | * completely removed. |
448 | * completely removed. |
461 | */ |
449 | */ |
462 | if (!used_space_remove(area, b, c)) |
450 | if (!used_space_remove(area, b, c)) |
463 | panic("Could not remove used space.\n"); |
451 | panic("Could not remove used " |
- | 452 | "space.\n"); |
|
464 | } |
453 | } |
465 | 454 | ||
466 | for (; i < c; i++) { |
455 | for (; i < c; i++) { |
467 | pte_t *pte; |
456 | pte_t *pte; |
468 | 457 | ||
Line 520... | Line 509... | ||
520 | return 0; |
509 | return 0; |
521 | } |
510 | } |
522 | 511 | ||
523 | /** Destroy address space area. |
512 | /** Destroy address space area. |
524 | * |
513 | * |
525 | * @param as Address space. |
514 | * @param as Address space. |
526 | * @param address Address withing the area to be deleted. |
515 | * @param address Address within the area to be deleted. |
527 | * |
516 | * |
528 | * @return Zero on success or a value from @ref errno.h on failure. |
517 | * @return Zero on success or a value from @ref errno.h on failure. |
529 | */ |
518 | */ |
530 | int as_area_destroy(as_t *as, uintptr_t address) |
519 | int as_area_destroy(as_t *as, uintptr_t address) |
531 | { |
520 | { |
532 | as_area_t *area; |
521 | as_area_t *area; |
533 | uintptr_t base; |
522 | uintptr_t base; |
Line 620... | Line 609... | ||
620 | * If the source address space area has not been shared so far, |
609 | * If the source address space area has not been shared so far, |
621 | * a new sh_info is created. The new address space area simply gets the |
610 | * a new sh_info is created. The new address space area simply gets the |
622 | * sh_info of the source area. The process of duplicating the |
611 | * sh_info of the source area. The process of duplicating the |
623 | * mapping is done through the backend share function. |
612 | * mapping is done through the backend share function. |
624 | * |
613 | * |
625 | * @param src_as Pointer to source address space. |
614 | * @param src_as Pointer to source address space. |
626 | * @param src_base Base address of the source address space area. |
615 | * @param src_base Base address of the source address space area. |
627 | * @param acc_size Expected size of the source area. |
616 | * @param acc_size Expected size of the source area. |
628 | * @param dst_as Pointer to destination address space. |
617 | * @param dst_as Pointer to destination address space. |
629 | * @param dst_base Target base address. |
618 | * @param dst_base Target base address. |
630 | * @param dst_flags_mask Destination address space area flags mask. |
619 | * @param dst_flags_mask Destination address space area flags mask. |
631 | * |
620 | * |
632 | * @return Zero on success or ENOENT if there is no such task or if there is no |
621 | * @return Zero on success or ENOENT if there is no such task or if |
633 | * such address space area, EPERM if there was a problem in accepting the area |
622 | * there is no such address space area, EPERM if there was |
- | 623 | * a problem in accepting the area or ENOMEM if there was a |
|
634 | * or ENOMEM if there was a problem in allocating destination address space |
624 | * problem in allocating destination address space area. |
635 | * area. ENOTSUP is returned if the address space area backend does not support |
625 | * ENOTSUP is returned if the address space area backend |
636 | * sharing. |
626 | * does not support sharing. |
637 | */ |
627 | */ |
638 | int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
628 | int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size, |
639 | as_t *dst_as, uintptr_t dst_base, int dst_flags_mask) |
629 | as_t *dst_as, uintptr_t dst_base, int dst_flags_mask) |
640 | { |
630 | { |
641 | ipl_t ipl; |
631 | ipl_t ipl; |
Line 750... | Line 740... | ||
750 | 740 | ||
751 | /** Check access mode for address space area. |
741 | /** Check access mode for address space area. |
752 | * |
742 | * |
753 | * The address space area must be locked prior to this call. |
743 | * The address space area must be locked prior to this call. |
754 | * |
744 | * |
755 | * @param area Address space area. |
745 | * @param area Address space area. |
756 | * @param access Access mode. |
746 | * @param access Access mode. |
757 | * |
747 | * |
758 | * @return False if access violates area's permissions, true otherwise. |
748 | * @return False if access violates area's permissions, true |
- | 749 | * otherwise. |
|
759 | */ |
750 | */ |
760 | bool as_area_check_access(as_area_t *area, pf_access_t access) |
751 | bool as_area_check_access(as_area_t *area, pf_access_t access) |
761 | { |
752 | { |
762 | int flagmap[] = { |
753 | int flagmap[] = { |
763 | [PF_ACCESS_READ] = AS_AREA_READ, |
754 | [PF_ACCESS_READ] = AS_AREA_READ, |
Line 769... | Line 760... | ||
769 | return false; |
760 | return false; |
770 | 761 | ||
771 | return true; |
762 | return true; |
772 | } |
763 | } |
773 | 764 | ||
774 | /** Change adress area flags. |
765 | /** Change adress space area flags. |
775 | * |
766 | * |
776 | * The idea is to have the same data, but with a different access mode. |
767 | * The idea is to have the same data, but with a different access mode. |
777 | * This is needed e.g. for writing code into memory and then executing it. |
768 | * This is needed e.g. for writing code into memory and then executing it. |
778 | * In order for this to work properly, this may copy the data |
769 | * In order for this to work properly, this may copy the data |
779 | * into private anonymous memory (unless it's already there). |
770 | * into private anonymous memory (unless it's already there). |
780 | * |
771 | * |
781 | * @param as Address space. |
772 | * @param as Address space. |
782 | * @param flags Flags of the area memory. |
773 | * @param flags Flags of the area memory. |
783 | * @param address Address withing the area to be changed. |
774 | * @param address Address withing the area to be changed. |
784 | * |
775 | * |
785 | * @return Zero on success or a value from @ref errno.h on failure. |
776 | * @return Zero on success or a value from @ref errno.h on failure. |
786 | */ |
777 | */ |
787 | int as_area_change_flags(as_t *as, int flags, uintptr_t address) |
778 | int as_area_change_flags(as_t *as, int flags, uintptr_t address) |
788 | { |
779 | { |
789 | as_area_t *area; |
780 | as_area_t *area; |
790 | uintptr_t base; |
781 | uintptr_t base; |
Line 885... | Line 876... | ||
885 | */ |
876 | */ |
886 | as_invalidate_translation_cache(as, area->base, area->pages); |
877 | as_invalidate_translation_cache(as, area->base, area->pages); |
887 | tlb_shootdown_finalize(); |
878 | tlb_shootdown_finalize(); |
888 | 879 | ||
889 | /* |
880 | /* |
- | 881 | * Set the new flags. |
|
- | 882 | */ |
|
- | 883 | area->flags = flags; |
|
- | 884 | ||
- | 885 | /* |
|
890 | * Map pages back in with new flags. This step is kept separate |
886 | * Map pages back in with new flags. This step is kept separate |
891 | * so that there's no instant when the memory area could be |
887 | * so that the memory area could not be accesed with both the old and |
892 | * accesed with both the old and the new flags at once. |
888 | * the new flags at once. |
893 | */ |
889 | */ |
894 | frame_idx = 0; |
890 | frame_idx = 0; |
895 | 891 | ||
896 | for (cur = area->used_space.leaf_head.next; |
892 | for (cur = area->used_space.leaf_head.next; |
897 | cur != &area->used_space.leaf_head; cur = cur->next) { |
893 | cur != &area->used_space.leaf_head; cur = cur->next) { |
Line 925... | Line 921... | ||
925 | } |
921 | } |
926 | 922 | ||
927 | 923 | ||
928 | /** Handle page fault within the current address space. |
924 | /** Handle page fault within the current address space. |
929 | * |
925 | * |
930 | * This is the high-level page fault handler. It decides |
926 | * This is the high-level page fault handler. It decides whether the page fault |
931 | * whether the page fault can be resolved by any backend |
- | |
932 | * and if so, it invokes the backend to resolve the page |
927 | * can be resolved by any backend and if so, it invokes the backend to resolve |
933 | * fault. |
928 | * the page fault. |
934 | * |
929 | * |
935 | * Interrupts are assumed disabled. |
930 | * Interrupts are assumed disabled. |
936 | * |
931 | * |
937 | * @param page Faulting page. |
932 | * @param page Faulting page. |
938 | * @param access Access mode that caused the fault (i.e. read/write/exec). |
933 | * @param access Access mode that caused the page fault (i.e. |
- | 934 | * read/write/exec). |
|
939 | * @param istate Pointer to interrupted state. |
935 | * @param istate Pointer to the interrupted state. |
940 | * |
936 | * |
941 | * @return AS_PF_FAULT on page fault, AS_PF_OK on success or AS_PF_DEFER if the |
937 | * @return AS_PF_FAULT on page fault, AS_PF_OK on success or |
942 | * fault was caused by copy_to_uspace() or copy_from_uspace(). |
938 | * AS_PF_DEFER if the fault was caused by copy_to_uspace() |
- | 939 | * or copy_from_uspace(). |
|
943 | */ |
940 | */ |
944 | int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate) |
941 | int as_page_fault(uintptr_t page, pf_access_t access, istate_t *istate) |
945 | { |
942 | { |
946 | pte_t *pte; |
943 | pte_t *pte; |
947 | as_area_t *area; |
944 | as_area_t *area; |
Line 983... | Line 980... | ||
983 | } |
980 | } |
984 | 981 | ||
985 | page_table_lock(AS, false); |
982 | page_table_lock(AS, false); |
986 | 983 | ||
987 | /* |
984 | /* |
988 | * To avoid race condition between two page faults |
985 | * To avoid race condition between two page faults on the same address, |
989 | * on the same address, we need to make sure |
- | |
990 | * the mapping has not been already inserted. |
986 | * we need to make sure the mapping has not been already inserted. |
991 | */ |
987 | */ |
992 | if ((pte = page_mapping_find(AS, page))) { |
988 | if ((pte = page_mapping_find(AS, page))) { |
993 | if (PTE_PRESENT(pte)) { |
989 | if (PTE_PRESENT(pte)) { |
994 | if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) || |
990 | if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) || |
995 | (access == PF_ACCESS_WRITE && PTE_WRITABLE(pte)) || |
991 | (access == PF_ACCESS_WRITE && PTE_WRITABLE(pte)) || |
Line 1039... | Line 1035... | ||
1039 | * scheduling. Sleeping here would lead to deadlock on wakeup. Another |
1035 | * scheduling. Sleeping here would lead to deadlock on wakeup. Another |
1040 | * thing which is forbidden in this context is locking the address space. |
1036 | * thing which is forbidden in this context is locking the address space. |
1041 | * |
1037 | * |
1042 | * When this function is enetered, no spinlocks may be held. |
1038 | * When this function is enetered, no spinlocks may be held. |
1043 | * |
1039 | * |
1044 | * @param old Old address space or NULL. |
1040 | * @param old Old address space or NULL. |
1045 | * @param new New address space. |
1041 | * @param new New address space. |
1046 | */ |
1042 | */ |
1047 | void as_switch(as_t *old_as, as_t *new_as) |
1043 | void as_switch(as_t *old_as, as_t *new_as) |
1048 | { |
1044 | { |
1049 | DEADLOCK_PROBE_INIT(p_asidlock); |
1045 | DEADLOCK_PROBE_INIT(p_asidlock); |
1050 | preemption_disable(); |
1046 | preemption_disable(); |
Line 1111... | Line 1107... | ||
1111 | AS = new_as; |
1107 | AS = new_as; |
1112 | } |
1108 | } |
1113 | 1109 | ||
1114 | /** Convert address space area flags to page flags. |
1110 | /** Convert address space area flags to page flags. |
1115 | * |
1111 | * |
1116 | * @param aflags Flags of some address space area. |
1112 | * @param aflags Flags of some address space area. |
1117 | * |
1113 | * |
1118 | * @return Flags to be passed to page_mapping_insert(). |
1114 | * @return Flags to be passed to page_mapping_insert(). |
1119 | */ |
1115 | */ |
1120 | int area_flags_to_page_flags(int aflags) |
1116 | int area_flags_to_page_flags(int aflags) |
1121 | { |
1117 | { |
1122 | int flags; |
1118 | int flags; |
1123 | 1119 | ||
Line 1141... | Line 1137... | ||
1141 | /** Compute flags for virtual address translation subsytem. |
1137 | /** Compute flags for virtual address translation subsytem. |
1142 | * |
1138 | * |
1143 | * The address space area must be locked. |
1139 | * The address space area must be locked. |
1144 | * Interrupts must be disabled. |
1140 | * Interrupts must be disabled. |
1145 | * |
1141 | * |
1146 | * @param a Address space area. |
1142 | * @param a Address space area. |
1147 | * |
1143 | * |
1148 | * @return Flags to be used in page_mapping_insert(). |
1144 | * @return Flags to be used in page_mapping_insert(). |
1149 | */ |
1145 | */ |
1150 | int as_area_get_flags(as_area_t *a) |
1146 | int as_area_get_flags(as_area_t *a) |
1151 | { |
1147 | { |
1152 | return area_flags_to_page_flags(a->flags); |
1148 | return area_flags_to_page_flags(a->flags); |
1153 | } |
1149 | } |
1154 | 1150 | ||
1155 | /** Create page table. |
1151 | /** Create page table. |
1156 | * |
1152 | * |
1157 | * Depending on architecture, create either address space |
1153 | * Depending on architecture, create either address space private or global page |
1158 | * private or global page table. |
1154 | * table. |
1159 | * |
1155 | * |
1160 | * @param flags Flags saying whether the page table is for kernel address space. |
1156 | * @param flags Flags saying whether the page table is for the kernel |
- | 1157 | * address space. |
|
1161 | * |
1158 | * |
1162 | * @return First entry of the page table. |
1159 | * @return First entry of the page table. |
1163 | */ |
1160 | */ |
1164 | pte_t *page_table_create(int flags) |
1161 | pte_t *page_table_create(int flags) |
1165 | { |
1162 | { |
1166 | #ifdef __OBJC__ |
- | |
1167 | return [as_t page_table_create: flags]; |
- | |
1168 | #else |
- | |
1169 | ASSERT(as_operations); |
1163 | ASSERT(as_operations); |
1170 | ASSERT(as_operations->page_table_create); |
1164 | ASSERT(as_operations->page_table_create); |
1171 | 1165 | ||
1172 | return as_operations->page_table_create(flags); |
1166 | return as_operations->page_table_create(flags); |
1173 | #endif |
- | |
1174 | } |
1167 | } |
1175 | 1168 | ||
1176 | /** Destroy page table. |
1169 | /** Destroy page table. |
1177 | * |
1170 | * |
1178 | * Destroy page table in architecture specific way. |
1171 | * Destroy page table in architecture specific way. |
1179 | * |
1172 | * |
1180 | * @param page_table Physical address of PTL0. |
1173 | * @param page_table Physical address of PTL0. |
1181 | */ |
1174 | */ |
1182 | void page_table_destroy(pte_t *page_table) |
1175 | void page_table_destroy(pte_t *page_table) |
1183 | { |
1176 | { |
1184 | #ifdef __OBJC__ |
- | |
1185 | return [as_t page_table_destroy: page_table]; |
- | |
1186 | #else |
- | |
1187 | ASSERT(as_operations); |
1177 | ASSERT(as_operations); |
1188 | ASSERT(as_operations->page_table_destroy); |
1178 | ASSERT(as_operations->page_table_destroy); |
1189 | 1179 | ||
1190 | as_operations->page_table_destroy(page_table); |
1180 | as_operations->page_table_destroy(page_table); |
1191 | #endif |
- | |
1192 | } |
1181 | } |
1193 | 1182 | ||
1194 | /** Lock page table. |
1183 | /** Lock page table. |
1195 | * |
1184 | * |
1196 | * This function should be called before any page_mapping_insert(), |
1185 | * This function should be called before any page_mapping_insert(), |
Line 1198... | Line 1187... | ||
1198 | * |
1187 | * |
1199 | * Locking order is such that address space areas must be locked |
1188 | * Locking order is such that address space areas must be locked |
1200 | * prior to this call. Address space can be locked prior to this |
1189 | * prior to this call. Address space can be locked prior to this |
1201 | * call in which case the lock argument is false. |
1190 | * call in which case the lock argument is false. |
1202 | * |
1191 | * |
1203 | * @param as Address space. |
1192 | * @param as Address space. |
1204 | * @param lock If false, do not attempt to lock as->lock. |
1193 | * @param lock If false, do not attempt to lock as->lock. |
1205 | */ |
1194 | */ |
1206 | void page_table_lock(as_t *as, bool lock) |
1195 | void page_table_lock(as_t *as, bool lock) |
1207 | { |
1196 | { |
1208 | #ifdef __OBJC__ |
- | |
1209 | [as page_table_lock: lock]; |
- | |
1210 | #else |
- | |
1211 | ASSERT(as_operations); |
1197 | ASSERT(as_operations); |
1212 | ASSERT(as_operations->page_table_lock); |
1198 | ASSERT(as_operations->page_table_lock); |
1213 | 1199 | ||
1214 | as_operations->page_table_lock(as, lock); |
1200 | as_operations->page_table_lock(as, lock); |
1215 | #endif |
- | |
1216 | } |
1201 | } |
1217 | 1202 | ||
1218 | /** Unlock page table. |
1203 | /** Unlock page table. |
1219 | * |
1204 | * |
1220 | * @param as Address space. |
1205 | * @param as Address space. |
1221 | * @param unlock If false, do not attempt to unlock as->lock. |
1206 | * @param unlock If false, do not attempt to unlock as->lock. |
1222 | */ |
1207 | */ |
1223 | void page_table_unlock(as_t *as, bool unlock) |
1208 | void page_table_unlock(as_t *as, bool unlock) |
1224 | { |
1209 | { |
1225 | #ifdef __OBJC__ |
- | |
1226 | [as page_table_unlock: unlock]; |
- | |
1227 | #else |
- | |
1228 | ASSERT(as_operations); |
1210 | ASSERT(as_operations); |
1229 | ASSERT(as_operations->page_table_unlock); |
1211 | ASSERT(as_operations->page_table_unlock); |
1230 | 1212 | ||
1231 | as_operations->page_table_unlock(as, unlock); |
1213 | as_operations->page_table_unlock(as, unlock); |
1232 | #endif |
- | |
1233 | } |
1214 | } |
1234 | 1215 | ||
1235 | 1216 | ||
1236 | /** Find address space area and lock it. |
1217 | /** Find address space area and lock it. |
1237 | * |
1218 | * |
1238 | * The address space must be locked and interrupts must be disabled. |
1219 | * The address space must be locked and interrupts must be disabled. |
1239 | * |
1220 | * |
1240 | * @param as Address space. |
1221 | * @param as Address space. |
1241 | * @param va Virtual address. |
1222 | * @param va Virtual address. |
1242 | * |
1223 | * |
1243 | * @return Locked address space area containing va on success or NULL on |
1224 | * @return Locked address space area containing va on success or |
1244 | * failure. |
1225 | * NULL on failure. |
1245 | */ |
1226 | */ |
1246 | as_area_t *find_area_and_lock(as_t *as, uintptr_t va) |
1227 | as_area_t *find_area_and_lock(as_t *as, uintptr_t va) |
1247 | { |
1228 | { |
1248 | as_area_t *a; |
1229 | as_area_t *a; |
1249 | btree_node_t *leaf, *lnode; |
1230 | btree_node_t *leaf, *lnode; |
Line 1291... | Line 1272... | ||
1291 | 1272 | ||
1292 | /** Check area conflicts with other areas. |
1273 | /** Check area conflicts with other areas. |
1293 | * |
1274 | * |
1294 | * The address space must be locked and interrupts must be disabled. |
1275 | * The address space must be locked and interrupts must be disabled. |
1295 | * |
1276 | * |
1296 | * @param as Address space. |
1277 | * @param as Address space. |
1297 | * @param va Starting virtual address of the area being tested. |
1278 | * @param va Starting virtual address of the area being tested. |
1298 | * @param size Size of the area being tested. |
1279 | * @param size Size of the area being tested. |
1299 | * @param avoid_area Do not touch this area. |
1280 | * @param avoid_area Do not touch this area. |
1300 | * |
1281 | * |
1301 | * @return True if there is no conflict, false otherwise. |
1282 | * @return True if there is no conflict, false otherwise. |
1302 | */ |
1283 | */ |
- | 1284 | bool |
|
1303 | bool check_area_conflicts(as_t *as, uintptr_t va, size_t size, |
1285 | check_area_conflicts(as_t *as, uintptr_t va, size_t size, as_area_t *avoid_area) |
1304 | as_area_t *avoid_area) |
- | |
1305 | { |
1286 | { |
1306 | as_area_t *a; |
1287 | as_area_t *a; |
1307 | btree_node_t *leaf, *node; |
1288 | btree_node_t *leaf, *node; |
1308 | unsigned int i; |
1289 | unsigned int i; |
1309 | 1290 | ||
Line 1388... | Line 1369... | ||
1388 | as_area_t *src_area; |
1369 | as_area_t *src_area; |
1389 | size_t size; |
1370 | size_t size; |
1390 | 1371 | ||
1391 | ipl = interrupts_disable(); |
1372 | ipl = interrupts_disable(); |
1392 | src_area = find_area_and_lock(AS, base); |
1373 | src_area = find_area_and_lock(AS, base); |
1393 | if (src_area){ |
1374 | if (src_area) { |
1394 | size = src_area->pages * PAGE_SIZE; |
1375 | size = src_area->pages * PAGE_SIZE; |
1395 | mutex_unlock(&src_area->lock); |
1376 | mutex_unlock(&src_area->lock); |
1396 | } else { |
1377 | } else { |
1397 | size = 0; |
1378 | size = 0; |
1398 | } |
1379 | } |
Line 1402... | Line 1383... | ||
1402 | 1383 | ||
1403 | /** Mark portion of address space area as used. |
1384 | /** Mark portion of address space area as used. |
1404 | * |
1385 | * |
1405 | * The address space area must be already locked. |
1386 | * The address space area must be already locked. |
1406 | * |
1387 | * |
1407 | * @param a Address space area. |
1388 | * @param a Address space area. |
1408 | * @param page First page to be marked. |
1389 | * @param page First page to be marked. |
1409 | * @param count Number of page to be marked. |
1390 | * @param count Number of page to be marked. |
1410 | * |
1391 | * |
1411 | * @return 0 on failure and 1 on success. |
1392 | * @return Zero on failure and non-zero on success. |
1412 | */ |
1393 | */ |
1413 | int used_space_insert(as_area_t *a, uintptr_t page, count_t count) |
1394 | int used_space_insert(as_area_t *a, uintptr_t page, count_t count) |
1414 | { |
1395 | { |
1415 | btree_node_t *leaf, *node; |
1396 | btree_node_t *leaf, *node; |
1416 | count_t pages; |
1397 | count_t pages; |
Line 1676... | Line 1657... | ||
1676 | return 1; |
1657 | return 1; |
1677 | } |
1658 | } |
1678 | } |
1659 | } |
1679 | } |
1660 | } |
1680 | 1661 | ||
1681 | panic("Inconsistency detected while adding %" PRIc " pages of used space at " |
1662 | panic("Inconsistency detected while adding %" PRIc " pages of used " |
1682 | "%p.\n", count, page); |
1663 | "space at %p.\n", count, page); |
1683 | } |
1664 | } |
1684 | 1665 | ||
1685 | /** Mark portion of address space area as unused. |
1666 | /** Mark portion of address space area as unused. |
1686 | * |
1667 | * |
1687 | * The address space area must be already locked. |
1668 | * The address space area must be already locked. |
1688 | * |
1669 | * |
1689 | * @param a Address space area. |
1670 | * @param a Address space area. |
1690 | * @param page First page to be marked. |
1671 | * @param page First page to be marked. |
1691 | * @param count Number of page to be marked. |
1672 | * @param count Number of page to be marked. |
1692 | * |
1673 | * |
1693 | * @return 0 on failure and 1 on success. |
1674 | * @return Zero on failure and non-zero on success. |
1694 | */ |
1675 | */ |
1695 | int used_space_remove(as_area_t *a, uintptr_t page, count_t count) |
1676 | int used_space_remove(as_area_t *a, uintptr_t page, count_t count) |
1696 | { |
1677 | { |
1697 | btree_node_t *leaf, *node; |
1678 | btree_node_t *leaf, *node; |
1698 | count_t pages; |
1679 | count_t pages; |
Line 1855... | Line 1836... | ||
1855 | return 0; |
1836 | return 0; |
1856 | } |
1837 | } |
1857 | } |
1838 | } |
1858 | 1839 | ||
1859 | error: |
1840 | error: |
1860 | panic("Inconsistency detected while removing %" PRIc " pages of used space " |
1841 | panic("Inconsistency detected while removing %" PRIc " pages of used " |
1861 | "from %p.\n", count, page); |
1842 | "space from %p.\n", count, page); |
1862 | } |
1843 | } |
1863 | 1844 | ||
1864 | /** Remove reference to address space area share info. |
1845 | /** Remove reference to address space area share info. |
1865 | * |
1846 | * |
1866 | * If the reference count drops to 0, the sh_info is deallocated. |
1847 | * If the reference count drops to 0, the sh_info is deallocated. |
1867 | * |
1848 | * |
1868 | * @param sh_info Pointer to address space area share info. |
1849 | * @param sh_info Pointer to address space area share info. |
1869 | */ |
1850 | */ |
1870 | void sh_info_remove_reference(share_info_t *sh_info) |
1851 | void sh_info_remove_reference(share_info_t *sh_info) |
1871 | { |
1852 | { |
1872 | bool dealloc = false; |
1853 | bool dealloc = false; |
1873 | 1854 | ||
Line 1932... | Line 1913... | ||
1932 | return (unative_t) as_area_destroy(AS, address); |
1913 | return (unative_t) as_area_destroy(AS, address); |
1933 | } |
1914 | } |
1934 | 1915 | ||
1935 | /** Print out information about address space. |
1916 | /** Print out information about address space. |
1936 | * |
1917 | * |
1937 | * @param as Address space. |
1918 | * @param as Address space. |
1938 | */ |
1919 | */ |
1939 | void as_print(as_t *as) |
1920 | void as_print(as_t *as) |
1940 | { |
1921 | { |
1941 | ipl_t ipl; |
1922 | ipl_t ipl; |
1942 | 1923 | ||
Line 1954... | Line 1935... | ||
1954 | unsigned int i; |
1935 | unsigned int i; |
1955 | for (i = 0; i < node->keys; i++) { |
1936 | for (i = 0; i < node->keys; i++) { |
1956 | as_area_t *area = node->value[i]; |
1937 | as_area_t *area = node->value[i]; |
1957 | 1938 | ||
1958 | mutex_lock(&area->lock); |
1939 | mutex_lock(&area->lock); |
1959 | printf("as_area: %p, base=%p, pages=%" PRIc " (%p - %p)\n", |
1940 | printf("as_area: %p, base=%p, pages=%" PRIc |
1960 | area, area->base, area->pages, area->base, |
1941 | " (%p - %p)\n", area, area->base, area->pages, |
1961 | area->base + FRAMES2SIZE(area->pages)); |
1942 | area->base, area->base + FRAMES2SIZE(area->pages)); |
1962 | mutex_unlock(&area->lock); |
1943 | mutex_unlock(&area->lock); |
1963 | } |
1944 | } |
1964 | } |
1945 | } |
1965 | 1946 | ||
1966 | mutex_unlock(&as->lock); |
1947 | mutex_unlock(&as->lock); |