Subversion Repositories HelenOS

Rev

Rev 3186 | Rev 3240 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3186 Rev 3222
Line 769... Line 769...
769
        return false;
769
        return false;
770
   
770
   
771
    return true;
771
    return true;
772
}
772
}
773
 
773
 
-
 
774
/** Change adress area flags.
-
 
775
 *
-
 
776
 * 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.
-
 
778
 * In order for this to work properly, this may copy the data
-
 
779
 * into private anonymous memory (unless it's already there).
-
 
780
 *
-
 
781
 * @param as Address space.
-
 
782
 * @param flags Flags of the area memory.
-
 
783
 * @param address Address withing the area to be changed.
-
 
784
 *
-
 
785
 * @return Zero on success or a value from @ref errno.h on failure.
-
 
786
 */
-
 
787
int as_area_change_flags(as_t *as, int flags, uintptr_t address)
-
 
788
{
-
 
789
    as_area_t *area;
-
 
790
    uintptr_t base;
-
 
791
    link_t *cur;
-
 
792
    ipl_t ipl;
-
 
793
    int page_flags;
-
 
794
    uintptr_t *old_frame;
-
 
795
    index_t frame_idx;
-
 
796
    count_t used_pages;
-
 
797
 
-
 
798
    /* Flags for the new memory mapping */
-
 
799
    page_flags = area_flags_to_page_flags(flags);
-
 
800
 
-
 
801
    ipl = interrupts_disable();
-
 
802
    mutex_lock(&as->lock);
-
 
803
 
-
 
804
    area = find_area_and_lock(as, address);
-
 
805
    if (!area) {
-
 
806
        mutex_unlock(&as->lock);
-
 
807
        interrupts_restore(ipl);
-
 
808
        return ENOENT;
-
 
809
    }
-
 
810
 
-
 
811
    if (area->sh_info || area->backend != &anon_backend) {
-
 
812
        /* Copying shared areas not supported yet */
-
 
813
        /* Copying non-anonymous memory not supported yet */
-
 
814
        mutex_unlock(&area->lock);
-
 
815
        mutex_unlock(&as->lock);
-
 
816
        interrupts_restore(ipl);
-
 
817
        return ENOTSUP;
-
 
818
    }
-
 
819
 
-
 
820
    base = area->base;
-
 
821
 
-
 
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
    /*
-
 
842
     * Start TLB shootdown sequence.
-
 
843
     */
-
 
844
    tlb_shootdown_start(TLB_INVL_PAGES, as->asid, area->base, area->pages);
-
 
845
 
-
 
846
    /*
-
 
847
     * Remove used pages from page tables and remember their frame
-
 
848
     * numbers.
-
 
849
     */
-
 
850
    frame_idx = 0;
-
 
851
 
-
 
852
    for (cur = area->used_space.leaf_head.next;
-
 
853
        cur != &area->used_space.leaf_head; cur = cur->next) {
-
 
854
        btree_node_t *node;
-
 
855
        unsigned int i;
-
 
856
       
-
 
857
        node = list_get_instance(cur, btree_node_t, leaf_link);
-
 
858
        for (i = 0; i < node->keys; i++) {
-
 
859
            uintptr_t b = node->key[i];
-
 
860
            count_t j;
-
 
861
            pte_t *pte;
-
 
862
           
-
 
863
            for (j = 0; j < (count_t) node->value[i]; j++) {
-
 
864
                page_table_lock(as, false);
-
 
865
                pte = page_mapping_find(as, b + j * PAGE_SIZE);
-
 
866
                ASSERT(pte && PTE_VALID(pte) &&
-
 
867
                    PTE_PRESENT(pte));
-
 
868
                old_frame[frame_idx++] = PTE_GET_FRAME(pte);
-
 
869
 
-
 
870
                /* Remove old mapping */
-
 
871
                page_mapping_remove(as, b + j * PAGE_SIZE);
-
 
872
                page_table_unlock(as, false);
-
 
873
            }
-
 
874
        }
-
 
875
    }
-
 
876
 
-
 
877
    /*
-
 
878
     * Finish TLB shootdown sequence.
-
 
879
     */
-
 
880
 
-
 
881
    tlb_invalidate_pages(as->asid, area->base, area->pages);
-
 
882
    /*
-
 
883
     * Invalidate potential software translation caches (e.g. TSB on
-
 
884
     * sparc64).
-
 
885
     */
-
 
886
    as_invalidate_translation_cache(as, area->base, area->pages);
-
 
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;
-
 
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
 
-
 
920
    mutex_unlock(&area->lock);
-
 
921
    mutex_unlock(&as->lock);
-
 
922
    interrupts_restore(ipl);
-
 
923
 
-
 
924
    return 0;
-
 
925
}
-
 
926
 
-
 
927
 
774
/** Handle page fault within the current address space.
928
/** Handle page fault within the current address space.
775
 *
929
 *
776
 * This is the high-level page fault handler. It decides
930
 * This is the high-level page fault handler. It decides
777
 * whether the page fault can be resolved by any backend
931
 * whether the page fault can be resolved by any backend
778
 * and if so, it invokes the backend to resolve the page
932
 * and if so, it invokes the backend to resolve the page
Line 1764... Line 1918...
1764
unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags)
1918
unative_t sys_as_area_resize(uintptr_t address, size_t size, int flags)
1765
{
1919
{
1766
    return (unative_t) as_area_resize(AS, address, size, 0);
1920
    return (unative_t) as_area_resize(AS, address, size, 0);
1767
}
1921
}
1768
 
1922
 
-
 
1923
/** Wrapper for as_area_change_flags(). */
-
 
1924
unative_t sys_as_area_change_flags(uintptr_t address, int flags)
-
 
1925
{
-
 
1926
    return (unative_t) as_area_change_flags(AS, flags, address);
-
 
1927
}
-
 
1928
 
1769
/** Wrapper for as_area_destroy(). */
1929
/** Wrapper for as_area_destroy(). */
1770
unative_t sys_as_area_destroy(uintptr_t address)
1930
unative_t sys_as_area_destroy(uintptr_t address)
1771
{
1931
{
1772
    return (unative_t) as_area_destroy(AS, address);
1932
    return (unative_t) as_area_destroy(AS, address);
1773
}
1933
}