Subversion Repositories HelenOS

Rev

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

Rev 2131 Rev 2292
Line 93... Line 93...
93
 */
93
 */
94
static slab_cache_t *as_slab;
94
static slab_cache_t *as_slab;
95
#endif
95
#endif
96
 
96
 
97
/**
97
/**
-
 
98
 * This lock serializes access to the ASID subsystem.
-
 
99
 * It protects:
98
 * This lock protects inactive_as_with_asid_head list. It must be acquired
100
 * - inactive_as_with_asid_head list
-
 
101
 * - as->asid for each as of the as_t type
99
 * before as_t mutex.
102
 * - asids_allocated counter
100
 */
103
 */
101
SPINLOCK_INITIALIZE(inactive_as_with_asid_lock);
104
SPINLOCK_INITIALIZE(asidlock);
102
 
105
 
103
/**
106
/**
104
 * This list contains address spaces that are not active on any
107
 * This list contains address spaces that are not active on any
105
 * processor and that have valid ASID.
108
 * processor and that have valid ASID.
106
 */
109
 */
Line 203... Line 206...
203
   
206
   
204
    /*
207
    /*
205
     * Since there is no reference to this area,
208
     * Since there is no reference to this area,
206
     * it is safe not to lock its mutex.
209
     * it is safe not to lock its mutex.
207
     */
210
     */
-
 
211
 
208
    ipl = interrupts_disable();
212
    ipl = interrupts_disable();
209
    spinlock_lock(&inactive_as_with_asid_lock);
213
    spinlock_lock(&asidlock);
210
    if (as->asid != ASID_INVALID && as != AS_KERNEL) {
214
    if (as->asid != ASID_INVALID && as != AS_KERNEL) {
211
        if (as != AS && as->cpu_refcount == 0)
215
        if (as != AS && as->cpu_refcount == 0)
212
            list_remove(&as->inactive_as_with_asid_link);
216
            list_remove(&as->inactive_as_with_asid_link);
213
        asid_put(as->asid);
217
        asid_put(as->asid);
214
    }
218
    }
215
    spinlock_unlock(&inactive_as_with_asid_lock);
219
    spinlock_unlock(&asidlock);
216
 
220
 
217
    /*
221
    /*
218
     * Destroy address space areas of the address space.
222
     * Destroy address space areas of the address space.
219
     * The B+tree must be walked carefully because it is
223
     * The B+tree must be walked carefully because it is
220
     * also being destroyed.
224
     * also being destroyed.
Line 409... Line 413...
409
                count_t c =
413
                count_t c =
410
                    (count_t) node->value[node->keys - 1];
414
                    (count_t) node->value[node->keys - 1];
411
                int i = 0;
415
                int i = 0;
412
           
416
           
413
                if (overlaps(b, c * PAGE_SIZE, area->base,
417
                if (overlaps(b, c * PAGE_SIZE, area->base,
414
                    pages*PAGE_SIZE)) {
418
                    pages * PAGE_SIZE)) {
415
                   
419
                   
416
                    if (b + c * PAGE_SIZE <= start_free) {
420
                    if (b + c * PAGE_SIZE <= start_free) {
417
                        /*
421
                        /*
418
                         * The whole interval fits
422
                         * The whole interval fits
419
                         * completely in the resized
423
                         * completely in the resized
Line 551... Line 555...
551
                ASSERT(pte && PTE_VALID(pte) &&
555
                ASSERT(pte && PTE_VALID(pte) &&
552
                    PTE_PRESENT(pte));
556
                    PTE_PRESENT(pte));
553
                if (area->backend &&
557
                if (area->backend &&
554
                    area->backend->frame_free) {
558
                    area->backend->frame_free) {
555
                    area->backend->frame_free(area, b +
559
                    area->backend->frame_free(area, b +
556
                    j * PAGE_SIZE, PTE_GET_FRAME(pte));
560
                        j * PAGE_SIZE, PTE_GET_FRAME(pte));
557
                }
561
                }
558
                page_mapping_remove(as, b + j * PAGE_SIZE);            
562
                page_mapping_remove(as, b + j * PAGE_SIZE);            
559
                page_table_unlock(as, false);
563
                page_table_unlock(as, false);
560
            }
564
            }
561
        }
565
        }
Line 611... Line 615...
611
 *
615
 *
612
 * @return Zero on success or ENOENT if there is no such task or if there is no
616
 * @return Zero on success or ENOENT if there is no such task or if there is no
613
 * such address space area, EPERM if there was a problem in accepting the area
617
 * such address space area, EPERM if there was a problem in accepting the area
614
 * or ENOMEM if there was a problem in allocating destination address space
618
 * or ENOMEM if there was a problem in allocating destination address space
615
 * area. ENOTSUP is returned if the address space area backend does not support
619
 * area. ENOTSUP is returned if the address space area backend does not support
616
 * sharing or if the kernel detects an attempt to create an illegal address
-
 
617
 * alias.
620
 * sharing.
618
 */
621
 */
619
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
622
int as_area_share(as_t *src_as, uintptr_t src_base, size_t acc_size,
620
          as_t *dst_as, uintptr_t dst_base, int dst_flags_mask)
623
          as_t *dst_as, uintptr_t dst_base, int dst_flags_mask)
621
{
624
{
622
    ipl_t ipl;
625
    ipl_t ipl;
Line 665... Line 668...
665
        mutex_unlock(&src_as->lock);
668
        mutex_unlock(&src_as->lock);
666
        interrupts_restore(ipl);
669
        interrupts_restore(ipl);
667
        return EPERM;
670
        return EPERM;
668
    }
671
    }
669
 
672
 
670
#ifdef CONFIG_VIRT_IDX_DCACHE
-
 
671
    if (!(dst_flags_mask & AS_AREA_EXEC)) {
-
 
672
        if (PAGE_COLOR(src_area->base) != PAGE_COLOR(dst_base)) {
-
 
673
            /*
-
 
674
             * Refuse to create an illegal address alias.
-
 
675
             */
-
 
676
            mutex_unlock(&src_area->lock);
-
 
677
            mutex_unlock(&src_as->lock);
-
 
678
            interrupts_restore(ipl);
-
 
679
            return ENOTSUP;
-
 
680
        }
-
 
681
    }
-
 
682
#endif /* CONFIG_VIRT_IDX_DCACHE */
-
 
683
 
-
 
684
    /*
673
    /*
685
     * Now we are committed to sharing the area.
674
     * Now we are committed to sharing the area.
686
     * First, prepare the area for sharing.
675
     * First, prepare the area for sharing.
687
     * Then it will be safe to unlock it.
676
     * Then it will be safe to unlock it.
688
     */
677
     */
Line 873... Line 862...
873
}
862
}
874
 
863
 
875
/** Switch address spaces.
864
/** Switch address spaces.
876
 *
865
 *
877
 * Note that this function cannot sleep as it is essentially a part of
866
 * Note that this function cannot sleep as it is essentially a part of
878
 * scheduling. Sleeping here would lead to deadlock on wakeup.
867
 * scheduling. Sleeping here would lead to deadlock on wakeup. Another
-
 
868
 * thing which is forbidden in this context is locking the address space.
879
 *
869
 *
880
 * @param old Old address space or NULL.
870
 * @param old Old address space or NULL.
881
 * @param new New address space.
871
 * @param new New address space.
882
 */
872
 */
883
void as_switch(as_t *old_as, as_t *new_as)
873
void as_switch(as_t *old_as, as_t *new_as)
884
{
874
{
885
    ipl_t ipl;
-
 
886
    bool needs_asid = false;
-
 
887
   
-
 
888
    ipl = interrupts_disable();
-
 
889
    spinlock_lock(&inactive_as_with_asid_lock);
875
    spinlock_lock(&asidlock);
890
 
876
 
891
    /*
877
    /*
892
     * First, take care of the old address space.
878
     * First, take care of the old address space.
893
     */
879
     */
894
    if (old_as) {
880
    if (old_as) {
895
        mutex_lock_active(&old_as->lock);
-
 
896
        ASSERT(old_as->cpu_refcount);
881
        ASSERT(old_as->cpu_refcount);
897
        if((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
882
        if((--old_as->cpu_refcount == 0) && (old_as != AS_KERNEL)) {
898
            /*
883
            /*
899
             * The old address space is no longer active on
884
             * The old address space is no longer active on
900
             * any processor. It can be appended to the
885
             * any processor. It can be appended to the
901
             * list of inactive address spaces with assigned
886
             * list of inactive address spaces with assigned
902
             * ASID.
887
             * ASID.
903
             */
888
             */
904
             ASSERT(old_as->asid != ASID_INVALID);
889
            ASSERT(old_as->asid != ASID_INVALID);
905
             list_append(&old_as->inactive_as_with_asid_link,
890
            list_append(&old_as->inactive_as_with_asid_link,
906
                 &inactive_as_with_asid_head);
891
                &inactive_as_with_asid_head);
907
        }
892
        }
908
        mutex_unlock(&old_as->lock);
-
 
909
 
893
 
910
        /*
894
        /*
911
         * Perform architecture-specific tasks when the address space
895
         * Perform architecture-specific tasks when the address space
912
         * is being removed from the CPU.
896
         * is being removed from the CPU.
913
         */
897
         */
Line 915... Line 899...
915
    }
899
    }
916
 
900
 
917
    /*
901
    /*
918
     * Second, prepare the new address space.
902
     * Second, prepare the new address space.
919
     */
903
     */
920
    mutex_lock_active(&new_as->lock);
-
 
921
    if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
904
    if ((new_as->cpu_refcount++ == 0) && (new_as != AS_KERNEL)) {
922
        if (new_as->asid != ASID_INVALID) {
905
        if (new_as->asid != ASID_INVALID)
923
            list_remove(&new_as->inactive_as_with_asid_link);
906
            list_remove(&new_as->inactive_as_with_asid_link);
924
        } else {
907
        else
925
            /*
-
 
926
             * Defer call to asid_get() until new_as->lock is released.
-
 
927
             */
-
 
928
            needs_asid = true;
908
            new_as->asid = asid_get();
929
        }
-
 
930
    }
909
    }
931
#ifdef AS_PAGE_TABLE
910
#ifdef AS_PAGE_TABLE
932
    SET_PTL0_ADDRESS(new_as->genarch.page_table);
911
    SET_PTL0_ADDRESS(new_as->genarch.page_table);
933
#endif
912
#endif
934
    mutex_unlock(&new_as->lock);
-
 
935
 
-
 
936
    if (needs_asid) {
-
 
937
        /*
-
 
938
         * Allocation of new ASID was deferred
-
 
939
         * until now in order to avoid deadlock.
-
 
940
         */
-
 
941
        asid_t asid;
-
 
942
       
-
 
943
        asid = asid_get();
-
 
944
        mutex_lock_active(&new_as->lock);
-
 
945
        new_as->asid = asid;
-
 
946
        mutex_unlock(&new_as->lock);
-
 
947
    }
-
 
948
    spinlock_unlock(&inactive_as_with_asid_lock);
-
 
949
    interrupts_restore(ipl);
-
 
950
   
913
   
951
    /*
914
    /*
952
     * Perform architecture-specific steps.
915
     * Perform architecture-specific steps.
953
     * (e.g. write ASID to hardware register etc.)
916
     * (e.g. write ASID to hardware register etc.)
954
     */
917
     */
955
    as_install_arch(new_as);
918
    as_install_arch(new_as);
-
 
919
 
-
 
920
    spinlock_unlock(&asidlock);
956
   
921
   
957
    AS = new_as;
922
    AS = new_as;
958
}
923
}
959
 
924
 
960
/** Convert address space area flags to page flags.
925
/** Convert address space area flags to page flags.