Subversion Repositories HelenOS

Rev

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

Rev 3013 Rev 3036
Line 984... Line 984...
984
 
984
 
985
restart:
985
restart:
986
    mutex_lock(&AS->lock);
986
    mutex_lock(&AS->lock);
987
    ipl = interrupts_disable();
987
    ipl = interrupts_disable();
988
    area = find_area_and_lock(AS, page);
988
    area = find_area_and_lock(AS, page);
-
 
989
    if (area->backend != &anon_backend || area->sh_info != NULL) {
-
 
990
        mutex_unlock(&area->lock);
-
 
991
        mutex_unlock(&AS->lock);
-
 
992
        interrupts_restore(ipl);
-
 
993
 
-
 
994
        rc = as_area_make_writeable(area->base);
-
 
995
        if (rc != 0) return rc;
-
 
996
 
-
 
997
        goto restart;
-
 
998
    }
989
 
999
 
990
    pte = page_mapping_find(AS, page);
1000
    pte = page_mapping_find(AS, page);
991
    if (! (pte && PTE_VALID(pte) && PTE_PRESENT(pte)) ) {
1001
    if (! (pte && PTE_VALID(pte) && PTE_PRESENT(pte)) ) {
992
        mutex_unlock(&area->lock);
1002
        mutex_unlock(&area->lock);
993
        mutex_unlock(&AS->lock);
1003
        mutex_unlock(&AS->lock);
Line 1031... Line 1041...
1031
    }
1041
    }
1032
 
1042
 
1033
    return EOK;
1043
    return EOK;
1034
}
1044
}
1035
 
1045
 
-
 
1046
/** Make sure area is private and anonymous.
-
 
1047
 *
-
 
1048
 * Not atomic atm.
-
 
1049
 * @param address   Virtual address in AS.
-
 
1050
 */
-
 
1051
int as_area_make_writeable(uintptr_t address)
-
 
1052
{
-
 
1053
    ipl_t ipl;
-
 
1054
    as_area_t *area;
-
 
1055
    uintptr_t base, page;
-
 
1056
    uintptr_t old_frame, frame;
-
 
1057
    size_t size;
-
 
1058
    int flags;
-
 
1059
    int page_flags;
-
 
1060
    pte_t *pte;
-
 
1061
    int rc;
-
 
1062
    uintptr_t *pagemap;
-
 
1063
 
-
 
1064
    ipl = interrupts_disable();
-
 
1065
    mutex_lock(&AS->lock);
-
 
1066
    area = find_area_and_lock(AS, address);
-
 
1067
    if (!area) {
-
 
1068
        /*
-
 
1069
         * Could not find the address space area.
-
 
1070
         */
-
 
1071
        mutex_unlock(&AS->lock);
-
 
1072
        interrupts_restore(ipl);
-
 
1073
        return ENOENT;
-
 
1074
    }
-
 
1075
 
-
 
1076
    if (area->backend == &anon_backend && !area->sh_info) {
-
 
1077
        /* Nothing to do */
-
 
1078
        mutex_unlock(&area->lock);
-
 
1079
        mutex_unlock(&AS->lock);
-
 
1080
        interrupts_restore(ipl);
-
 
1081
        return EOK;
-
 
1082
    }
-
 
1083
 
-
 
1084
    base = area->base;
-
 
1085
    size = area->pages * PAGE_SIZE;
-
 
1086
    flags = area->flags;
-
 
1087
    page_flags = as_area_get_flags(area);
-
 
1088
 
-
 
1089
    pagemap = malloc(area->pages * sizeof(uintptr_t), 0);
-
 
1090
    page_table_lock(AS, false);
-
 
1091
 
-
 
1092
    for (page = base; page < base + size; page += PAGE_SIZE) {
-
 
1093
        pte = page_mapping_find(AS, page);
-
 
1094
        if (!pte || !PTE_PRESENT(pte) || !PTE_READABLE(pte)) {
-
 
1095
            /* Fetch the missing page */
-
 
1096
            if (!area->backend || !area->backend->page_fault) {
-
 
1097
                page_table_unlock(AS, false);
-
 
1098
                mutex_unlock(&area->lock);
-
 
1099
                mutex_unlock(&AS->lock);
-
 
1100
                interrupts_restore(ipl);
-
 
1101
                return EINVAL;
-
 
1102
            }
-
 
1103
            if (area->backend->page_fault(area, page, PF_ACCESS_READ) != AS_PF_OK) {
-
 
1104
                page_table_unlock(AS, false);
-
 
1105
                mutex_unlock(&area->lock);
-
 
1106
                mutex_unlock(&AS->lock);
-
 
1107
                interrupts_restore(ipl);
-
 
1108
                return EINVAL;
-
 
1109
            }
-
 
1110
        }
-
 
1111
        ASSERT(PTE_VALID(pte));
-
 
1112
 
-
 
1113
        old_frame = PTE_GET_FRAME(pte);
-
 
1114
 
-
 
1115
        frame = (uintptr_t)frame_alloc(ONE_FRAME, 0);
-
 
1116
        memcpy((void *) PA2KA(frame), (void *)PA2KA(old_frame),
-
 
1117
            FRAME_SIZE);
-
 
1118
 
-
 
1119
        pagemap[(page - base) / PAGE_SIZE] = frame;
-
 
1120
    }
-
 
1121
 
-
 
1122
    page_table_unlock(AS, false);
-
 
1123
    mutex_unlock(&area->lock);
-
 
1124
    mutex_unlock(&AS->lock);
-
 
1125
    interrupts_restore(ipl);
-
 
1126
 
-
 
1127
    rc = as_area_destroy(AS, address);
-
 
1128
    if (rc < 0) {
-
 
1129
        free(pagemap);
-
 
1130
        return rc;
-
 
1131
    }
-
 
1132
 
-
 
1133
    area = as_area_create(AS, flags, size, base, AS_AREA_ATTR_PARTIAL,
-
 
1134
        &anon_backend, NULL);
-
 
1135
    if (area == NULL) {
-
 
1136
        free(pagemap);
-
 
1137
        return rc;
-
 
1138
    }
-
 
1139
 
-
 
1140
    mutex_lock(&AS->lock);
-
 
1141
    mutex_lock(&area->lock);
-
 
1142
    page_table_lock(AS, false);
-
 
1143
    for (page = base; page < base + size; page += PAGE_SIZE) {
-
 
1144
        frame = pagemap[(page - base) / PAGE_SIZE];
-
 
1145
 
-
 
1146
        page_mapping_insert(AS, page, frame, page_flags);
-
 
1147
        if (!used_space_insert(area, page, 1))
-
 
1148
            panic("Could not insert used space.\n");
-
 
1149
    }
-
 
1150
 
-
 
1151
    page_table_unlock(AS, false);
-
 
1152
 
-
 
1153
    area->attributes &= ~AS_AREA_ATTR_PARTIAL;
-
 
1154
 
-
 
1155
    mutex_unlock(&area->lock);
-
 
1156
    mutex_unlock(&AS->lock);
-
 
1157
 
-
 
1158
    free(pagemap);
-
 
1159
 
-
 
1160
    return EOK;
-
 
1161
}
-
 
1162
 
1036
/** Convert address space area flags to page flags.
1163
/** Convert address space area flags to page flags.
1037
 *
1164
 *
1038
 * @param aflags Flags of some address space area.
1165
 * @param aflags Flags of some address space area.
1039
 *
1166
 *
1040
 * @return Flags to be passed to page_mapping_insert().
1167
 * @return Flags to be passed to page_mapping_insert().