Diff markup
001 !! 001
002 002
003 003
004 004
005 005
006 006
007 007
008 008
009 009
010 010
011 011
012 012
013 013
014 014
015 015
016 016
017 017
018 018
019 #include <sos/assert.h> 019 #include <sos/assert.h>
020 #include <sos/list.h> 020 #include <sos/list.h>
021 #include <sos/physmem.h> 021 #include <sos/physmem.h>
022 #include <sos/kmem_slab.h> 022 #include <sos/kmem_slab.h>
023 #include <drivers/bochs.h> 023 #include <drivers/bochs.h>
024 #include <hwcore/mm_context.h> 024 #include <hwcore/mm_context.h>
025 #include <hwcore/paging.h> 025 #include <hwcore/paging.h>
026 #include <drivers/zero.h> 026 #include <drivers/zero.h>
027 027
028 #include "umem_vmm.h" 028 #include "umem_vmm.h"
029 029
030 030
031 struct sos_umem_vmm_as 031 struct sos_umem_vmm_as
032 { 032 {
033 033
034 struct sos_process * process; 034 struct sos_process * process;
035 035
036 036
037 struct sos_mm_context * mm_context; 037 struct sos_mm_context * mm_context;
038 038
039 039
040 struct sos_umem_vmm_vr * list_vr; 040 struct sos_umem_vmm_vr * list_vr;
041 041
042 042
043 sos_uaddr_t heap_start; 043 sos_uaddr_t heap_start;
044 sos_size_t heap_size; 044 sos_size_t heap_size;
045 045
046 046
047 sos_size_t phys_total; 047 sos_size_t phys_total;
048 struct vm_usage 048 struct vm_usage
049 { 049 {
050 sos_size_t overall; 050 sos_size_t overall;
051 sos_size_t ro, rw, code 051 sos_size_t ro, rw, code ;
052 } vm_total, vm_shrd; 052 } vm_total, vm_shrd;
053 053
054 054
055 sos_size_t pgflt_cow; 055 sos_size_t pgflt_cow;
056 sos_size_t pgflt_page_in; 056 sos_size_t pgflt_page_in;
057 sos_size_t pgflt_invalid; 057 sos_size_t pgflt_invalid;
058 }; 058 };
059 059
060 060
061 struct sos_umem_vmm_vr 061 struct sos_umem_vmm_vr
062 { 062 {
063 063
064 struct sos_umem_vmm_as *address_space; 064 struct sos_umem_vmm_as *address_space;
065 065
066 066
067 sos_uaddr_t start; 067 sos_uaddr_t start;
068 sos_size_t size; 068 sos_size_t size;
069 069
070 070
071 071
072 sos_ui32_t access_rights; 072 sos_ui32_t access_rights;
073 073
074 074
075 075
076 076
077 sos_ui32_t flags; 077 sos_ui32_t flags;
078 078
079 079
080 080
081 081
082 082
083 struct sos_umem_vmm_vr_ops *ops; 083 struct sos_umem_vmm_vr_ops *ops;
084 084
085 085
086 struct sos_umem_vmm_mapped_resource *mapped_ 086 struct sos_umem_vmm_mapped_resource *mapped_resource;
087 sos_luoffset_t offset_in_resource; 087 sos_luoffset_t offset_in_resource;
088 088
089 089
090 090
091 struct sos_umem_vmm_vr *prev_in_as, *next_in 091 struct sos_umem_vmm_vr *prev_in_as, *next_in_as;
092 092
093 093
094 094
095 struct sos_umem_vmm_vr *prev_in_mapped_resou 095 struct sos_umem_vmm_vr *prev_in_mapped_resource, *next_in_mapped_resource;
096 }; 096 };
097 097
098 098
099 099
100 100
101 101
102 static struct sos_kslab_cache * cache_of_as; 102 static struct sos_kslab_cache * cache_of_as;
103 static struct sos_kslab_cache * cache_of_vr; 103 static struct sos_kslab_cache * cache_of_vr;
104 104
105 105
106 106
107 void sos_dump_as(const struct sos_umem_vmm_as 107 void sos_dump_as(const struct sos_umem_vmm_as * as, const char *str)
108 { 108 {
109 struct sos_umem_vmm_vr *vr; 109 struct sos_umem_vmm_vr *vr;
110 int nb_vr; 110 int nb_vr;
111 111
112 sos_bochs_printf("AS %p - %s:\n", as, str); 112 sos_bochs_printf("AS %p - %s:\n", as, str);
113 sos_bochs_printf(" physical mem: %x\n", 113 sos_bochs_printf(" physical mem: %x\n",
114 as->phys_total); 114 as->phys_total);
115 sos_bochs_printf(" VM (all/ro+rw/exec) tot 115 sos_bochs_printf(" VM (all/ro+rw/exec) tot:%x/%x+%x/%x shrd:%x/%x+%x/%x\n",
116 as->vm_total.overall, 116 as->vm_total.overall,
117 as->vm_total.ro, as->vm_tot 117 as->vm_total.ro, as->vm_total.rw, as->vm_total.code,
118 as->vm_shrd.overall, 118 as->vm_shrd.overall,
119 as->vm_shrd.ro, as->vm_shrd 119 as->vm_shrd.ro, as->vm_shrd.rw, as->vm_shrd.code);
120 sos_bochs_printf(" pgflt cow=%d pgin=%d in 120 sos_bochs_printf(" pgflt cow=%d pgin=%d inv=%d\n",
121 as->pgflt_cow, as->pgflt_pa 121 as->pgflt_cow, as->pgflt_page_in, as->pgflt_invalid);
122 list_foreach_named(as->list_vr, vr, nb_vr, p 122 list_foreach_named(as->list_vr, vr, nb_vr, prev_in_as, next_in_as)
123 { 123 {
124 sos_bochs_printf(" VR[%d]=%x: [%x,%x[ ( 124 sos_bochs_printf(" VR[%d]=%x: [%x,%x[ (sz=%x) mr=(%x)+%llx %c%c%c fl=%x\n",
125 nb_vr, (unsigned)vr, 125 nb_vr, (unsigned)vr,
126 vr->start, vr->start + 126 vr->start, vr->start + vr->size, vr->size,
127 (unsigned)vr->mapped_re 127 (unsigned)vr->mapped_resource,
128 vr->offset_in_resource, 128 vr->offset_in_resource,
129 (vr->access_rights & SO 129 (vr->access_rights & SOS_VM_MAP_PROT_READ)?'r':'-',
130 (vr->access_rights & SO 130 (vr->access_rights & SOS_VM_MAP_PROT_WRITE)?'w':'-',
131 (vr->access_rights & SO 131 (vr->access_rights & SOS_VM_MAP_PROT_EXEC)?'x':'-',
132 (unsigned)vr->flags); 132 (unsigned)vr->flags);
133 } 133 }
134 sos_bochs_printf("FIN (%s)\n", str); 134 sos_bochs_printf("FIN (%s)\n", str);
135 } 135 }
136 136
137 137
138 138
139 139
140 140
141 141
142 sos_paddr_t sos_zero_physpage = 0 !! 142 sos_paddr_t sos_zero_page = 0 ;
143 sos_vaddr_t sos_zero_kernelpage = 0 <<
144 143
145 144
146 145
147 146
148 147
149 148
150 149
151 150
152 151
153 static struct sos_umem_vmm_vr * 152 static struct sos_umem_vmm_vr *
154 find_enclosing_or_next_vr(struct sos_umem_vmm_ 153 find_enclosing_or_next_vr(struct sos_umem_vmm_as * as,
155 sos_uaddr_t uaddr); 154 sos_uaddr_t uaddr);
156 155
157 156
158 157
159 158
160 159
161 160
162 static struct sos_umem_vmm_vr * 161 static struct sos_umem_vmm_vr *
163 find_first_intersecting_vr(struct sos_umem_vmm 162 find_first_intersecting_vr(struct sos_umem_vmm_as * as,
164 sos_uaddr_t start_u 163 sos_uaddr_t start_uaddr, sos_size_t size);
165 164
166 165
167 166
168 167
169 168
170 169
171 170
172 171
173 172
174 static sos_uaddr_t 173 static sos_uaddr_t
175 find_first_free_interval(struct sos_umem_vmm_a 174 find_first_free_interval(struct sos_umem_vmm_as * as,
176 sos_uaddr_t hint_uadd 175 sos_uaddr_t hint_uaddr, sos_size_t size);
177 176
178 177
179 178
180 179
181 static void 180 static void
182 as_account_change_of_vr_protection(struct sos_ 181 as_account_change_of_vr_protection(struct sos_umem_vmm_as * as,
183 sos_bool_t 182 sos_bool_t is_shared,
184 sos_size_t 183 sos_size_t size,
185 sos_ui32_t 184 sos_ui32_t prev_access_rights,
186 sos_ui32_t 185 sos_ui32_t new_access_rights);
187 186
188 187
189 sos_ret_t sos_umem_vmm_subsystem_setup() 188 sos_ret_t sos_umem_vmm_subsystem_setup()
190 { 189 {
>> 190 sos_vaddr_t vaddr_zero_page;
>> 191
191 192
192 193
193 sos_zero_kernelpage = sos_kmem_vmm_alloc(1, !! 194 vaddr_zero_page = sos_kmem_vmm_alloc(1, SOS_KMEM_VMM_MAP);
194 if (sos_zero_kernelpage == (sos_vaddr_t)NULL !! 195 if (vaddr_zero_page == (sos_vaddr_t)NULL)
195 return -SOS_ENOMEM; 196 return -SOS_ENOMEM;
196 memset((void*)sos_zero_kernelpage, 0x0, SOS_ !! 197 memset((void*)vaddr_zero_page, 0x0, SOS_PAGE_SIZE);
197 198
198 199
199 sos_zero_physpage = sos_paging_get_paddr(sos !! 200 sos_zero_page = sos_paging_get_paddr(vaddr_zero_page);
200 SOS_ASSERT_FATAL(NULL != (void*)sos_zero_phy !! 201 SOS_ASSERT_FATAL(NULL != (void*)sos_zero_page);
201 sos_physmem_ref_physpage_at(sos_zero_physpag !! 202 sos_physmem_ref_physpage_at(sos_zero_page);
>> 203
>> 204
>> 205
>> 206 sos_paging_unmap(vaddr_zero_page);
202 207
203 208
204 cache_of_as 209 cache_of_as
205 = sos_kmem_cache_create("Address space str 210 = sos_kmem_cache_create("Address space structures",
206 sizeof(struct sos_ 211 sizeof(struct sos_umem_vmm_as),
207 1, 0, 212 1, 0,
208 SOS_KSLAB_CREATE_M 213 SOS_KSLAB_CREATE_MAP
209 | SOS_KSLAB_CREATE 214 | SOS_KSLAB_CREATE_ZERO);
210 if (! cache_of_as) 215 if (! cache_of_as)
211 { 216 {
212 sos_physmem_unref_physpage(sos_zero_phys !! 217 sos_physmem_unref_physpage(sos_zero_page);
213 return -SOS_ENOMEM; 218 return -SOS_ENOMEM;
214 } 219 }
215 220
216 cache_of_vr 221 cache_of_vr
217 = sos_kmem_cache_create("Virtual Region st 222 = sos_kmem_cache_create("Virtual Region structures",
218 sizeof(struct sos_ 223 sizeof(struct sos_umem_vmm_vr),
219 1, 0, 224 1, 0,
220 SOS_KSLAB_CREATE_M 225 SOS_KSLAB_CREATE_MAP
221 | SOS_KSLAB_CREATE 226 | SOS_KSLAB_CREATE_ZERO);
222 if (! cache_of_vr) 227 if (! cache_of_vr)
223 { 228 {
224 sos_physmem_unref_physpage(sos_zero_phys !! 229 sos_physmem_unref_physpage(sos_zero_page);
225 sos_kmem_cache_destroy(cache_of_as); 230 sos_kmem_cache_destroy(cache_of_as);
226 return -SOS_ENOMEM; 231 return -SOS_ENOMEM;
227 } 232 }
228 233
229 return SOS_OK; 234 return SOS_OK;
230 } 235 }
231 236
232 237
233 struct sos_umem_vmm_as * 238 struct sos_umem_vmm_as *
234 sos_umem_vmm_create_empty_as(struct sos_proces 239 sos_umem_vmm_create_empty_as(struct sos_process *owner)
235 { 240 {
236 struct sos_umem_vmm_as * as 241 struct sos_umem_vmm_as * as
237 = (struct sos_umem_vmm_as *) sos_kmem_cach 242 = (struct sos_umem_vmm_as *) sos_kmem_cache_alloc(cache_of_as, 0);
238 if (! as) 243 if (! as)
239 return NULL; 244 return NULL;
240 245
241 as->mm_context = sos_mm_context_create(); 246 as->mm_context = sos_mm_context_create();
242 if (NULL == as->mm_context) 247 if (NULL == as->mm_context)
243 { 248 {
244 249
245 sos_kmem_cache_free((sos_vaddr_t)as); 250 sos_kmem_cache_free((sos_vaddr_t)as);
246 return NULL; 251 return NULL;
247 } 252 }
248 253
249 as->process = owner; 254 as->process = owner;
250 return as; 255 return as;
251 } 256 }
252 257
253 258
254 struct sos_umem_vmm_as * 259 struct sos_umem_vmm_as *
255 sos_umem_vmm_duplicate_current_thread_as(struc 260 sos_umem_vmm_duplicate_current_thread_as(struct sos_process *owner)
256 { 261 {
257 __label__ undo_creation; 262 __label__ undo_creation;
258 struct sos_umem_vmm_as * my_as; 263 struct sos_umem_vmm_as * my_as;
259 struct sos_umem_vmm_vr * model_vr; 264 struct sos_umem_vmm_vr * model_vr;
260 int nb_vr; 265 int nb_vr;
261 266
262 struct sos_umem_vmm_as * new_as 267 struct sos_umem_vmm_as * new_as
263 = (struct sos_umem_vmm_as *) sos_kmem_cach 268 = (struct sos_umem_vmm_as *) sos_kmem_cache_alloc(cache_of_as, 0);
264 if (! new_as) 269 if (! new_as)
265 return NULL; 270 return NULL;
266 271
267 my_as = sos_process_get_address_space(sos_th 272 my_as = sos_process_get_address_space(sos_thread_get_current()->process);
268 new_as->process = owner; 273 new_as->process = owner;
269 list_init_named(new_as->list_vr, prev_in_as, 274 list_init_named(new_as->list_vr, prev_in_as, next_in_as);
270 275
271 276
272 277
273 278
274 279
275 280
276 SOS_ASSERT_FATAL(SOS_OK 281 SOS_ASSERT_FATAL(SOS_OK
277 == sos_thread_prepare_user_ 282 == sos_thread_prepare_user_space_access(my_as,
278 283 (sos_vaddr_t)
279 284 NULL));
280 285
281 286
282 list_foreach_named(my_as->list_vr, model_vr, 287 list_foreach_named(my_as->list_vr, model_vr, nb_vr, prev_in_as, next_in_as)
283 { 288 {
284 struct sos_umem_vmm_vr * vr; 289 struct sos_umem_vmm_vr * vr;
285 290
286 291
287 if ( !(model_vr->flags & SOS_VR_MAP_SHAR 292 if ( !(model_vr->flags & SOS_VR_MAP_SHARED)
288 && (model_vr->access_rights & SOS_V 293 && (model_vr->access_rights & SOS_VM_MAP_PROT_WRITE) )
289 { 294 {
290 295
291 296
292 SOS_ASSERT_FATAL(SOS_OK 297 SOS_ASSERT_FATAL(SOS_OK
293 == sos_paging_prepa 298 == sos_paging_prepare_COW(model_vr->start,
294 299 model_vr->size));
295 } 300 }
296 301
297 302
298 vr = (struct sos_umem_vmm_vr *) sos_kmem 303 vr = (struct sos_umem_vmm_vr *) sos_kmem_cache_alloc(cache_of_vr, 0);
299 if (! vr) 304 if (! vr)
300 goto undo_creation; 305 goto undo_creation;
301 memcpy(vr, model_vr, sizeof(*vr)); 306 memcpy(vr, model_vr, sizeof(*vr));
302 vr->address_space = new_as; 307 vr->address_space = new_as;
303 308
304 309
305 if (vr->ops && vr->ops->ref) 310 if (vr->ops && vr->ops->ref)
306 vr->ops->ref(vr); 311 vr->ops->ref(vr);
307 312
308 313
309 list_add_tail_named(new_as->list_vr, vr, 314 list_add_tail_named(new_as->list_vr, vr, prev_in_as, next_in_as);
310 315
311 316
312 list_add_tail_named(model_vr->mapped_res 317 list_add_tail_named(model_vr->mapped_resource->list_vr, vr,
313 prev_in_mapped_resou 318 prev_in_mapped_resource,
314 next_in_mapped_resou 319 next_in_mapped_resource);
315 } 320 }
316 321
317 322
318 new_as->mm_context = sos_mm_context_duplicat 323 new_as->mm_context = sos_mm_context_duplicate(my_as->mm_context);
319 if (NULL == new_as->mm_context) 324 if (NULL == new_as->mm_context)
320 goto undo_creation; 325 goto undo_creation;
321 326
322 327
323 new_as->heap_start = my_as->heap_start; 328 new_as->heap_start = my_as->heap_start;
324 new_as->heap_size = my_as->heap_size; 329 new_as->heap_size = my_as->heap_size;
325 new_as->phys_total = my_as->phys_total; 330 new_as->phys_total = my_as->phys_total;
326 memcpy(& new_as->vm_total, & my_as->vm_total 331 memcpy(& new_as->vm_total, & my_as->vm_total, sizeof(struct vm_usage));
327 memcpy(& new_as->vm_shrd, & my_as->vm_shrd, 332 memcpy(& new_as->vm_shrd, & my_as->vm_shrd, sizeof(struct vm_usage));
328 SOS_ASSERT_FATAL(SOS_OK == sos_thread_end_us 333 SOS_ASSERT_FATAL(SOS_OK == sos_thread_end_user_space_access());
329 return new_as; 334 return new_as;
330 335
331 336
332 undo_creation: 337 undo_creation:
333 SOS_ASSERT_FATAL(SOS_OK == sos_thread_end_us 338 SOS_ASSERT_FATAL(SOS_OK == sos_thread_end_user_space_access());
334 sos_umem_vmm_delete_as(new_as); 339 sos_umem_vmm_delete_as(new_as);
335 return NULL; 340 return NULL;
336 } 341 }
337 342
338 343
339 sos_ret_t 344 sos_ret_t
340 sos_umem_vmm_delete_as(struct sos_umem_vmm_as 345 sos_umem_vmm_delete_as(struct sos_umem_vmm_as * as)
341 { 346 {
342 while(! list_is_empty_named(as->list_vr, pre 347 while(! list_is_empty_named(as->list_vr, prev_in_as, next_in_as))
343 { 348 {
344 struct sos_umem_vmm_vr * vr; 349 struct sos_umem_vmm_vr * vr;
345 vr = list_get_head_named(as->list_vr, pr 350 vr = list_get_head_named(as->list_vr, prev_in_as, next_in_as);
346 351
347 352
348 list_pop_head_named(as->list_vr, prev_in 353 list_pop_head_named(as->list_vr, prev_in_as, next_in_as);
349 list_delete_named(vr->mapped_resource->l 354 list_delete_named(vr->mapped_resource->list_vr, vr,
350 prev_in_mapped_resourc 355 prev_in_mapped_resource,
351 next_in_mapped_resourc 356 next_in_mapped_resource);
352 357
353 358
354 359
355 if (vr->ops) 360 if (vr->ops)
356 { 361 {
357 if (vr->ops->unmap) 362 if (vr->ops->unmap)
358 vr->ops->unmap(vr, vr->start, vr-> 363 vr->ops->unmap(vr, vr->start, vr->size);
359 if (vr->ops->unref) 364 if (vr->ops->unref)
360 vr->ops->unref(vr); 365 vr->ops->unref(vr);
361 } 366 }
362 367
363 sos_kmem_cache_free((sos_vaddr_t)vr); 368 sos_kmem_cache_free((sos_vaddr_t)vr);
364 } 369 }
365 370
366 371
367 if (as->mm_context) 372 if (as->mm_context)
368 sos_mm_context_unref(as->mm_context); 373 sos_mm_context_unref(as->mm_context);
369 374
370 375
371 sos_kmem_cache_free((sos_vaddr_t)as); 376 sos_kmem_cache_free((sos_vaddr_t)as);
372 377
373 return SOS_OK; 378 return SOS_OK;
374 } 379 }
375 380
376 381
377 struct sos_process * 382 struct sos_process *
378 sos_umem_vmm_get_process(struct sos_umem_vmm_a 383 sos_umem_vmm_get_process(struct sos_umem_vmm_as * as)
379 { 384 {
380 return as->process; 385 return as->process;
381 } 386 }
382 387
383 388
384 struct sos_mm_context * 389 struct sos_mm_context *
385 sos_umem_vmm_get_mm_context(struct sos_umem_vm 390 sos_umem_vmm_get_mm_context(struct sos_umem_vmm_as * as)
386 { 391 {
387 return as->mm_context; 392 return as->mm_context;
388 } 393 }
389 394
390 395
391 struct sos_umem_vmm_vr * 396 struct sos_umem_vmm_vr *
392 sos_umem_vmm_get_vr_at_address(struct sos_umem 397 sos_umem_vmm_get_vr_at_address(struct sos_umem_vmm_as * as,
393 sos_uaddr_t uad 398 sos_uaddr_t uaddr)
394 { 399 {
395 struct sos_umem_vmm_vr * vr; 400 struct sos_umem_vmm_vr * vr;
396 vr = find_enclosing_or_next_vr(as, uaddr); 401 vr = find_enclosing_or_next_vr(as, uaddr);
397 if (! vr) 402 if (! vr)
398 return NULL; 403 return NULL;
399 404
400 405
401 if (uaddr < vr->start) 406 if (uaddr < vr->start)
402 return NULL; 407 return NULL;
403 408
404 return vr; 409 return vr;
405 } 410 }
406 411
407 412
408 struct sos_umem_vmm_as * 413 struct sos_umem_vmm_as *
409 sos_umem_vmm_get_as_of_vr(struct sos_umem_vmm_ 414 sos_umem_vmm_get_as_of_vr(struct sos_umem_vmm_vr * vr)
410 { 415 {
411 return vr->address_space; 416 return vr->address_space;
412 } 417 }
413 418
414 419
415 struct sos_umem_vmm_vr_ops * 420 struct sos_umem_vmm_vr_ops *
416 sos_umem_vmm_get_ops_of_vr(struct sos_umem_vmm 421 sos_umem_vmm_get_ops_of_vr(struct sos_umem_vmm_vr * vr)
417 { 422 {
418 return vr->ops; 423 return vr->ops;
419 } 424 }
420 425
421 426
422 sos_ui32_t sos_umem_vmm_get_prot_of_vr(struct 427 sos_ui32_t sos_umem_vmm_get_prot_of_vr(struct sos_umem_vmm_vr * vr)
423 { 428 {
424 return vr->access_rights; 429 return vr->access_rights;
425 } 430 }
426 431
427 432
428 sos_ui32_t sos_umem_vmm_get_flags_of_vr(struct 433 sos_ui32_t sos_umem_vmm_get_flags_of_vr(struct sos_umem_vmm_vr * vr)
429 { 434 {
430 return vr->flags; 435 return vr->flags;
431 } 436 }
432 437
433 438
434 struct sos_umem_vmm_mapped_resource * 439 struct sos_umem_vmm_mapped_resource *
435 sos_umem_vmm_get_mapped_resource_of_vr(struct 440 sos_umem_vmm_get_mapped_resource_of_vr(struct sos_umem_vmm_vr * vr)
436 { 441 {
437 return vr->mapped_resource; 442 return vr->mapped_resource;
438 } 443 }
439 444
440 445
441 sos_uaddr_t sos_umem_vmm_get_start_of_vr(struc 446 sos_uaddr_t sos_umem_vmm_get_start_of_vr(struct sos_umem_vmm_vr * vr)
442 { 447 {
443 return vr->start; 448 return vr->start;
444 } 449 }
445 450
446 451
447 sos_size_t sos_umem_vmm_get_size_of_vr(struct 452 sos_size_t sos_umem_vmm_get_size_of_vr(struct sos_umem_vmm_vr * vr)
448 { 453 {
449 return vr->size; 454 return vr->size;
450 } 455 }
451 456
452 457
453 sos_luoffset_t sos_umem_vmm_get_offset_in_reso 458 sos_luoffset_t sos_umem_vmm_get_offset_in_resource(struct sos_umem_vmm_vr * vr)
454 { 459 {
455 return vr->offset_in_resource; 460 return vr->offset_in_resource;
456 } 461 }
457 462
458 463
459 sos_ret_t 464 sos_ret_t
460 sos_umem_vmm_set_ops_of_vr(struct sos_umem_vmm 465 sos_umem_vmm_set_ops_of_vr(struct sos_umem_vmm_vr * vr,
461 struct sos_umem_vmm 466 struct sos_umem_vmm_vr_ops * ops)
462 { 467 {
463 468
464 SOS_ASSERT_FATAL(NULL == vr->ops); 469 SOS_ASSERT_FATAL(NULL == vr->ops);
465 470
466 vr->ops = ops; 471 vr->ops = ops;
467 return SOS_OK; 472 return SOS_OK;
468 } 473 }
469 474
470 475
471 476
472 477
473 478
474 479
475 #define INTERNAL_MAP_CALLED_FROM_MREMAP (1 << 480 #define INTERNAL_MAP_CALLED_FROM_MREMAP (1 << 8)
476 481
477 sos_ret_t 482 sos_ret_t
478 sos_umem_vmm_map(struct sos_umem_vmm_as * as, 483 sos_umem_vmm_map(struct sos_umem_vmm_as * as,
479 sos_uaddr_t * uaddr 484 sos_uaddr_t * uaddr, sos_size_t size,
480 sos_ui32_t access_rights, 485 sos_ui32_t access_rights,
481 sos_ui32_t flags, 486 sos_ui32_t flags,
482 struct sos_umem_vmm_mapped_re 487 struct sos_umem_vmm_mapped_resource * resource,
483 sos_luoffset_t offset_in_reso 488 sos_luoffset_t offset_in_resource)
484 { 489 {
485 __label__ return_mmap; 490 __label__ return_mmap;
486 sos_uaddr_t hint_uaddr; 491 sos_uaddr_t hint_uaddr;
487 struct sos_umem_vmm_vr *prev_vr, *next_vr, * 492 struct sos_umem_vmm_vr *prev_vr, *next_vr, *vr, *preallocated_vr;
488 sos_bool_t merge_with_preceding, merge_with_ 493 sos_bool_t merge_with_preceding, merge_with_next, used_preallocated_vr;
489 sos_bool_t internal_map_called_from_mremap 494 sos_bool_t internal_map_called_from_mremap
490 = (flags & INTERNAL_MAP_CALLED_FROM_MREMAP 495 = (flags & INTERNAL_MAP_CALLED_FROM_MREMAP);
491 496
492 sos_ret_t retval = SOS_OK; 497 sos_ret_t retval = SOS_OK;
493 used_preallocated_vr = FALSE; 498 used_preallocated_vr = FALSE;
494 hint_uaddr = *uaddr; 499 hint_uaddr = *uaddr;
495 500
496 501
497 *uaddr = (sos_vaddr_t)NULL; 502 *uaddr = (sos_vaddr_t)NULL;
498 503
499 if (! resource) 504 if (! resource)
500 return -SOS_EINVAL; 505 return -SOS_EINVAL;
501 if (! resource->mmap) 506 if (! resource->mmap)
502 return -SOS_EPERM; 507 return -SOS_EPERM;
503 508
504 if (! SOS_IS_PAGE_ALIGNED(hint_uaddr)) 509 if (! SOS_IS_PAGE_ALIGNED(hint_uaddr))
505 return -SOS_EINVAL; 510 return -SOS_EINVAL;
506 511
507 if (size <= 0) 512 if (size <= 0)
508 return -SOS_EINVAL; 513 return -SOS_EINVAL;
509 size = SOS_PAGE_ALIGN_SUP(size); 514 size = SOS_PAGE_ALIGN_SUP(size);
510 515
511 if (flags & SOS_VR_MAP_SHARED) 516 if (flags & SOS_VR_MAP_SHARED)
512 { 517 {
513 518
514 if ( ( (access_rights & SOS_VM_MAP_PROT_ 519 if ( ( (access_rights & SOS_VM_MAP_PROT_READ)
515 && !(resource->allowed_access_rig 520 && !(resource->allowed_access_rights & SOS_VM_MAP_PROT_READ) )
516 || ( (access_rights & SOS_VM_MAP_PR 521 || ( (access_rights & SOS_VM_MAP_PROT_WRITE)
517 && !(resource->allowed_access_ 522 && !(resource->allowed_access_rights & SOS_VM_MAP_PROT_WRITE) )
518 || ( (access_rights & SOS_VM_MAP_PR 523 || ( (access_rights & SOS_VM_MAP_PROT_EXEC)
519 && !(resource->allowed_access_ 524 && !(resource->allowed_access_rights & SOS_VM_MAP_PROT_EXEC)) )
520 return -SOS_EPERM; 525 return -SOS_EPERM;
521 } 526 }
522 527
523 528
524 if ( !internal_map_called_from_mremap 529 if ( !internal_map_called_from_mremap
525 && ( resource->flags & SOS_MAPPED_RESOU 530 && ( resource->flags & SOS_MAPPED_RESOURCE_ANONYMOUS ) )
526 531
527 { 532 {
528 533
529 } 534 }
530 535
531 536
532 else if (offset_in_resource + size <= offset 537 else if (offset_in_resource + size <= offset_in_resource)
533 return -SOS_EINVAL; 538 return -SOS_EINVAL;
534 539
535 540
536 access_rights &= (SOS_VM_MAP_PROT_READ 541 access_rights &= (SOS_VM_MAP_PROT_READ
537 | SOS_VM_MAP_PROT_WRITE 542 | SOS_VM_MAP_PROT_WRITE
538 | SOS_VM_MAP_PROT_EXEC); 543 | SOS_VM_MAP_PROT_EXEC);
539 flags &= (SOS_VR_MAP_SHARED 544 flags &= (SOS_VR_MAP_SHARED
540 | SOS_VR_MAP_FIXED); 545 | SOS_VR_MAP_FIXED);
541 546
542 547
543 548
544 549
545 preallocated_vr 550 preallocated_vr
546 = (struct sos_umem_vmm_vr *)sos_kmem_cache 551 = (struct sos_umem_vmm_vr *)sos_kmem_cache_alloc(cache_of_vr, 0);
547 if (! preallocated_vr) 552 if (! preallocated_vr)
548 return -SOS_ENOMEM; 553 return -SOS_ENOMEM;
549 554
550 555
551 if (flags & SOS_VR_MAP_FIXED) 556 if (flags & SOS_VR_MAP_FIXED)
552 { 557 {
553 558
554 559
555 560
556 561
557 562
558 if (hint_uaddr < SOS_PAGING_BASE_USER_AD 563 if (hint_uaddr < SOS_PAGING_BASE_USER_ADDRESS)
559 { retval = -SOS_EINVAL; goto return_mm 564 { retval = -SOS_EINVAL; goto return_mmap; }
560 if (hint_uaddr > SOS_PAGING_TOP_USER_ADD 565 if (hint_uaddr > SOS_PAGING_TOP_USER_ADDRESS - size)
561 { retval = -SOS_EINVAL; goto return_mm 566 { retval = -SOS_EINVAL; goto return_mmap; }
562 567
563 568
564 retval = sos_umem_vmm_unmap(as, hint_uad 569 retval = sos_umem_vmm_unmap(as, hint_uaddr, size);
565 if (SOS_OK != retval) 570 if (SOS_OK != retval)
566 { goto return_mmap; } 571 { goto return_mmap; }
567 } 572 }
568 else 573 else
569 { 574 {
570 575
571 576
572 577
573 578
574 579
575 hint_uaddr = find_first_free_interval(as 580 hint_uaddr = find_first_free_interval(as, hint_uaddr, size);
576 if (! hint_uaddr) 581 if (! hint_uaddr)
577 { retval = -SOS_ENOMEM; goto return_mm 582 { retval = -SOS_ENOMEM; goto return_mmap; }
578 } 583 }
579 584
580 585
581 586
582 587
583 if ( !internal_map_called_from_mremap 588 if ( !internal_map_called_from_mremap
584 && (resource->flags & SOS_MAPPED_RESOUR 589 && (resource->flags & SOS_MAPPED_RESOURCE_ANONYMOUS ) )
585 offset_in_resource = hint_uaddr; 590 offset_in_resource = hint_uaddr;
586 591
587 592
588 593
589 next_vr = find_enclosing_or_next_vr(as, hint 594 next_vr = find_enclosing_or_next_vr(as, hint_uaddr);
590 if (next_vr) 595 if (next_vr)
591 { 596 {
592 597
593 prev_vr = next_vr->prev_in_as; 598 prev_vr = next_vr->prev_in_as;
594 599
595 600
596 if (prev_vr->start > hint_uaddr) 601 if (prev_vr->start > hint_uaddr)
597 prev_vr = NULL; 602 prev_vr = NULL;
598 } 603 }
599 else 604 else
600 { 605 {
601 606
602 prev_vr = list_get_tail_named(as->list_v 607 prev_vr = list_get_tail_named(as->list_vr, prev_in_as, next_in_as);
603 } 608 }
604 609
605 610
606 merge_with_preceding 611 merge_with_preceding
607 = ( (NULL != prev_vr) 612 = ( (NULL != prev_vr)
608 && (prev_vr->mapped_resource == resour 613 && (prev_vr->mapped_resource == resource)
609 && (prev_vr->offset_in_resource + prev 614 && (prev_vr->offset_in_resource + prev_vr->size == offset_in_resource)
610 && (prev_vr->start + prev_vr->size == 615 && (prev_vr->start + prev_vr->size == hint_uaddr)
611 && (prev_vr->flags == flags) 616 && (prev_vr->flags == flags)
612 && (prev_vr->access_rights == access_r 617 && (prev_vr->access_rights == access_rights) );
613 618
614 619
615 merge_with_next 620 merge_with_next
616 = ( (NULL != next_vr) 621 = ( (NULL != next_vr)
617 && (next_vr->mapped_resource == resour 622 && (next_vr->mapped_resource == resource)
618 && (offset_in_resource + size == next_ 623 && (offset_in_resource + size == next_vr->offset_in_resource)
619 && (hint_uaddr + size == next_vr->star 624 && (hint_uaddr + size == next_vr->start)
620 && (next_vr->flags == flags) 625 && (next_vr->flags == flags)
621 && (next_vr->access_rights == access_r 626 && (next_vr->access_rights == access_rights) );
622 627
623 if (merge_with_preceding && merge_with_next) 628 if (merge_with_preceding && merge_with_next)
624 { 629 {
625 630
626 vr = prev_vr; 631 vr = prev_vr;
627 vr->size += size + next_vr->size; 632 vr->size += size + next_vr->size;
628 633
629 634
630 list_delete_named(as->list_vr, next_vr, 635 list_delete_named(as->list_vr, next_vr, prev_in_as, next_in_as);
631 list_delete_named(next_vr->mapped_resour 636 list_delete_named(next_vr->mapped_resource->list_vr, next_vr,
632 prev_in_mapped_resourc 637 prev_in_mapped_resource, next_in_mapped_resource);
633 638
634 if (next_vr->ops && next_vr->ops->unref) 639 if (next_vr->ops && next_vr->ops->unref)
635 next_vr->ops->unref(next_vr); 640 next_vr->ops->unref(next_vr);
636 641
637 sos_kmem_vmm_free((sos_vaddr_t) next_vr) 642 sos_kmem_vmm_free((sos_vaddr_t) next_vr);
638 } 643 }
639 else if (merge_with_preceding) 644 else if (merge_with_preceding)
640 { 645 {
641 646
642 vr = prev_vr; 647 vr = prev_vr;
643 vr->size += size; 648 vr->size += size;
644 } 649 }
645 else if (merge_with_next) 650 else if (merge_with_next)
646 { 651 {
647 652
648 vr = next_vr; 653 vr = next_vr;
649 vr->start -= size; 654 vr->start -= size;
650 vr->size += size; 655 vr->size += size;
651 } 656 }
652 else 657 else
653 { 658 {
654 659
655 660
656 vr = preallocated_vr; 661 vr = preallocated_vr;
657 used_preallocated_vr = TRUE; 662 used_preallocated_vr = TRUE;
658 663
659 vr->start = hint_uaddr; 664 vr->start = hint_uaddr;
660 vr->size = size; 665 vr->size = size;
661 vr->access_rights = access_rights; 666 vr->access_rights = access_rights;
662 vr->flags = flags; 667 vr->flags = flags;
663 vr->mapped_resource = resource; 668 vr->mapped_resource = resource;
664 vr->offset_in_resource = offset_in_resou 669 vr->offset_in_resource = offset_in_resource;
665 670
666 671
667 vr->address_space = as; 672 vr->address_space = as;
668 if (prev_vr) 673 if (prev_vr)
669 list_insert_after_named(as->list_vr, p 674 list_insert_after_named(as->list_vr, prev_vr, vr,
670 prev_in_as, ne 675 prev_in_as, next_in_as);
671 else 676 else
672 list_add_head_named(as->list_vr, vr, p 677 list_add_head_named(as->list_vr, vr, prev_in_as, next_in_as);
673 <<
674 list_add_tail_named(vr->mapped_resource- 678 list_add_tail_named(vr->mapped_resource->list_vr, vr,
675 prev_in_mapped_resou 679 prev_in_mapped_resource,
676 next_in_mapped_resou 680 next_in_mapped_resource);
677 681
678 682
679 if (resource && resource->mmap) 683 if (resource && resource->mmap)
680 { 684 {
681 retval = resource->mmap(vr); 685 retval = resource->mmap(vr);
682 if (SOS_OK != retval) 686 if (SOS_OK != retval)
683 { 687 {
684 retval = sos_umem_vmm_unmap(as, 688 retval = sos_umem_vmm_unmap(as, vr->start, vr->size);
685 goto return_mmap; 689 goto return_mmap;
686 } 690 }
687 691
688 692
689 SOS_ASSERT_FATAL(vr->ops && vr->ops- 693 SOS_ASSERT_FATAL(vr->ops && vr->ops->page_in);
690 } 694 }
691 695
692 if (vr->ops && vr->ops->ref) 696 if (vr->ops && vr->ops->ref)
693 vr->ops->ref(vr); 697 vr->ops->ref(vr);
694 } 698 }
695 699
696 700
697 *uaddr = hint_uaddr; 701 *uaddr = hint_uaddr;
698 as_account_change_of_vr_protection(as, vr->f 702 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
699 size, 0, 703 size, 0, vr->access_rights);
700 retval = SOS_OK; 704 retval = SOS_OK;
701 705
702 return_mmap: 706 return_mmap:
703 if (! used_preallocated_vr) 707 if (! used_preallocated_vr)
704 sos_kmem_vmm_free((sos_vaddr_t)preallocate 708 sos_kmem_vmm_free((sos_vaddr_t)preallocated_vr);
705 709
706 return retval; 710 return retval;
707 } 711 }
708 712
709 713
710 sos_ret_t 714 sos_ret_t
711 sos_umem_vmm_unmap(struct sos_umem_vmm_as * as 715 sos_umem_vmm_unmap(struct sos_umem_vmm_as * as,
712 sos_uaddr_t uaddr, sos_size 716 sos_uaddr_t uaddr, sos_size_t size)
713 { 717 {
714 struct sos_umem_vmm_vr *vr, *preallocated_vr 718 struct sos_umem_vmm_vr *vr, *preallocated_vr;
715 sos_bool_t need_to_setup_mmu; 719 sos_bool_t need_to_setup_mmu;
716 sos_bool_t used_preallocated_vr; 720 sos_bool_t used_preallocated_vr;
717 721
718 if (! SOS_IS_PAGE_ALIGNED(uaddr)) 722 if (! SOS_IS_PAGE_ALIGNED(uaddr))
719 return -SOS_EINVAL; 723 return -SOS_EINVAL;
720 if (size <= 0) 724 if (size <= 0)
721 return -SOS_EINVAL; 725 return -SOS_EINVAL;
722 size = SOS_PAGE_ALIGN_SUP(size); 726 size = SOS_PAGE_ALIGN_SUP(size);
723 727
724 728
725 if (uaddr < SOS_PAGING_BASE_USER_ADDRESS) 729 if (uaddr < SOS_PAGING_BASE_USER_ADDRESS)
726 return -SOS_EINVAL; 730 return -SOS_EINVAL;
727 if (uaddr > SOS_PAGING_TOP_USER_ADDRESS - si 731 if (uaddr > SOS_PAGING_TOP_USER_ADDRESS - size)
728 return -SOS_EINVAL; 732 return -SOS_EINVAL;
729 733
730 734
731 735
732 736
733 737
734 738
735 used_preallocated_vr = FALSE; 739 used_preallocated_vr = FALSE;
736 preallocated_vr 740 preallocated_vr
737 = (struct sos_umem_vmm_vr *)sos_kmem_cache 741 = (struct sos_umem_vmm_vr *)sos_kmem_cache_alloc(cache_of_vr, 0);
738 if (! preallocated_vr) 742 if (! preallocated_vr)
739 return -SOS_ENOMEM; 743 return -SOS_ENOMEM;
740 744
741 745
742 vr = find_first_intersecting_vr(as, uaddr, s 746 vr = find_first_intersecting_vr(as, uaddr, size);
743 747
744 748
745 while (NULL != vr) 749 while (NULL != vr)
746 { 750 {
747 751
748 752
749 if (vr->start + vr->size <= uaddr) 753 if (vr->start + vr->size <= uaddr)
750 754
751 break; 755 break;
752 756
753 757
754 if (uaddr + size <= vr->start) 758 if (uaddr + size <= vr->start)
755 759
756 break; 760 break;
757 761
758 762
759 if ((vr->start >= uaddr) 763 if ((vr->start >= uaddr)
760 && (vr->start + vr->size <= uaddr + 764 && (vr->start + vr->size <= uaddr + size))
761 { 765 {
762 struct sos_umem_vmm_vr *next_vr; 766 struct sos_umem_vmm_vr *next_vr;
763 767
764 768
765 if (vr->ops && vr->ops->unmap) 769 if (vr->ops && vr->ops->unmap)
766 vr->ops->unmap(vr, vr->start, vr-> 770 vr->ops->unmap(vr, vr->start, vr->size);
767 771
768 772
769 next_vr = vr->next_in_as; 773 next_vr = vr->next_in_as;
770 if (next_vr == vr) 774 if (next_vr == vr)
771 next_vr = NULL; 775 next_vr = NULL;
772 list_delete_named(as->list_vr, vr, p 776 list_delete_named(as->list_vr, vr, prev_in_as, next_in_as);
773 777
774 778
775 list_delete_named(vr->mapped_resourc 779 list_delete_named(vr->mapped_resource->list_vr, vr,
776 prev_in_mapped_res 780 prev_in_mapped_resource,
777 next_in_mapped_res 781 next_in_mapped_resource);
778 782
779 if (vr->ops && vr->ops->unref) 783 if (vr->ops && vr->ops->unref)
780 vr->ops->unref(vr); 784 vr->ops->unref(vr);
781 785
782 as_account_change_of_vr_protection(a 786 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
783 v 787 vr->size, vr->access_rights, 0);
784 sos_kmem_vmm_free((sos_vaddr_t)vr); 788 sos_kmem_vmm_free((sos_vaddr_t)vr);
785 789
786 790
787 vr = next_vr; 791 vr = next_vr;
788 continue; 792 continue;
789 } 793 }
790 794
791 795
792 else if ( (vr->start < uaddr) 796 else if ( (vr->start < uaddr)
793 && (vr->start + vr->size > uad 797 && (vr->start + vr->size > uaddr + size) )
794 { 798 {
795 799
796 800
797 801
798 used_preallocated_vr = TRUE; 802 used_preallocated_vr = TRUE;
799 memcpy(preallocated_vr, vr, sizeof(* 803 memcpy(preallocated_vr, vr, sizeof(*vr));
800 804
801 805
802 preallocated_vr->start = uaddr + siz 806 preallocated_vr->start = uaddr + size;
803 preallocated_vr->size = vr->start + 807 preallocated_vr->size = vr->start + vr->size - (uaddr + size);
804 preallocated_vr->offset_in_resource 808 preallocated_vr->offset_in_resource += uaddr + size - vr->start;
805 vr->size 809 vr->size = uaddr - vr->start;
806 810
807 811
808 list_insert_after_named(as->list_vr, 812 list_insert_after_named(as->list_vr, vr, preallocated_vr,
809 prev_in_as, 813 prev_in_as, next_in_as);
810 list_add_tail_named(vr->mapped_resou 814 list_add_tail_named(vr->mapped_resource->list_vr, preallocated_vr,
811 prev_in_mapped_r 815 prev_in_mapped_resource,
812 next_in_mapped_r 816 next_in_mapped_resource);
813 817
814 818
815 if (vr->ops && vr->ops->unmap) 819 if (vr->ops && vr->ops->unmap)
816 vr->ops->unmap(vr, uaddr, size); 820 vr->ops->unmap(vr, uaddr, size);
817 if (preallocated_vr->ops && prealloc 821 if (preallocated_vr->ops && preallocated_vr->ops->ref)
818 preallocated_vr->ops->ref(prealloc 822 preallocated_vr->ops->ref(preallocated_vr);
819 823
820 824
821 as_account_change_of_vr_protection(a 825 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
822 s 826 size, vr->access_rights, 0);
823 827
824 828
825 break; 829 break;
826 } 830 }
827 831
828 832
829 else if (uaddr <= vr->start) 833 else if (uaddr <= vr->start)
830 { 834 {
831 sos_size_t translation = uaddr + siz 835 sos_size_t translation = uaddr + size - vr->start;
832 836
833 837
834 vr->size -= translatio 838 vr->size -= translation;
835 vr->offset_in_resource += translatio 839 vr->offset_in_resource += translation;
836 vr->start += translatio 840 vr->start += translation;
837 841
838 842
839 if (vr->ops && vr->ops->unmap) 843 if (vr->ops && vr->ops->unmap)
840 vr->ops->unmap(vr, uaddr + size, 844 vr->ops->unmap(vr, uaddr + size,
841 translation); 845 translation);
842 846
843 847
844 as_account_change_of_vr_protection(a 848 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
845 t 849 translation,
846 v 850 vr->access_rights, 0);
847 851
848 852
849 853
850 break; 854 break;
851 } 855 }
852 856
853 857
854 else if (uaddr + size >= vr->start + vr- 858 else if (uaddr + size >= vr->start + vr->size)
855 { 859 {
856 sos_size_t unmapped_size = vr->start 860 sos_size_t unmapped_size = vr->start + vr->size - uaddr;
857 861
858 862
859 vr->size = uaddr - vr->start; 863 vr->size = uaddr - vr->start;
860 864
861 865
862 if (vr->ops && vr->ops->unmap) 866 if (vr->ops && vr->ops->unmap)
863 vr->ops->unmap(vr, uaddr, unmapped 867 vr->ops->unmap(vr, uaddr, unmapped_size);
864 868
865 869
866 as_account_change_of_vr_protection(a 870 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
867 u 871 unmapped_size,
868 v 872 vr->access_rights, 0);
869 873
870 vr = vr->next_in_as; 874 vr = vr->next_in_as;
871 continue; 875 continue;
872 } 876 }
873 877
874 sos_display_fatal_error("BUG uaddr=%x sz 878 sos_display_fatal_error("BUG uaddr=%x sz=%x vr_start=%x, vr_sz=%x",
875 uaddr, size, vr- 879 uaddr, size, vr->start, vr->size);
876 } 880 }
877 881
878 need_to_setup_mmu = (sos_thread_get_current( 882 need_to_setup_mmu = (sos_thread_get_current()->squatted_mm_context
879 != as->mm_context); 883 != as->mm_context);
880 if (need_to_setup_mmu) 884 if (need_to_setup_mmu)
881 SOS_ASSERT_FATAL(SOS_OK 885 SOS_ASSERT_FATAL(SOS_OK
882 == sos_thread_prepare_use 886 == sos_thread_prepare_user_space_access(as,
883 887 (sos_vaddr_t)
884 888 NULL));
885 { 889 {
886 sos_ret_t sz_unmapped = sos_paging_unmap_i !! 890 sos_size_t sz_unmapped = sos_paging_unmap_interval(uaddr, size);
887 SOS_ASSERT_FATAL(sz_unmapped >= 0); 891 SOS_ASSERT_FATAL(sz_unmapped >= 0);
888 as->phys_total -= sz_unmapped; 892 as->phys_total -= sz_unmapped;
889 } 893 }
890 if (need_to_setup_mmu) 894 if (need_to_setup_mmu)
891 SOS_ASSERT_FATAL(SOS_OK == sos_thread_end_ 895 SOS_ASSERT_FATAL(SOS_OK == sos_thread_end_user_space_access());
892 896
893 if (! used_preallocated_vr) 897 if (! used_preallocated_vr)
894 sos_kmem_vmm_free((sos_vaddr_t)preallocate 898 sos_kmem_vmm_free((sos_vaddr_t)preallocated_vr);
895 899
896 return SOS_OK; 900 return SOS_OK;
897 } 901 }
898 902
899 903
900 sos_ret_t 904 sos_ret_t
901 sos_umem_vmm_chprot(struct sos_umem_vmm_as * a 905 sos_umem_vmm_chprot(struct sos_umem_vmm_as * as,
902 sos_uaddr_t uaddr, sos_siz 906 sos_uaddr_t uaddr, sos_size_t size,
903 sos_ui32_t new_access_righ 907 sos_ui32_t new_access_rights)
904 { 908 {
905 struct sos_umem_vmm_vr *start_vr, *vr, 909 struct sos_umem_vmm_vr *start_vr, *vr,
906 *preallocated_middle_vr, *preallocated_rig 910 *preallocated_middle_vr, *preallocated_right_vr;
907 sos_bool_t used_preallocated_middle_vr, used 911 sos_bool_t used_preallocated_middle_vr, used_preallocated_right_vr;
908 912
909 if (! SOS_IS_PAGE_ALIGNED(uaddr)) 913 if (! SOS_IS_PAGE_ALIGNED(uaddr))
910 return -SOS_EINVAL; 914 return -SOS_EINVAL;
911 if (size <= 0) 915 if (size <= 0)
912 return -SOS_EINVAL; 916 return -SOS_EINVAL;
913 size = SOS_PAGE_ALIGN_SUP(size); 917 size = SOS_PAGE_ALIGN_SUP(size);
914 918
915 919
916 if (uaddr < SOS_PAGING_BASE_USER_ADDRESS) 920 if (uaddr < SOS_PAGING_BASE_USER_ADDRESS)
917 return -SOS_EINVAL; 921 return -SOS_EINVAL;
918 if (uaddr > SOS_PAGING_TOP_USER_ADDRESS - si 922 if (uaddr > SOS_PAGING_TOP_USER_ADDRESS - size)
919 return -SOS_EINVAL; 923 return -SOS_EINVAL;
920 924
921 925
922 926
923 used_preallocated_middle_vr = FALSE; 927 used_preallocated_middle_vr = FALSE;
924 used_preallocated_right_vr = FALSE; 928 used_preallocated_right_vr = FALSE;
925 preallocated_middle_vr 929 preallocated_middle_vr
926 = (struct sos_umem_vmm_vr *)sos_kmem_cache 930 = (struct sos_umem_vmm_vr *)sos_kmem_cache_alloc(cache_of_vr, 0);
927 if (! preallocated_middle_vr) 931 if (! preallocated_middle_vr)
928 return -SOS_ENOMEM; 932 return -SOS_ENOMEM;
929 preallocated_right_vr 933 preallocated_right_vr
930 = (struct sos_umem_vmm_vr *)sos_kmem_cache 934 = (struct sos_umem_vmm_vr *)sos_kmem_cache_alloc(cache_of_vr, 0);
931 if (! preallocated_right_vr) 935 if (! preallocated_right_vr)
932 { 936 {
933 sos_kmem_vmm_free((sos_vaddr_t)prealloca 937 sos_kmem_vmm_free((sos_vaddr_t)preallocated_middle_vr);
934 return -SOS_ENOMEM; 938 return -SOS_ENOMEM;
935 } 939 }
936 940
937 941
938 start_vr = find_first_intersecting_vr(as, ua 942 start_vr = find_first_intersecting_vr(as, uaddr, size);
939 if (NULL == start_vr) 943 if (NULL == start_vr)
940 return SOS_OK; 944 return SOS_OK;
941 945
942 946
943 947
944 vr = start_vr; 948 vr = start_vr;
945 while (TRUE) 949 while (TRUE)
946 { 950 {
947 951
948 952
949 if (vr->start + vr->size <= uaddr) 953 if (vr->start + vr->size <= uaddr)
950 954
951 break; 955 break;
952 956
953 957
954 if (uaddr + size < vr->start) 958 if (uaddr + size < vr->start)
955 959
956 break; 960 break;
957 961
958 if (vr->flags & SOS_VR_MAP_SHARED) 962 if (vr->flags & SOS_VR_MAP_SHARED)
959 { 963 {
960 964
961 965
962 if ( ( (new_access_rights & SOS_VM_M 966 if ( ( (new_access_rights & SOS_VM_MAP_PROT_READ)
963 && !(vr->mapped_resource->all 967 && !(vr->mapped_resource->allowed_access_rights
964 & SOS_VM_MAP_PROT_READ) 968 & SOS_VM_MAP_PROT_READ) )
965 || ( (new_access_rights & SOS_V 969 || ( (new_access_rights & SOS_VM_MAP_PROT_WRITE)
966 && !(vr->mapped_resource-> 970 && !(vr->mapped_resource->allowed_access_rights
967 & SOS_VM_MAP_PROT_WRI 971 & SOS_VM_MAP_PROT_WRITE) )
968 || ( (new_access_rights & SOS_V 972 || ( (new_access_rights & SOS_VM_MAP_PROT_EXEC)
969 && !(vr->mapped_resource-> 973 && !(vr->mapped_resource->allowed_access_rights
970 & SOS_VM_MAP_PROT_EXE 974 & SOS_VM_MAP_PROT_EXEC) ) )
971 return -SOS_EPERM; 975 return -SOS_EPERM;
972 } 976 }
973 977
974 vr = vr->next_in_as; 978 vr = vr->next_in_as;
975 } 979 }
976 980
977 981
978 982
979 vr = start_vr; 983 vr = start_vr;
980 while (TRUE) 984 while (TRUE)
981 { 985 {
982 986
983 987
984 988
985 if (vr->start + vr->size <= uaddr) 989 if (vr->start + vr->size <= uaddr)
986 990
987 break; 991 break;
988 992
989 993
990 if (uaddr + size <= vr->start) 994 if (uaddr + size <= vr->start)
991 995
992 break; 996 break;
993 997
994 998
995 if (vr->access_rights == new_access_righ 999 if (vr->access_rights == new_access_rights)
996 1000
997 { 1001 {
998 vr = vr->next_in_as; 1002 vr = vr->next_in_as;
999 continue; 1003 continue;
1000 } 1004 }
1001 1005
1002 1006
1003 if ((vr->start >= uaddr) 1007 if ((vr->start >= uaddr)
1004 && (vr->start + vr->size <= uaddr + 1008 && (vr->start + vr->size <= uaddr + size))
1005 { 1009 {
1006 1010
1007 as_account_change_of_vr_protection( 1011 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
1008 1012 vr->size, vr->access_rights,
1009 1013 new_access_rights);
1010 vr->access_rights = new_access_righ 1014 vr->access_rights = new_access_rights;
1011 1015
1012 if (vr->flags & SOS_VR_MAP_SHARED) 1016 if (vr->flags & SOS_VR_MAP_SHARED)
1013 1017
1014 1018
1015 sos_paging_set_prot_of_interval(v 1019 sos_paging_set_prot_of_interval(vr->start, vr->size,
1016 n 1020 new_access_rights);
1017 else 1021 else
1018 1022
1019 { 1023 {
1020 1024
1021 1025
1022 1026
1023 1027
1024 1028
1025 if (! (new_access_rights & SOS_ 1029 if (! (new_access_rights & SOS_VM_MAP_PROT_WRITE))
1026 sos_paging_set_prot_of_interv 1030 sos_paging_set_prot_of_interval(vr->start, vr->size,
1027 1031 new_access_rights);
1028 } 1032 }
1029 1033
1030 vr = vr->next_in_as; 1034 vr = vr->next_in_as;
1031 continue; 1035 continue;
1032 } 1036 }
1033 1037
1034 1038
1035 else if ( (vr->start < uaddr) 1039 else if ( (vr->start < uaddr)
1036 && (vr->start + vr->size > ua 1040 && (vr->start + vr->size > uaddr + size) )
1037 { 1041 {
1038 1042
1039 1043
1040 1044
1041 SOS_ASSERT_FATAL(! used_preallocate 1045 SOS_ASSERT_FATAL(! used_preallocated_middle_vr);
1042 SOS_ASSERT_FATAL(! used_preallocate 1046 SOS_ASSERT_FATAL(! used_preallocated_right_vr);
1043 used_preallocated_middle_vr = TRUE; 1047 used_preallocated_middle_vr = TRUE;
1044 memcpy(preallocated_middle_vr, vr, 1048 memcpy(preallocated_middle_vr, vr, sizeof(*vr));
1045 used_preallocated_right_vr = TRUE; 1049 used_preallocated_right_vr = TRUE;
1046 memcpy(preallocated_right_vr, vr, s 1050 memcpy(preallocated_right_vr, vr, sizeof(*vr));
1047 1051
1048 1052
1049 preallocated_middle_vr->start = uad 1053 preallocated_middle_vr->start = uaddr;
1050 preallocated_middle_vr->size = siz 1054 preallocated_middle_vr->size = size;
1051 preallocated_right_vr->start = uad 1055 preallocated_right_vr->start = uaddr + size;
1052 preallocated_right_vr->size = vr- 1056 preallocated_right_vr->size = vr->start + vr->size
1053 - 1057 - (uaddr + size);
1054 preallocated_middle_vr->offset_in_r 1058 preallocated_middle_vr->offset_in_resource
1055 += uaddr - vr->start; 1059 += uaddr - vr->start;
1056 preallocated_right_vr->offset_in_re 1060 preallocated_right_vr->offset_in_resource
1057 += uaddr + size - vr->start; 1061 += uaddr + size - vr->start;
1058 vr->size = uaddr - vr->start; 1062 vr->size = uaddr - vr->start;
1059 1063
1060 1064
1061 preallocated_middle_vr->access_righ 1065 preallocated_middle_vr->access_rights = new_access_rights;
1062 as_account_change_of_vr_protection( 1066 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
1063 1067 size, vr->access_rights,
1064 1068 new_access_rights);
1065 1069
1066 1070
1067 list_insert_after_named(as->list_vr 1071 list_insert_after_named(as->list_vr, vr, preallocated_middle_vr,
1068 prev_in_as, 1072 prev_in_as, next_in_as);
1069 list_insert_after_named(as->list_vr 1073 list_insert_after_named(as->list_vr, preallocated_middle_vr,
1070 preallocate 1074 preallocated_right_vr,
1071 prev_in_as, 1075 prev_in_as, next_in_as);
1072 1076
1073 list_add_tail_named(vr->mapped_reso 1077 list_add_tail_named(vr->mapped_resource->list_vr,
1074 preallocated_mi 1078 preallocated_middle_vr,
1075 prev_in_mapped_ 1079 prev_in_mapped_resource,
1076 next_in_mapped_ 1080 next_in_mapped_resource);
1077 list_add_tail_named(vr->mapped_reso 1081 list_add_tail_named(vr->mapped_resource->list_vr,
1078 preallocated_ri 1082 preallocated_right_vr,
1079 prev_in_mapped_ 1083 prev_in_mapped_resource,
1080 next_in_mapped_ 1084 next_in_mapped_resource);
1081 1085
1082 1086
1083 if (!(preallocated_middle_vr->flags 1087 if (!(preallocated_middle_vr->flags & SOS_VR_MAP_SHARED)
1084 && (new_access_rights & SOS_VM_ 1088 && (new_access_rights & SOS_VM_MAP_PROT_WRITE))
1085 1089
1086 sos_paging_prepare_COW(preallocat 1090 sos_paging_prepare_COW(preallocated_middle_vr->start,
1087 preallocat 1091 preallocated_middle_vr->size);
1088 else 1092 else
1089 sos_paging_set_prot_of_interval(p 1093 sos_paging_set_prot_of_interval(preallocated_middle_vr->start,
1090 p 1094 preallocated_middle_vr->size,
1091 n 1095 new_access_rights);
1092 1096
1093 if (preallocated_right_vr->ops && p 1097 if (preallocated_right_vr->ops && preallocated_right_vr->ops->ref)
1094 preallocated_right_vr->ops->ref(p 1098 preallocated_right_vr->ops->ref(preallocated_right_vr);
1095 if (preallocated_middle_vr->ops && 1099 if (preallocated_middle_vr->ops && preallocated_middle_vr->ops->ref)
1096 preallocated_middle_vr->ops->ref( 1100 preallocated_middle_vr->ops->ref(preallocated_middle_vr);
1097 1101
1098 1102
1099 break; 1103 break;
1100 } 1104 }
1101 1105
1102 1106
1103 else if (uaddr <= vr->start) 1107 else if (uaddr <= vr->start)
1104 { 1108 {
1105 1109
1106 sos_uoffset_t offset_in_region = ua 1110 sos_uoffset_t offset_in_region = uaddr + size - vr->start;
1107 1111
1108 1112
1109 SOS_ASSERT_FATAL(! used_preallocate 1113 SOS_ASSERT_FATAL(! used_preallocated_middle_vr);
1110 used_preallocated_middle_vr = TRUE; 1114 used_preallocated_middle_vr = TRUE;
1111 memcpy(preallocated_middle_vr, vr, 1115 memcpy(preallocated_middle_vr, vr, sizeof(*vr));
1112 1116
1113 1117
1114 preallocated_middle_vr->start += of 1118 preallocated_middle_vr->start += offset_in_region;
1115 preallocated_middle_vr->size -= of 1119 preallocated_middle_vr->size -= offset_in_region;
1116 vr->size = of 1120 vr->size = offset_in_region;
1117 preallocated_middle_vr->offset_in_r 1121 preallocated_middle_vr->offset_in_resource += offset_in_region;
1118 1122
1119 1123
1120 as_account_change_of_vr_protection( 1124 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
1121 1125 vr->size,
1122 1126 vr->access_rights,
1123 1127 new_access_rights);
1124 vr->access_rights = new_access_righ 1128 vr->access_rights = new_access_rights;
1125 1129
1126 1130
1127 list_insert_after_named(as->list_vr 1131 list_insert_after_named(as->list_vr, vr,
1128 preallocate 1132 preallocated_middle_vr,
1129 prev_in_as, 1133 prev_in_as, next_in_as);
1130 list_add_tail_named(vr->mapped_reso 1134 list_add_tail_named(vr->mapped_resource->list_vr,
1131 preallocated_mi 1135 preallocated_middle_vr,
1132 prev_in_mapped_ 1136 prev_in_mapped_resource,
1133 next_in_mapped_ 1137 next_in_mapped_resource);
1134 1138
1135 1139
1136 if (!(vr->flags & SOS_VR_MAP_SHARED 1140 if (!(vr->flags & SOS_VR_MAP_SHARED)
1137 && (new_access_rights & SOS_VM_ 1141 && (new_access_rights & SOS_VM_MAP_PROT_WRITE))
1138 1142
1139 sos_paging_prepare_COW(vr->start, 1143 sos_paging_prepare_COW(vr->start, vr->size);
1140 else 1144 else
1141 sos_paging_set_prot_of_interval(v 1145 sos_paging_set_prot_of_interval(vr->start, vr->size,
1142 n 1146 new_access_rights);
1143 1147
1144 if (preallocated_middle_vr->ops && 1148 if (preallocated_middle_vr->ops && preallocated_middle_vr->ops->ref)
1145 preallocated_middle_vr->ops->ref( 1149 preallocated_middle_vr->ops->ref(preallocated_middle_vr);
1146 1150
1147 1151
1148 1152
1149 break; 1153 break;
1150 } 1154 }
1151 1155
1152 1156
1153 else if (uaddr + size >= vr->start + vr 1157 else if (uaddr + size >= vr->start + vr->size)
1154 { 1158 {
1155 1159
1156 sos_uoffset_t offset_in_region = ua 1160 sos_uoffset_t offset_in_region = uaddr - vr->start;
1157 1161
1158 1162
1159 SOS_ASSERT_FATAL(! used_preallocate 1163 SOS_ASSERT_FATAL(! used_preallocated_right_vr);
1160 used_preallocated_right_vr = TRUE; 1164 used_preallocated_right_vr = TRUE;
1161 memcpy(preallocated_right_vr, vr, s 1165 memcpy(preallocated_right_vr, vr, sizeof(*vr));
1162 1166
1163 1167
1164 preallocated_right_vr->start 1168 preallocated_right_vr->start += offset_in_region;
1165 preallocated_right_vr->size 1169 preallocated_right_vr->size -= offset_in_region;
1166 vr->size 1170 vr->size = offset_in_region;
1167 preallocated_right_vr->offset_in_re 1171 preallocated_right_vr->offset_in_resource += offset_in_region;
1168 1172
1169 1173
1170 as_account_change_of_vr_protection( 1174 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
1171 1175 preallocated_right_vr->size,
1172 1176 vr->access_rights,
1173 1177 new_access_rights);
1174 preallocated_right_vr->access_right 1178 preallocated_right_vr->access_rights = new_access_rights;
1175 1179
1176 1180
1177 list_insert_after_named(as->list_vr 1181 list_insert_after_named(as->list_vr, vr,
1178 preallocate 1182 preallocated_right_vr,
1179 prev_in_as, 1183 prev_in_as, next_in_as);
1180 list_add_tail_named(vr->mapped_reso 1184 list_add_tail_named(vr->mapped_resource->list_vr,
1181 preallocated_ri 1185 preallocated_right_vr,
1182 prev_in_mapped_ 1186 prev_in_mapped_resource,
1183 next_in_mapped_ 1187 next_in_mapped_resource);
1184 1188
1185 1189
1186 if (!(preallocated_right_vr->flags 1190 if (!(preallocated_right_vr->flags & SOS_VR_MAP_SHARED)
1187 && (new_access_rights & SOS_VM_ 1191 && (new_access_rights & SOS_VM_MAP_PROT_WRITE))
1188 1192
1189 sos_paging_prepare_COW(preallocat 1193 sos_paging_prepare_COW(preallocated_right_vr->start,
1190 preallocat 1194 preallocated_right_vr->size);
1191 else 1195 else
1192 sos_paging_set_prot_of_interval(p 1196 sos_paging_set_prot_of_interval(preallocated_right_vr->start,
1193 p 1197 preallocated_right_vr->size,
1194 n 1198 new_access_rights);
1195 1199
1196 if (preallocated_right_vr->ops && p 1200 if (preallocated_right_vr->ops && preallocated_right_vr->ops->ref)
1197 preallocated_right_vr->ops->ref(p 1201 preallocated_right_vr->ops->ref(preallocated_right_vr);
1198 1202
1199 vr = vr->next_in_as; 1203 vr = vr->next_in_as;
1200 continue; 1204 continue;
1201 } 1205 }
1202 1206
1203 sos_display_fatal_error("BUG"); 1207 sos_display_fatal_error("BUG");
1204 } 1208 }
1205 1209
1206 if (! used_preallocated_middle_vr) 1210 if (! used_preallocated_middle_vr)
1207 sos_kmem_vmm_free((sos_vaddr_t)preallocat 1211 sos_kmem_vmm_free((sos_vaddr_t)preallocated_middle_vr);
1208 if (! used_preallocated_right_vr) 1212 if (! used_preallocated_right_vr)
1209 sos_kmem_vmm_free((sos_vaddr_t)preallocat 1213 sos_kmem_vmm_free((sos_vaddr_t)preallocated_right_vr);
1210 <<
1211 return SOS_OK; <<
1212 } <<
1213 <<
1214 <<
1215 sos_ret_t <<
1216 sos_umem_vmm_sync(struct sos_umem_vmm_as * as <<
1217 sos_uaddr_t uaddr, sos_size <<
1218 sos_ui32_t flags) <<
1219 { <<
1220 if (! SOS_IS_PAGE_ALIGNED(uaddr)) <<
1221 return -SOS_EINVAL; <<
1222 if (size <= 0) <<
1223 return -SOS_EINVAL; <<
1224 size = SOS_PAGE_ALIGN_SUP(size); <<
1225 <<
1226 <<
1227 if (uaddr < SOS_PAGING_BASE_USER_ADDRESS) <<
1228 return -SOS_EINVAL; <<
1229 if (uaddr > SOS_PAGING_TOP_USER_ADDRESS - s <<
1230 return -SOS_EINVAL; <<
1231 <<
1232 <<
1233 <<
1234 while (TRUE) <<
1235 { <<
1236 struct sos_umem_vmm_vr *vr; <<
1237 <<
1238 if (size <= 0) <<
1239 break; <<
1240 <<
1241 <<
1242 vr = find_first_intersecting_vr(as, uad <<
1243 if (NULL == vr) <<
1244 break; <<
1245 <<
1246 <<
1247 if ( !(vr->flags & SOS_VR_MAP_SHARED) <<
1248 || (vr->mapped_resource->flags & S <<
1249 <<
1250 <<
1251 || ! vr->ops->sync_page ) <<
1252 { <<
1253 if (size <= vr->size) <<
1254 break; <<
1255 <<
1256 uaddr += vr->size; <<
1257 size -= vr->size; <<
1258 } <<
1259 <<
1260 <<
1261 for ( ; (size > 0) <<
1262 && (uaddr - vr->start < vr->siz <<
1263 uaddr += SOS_PAGE_SIZE, <<
1264 size -= SOS_PAGE_SIZE) <<
1265 if (sos_paging_is_dirty(uaddr)) <<
1266 { <<
1267 <<
1268 vr->ops->sync_page(vr, uaddr, fla <<
1269 uaddr += SOS_PAGE_SIZE; <<
1270 size -= SOS_PAGE_SIZE; <<
1271 break; <<
1272 } <<
1273 } <<
1274 1214
1275 return SOS_OK; 1215 return SOS_OK;
1276 } 1216 }
1277 1217
1278 1218
1279 sos_ret_t 1219 sos_ret_t
1280 sos_umem_vmm_resize(struct sos_umem_vmm_as * 1220 sos_umem_vmm_resize(struct sos_umem_vmm_as * as,
1281 sos_uaddr_t old_uaddr, so 1221 sos_uaddr_t old_uaddr, sos_size_t old_size,
1282 sos_uaddr_t *new_uaddr, s 1222 sos_uaddr_t *new_uaddr, sos_size_t new_size,
1283 sos_ui32_t flags) 1223 sos_ui32_t flags)
1284 { 1224 {
1285 sos_luoffset_t new_offset_in_resource; 1225 sos_luoffset_t new_offset_in_resource;
1286 sos_bool_t must_move_vr = FALSE; 1226 sos_bool_t must_move_vr = FALSE;
1287 struct sos_umem_vmm_vr *vr, *prev_vr, *next 1227 struct sos_umem_vmm_vr *vr, *prev_vr, *next_vr;
1288 1228
1289 1229
1290 if (*new_uaddr < SOS_PAGING_BASE_USER_ADDRE 1230 if (*new_uaddr < SOS_PAGING_BASE_USER_ADDRESS)
1291 return -SOS_EINVAL; 1231 return -SOS_EINVAL;
1292 if (*new_uaddr > SOS_PAGING_TOP_USER_ADDRES 1232 if (*new_uaddr > SOS_PAGING_TOP_USER_ADDRESS - new_size)
1293 return -SOS_EINVAL; 1233 return -SOS_EINVAL;
1294 1234
1295 old_uaddr = SOS_PAGE_ALIGN_INF(old_uaddr); 1235 old_uaddr = SOS_PAGE_ALIGN_INF(old_uaddr);
1296 old_size = SOS_PAGE_ALIGN_SUP(old_size); 1236 old_size = SOS_PAGE_ALIGN_SUP(old_size);
1297 if (! SOS_IS_PAGE_ALIGNED(*new_uaddr)) 1237 if (! SOS_IS_PAGE_ALIGNED(*new_uaddr))
1298 return -SOS_EINVAL; 1238 return -SOS_EINVAL;
1299 if (new_size <= 0) 1239 if (new_size <= 0)
1300 return -SOS_EINVAL; 1240 return -SOS_EINVAL;
1301 new_size = SOS_PAGE_ALIGN_SUP(new_size); 1241 new_size = SOS_PAGE_ALIGN_SUP(new_size);
1302 1242
1303 1243
1304 vr = find_first_intersecting_vr(as, old_uad 1244 vr = find_first_intersecting_vr(as, old_uaddr, old_size);
1305 if (! vr) 1245 if (! vr)
1306 return -SOS_EINVAL; 1246 return -SOS_EINVAL;
1307 1247
1308 1248
1309 if ( (vr->start > old_uaddr) 1249 if ( (vr->start > old_uaddr)
1310 || (vr->start + vr->size < old_uaddr + 1250 || (vr->start + vr->size < old_uaddr + old_size) )
1311 return -SOS_EINVAL; 1251 return -SOS_EINVAL;
1312 1252
1313 1253
1314 1254
1315 prev_vr = vr->prev_in_as; 1255 prev_vr = vr->prev_in_as;
1316 if (prev_vr->start >= vr->start) 1256 if (prev_vr->start >= vr->start)
1317 prev_vr = NULL; 1257 prev_vr = NULL;
1318 next_vr = vr->prev_in_as; 1258 next_vr = vr->prev_in_as;
1319 if (next_vr->start <= vr->start) 1259 if (next_vr->start <= vr->start)
1320 next_vr = NULL; 1260 next_vr = NULL;
1321 1261
1322 1262
1323 1263
1324 1264
1325 1265
1326 1266
1327 1267
1328 if ( (*new_uaddr < vr->start) 1268 if ( (*new_uaddr < vr->start)
1329 && (vr->start - *new_uaddr > vr->offse 1269 && (vr->start - *new_uaddr > vr->offset_in_resource) )
1330 return -SOS_EINVAL; 1270 return -SOS_EINVAL;
1331 1271
1332 1272
1333 if (vr->start > *new_uaddr) 1273 if (vr->start > *new_uaddr)
1334 new_offset_in_resource 1274 new_offset_in_resource
1335 = vr->offset_in_resource 1275 = vr->offset_in_resource
1336 - (vr->start - *new_uaddr); 1276 - (vr->start - *new_uaddr);
1337 else 1277 else
1338 new_offset_in_resource 1278 new_offset_in_resource
1339 = vr->offset_in_resource 1279 = vr->offset_in_resource
1340 + (*new_uaddr - vr->start); 1280 + (*new_uaddr - vr->start);
1341 1281
1342 1282
1343 1283
1344 if (prev_vr && (prev_vr->start + prev_vr->s 1284 if (prev_vr && (prev_vr->start + prev_vr->size > *new_uaddr))
1345 must_move_vr |= TRUE; 1285 must_move_vr |= TRUE;
1346 if (next_vr && (next_vr->start < *new_uaddr 1286 if (next_vr && (next_vr->start < *new_uaddr + new_size))
1347 must_move_vr |= TRUE; 1287 must_move_vr |= TRUE;
1348 1288
1349 1289
1350 if (*new_uaddr < SOS_PAGING_BASE_USER_ADDRE 1290 if (*new_uaddr < SOS_PAGING_BASE_USER_ADDRESS)
1351 must_move_vr |= TRUE; 1291 must_move_vr |= TRUE;
1352 if (*new_uaddr > SOS_PAGING_TOP_USER_ADDRES 1292 if (*new_uaddr > SOS_PAGING_TOP_USER_ADDRESS - new_size)
1353 must_move_vr |= TRUE; 1293 must_move_vr |= TRUE;
1354 1294
1355 1295
1356 if ( must_move_vr && !(flags & SOS_VR_REMAP 1296 if ( must_move_vr && !(flags & SOS_VR_REMAP_MAYMOVE) )
1357 return -SOS_EINVAL; 1297 return -SOS_EINVAL;
1358 1298
1359 1299
1360 1300
1361 if (must_move_vr) 1301 if (must_move_vr)
1362 { 1302 {
1363 sos_uaddr_t uaddr, result_uaddr; 1303 sos_uaddr_t uaddr, result_uaddr;
1364 sos_ret_t retval; 1304 sos_ret_t retval;
1365 1305
1366 result_uaddr = *new_uaddr; 1306 result_uaddr = *new_uaddr;
1367 retval = sos_umem_vmm_map(as, & result_ 1307 retval = sos_umem_vmm_map(as, & result_uaddr, new_size,
1368 vr->access_ri 1308 vr->access_rights,
1369 vr->flags | I 1309 vr->flags | INTERNAL_MAP_CALLED_FROM_MREMAP,
1370 vr->mapped_re 1310 vr->mapped_resource,
1371 new_offset_in 1311 new_offset_in_resource);
1372 if (SOS_OK != retval) 1312 if (SOS_OK != retval)
1373 return retval; 1313 return retval;
1374 1314
1375 1315
1376 for (uaddr = vr->start ; 1316 for (uaddr = vr->start ;
1377 uaddr < vr->start + vr->size ; 1317 uaddr < vr->start + vr->size ;
1378 uaddr += SOS_PAGE_SIZE) 1318 uaddr += SOS_PAGE_SIZE)
1379 { 1319 {
1380 sos_paddr_t paddr; 1320 sos_paddr_t paddr;
1381 sos_ui32_t prot; 1321 sos_ui32_t prot;
1382 sos_uaddr_t vaddr; 1322 sos_uaddr_t vaddr;
1383 1323
1384 if (uaddr < *new_uaddr) 1324 if (uaddr < *new_uaddr)
1385 continue; 1325 continue;
1386 if (uaddr > *new_uaddr + new_size) 1326 if (uaddr > *new_uaddr + new_size)
1387 continue; 1327 continue;
1388 1328
1389 1329
1390 1330
1391 if (vr->start >= *new_uaddr) 1331 if (vr->start >= *new_uaddr)
1392 vaddr = result_uaddr 1332 vaddr = result_uaddr
1393 + (uaddr - vr->start) 1333 + (uaddr - vr->start)
1394 + (vr->start - *new_uaddr); 1334 + (vr->start - *new_uaddr);
1395 else 1335 else
1396 vaddr = result_uaddr 1336 vaddr = result_uaddr
1397 + (uaddr - vr->start) 1337 + (uaddr - vr->start)
1398 - (*new_uaddr - vr->start); 1338 - (*new_uaddr - vr->start);
1399 1339
1400 paddr = sos_paging_get_paddr(uaddr) 1340 paddr = sos_paging_get_paddr(uaddr);
1401 if (! paddr) 1341 if (! paddr)
1402 1342
1403 continue; 1343 continue;
1404 1344
1405 prot = sos_paging_get_prot(uaddr); 1345 prot = sos_paging_get_prot(uaddr);
1406 SOS_ASSERT_FATAL(prot); 1346 SOS_ASSERT_FATAL(prot);
1407 1347
1408 1348
1409 retval = sos_paging_map(paddr, vadd 1349 retval = sos_paging_map(paddr, vaddr, TRUE, prot);
1410 if (SOS_OK != retval) 1350 if (SOS_OK != retval)
1411 { 1351 {
1412 sos_umem_vmm_unmap(as, result_u 1352 sos_umem_vmm_unmap(as, result_uaddr, new_size);
1413 return retval; 1353 return retval;
1414 } 1354 }
1415 } 1355 }
1416 1356
1417 retval = sos_umem_vmm_unmap(as, vr->sta 1357 retval = sos_umem_vmm_unmap(as, vr->start, vr->size);
1418 if (SOS_OK != retval) 1358 if (SOS_OK != retval)
1419 { 1359 {
1420 sos_umem_vmm_unmap(as, result_uaddr 1360 sos_umem_vmm_unmap(as, result_uaddr, new_size);
1421 return retval; 1361 return retval;
1422 } 1362 }
1423 1363
1424 *new_uaddr = result_uaddr; 1364 *new_uaddr = result_uaddr;
1425 return retval; 1365 return retval;
1426 } 1366 }
1427 1367
1428 1368
1429 1369
1430 1370
1431 if (*new_uaddr + new_size < vr->start + vr- 1371 if (*new_uaddr + new_size < vr->start + vr->size)
1432 sos_umem_vmm_unmap(as, *new_uaddr + new_s 1372 sos_umem_vmm_unmap(as, *new_uaddr + new_size,
1433 vr->start + vr->size - 1373 vr->start + vr->size - (*new_uaddr + new_size));
1434 else 1374 else
1435 { 1375 {
1436 as_account_change_of_vr_protection(as, 1376 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
1437 *new 1377 *new_uaddr + new_size
1438 - 1378 - (vr->start + vr->size),
1439 0, v 1379 0, vr->access_rights);
1440 vr->size += *new_uaddr + new_size - (vr 1380 vr->size += *new_uaddr + new_size - (vr->start + vr->size);
1441 } 1381 }
1442 1382
1443 if (*new_uaddr > vr->start) 1383 if (*new_uaddr > vr->start)
1444 sos_umem_vmm_unmap(as, vr->start, *new_ua 1384 sos_umem_vmm_unmap(as, vr->start, *new_uaddr - vr->start);
1445 else 1385 else
1446 { 1386 {
1447 as_account_change_of_vr_protection(as, 1387 as_account_change_of_vr_protection(as, vr->flags & SOS_VR_MAP_SHARED,
1448 vr-> 1388 vr->start - *new_uaddr,
1449 0, v 1389 0, vr->access_rights);
1450 vr->size += vr->start - *new_uaddr; 1390 vr->size += vr->start - *new_uaddr;
1451 vr->start = *new_uaddr; 1391 vr->start = *new_uaddr;
1452 vr->offset_in_resource = new_offset_in_ 1392 vr->offset_in_resource = new_offset_in_resource;
1453 } 1393 }
1454 1394
1455 SOS_ASSERT_FATAL(vr->start == *new_uaddr); 1395 SOS_ASSERT_FATAL(vr->start == *new_uaddr);
1456 SOS_ASSERT_FATAL(vr->size == new_size); 1396 SOS_ASSERT_FATAL(vr->size == new_size);
1457 SOS_ASSERT_FATAL(vr->offset_in_resource == 1397 SOS_ASSERT_FATAL(vr->offset_in_resource == new_offset_in_resource);
1458 1398
1459 return SOS_OK; 1399 return SOS_OK;
1460 } 1400 }
1461 1401
1462 1402
1463 sos_ret_t sos_umem_vmm_try_resolve_page_fault 1403 sos_ret_t sos_umem_vmm_try_resolve_page_fault(sos_uaddr_t uaddr,
1464 1404 sos_bool_t write_access,
1465 1405 sos_bool_t user_access)
1466 { 1406 {
1467 struct sos_process *process = sos_threa 1407 struct sos_process *process = sos_thread_get_current()->process;
1468 struct sos_umem_vmm_as *as; 1408 struct sos_umem_vmm_as *as;
1469 struct sos_umem_vmm_vr *vr; 1409 struct sos_umem_vmm_vr *vr;
1470 1410
1471 if (! process) 1411 if (! process)
1472 return -SOS_EFAULT; 1412 return -SOS_EFAULT;
1473 1413
1474 as = sos_process_get_address_space(process) 1414 as = sos_process_get_address_space(process);
1475 if (! as) 1415 if (! as)
1476 return -SOS_EFAULT; 1416 return -SOS_EFAULT;
1477 1417
1478 vr = find_first_intersecting_vr(as, uaddr, 1418 vr = find_first_intersecting_vr(as, uaddr, 1);
1479 if (! vr) 1419 if (! vr)
1480 return -SOS_EFAULT; 1420 return -SOS_EFAULT;
1481 1421
1482 1422
1483 if (write_access && !(vr->access_rights & S 1423 if (write_access && !(vr->access_rights & SOS_VM_MAP_PROT_WRITE))
1484 return -SOS_EFAULT; 1424 return -SOS_EFAULT;
1485 1425
1486 1426
1487 if (write_access && !(vr->flags & SOS_VR_MA 1427 if (write_access && !(vr->flags & SOS_VR_MAP_SHARED))
1488 { 1428 {
1489 if (SOS_OK == sos_paging_try_resolve_CO 1429 if (SOS_OK == sos_paging_try_resolve_COW(uaddr))
1490 { 1430 {
1491 as->pgflt_cow ++; 1431 as->pgflt_cow ++;
1492 return SOS_OK; 1432 return SOS_OK;
1493 } 1433 }
1494 } 1434 }
1495 1435
1496 1436
1497 if (SOS_OK != vr->ops->page_in(vr, uaddr, w 1437 if (SOS_OK != vr->ops->page_in(vr, uaddr, write_access))
1498 { 1438 {
1499 as->pgflt_invalid ++; 1439 as->pgflt_invalid ++;
1500 return -SOS_EFAULT; 1440 return -SOS_EFAULT;
1501 } 1441 }
1502 1442
1503 as->phys_total += SOS_PAGE_SIZE; 1443 as->phys_total += SOS_PAGE_SIZE;
1504 as->pgflt_page_in ++; 1444 as->pgflt_page_in ++;
1505 1445
1506 1446
1507 if (!(vr->flags & SOS_VR_MAP_SHARED)) 1447 if (!(vr->flags & SOS_VR_MAP_SHARED))
1508 { 1448 {
1509 sos_paging_prepare_COW(SOS_PAGE_ALIGN_I 1449 sos_paging_prepare_COW(SOS_PAGE_ALIGN_INF(uaddr),
1510 SOS_PAGE_SIZE); 1450 SOS_PAGE_SIZE);
1511 } 1451 }
1512 1452
1513 return SOS_OK; 1453 return SOS_OK;
1514 } 1454 }
1515 1455
1516 1456
1517 sos_ret_t 1457 sos_ret_t
1518 sos_umem_vmm_init_heap(struct sos_umem_vmm_as 1458 sos_umem_vmm_init_heap(struct sos_umem_vmm_as * as,
1519 sos_uaddr_t heap_start 1459 sos_uaddr_t heap_start)
1520 { 1460 {
1521 SOS_ASSERT_FATAL(! as->heap_start); 1461 SOS_ASSERT_FATAL(! as->heap_start);
1522 1462
1523 as->heap_start = heap_start; 1463 as->heap_start = heap_start;
1524 as->heap_size = 0; 1464 as->heap_size = 0;
1525 return SOS_OK; 1465 return SOS_OK;
1526 } 1466 }
1527 1467
1528 1468
1529 sos_uaddr_t 1469 sos_uaddr_t
1530 sos_umem_vmm_brk(struct sos_umem_vmm_as * as, 1470 sos_umem_vmm_brk(struct sos_umem_vmm_as * as,
1531 sos_uaddr_t new_top_uaddr) 1471 sos_uaddr_t new_top_uaddr)
1532 { 1472 {
1533 sos_uaddr_t new_start; 1473 sos_uaddr_t new_start;
1534 sos_size_t new_size; 1474 sos_size_t new_size;
1535 SOS_ASSERT_FATAL(as->heap_start); 1475 SOS_ASSERT_FATAL(as->heap_start);
1536 1476
1537 if (! new_top_uaddr) 1477 if (! new_top_uaddr)
1538 return as->heap_start + as->heap_size; 1478 return as->heap_start + as->heap_size;
1539 1479
1540 if (new_top_uaddr == as->heap_start + as->h 1480 if (new_top_uaddr == as->heap_start + as->heap_size)
1541 return as->heap_start + as->heap_size; 1481 return as->heap_start + as->heap_size;
1542 1482
1543 if (new_top_uaddr < as->heap_start) 1483 if (new_top_uaddr < as->heap_start)
1544 return (sos_uaddr_t)NULL; 1484 return (sos_uaddr_t)NULL;
1545 1485
1546 new_top_uaddr = SOS_PAGE_ALIGN_SUP(new_top_ 1486 new_top_uaddr = SOS_PAGE_ALIGN_SUP(new_top_uaddr);
1547 new_start = as->heap_start; 1487 new_start = as->heap_start;
1548 new_size = new_top_uaddr - as->heap_start; 1488 new_size = new_top_uaddr - as->heap_start;
1549 1489
1550 1490
1551 if (! as->heap_size) 1491 if (! as->heap_size)
1552 { 1492 {
1553 if (SOS_OK != sos_dev_zero_map(as, & as 1493 if (SOS_OK != sos_dev_zero_map(as, & as->heap_start,
1554 new_size 1494 new_size,
1555 SOS_VM_M 1495 SOS_VM_MAP_PROT_READ
1556 | SOS_VM 1496 | SOS_VM_MAP_PROT_WRITE,
1557 0 1497 0 ))
1558 return (sos_uaddr_t)NULL; 1498 return (sos_uaddr_t)NULL;
1559 1499
1560 as->heap_size = new_size; 1500 as->heap_size = new_size;
1561 return as->heap_start + as->heap_size; 1501 return as->heap_start + as->heap_size;
1562 } 1502 }
1563 1503
1564 1504
1565 if (new_size <= 0) 1505 if (new_size <= 0)
1566 { 1506 {
1567 if (SOS_OK != sos_umem_vmm_unmap(as, 1507 if (SOS_OK != sos_umem_vmm_unmap(as,
1568 as->he 1508 as->heap_start, as->heap_size))
1569 return (sos_uaddr_t)NULL; 1509 return (sos_uaddr_t)NULL;
1570 } 1510 }
1571 else 1511 else
1572 { 1512 {
1573 if (SOS_OK != sos_umem_vmm_resize(as, 1513 if (SOS_OK != sos_umem_vmm_resize(as,
1574 as->h 1514 as->heap_start, as->heap_size,
1575 & new 1515 & new_start, new_size,
1576 0)) 1516 0))
1577 return (sos_uaddr_t)NULL; 1517 return (sos_uaddr_t)NULL;
1578 } 1518 }
1579 1519
1580 SOS_ASSERT_FATAL(new_start == as->heap_star 1520 SOS_ASSERT_FATAL(new_start == as->heap_start);
1581 as->heap_size = new_size; 1521 as->heap_size = new_size;
1582 return new_top_uaddr; 1522 return new_top_uaddr;
1583 } 1523 }
1584 1524
1585 1525
1586 static struct sos_umem_vmm_vr * 1526 static struct sos_umem_vmm_vr *
1587 find_enclosing_or_next_vr(struct sos_umem_vmm 1527 find_enclosing_or_next_vr(struct sos_umem_vmm_as * as,
1588 sos_uaddr_t uaddr) 1528 sos_uaddr_t uaddr)
1589 { 1529 {
1590 struct sos_umem_vmm_vr *vr; 1530 struct sos_umem_vmm_vr *vr;
1591 int nb_vr; 1531 int nb_vr;
1592 1532
1593 if (uaddr < SOS_PAGING_BASE_USER_ADDRESS) 1533 if (uaddr < SOS_PAGING_BASE_USER_ADDRESS)
1594 return NULL; 1534 return NULL;
1595 if (uaddr > SOS_PAGING_TOP_USER_ADDRESS) 1535 if (uaddr > SOS_PAGING_TOP_USER_ADDRESS)
1596 return NULL; 1536 return NULL;
1597 1537
1598 list_foreach_named(as->list_vr, vr, nb_vr, 1538 list_foreach_named(as->list_vr, vr, nb_vr, prev_in_as, next_in_as)
1599 { 1539 {
1600 1540
1601 1541
1602 if (uaddr <= vr->start + (vr->size - 1) 1542 if (uaddr <= vr->start + (vr->size - 1))
1603 return vr; 1543 return vr;
1604 } 1544 }
1605 1545
1606 return NULL; 1546 return NULL;
1607 } 1547 }
1608 1548
1609 1549
1610 static struct sos_umem_vmm_vr * 1550 static struct sos_umem_vmm_vr *
1611 find_first_intersecting_vr(struct sos_umem_vm 1551 find_first_intersecting_vr(struct sos_umem_vmm_as * as,
1612 sos_uaddr_t start_ 1552 sos_uaddr_t start_uaddr, sos_size_t size)
1613 { 1553 {
1614 struct sos_umem_vmm_vr * vr; 1554 struct sos_umem_vmm_vr * vr;
1615 vr = find_enclosing_or_next_vr(as, start_ua 1555 vr = find_enclosing_or_next_vr(as, start_uaddr);
1616 if (! vr) 1556 if (! vr)
1617 return NULL; 1557 return NULL;
1618 1558
1619 if (start_uaddr + size <= vr->start) 1559 if (start_uaddr + size <= vr->start)
1620 return NULL; 1560 return NULL;
1621 1561
1622 return vr; 1562 return vr;
1623 } 1563 }
1624 1564
1625 1565
1626 static sos_uaddr_t 1566 static sos_uaddr_t
1627 find_first_free_interval(struct sos_umem_vmm_ 1567 find_first_free_interval(struct sos_umem_vmm_as * as,
1628 sos_uaddr_t hint_uad 1568 sos_uaddr_t hint_uaddr, sos_size_t size)
1629 { 1569 {
1630 struct sos_umem_vmm_vr * initial_vr, * vr; 1570 struct sos_umem_vmm_vr * initial_vr, * vr;
1631 1571
1632 if (hint_uaddr < SOS_PAGING_BASE_USER_ADDRE 1572 if (hint_uaddr < SOS_PAGING_BASE_USER_ADDRESS)
1633 hint_uaddr = SOS_PAGING_BASE_USER_ADDRESS 1573 hint_uaddr = SOS_PAGING_BASE_USER_ADDRESS;
1634 1574
1635 if (hint_uaddr > SOS_PAGING_TOP_USER_ADDRES 1575 if (hint_uaddr > SOS_PAGING_TOP_USER_ADDRESS - size + 1)
1636 return (sos_uaddr_t)NULL; 1576 return (sos_uaddr_t)NULL;
1637 1577
1638 initial_vr = vr = find_enclosing_or_next_vr 1578 initial_vr = vr = find_enclosing_or_next_vr(as, hint_uaddr);
1639 if (! vr) 1579 if (! vr)
1640 1580
1641 return hint_uaddr; 1581 return hint_uaddr;
1642 1582
1643 1583
1644 do 1584 do
1645 { 1585 {
1646 1586
1647 if (hint_uaddr + size <= vr->start) 1587 if (hint_uaddr + size <= vr->start)
1648 1588
1649 return hint_uaddr; 1589 return hint_uaddr;
1650 1590
1651 1591
1652 1592
1653 if (vr->next_in_as->start >= hint_uaddr 1593 if (vr->next_in_as->start >= hint_uaddr)
1654 1594
1655 hint_uaddr = vr->start + vr->size; 1595 hint_uaddr = vr->start + vr->size;
1656 else 1596 else
1657 { 1597 {
1658 1598
1659 1599
1660 1600
1661 if (hint_uaddr <= SOS_PAGING_TOP_US 1601 if (hint_uaddr <= SOS_PAGING_TOP_USER_ADDRESS - size)
1662 return hint_uaddr; 1602 return hint_uaddr;
1663 1603
1664 hint_uaddr = SOS_PAGING_BASE_USER_A 1604 hint_uaddr = SOS_PAGING_BASE_USER_ADDRESS;
1665 } 1605 }
1666 1606
1667 1607
1668 vr = vr->next_in_as; 1608 vr = vr->next_in_as;
1669 } 1609 }
1670 while (vr != initial_vr); 1610 while (vr != initial_vr);
1671 1611
1672 1612
1673 1613
1674 1614
1675 return (sos_uaddr_t)NULL; 1615 return (sos_uaddr_t)NULL;
1676 } 1616 }
1677 1617
1678 1618
1679 static void 1619 static void
1680 as_account_change_of_vr_protection(struct sos 1620 as_account_change_of_vr_protection(struct sos_umem_vmm_as * as,
1681 sos_bool_t 1621 sos_bool_t is_shared,
1682 sos_size_t 1622 sos_size_t size,
1683 sos_ui32_t 1623 sos_ui32_t prev_access_rights,
1684 sos_ui32_t 1624 sos_ui32_t new_access_rights)
1685 { 1625 {
1686 if (prev_access_rights == new_access_rights 1626 if (prev_access_rights == new_access_rights)
1687 return; 1627 return;
1688 1628
1689 #define _UPDATE_VMSTAT(field,is_increment) \ 1629 #define _UPDATE_VMSTAT(field,is_increment) \
1690 ({ if (is_increment > 0) \ 1630 ({ if (is_increment > 0) \
1691 as->field += size; \ 1631 as->field += size; \
1692 else \ 1632 else \
1693 { SOS_ASSERT_FATAL(as->field >= size); 1633 { SOS_ASSERT_FATAL(as->field >= size); as->field -= size; } })
1694 #define UPDATE_VMSTAT(field,is_increment) \ 1634 #define UPDATE_VMSTAT(field,is_increment) \
1695 ({ if (is_shared) _UPDATE_VMSTAT(vm_shrd.fi 1635 ({ if (is_shared) _UPDATE_VMSTAT(vm_shrd.field, is_increment); \
1696 _UPDATE_VMSTAT(vm_total.field, is_increm 1636 _UPDATE_VMSTAT(vm_total.field, is_increment); \
1697 SOS_ASSERT_FATAL(as->vm_total.field >= a 1637 SOS_ASSERT_FATAL(as->vm_total.field >= as->vm_shrd.field); })
1698 1638
1699 if ( (new_access_rights & SOS_VM_MAP_PROT_W 1639 if ( (new_access_rights & SOS_VM_MAP_PROT_WRITE)
1700 && !(prev_access_rights & SOS_VM_MAP_P 1640 && !(prev_access_rights & SOS_VM_MAP_PROT_WRITE))
1701 { 1641 {
1702 UPDATE_VMSTAT(rw, +1); 1642 UPDATE_VMSTAT(rw, +1);
1703 if (prev_access_rights & SOS_VM_MAP_PRO 1643 if (prev_access_rights & SOS_VM_MAP_PROT_READ)
1704 UPDATE_VMSTAT(ro, -1); 1644 UPDATE_VMSTAT(ro, -1);
1705 } 1645 }
1706 else if ( !(new_access_rights & SOS_VM_MAP_ 1646 else if ( !(new_access_rights & SOS_VM_MAP_PROT_WRITE)
1707 && (prev_access_rights & SOS_VM_M 1647 && (prev_access_rights & SOS_VM_MAP_PROT_WRITE))
1708 { 1648 {
1709 if (new_access_rights & SOS_VM_MAP_PROT 1649 if (new_access_rights & SOS_VM_MAP_PROT_READ)
1710 UPDATE_VMSTAT(ro, +1); 1650 UPDATE_VMSTAT(ro, +1);
1711 UPDATE_VMSTAT(rw, -1); 1651 UPDATE_VMSTAT(rw, -1);
1712 } 1652 }
1713 else if (new_access_rights & SOS_VM_MAP_PRO 1653 else if (new_access_rights & SOS_VM_MAP_PROT_READ)
1714 UPDATE_VMSTAT(ro, +1); 1654 UPDATE_VMSTAT(ro, +1);
1715 else if (!(new_access_rights & SOS_VM_MAP_P 1655 else if (!(new_access_rights & SOS_VM_MAP_PROT_READ))
1716 UPDATE_VMSTAT(ro, -1); 1656 UPDATE_VMSTAT(ro, -1);
1717 1657
1718 if ( (new_access_rights & SOS_VM_MAP_PROT_E 1658 if ( (new_access_rights & SOS_VM_MAP_PROT_EXEC)
1719 && !(prev_access_rights & SOS_VM_MAP_P 1659 && !(prev_access_rights & SOS_VM_MAP_PROT_EXEC))
1720 { 1660 {
1721 UPDATE_VMSTAT(code, +1); 1661 UPDATE_VMSTAT(code, +1);
1722 } 1662 }
1723 else if ( !(new_access_rights & SOS_VM_MAP_ 1663 else if ( !(new_access_rights & SOS_VM_MAP_PROT_EXEC)
1724 && (prev_access_rights & SOS_VM_M 1664 && (prev_access_rights & SOS_VM_MAP_PROT_EXEC))
1725 { 1665 {
1726 UPDATE_VMSTAT(code, -1); 1666 UPDATE_VMSTAT(code, -1);
1727 } 1667 }
1728 1668
1729 if (new_access_rights && !prev_access_right 1669 if (new_access_rights && !prev_access_rights)
1730 UPDATE_VMSTAT(overall, +1); 1670 UPDATE_VMSTAT(overall, +1);
1731 else if (!new_access_rights && prev_access_ 1671 else if (!new_access_rights && prev_access_rights)
1732 UPDATE_VMSTAT(overall, -1); 1672 UPDATE_VMSTAT(overall, -1);
1733 1673
1734 } 1674 }