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; |