Rev 3153 | Rev 3191 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3153 | Rev 3156 | ||
|---|---|---|---|
| Line 789... | Line 789... | ||
| 789 | as_area_t *area; |
789 | as_area_t *area; |
| 790 | uintptr_t base; |
790 | uintptr_t base; |
| 791 | link_t *cur; |
791 | link_t *cur; |
| 792 | ipl_t ipl; |
792 | ipl_t ipl; |
| 793 | int page_flags; |
793 | int page_flags; |
| 794 | uintptr_t old_frame; |
794 | uintptr_t *old_frame; |
| - | 795 | index_t frame_idx; |
|
| - | 796 | count_t used_pages; |
|
| 795 | 797 | ||
| 796 | /* Flags for the new memory mapping */ |
798 | /* Flags for the new memory mapping */ |
| 797 | page_flags = area_flags_to_page_flags(flags); |
799 | page_flags = area_flags_to_page_flags(flags); |
| 798 | 800 | ||
| 799 | ipl = interrupts_disable(); |
801 | ipl = interrupts_disable(); |
| Line 816... | Line 818... | ||
| 816 | } |
818 | } |
| 817 | 819 | ||
| 818 | base = area->base; |
820 | base = area->base; |
| 819 | 821 | ||
| 820 | /* |
822 | /* |
| - | 823 | * Compute total number of used pages in the used_space B+tree |
|
| - | 824 | */ |
|
| - | 825 | used_pages = 0; |
|
| - | 826 | ||
| - | 827 | for (cur = area->used_space.leaf_head.next; |
|
| - | 828 | cur != &area->used_space.leaf_head; cur = cur->next) { |
|
| - | 829 | btree_node_t *node; |
|
| - | 830 | unsigned int i; |
|
| - | 831 | ||
| - | 832 | node = list_get_instance(cur, btree_node_t, leaf_link); |
|
| - | 833 | for (i = 0; i < node->keys; i++) { |
|
| - | 834 | used_pages += (count_t) node->value[i]; |
|
| - | 835 | } |
|
| - | 836 | } |
|
| - | 837 | ||
| - | 838 | /* An array for storing frame numbers */ |
|
| - | 839 | old_frame = malloc(used_pages * sizeof(uintptr_t), 0); |
|
| - | 840 | ||
| - | 841 | /* |
|
| 821 | * Start TLB shootdown sequence. |
842 | * Start TLB shootdown sequence. |
| 822 | */ |
843 | */ |
| 823 | tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages); |
844 | tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages); |
| 824 | 845 | ||
| 825 | /* |
846 | /* |
| 826 | * Visit only the pages mapped by used_space B+tree. |
847 | * Remove used pages from page tables and remember their frame |
| - | 848 | * numbers. |
|
| 827 | */ |
849 | */ |
| - | 850 | frame_idx = 0; |
|
| - | 851 | ||
| 828 | for (cur = area->used_space.leaf_head.next; |
852 | for (cur = area->used_space.leaf_head.next; |
| 829 | cur != &area->used_space.leaf_head; cur = cur->next) { |
853 | cur != &area->used_space.leaf_head; cur = cur->next) { |
| 830 | btree_node_t *node; |
854 | btree_node_t *node; |
| 831 | unsigned int i; |
855 | unsigned int i; |
| 832 | 856 | ||
| Line 839... | Line 863... | ||
| 839 | for (j = 0; j < (count_t) node->value[i]; j++) { |
863 | for (j = 0; j < (count_t) node->value[i]; j++) { |
| 840 | page_table_lock(as, false); |
864 | page_table_lock(as, false); |
| 841 | pte = page_mapping_find(as, b + j * PAGE_SIZE); |
865 | pte = page_mapping_find(as, b + j * PAGE_SIZE); |
| 842 | ASSERT(pte && PTE_VALID(pte) && |
866 | ASSERT(pte && PTE_VALID(pte) && |
| 843 | PTE_PRESENT(pte)); |
867 | PTE_PRESENT(pte)); |
| 844 | old_frame = PTE_GET_FRAME(pte); |
868 | old_frame[frame_idx++] = PTE_GET_FRAME(pte); |
| 845 | 869 | ||
| 846 | /* Remove old mapping and insert the new one */ |
870 | /* Remove old mapping */ |
| 847 | page_mapping_remove(as, b + j * PAGE_SIZE); |
871 | page_mapping_remove(as, b + j * PAGE_SIZE); |
| 848 | page_mapping_insert(as, b + j * PAGE_SIZE, |
- | |
| 849 | old_frame, page_flags); |
- | |
| 850 | - | ||
| 851 | page_table_unlock(as, false); |
872 | page_table_unlock(as, false); |
| 852 | } |
873 | } |
| 853 | } |
874 | } |
| 854 | } |
875 | } |
| 855 | 876 | ||
| Line 862... | Line 883... | ||
| 862 | * Invalidate potential software translation caches (e.g. TSB on |
883 | * Invalidate potential software translation caches (e.g. TSB on |
| 863 | * sparc64). |
884 | * sparc64). |
| 864 | */ |
885 | */ |
| 865 | as_invalidate_translation_cache(as, area->base, area->pages); |
886 | as_invalidate_translation_cache(as, area->base, area->pages); |
| 866 | tlb_shootdown_finalize(); |
887 | tlb_shootdown_finalize(); |
| - | 888 | ||
| - | 889 | /* |
|
| - | 890 | * 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 |
|
| - | 892 | * accesed with both the old and the new flags at once. |
|
| - | 893 | */ |
|
| - | 894 | frame_idx = 0; |
|
| - | 895 | ||
| - | 896 | for (cur = area->used_space.leaf_head.next; |
|
| - | 897 | cur != &area->used_space.leaf_head; cur = cur->next) { |
|
| - | 898 | btree_node_t *node; |
|
| - | 899 | unsigned int i; |
|
| 867 | 900 | ||
| - | 901 | node = list_get_instance(cur, btree_node_t, leaf_link); |
|
| - | 902 | for (i = 0; i < node->keys; i++) { |
|
| - | 903 | uintptr_t b = node->key[i]; |
|
| - | 904 | count_t j; |
|
| - | 905 | ||
| - | 906 | for (j = 0; j < (count_t) node->value[i]; j++) { |
|
| - | 907 | page_table_lock(as, false); |
|
| - | 908 | ||
| - | 909 | /* Insert the new mapping */ |
|
| - | 910 | page_mapping_insert(as, b + j * PAGE_SIZE, |
|
| - | 911 | old_frame[frame_idx++], page_flags); |
|
| - | 912 | ||
| - | 913 | page_table_unlock(as, false); |
|
| - | 914 | } |
|
| - | 915 | } |
|
| - | 916 | } |
|
| - | 917 | ||
| - | 918 | free(old_frame); |
|
| - | 919 | ||
| 868 | mutex_unlock(&area->lock); |
920 | mutex_unlock(&area->lock); |
| 869 | mutex_unlock(&as->lock); |
921 | mutex_unlock(&as->lock); |
| 870 | interrupts_restore(ipl); |
922 | interrupts_restore(ipl); |
| 871 | 923 | ||
| 872 | return 0; |
924 | return 0; |