00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00039 #include <mm/as.h>
00040 #include <mm/page.h>
00041 #include <genarch/mm/page_pt.h>
00042 #include <genarch/mm/page_ht.h>
00043 #include <mm/frame.h>
00044 #include <mm/slab.h>
00045 #include <synch/mutex.h>
00046 #include <adt/list.h>
00047 #include <adt/btree.h>
00048 #include <errno.h>
00049 #include <arch/types.h>
00050 #include <typedefs.h>
00051 #include <align.h>
00052 #include <arch.h>
00053
00054 static int anon_page_fault(as_area_t *area, __address addr, pf_access_t access);
00055 static void anon_frame_free(as_area_t *area, __address page, __address frame);
00056 static void anon_share(as_area_t *area);
00057
00058 mem_backend_t anon_backend = {
00059 .page_fault = anon_page_fault,
00060 .frame_free = anon_frame_free,
00061 .share = anon_share
00062 };
00063
00074 int anon_page_fault(as_area_t *area, __address addr, pf_access_t access)
00075 {
00076 __address frame;
00077
00078 if (!as_area_check_access(area, access))
00079 return AS_PF_FAULT;
00080
00081 if (area->sh_info) {
00082 btree_node_t *leaf;
00083
00084
00085
00086
00087
00088
00089
00090 mutex_lock(&area->sh_info->lock);
00091 frame = (__address) btree_search(&area->sh_info->pagemap,
00092 ALIGN_DOWN(addr, PAGE_SIZE) - area->base, &leaf);
00093 if (!frame) {
00094 bool allocate = true;
00095 int i;
00096
00097
00098
00099
00100
00101 for (i = 0; i < leaf->keys; i++) {
00102 if (leaf->key[i] == ALIGN_DOWN(addr, PAGE_SIZE)) {
00103 allocate = false;
00104 break;
00105 }
00106 }
00107 if (allocate) {
00108 frame = PFN2ADDR(frame_alloc(ONE_FRAME, 0));
00109 memsetb(PA2KA(frame), FRAME_SIZE, 0);
00110
00111
00112
00113
00114 btree_insert(&area->sh_info->pagemap, ALIGN_DOWN(addr, PAGE_SIZE) - area->base, (void *) frame, leaf);
00115 }
00116 }
00117 frame_reference_add(ADDR2PFN(frame));
00118 mutex_unlock(&area->sh_info->lock);
00119 } else {
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 frame = PFN2ADDR(frame_alloc(ONE_FRAME, 0));
00136 memsetb(PA2KA(frame), FRAME_SIZE, 0);
00137 }
00138
00139
00140
00141
00142
00143
00144 page_mapping_insert(AS, addr, frame, as_area_get_flags(area));
00145 if (!used_space_insert(area, ALIGN_DOWN(addr, PAGE_SIZE), 1))
00146 panic("Could not insert used space.\n");
00147
00148 return AS_PF_OK;
00149 }
00150
00159 void anon_frame_free(as_area_t *area, __address page, __address frame)
00160 {
00161 frame_free(ADDR2PFN(frame));
00162 }
00163
00173 void anon_share(as_area_t *area)
00174 {
00175 link_t *cur;
00176
00177
00178
00179
00180 mutex_lock(&area->sh_info->lock);
00181 for (cur = area->used_space.leaf_head.next; cur != &area->used_space.leaf_head; cur = cur->next) {
00182 btree_node_t *node;
00183 int i;
00184
00185 node = list_get_instance(cur, btree_node_t, leaf_link);
00186 for (i = 0; i < node->keys; i++) {
00187 __address base = node->key[i];
00188 count_t count = (count_t) node->value[i];
00189 int j;
00190
00191 for (j = 0; j < count; j++) {
00192 pte_t *pte;
00193
00194 page_table_lock(area->as, false);
00195 pte = page_mapping_find(area->as, base + j*PAGE_SIZE);
00196 ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte));
00197 btree_insert(&area->sh_info->pagemap, (base + j*PAGE_SIZE) - area->base,
00198 (void *) PTE_GET_FRAME(pte), NULL);
00199 page_table_unlock(area->as, false);
00200 frame_reference_add(ADDR2PFN(PTE_GET_FRAME(pte)));
00201 }
00202
00203 }
00204 }
00205 mutex_unlock(&area->sh_info->lock);
00206 }
00207