Rev 3383 | Rev 3422 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3383 | Rev 3384 | ||
---|---|---|---|
Line 109... | Line 109... | ||
109 | LIST_INITIALIZE(inactive_as_with_asid_head); |
109 | LIST_INITIALIZE(inactive_as_with_asid_head); |
110 | 110 | ||
111 | /** Kernel address space. */ |
111 | /** Kernel address space. */ |
112 | as_t *AS_KERNEL = NULL; |
112 | as_t *AS_KERNEL = NULL; |
113 | 113 | ||
114 | static int area_flags_to_page_flags(int aflags); |
114 | static int area_flags_to_page_flags(int); |
115 | 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); |
116 | 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 *); |
117 | as_area_t *avoid_area); |
- | |
118 | static void sh_info_remove_reference(share_info_t *sh_info); |
117 | static void sh_info_remove_reference(share_info_t *); |
119 | 118 | ||
120 | static int as_constructor(void *obj, int flags) |
119 | static int as_constructor(void *obj, int flags) |
121 | { |
120 | { |
122 | as_t *as = (as_t *) obj; |
121 | as_t *as = (as_t *) obj; |
123 | int rc; |
122 | int rc; |
Line 151... | Line 150... | ||
151 | 150 | ||
152 | } |
151 | } |
153 | 152 | ||
154 | /** Create address space. |
153 | /** Create address space. |
155 | * |
154 | * |
156 | * @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. |
|
157 | */ |
157 | */ |
158 | as_t *as_create(int flags) |
158 | as_t *as_create(int flags) |
159 | { |
159 | { |
160 | as_t *as; |
160 | as_t *as; |
161 | 161 | ||
Line 184... | Line 184... | ||
184 | * |
184 | * |
185 | * 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 |
186 | * zero), the address space can be destroyed. |
186 | * zero), the address space can be destroyed. |
187 | * |
187 | * |
188 | * 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. |
|
189 | */ |
191 | */ |
190 | void as_destroy(as_t *as) |
192 | void as_destroy(as_t *as) |
191 | { |
193 | { |
192 | ipl_t ipl; |
194 | ipl_t ipl; |
193 | bool cond; |
195 | bool cond; |
Line 320... | Line 322... | ||
320 | } |
322 | } |
321 | 323 | ||
322 | /** Find address space area and change it. |
324 | /** Find address space area and change it. |
323 | * |
325 | * |
324 | * @param as Address space. |
326 | * @param as Address space. |
325 | * @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. |
326 | * page-aligned. |
328 | * Must be page-aligned. |
327 | * @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. |
|
328 | * @param flags Flags influencing the remap operation. Currently unused. |
331 | * @param flags Flags influencing the remap operation. Currently unused. |
329 | * |
332 | * |
330 | * @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. |
331 | */ |
334 | */ |
332 | 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) |
Line 433... | Line 436... | ||
433 | * address space area. |
436 | * address space area. |
434 | */ |
437 | */ |
435 | 438 | ||
436 | cond = false; /* we are almost done */ |
439 | cond = false; /* we are almost done */ |
437 | i = (start_free - b) >> PAGE_WIDTH; |
440 | i = (start_free - b) >> PAGE_WIDTH; |
438 | if (!used_space_remove(area, start_free, c - i)) |
441 | if (!used_space_remove(area, start_free, |
- | 442 | c - i)) |
|
439 | panic("Could not remove used space.\n"); |
443 | panic("Could not remove used " |
- | 444 | "space.\n"); |
|
440 | } else { |
445 | } else { |
441 | /* |
446 | /* |
442 | * The interval of used space can be |
447 | * The interval of used space can be |
443 | * completely removed. |
448 | * completely removed. |
444 | */ |
449 | */ |
445 | if (!used_space_remove(area, b, c)) |
450 | if (!used_space_remove(area, b, c)) |
446 | panic("Could not remove used space.\n"); |
451 | panic("Could not remove used " |
- | 452 | "space.\n"); |
|
447 | } |
453 | } |
448 | 454 | ||
449 | for (; i < c; i++) { |
455 | for (; i < c; i++) { |
450 | pte_t *pte; |
456 | pte_t *pte; |
451 | 457 | ||
Line 504... | Line 510... | ||
504 | } |
510 | } |
505 | 511 | ||
506 | /** Destroy address space area. |
512 | /** Destroy address space area. |
507 | * |
513 | * |
508 | * @param as Address space. |
514 | * @param as Address space. |
509 | * @param address Address withing the area to be deleted. |
515 | * @param address Address within the area to be deleted. |
510 | * |
516 | * |
511 | * @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. |
512 | */ |
518 | */ |
513 | int as_area_destroy(as_t *as, uintptr_t address) |
519 | int as_area_destroy(as_t *as, uintptr_t address) |
514 | { |
520 | { |
Line 610... | Line 616... | ||
610 | * @param acc_size Expected size of the source area. |
616 | * @param acc_size Expected size of the source area. |
611 | * @param dst_as Pointer to destination address space. |
617 | * @param dst_as Pointer to destination address space. |
612 | * @param dst_base Target base address. |
618 | * @param dst_base Target base address. |
613 | * @param dst_flags_mask Destination address space area flags mask. |
619 | * @param dst_flags_mask Destination address space area flags mask. |
614 | * |
620 | * |
615 | * @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 |
616 | * 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 |
|
617 | * or ENOMEM if there was a problem in allocating destination address space |
624 | * problem in allocating destination address space area. |
618 | * area. ENOTSUP is returned if the address space area backend does not support |
625 | * ENOTSUP is returned if the address space area backend |
619 | * sharing. |
626 | * does not support sharing. |
620 | */ |
627 | */ |
621 | 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, |
622 | 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) |
623 | { |
630 | { |
624 | ipl_t ipl; |
631 | ipl_t ipl; |
Line 736... | Line 743... | ||
736 | * The address space area must be locked prior to this call. |
743 | * The address space area must be locked prior to this call. |
737 | * |
744 | * |
738 | * @param area Address space area. |
745 | * @param area Address space area. |
739 | * @param access Access mode. |
746 | * @param access Access mode. |
740 | * |
747 | * |
741 | * @return False if access violates area's permissions, true otherwise. |
748 | * @return False if access violates area's permissions, true |
- | 749 | * otherwise. |
|
742 | */ |
750 | */ |
743 | 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) |
744 | { |
752 | { |
745 | int flagmap[] = { |
753 | int flagmap[] = { |
746 | [PF_ACCESS_READ] = AS_AREA_READ, |
754 | [PF_ACCESS_READ] = AS_AREA_READ, |
Line 752... | Line 760... | ||
752 | return false; |
760 | return false; |
753 | 761 | ||
754 | return true; |
762 | return true; |
755 | } |
763 | } |
756 | 764 | ||
757 | /** Change adress area flags. |
765 | /** Change adress space area flags. |
758 | * |
766 | * |
759 | * 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. |
760 | * 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. |
761 | * 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 |
762 | * into private anonymous memory (unless it's already there). |
770 | * into private anonymous memory (unless it's already there). |
Line 874... | Line 882... | ||
874 | */ |
882 | */ |
875 | area->flags = flags; |
883 | area->flags = flags; |
876 | 884 | ||
877 | /* |
885 | /* |
878 | * 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 |
879 | * 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 |
880 | * accesed with both the old and the new flags at once. |
888 | * the new flags at once. |
881 | */ |
889 | */ |
882 | frame_idx = 0; |
890 | frame_idx = 0; |
883 | 891 | ||
884 | for (cur = area->used_space.leaf_head.next; |
892 | for (cur = area->used_space.leaf_head.next; |
885 | cur != &area->used_space.leaf_head; cur = cur->next) { |
893 | cur != &area->used_space.leaf_head; cur = cur->next) { |
Line 913... | Line 921... | ||
913 | } |
921 | } |
914 | 922 | ||
915 | 923 | ||
916 | /** Handle page fault within the current address space. |
924 | /** Handle page fault within the current address space. |
917 | * |
925 | * |
918 | * 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 |
919 | * whether the page fault can be resolved by any backend |
- | |
920 | * 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 |
921 | * fault. |
928 | * the page fault. |
922 | * |
929 | * |
923 | * Interrupts are assumed disabled. |
930 | * Interrupts are assumed disabled. |
924 | * |
931 | * |
925 | * @param page Faulting page. |
932 | * @param page Faulting page. |
926 | * @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). |
|
927 | * @param istate Pointer to interrupted state. |
935 | * @param istate Pointer to the interrupted state. |
928 | * |
936 | * |
929 | * @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 |
930 | * 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(). |
|
931 | */ |
940 | */ |
932 | 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) |
933 | { |
942 | { |
934 | pte_t *pte; |
943 | pte_t *pte; |
935 | as_area_t *area; |
944 | as_area_t *area; |
Line 971... | Line 980... | ||
971 | } |
980 | } |
972 | 981 | ||
973 | page_table_lock(AS, false); |
982 | page_table_lock(AS, false); |
974 | 983 | ||
975 | /* |
984 | /* |
976 | * To avoid race condition between two page faults |
985 | * To avoid race condition between two page faults on the same address, |
977 | * on the same address, we need to make sure |
- | |
978 | * the mapping has not been already inserted. |
986 | * we need to make sure the mapping has not been already inserted. |
979 | */ |
987 | */ |
980 | if ((pte = page_mapping_find(AS, page))) { |
988 | if ((pte = page_mapping_find(AS, page))) { |
981 | if (PTE_PRESENT(pte)) { |
989 | if (PTE_PRESENT(pte)) { |
982 | if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) || |
990 | if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) || |
983 | (access == PF_ACCESS_WRITE && PTE_WRITABLE(pte)) || |
991 | (access == PF_ACCESS_WRITE && PTE_WRITABLE(pte)) || |
Line 1140... | Line 1148... | ||
1140 | return area_flags_to_page_flags(a->flags); |
1148 | return area_flags_to_page_flags(a->flags); |
1141 | } |
1149 | } |
1142 | 1150 | ||
1143 | /** Create page table. |
1151 | /** Create page table. |
1144 | * |
1152 | * |
1145 | * Depending on architecture, create either address space |
1153 | * Depending on architecture, create either address space private or global page |
1146 | * private or global page table. |
1154 | * table. |
1147 | * |
1155 | * |
1148 | * @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. |
|
1149 | * |
1158 | * |
1150 | * @return First entry of the page table. |
1159 | * @return First entry of the page table. |
1151 | */ |
1160 | */ |
1152 | pte_t *page_table_create(int flags) |
1161 | pte_t *page_table_create(int flags) |
1153 | { |
1162 | { |
Line 1210... | Line 1219... | ||
1210 | * The address space must be locked and interrupts must be disabled. |
1219 | * The address space must be locked and interrupts must be disabled. |
1211 | * |
1220 | * |
1212 | * @param as Address space. |
1221 | * @param as Address space. |
1213 | * @param va Virtual address. |
1222 | * @param va Virtual address. |
1214 | * |
1223 | * |
1215 | * @return Locked address space area containing va on success or NULL on |
1224 | * @return Locked address space area containing va on success or |
1216 | * failure. |
1225 | * NULL on failure. |
1217 | */ |
1226 | */ |
1218 | 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) |
1219 | { |
1228 | { |
1220 | as_area_t *a; |
1229 | as_area_t *a; |
1221 | btree_node_t *leaf, *lnode; |
1230 | btree_node_t *leaf, *lnode; |
Line 1270... | Line 1279... | ||
1270 | * @param size Size of the area being tested. |
1279 | * @param size Size of the area being tested. |
1271 | * @param avoid_area Do not touch this area. |
1280 | * @param avoid_area Do not touch this area. |
1272 | * |
1281 | * |
1273 | * @return True if there is no conflict, false otherwise. |
1282 | * @return True if there is no conflict, false otherwise. |
1274 | */ |
1283 | */ |
- | 1284 | bool |
|
1275 | 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) |
1276 | as_area_t *avoid_area) |
- | |
1277 | { |
1286 | { |
1278 | as_area_t *a; |
1287 | as_area_t *a; |
1279 | btree_node_t *leaf, *node; |
1288 | btree_node_t *leaf, *node; |
1280 | unsigned int i; |
1289 | unsigned int i; |
1281 | 1290 | ||
Line 1378... | Line 1387... | ||
1378 | * |
1387 | * |
1379 | * @param a Address space area. |
1388 | * @param a Address space area. |
1380 | * @param page First page to be marked. |
1389 | * @param page First page to be marked. |
1381 | * @param count Number of page to be marked. |
1390 | * @param count Number of page to be marked. |
1382 | * |
1391 | * |
1383 | * @return 0 on failure and 1 on success. |
1392 | * @return Zero on failure and non-zero on success. |
1384 | */ |
1393 | */ |
1385 | 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) |
1386 | { |
1395 | { |
1387 | btree_node_t *leaf, *node; |
1396 | btree_node_t *leaf, *node; |
1388 | count_t pages; |
1397 | count_t pages; |
Line 1648... | Line 1657... | ||
1648 | return 1; |
1657 | return 1; |
1649 | } |
1658 | } |
1650 | } |
1659 | } |
1651 | } |
1660 | } |
1652 | 1661 | ||
1653 | panic("Inconsistency detected while adding %" PRIc " pages of used space at " |
1662 | panic("Inconsistency detected while adding %" PRIc " pages of used " |
1654 | "%p.\n", count, page); |
1663 | "space at %p.\n", count, page); |
1655 | } |
1664 | } |
1656 | 1665 | ||
1657 | /** Mark portion of address space area as unused. |
1666 | /** Mark portion of address space area as unused. |
1658 | * |
1667 | * |
1659 | * The address space area must be already locked. |
1668 | * The address space area must be already locked. |
1660 | * |
1669 | * |
1661 | * @param a Address space area. |
1670 | * @param a Address space area. |
1662 | * @param page First page to be marked. |
1671 | * @param page First page to be marked. |
1663 | * @param count Number of page to be marked. |
1672 | * @param count Number of page to be marked. |
1664 | * |
1673 | * |
1665 | * @return 0 on failure and 1 on success. |
1674 | * @return Zero on failure and non-zero on success. |
1666 | */ |
1675 | */ |
1667 | 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) |
1668 | { |
1677 | { |
1669 | btree_node_t *leaf, *node; |
1678 | btree_node_t *leaf, *node; |
1670 | count_t pages; |
1679 | count_t pages; |
Line 1827... | Line 1836... | ||
1827 | return 0; |
1836 | return 0; |
1828 | } |
1837 | } |
1829 | } |
1838 | } |
1830 | 1839 | ||
1831 | error: |
1840 | error: |
1832 | panic("Inconsistency detected while removing %" PRIc " pages of used space " |
1841 | panic("Inconsistency detected while removing %" PRIc " pages of used " |
1833 | "from %p.\n", count, page); |
1842 | "space from %p.\n", count, page); |
1834 | } |
1843 | } |
1835 | 1844 | ||
1836 | /** Remove reference to address space area share info. |
1845 | /** Remove reference to address space area share info. |
1837 | * |
1846 | * |
1838 | * 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. |
Line 1926... | Line 1935... | ||
1926 | unsigned int i; |
1935 | unsigned int i; |
1927 | for (i = 0; i < node->keys; i++) { |
1936 | for (i = 0; i < node->keys; i++) { |
1928 | as_area_t *area = node->value[i]; |
1937 | as_area_t *area = node->value[i]; |
1929 | 1938 | ||
1930 | mutex_lock(&area->lock); |
1939 | mutex_lock(&area->lock); |
1931 | printf("as_area: %p, base=%p, pages=%" PRIc " (%p - %p)\n", |
1940 | printf("as_area: %p, base=%p, pages=%" PRIc |
1932 | area, area->base, area->pages, area->base, |
1941 | " (%p - %p)\n", area, area->base, area->pages, |
1933 | area->base + FRAMES2SIZE(area->pages)); |
1942 | area->base, area->base + FRAMES2SIZE(area->pages)); |
1934 | mutex_unlock(&area->lock); |
1943 | mutex_unlock(&area->lock); |
1935 | } |
1944 | } |
1936 | } |
1945 | } |
1937 | 1946 | ||
1938 | mutex_unlock(&as->lock); |
1947 | mutex_unlock(&as->lock); |