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/kmalloc.h> 020 #include <sos/kmalloc.h>
021 #include <sos/physmem.h> 021 #include <sos/physmem.h>
022 #include <hwcore/paging.h> 022 #include <hwcore/paging.h>
023 #include <sos/kmem_slab.h> 023 #include <sos/kmem_slab.h>
024 #include <sos/list.h> 024 #include <sos/list.h>
025 #include <hwcore/paging.h> 025 #include <hwcore/paging.h>
026 #include <drivers/devices.h> <<
027 #include <sos/kmem_vmm.h> <<
028 #include <sos/uaccess.h> <<
029 #include <sos/chardev.h> <<
030 026
031 #include "mem.h" 027 #include "mem.h"
032 028
033 029
034 030
035 031
036 032
037 struct kernel_remapped_resource 033 struct kernel_remapped_resource
038 { 034 {
039 int ref_cnt; 035 int ref_cnt;
040 struct sos_umem_vmm_mapped_resource mr; 036 struct sos_umem_vmm_mapped_resource mr;
041 }; 037 };
042 038
043 039
044 040
045 041
046 static void resource_ref(struct sos_umem_vmm_v 042 static void resource_ref(struct sos_umem_vmm_vr * vr)
047 { 043 {
048 044
049 struct kernel_remapped_resource * resource; 045 struct kernel_remapped_resource * resource;
050 resource 046 resource
051 = (struct kernel_remapped_resource*) 047 = (struct kernel_remapped_resource*)
052 sos_umem_vmm_get_mapped_resource_of_vr(vr) 048 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
053 049
054 050
055 resource->ref_cnt ++; 051 resource->ref_cnt ++;
056 } 052 }
057 053
058 054
059 055
060 056
061 static void resource_unref(struct sos_umem_vmm 057 static void resource_unref(struct sos_umem_vmm_vr * vr)
062 { 058 {
063 059
064 struct kernel_remapped_resource * resource; 060 struct kernel_remapped_resource * resource;
065 resource 061 resource
066 = (struct kernel_remapped_resource*) 062 = (struct kernel_remapped_resource*)
067 sos_umem_vmm_get_mapped_resource_of_vr(vr) 063 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
068 064
069 065
070 SOS_ASSERT_FATAL(resource->ref_cnt > 0); 066 SOS_ASSERT_FATAL(resource->ref_cnt > 0);
071 resource->ref_cnt --; 067 resource->ref_cnt --;
072 068
073 069
074 if (resource->ref_cnt == 0) 070 if (resource->ref_cnt == 0)
075 sos_kfree((sos_vaddr_t)resource); 071 sos_kfree((sos_vaddr_t)resource);
076 } 072 }
077 073
078 074
079 075
080 076
081 static sos_ret_t kmem_page_in(struct sos_umem_ 077 static sos_ret_t kmem_page_in(struct sos_umem_vmm_vr * vr,
082 sos_uaddr_t uadd 078 sos_uaddr_t uaddr,
083 sos_bool_t write 079 sos_bool_t write_access)
084 { 080 {
085 sos_vaddr_t vaddr; 081 sos_vaddr_t vaddr;
086 sos_ret_t retval = SOS_OK; 082 sos_ret_t retval = SOS_OK;
087 sos_paddr_t ppage_paddr; 083 sos_paddr_t ppage_paddr;
088 084
089 085
090 vaddr = uaddr - sos_umem_vmm_get_start_of_vr 086 vaddr = uaddr - sos_umem_vmm_get_start_of_vr(vr)
091 + sos_umem_vmm_get_offset_in_resource(vr); 087 + sos_umem_vmm_get_offset_in_resource(vr);
092 088
093 089
094 if (vaddr >= SOS_PAGING_BASE_USER_ADDRESS) 090 if (vaddr >= SOS_PAGING_BASE_USER_ADDRESS)
095 return -SOS_EFAULT; 091 return -SOS_EFAULT;
096 092
097 093
098 ppage_paddr = sos_paging_get_paddr(SOS_PAGE_ 094 ppage_paddr = sos_paging_get_paddr(SOS_PAGE_ALIGN_INF(vaddr));
099 095
100 096
101 if (! ppage_paddr) 097 if (! ppage_paddr)
102 return -SOS_EFAULT; 098 return -SOS_EFAULT;
103 099
104 100
105 retval = sos_paging_map(ppage_paddr, 101 retval = sos_paging_map(ppage_paddr,
106 SOS_PAGE_ALIGN_INF(u 102 SOS_PAGE_ALIGN_INF(uaddr),
107 TRUE, 103 TRUE,
108 sos_umem_vmm_get_pro 104 sos_umem_vmm_get_prot_of_vr(vr));
109 105
110 return retval; 106 return retval;
111 } 107 }
112 108
113 109
114 110
115 static struct sos_umem_vmm_vr_ops kmem_ops = ( 111 static struct sos_umem_vmm_vr_ops kmem_ops = (struct sos_umem_vmm_vr_ops)
116 { 112 {
117 .ref = resource_ref, 113 .ref = resource_ref,
118 .unref = resource_unref, 114 .unref = resource_unref,
119 .page_in = kmem_page_in, 115 .page_in = kmem_page_in,
120 }; 116 };
121 117
122 118
123 119
124 static sos_ret_t kmem_mmap(struct sos_umem_vmm 120 static sos_ret_t kmem_mmap(struct sos_umem_vmm_vr *vr)
125 { 121 {
126 return sos_umem_vmm_set_ops_of_vr(vr, &kmem_ 122 return sos_umem_vmm_set_ops_of_vr(vr, &kmem_ops);
127 } 123 }
128 124
129 125
130 126
131 127
132 static <<
133 sos_ret_t sos_dev_kmem_map(struct sos_umem_vmm 128 sos_ret_t sos_dev_kmem_map(struct sos_umem_vmm_as * dest_as,
134 sos_uaddr_t *uaddr, 129 sos_uaddr_t *uaddr,
135 sos_size_t size, 130 sos_size_t size,
136 sos_vaddr_t offset, 131 sos_vaddr_t offset,
137 sos_ui32_t access_r 132 sos_ui32_t access_rights,
138 sos_ui32_t flags) 133 sos_ui32_t flags)
139 { 134 {
140 sos_ret_t retval; 135 sos_ret_t retval;
141 struct kernel_remapped_resource * kmem_resou 136 struct kernel_remapped_resource * kmem_resource;
142 137
143 138
144 kmem_resource 139 kmem_resource
145 = (struct kernel_remapped_resource*) sos_k 140 = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*kmem_resource),
146 141 0);
147 if (! kmem_resource) 142 if (! kmem_resource)
148 return -SOS_ENOMEM; 143 return -SOS_ENOMEM;
149 144
150 memset(kmem_resource, 0x0, sizeof(*kmem_reso 145 memset(kmem_resource, 0x0, sizeof(*kmem_resource));
151 kmem_resource->mr.allowed_access_rights 146 kmem_resource->mr.allowed_access_rights
152 = SOS_VM_MAP_PROT_READ 147 = SOS_VM_MAP_PROT_READ
153 | SOS_VM_MAP_PROT_WRITE 148 | SOS_VM_MAP_PROT_WRITE
154 | SOS_VM_MAP_PROT_EXEC; 149 | SOS_VM_MAP_PROT_EXEC;
155 kmem_resource->mr.custom_data = kmem_reso 150 kmem_resource->mr.custom_data = kmem_resource;
156 kmem_resource->mr.mmap = kmem_mmap 151 kmem_resource->mr.mmap = kmem_mmap;
157 152
158 153
159 retval = sos_umem_vmm_map(dest_as, uaddr, si 154 retval = sos_umem_vmm_map(dest_as, uaddr, size,
160 access_rights, fla 155 access_rights, flags,
161 & kmem_resource->m 156 & kmem_resource->mr, offset);
162 if (SOS_OK != retval) 157 if (SOS_OK != retval)
163 { 158 {
164 sos_kfree((sos_vaddr_t)kmem_resource); 159 sos_kfree((sos_vaddr_t)kmem_resource);
165 return retval; 160 return retval;
166 } 161 }
167 162
168 return SOS_OK; 163 return SOS_OK;
169 } 164 }
170 165
171 166
172 167
173 168
174 static sos_ret_t physmem_page_in(struct sos_um 169 static sos_ret_t physmem_page_in(struct sos_umem_vmm_vr * vr,
175 sos_uaddr_t u 170 sos_uaddr_t uaddr,
176 sos_bool_t wr 171 sos_bool_t write_access)
177 { 172 {
178 sos_ret_t retval = SOS_OK; 173 sos_ret_t retval = SOS_OK;
179 sos_paddr_t ppage_paddr; 174 sos_paddr_t ppage_paddr;
180 175
181 176
182 ppage_paddr = uaddr - sos_umem_vmm_get_start 177 ppage_paddr = uaddr - sos_umem_vmm_get_start_of_vr(vr)
183 + sos_umem_vmm_get_offset_in_resource(vr); 178 + sos_umem_vmm_get_offset_in_resource(vr);
184 179
185 180
186 retval = sos_paging_map(SOS_PAGE_ALIGN_INF(p 181 retval = sos_paging_map(SOS_PAGE_ALIGN_INF(ppage_paddr),
187 SOS_PAGE_ALIGN_INF(u 182 SOS_PAGE_ALIGN_INF(uaddr),
188 TRUE, 183 TRUE,
189 sos_umem_vmm_get_pro 184 sos_umem_vmm_get_prot_of_vr(vr));
190 return retval; 185 return retval;
191 } 186 }
192 187
193 188
194 189
195 static struct sos_umem_vmm_vr_ops physmem_ops 190 static struct sos_umem_vmm_vr_ops physmem_ops = (struct sos_umem_vmm_vr_ops)
196 { 191 {
197 .ref = resource_ref, 192 .ref = resource_ref,
198 .unref = resource_unref, 193 .unref = resource_unref,
199 .page_in = physmem_page_in, 194 .page_in = physmem_page_in,
200 }; 195 };
201 196
202 197
203 198
204 static sos_ret_t physmem_mmap(struct sos_umem_ 199 static sos_ret_t physmem_mmap(struct sos_umem_vmm_vr *vr)
205 { 200 {
206 return sos_umem_vmm_set_ops_of_vr(vr, &physm 201 return sos_umem_vmm_set_ops_of_vr(vr, &physmem_ops);
207 } 202 }
208 203
209 204
210 205
211 206
212 static <<
213 sos_ret_t sos_dev_physmem_map(struct sos_umem_ 207 sos_ret_t sos_dev_physmem_map(struct sos_umem_vmm_as * dest_as,
214 sos_uaddr_t *uad 208 sos_uaddr_t *uaddr,
215 sos_size_t size, 209 sos_size_t size,
216 sos_paddr_t offs 210 sos_paddr_t offset,
217 sos_ui32_t acces 211 sos_ui32_t access_rights,
218 sos_ui32_t flags 212 sos_ui32_t flags)
219 { 213 {
220 sos_ret_t retval; 214 sos_ret_t retval;
221 struct kernel_remapped_resource * physmem_re 215 struct kernel_remapped_resource * physmem_resource;
222 216
223 physmem_resource 217 physmem_resource
224 = (struct kernel_remapped_resource*) sos_k 218 = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*physmem_resource),
225 219 0);
226 if (! physmem_resource) 220 if (! physmem_resource)
227 return -SOS_ENOMEM; 221 return -SOS_ENOMEM;
228 222
229 memset(physmem_resource, 0x0, sizeof(*physme 223 memset(physmem_resource, 0x0, sizeof(*physmem_resource));
230 physmem_resource->mr.allowed_access_rights 224 physmem_resource->mr.allowed_access_rights
231 = SOS_VM_MAP_PROT_READ 225 = SOS_VM_MAP_PROT_READ
232 | SOS_VM_MAP_PROT_WRITE 226 | SOS_VM_MAP_PROT_WRITE
233 | SOS_VM_MAP_PROT_EXEC; 227 | SOS_VM_MAP_PROT_EXEC;
234 physmem_resource->mr.custom_data = physme 228 physmem_resource->mr.custom_data = physmem_resource;
235 physmem_resource->mr.mmap = physme 229 physmem_resource->mr.mmap = physmem_mmap;
236 230
237 retval = sos_umem_vmm_map(dest_as, uaddr, si 231 retval = sos_umem_vmm_map(dest_as, uaddr, size,
238 access_rights, fla 232 access_rights, flags,
239 & physmem_resource 233 & physmem_resource->mr, offset);
240 if (SOS_OK != retval) 234 if (SOS_OK != retval)
241 { 235 {
242 sos_kfree((sos_vaddr_t)physmem_resource) 236 sos_kfree((sos_vaddr_t)physmem_resource);
243 return retval; 237 return retval;
244 } 238 }
245 239
246 return SOS_OK; 240 return SOS_OK;
247 } <<
248 <<
249 <<
250 <<
251 <<
252 <<
253 <<
254 <<
255 <<
256 #define GET_DEV_SIZE(fsnode) \ <<
257 ((sos_size_t)(fsnode)->custom_data) <<
258 <<
259 static sos_ret_t dev_mem_fs_open(struct sos_fs <<
260 struct sos_fs <<
261 void * charde <<
262 { <<
263 <<
264 <<
265 switch (fsnode->dev_id.device_instance) <<
266 { <<
267 <<
268 case SOS_CHARDEV_KMEM_MINOR: <<
269 fsnode->custom_data = (void*)SOS_PAGING_ <<
270 return SOS_OK; <<
271 break; <<
272 <<
273 <<
274 case SOS_CHARDEV_PHYSMEM_MINOR: <<
275 { <<
276 sos_size_t ram_pages = 0; <<
277 sos_physmem_get_state(& ram_pages, NUL <<
278 fsnode->custom_data = (void*)(ram_page <<
279 } <<
280 return SOS_OK; <<
281 break; <<
282 <<
283 default: <<
284 break; <<
285 } <<
286 <<
287 return -SOS_ENODEV; <<
288 } <<
289 <<
290 <<
291 static sos_ret_t dev_mem_fs_seek(struct sos_fs <<
292 sos_lsoffset_ <<
293 sos_seek_when <<
294 sos <<
295 { <<
296 <<
297 struct sos_fs_node * fsnode = sos_fs_nscache <<
298 <<
299 <<
300 sos_lsoffset_t ref_offs; <<
301 sos_lsoffset_t dev_size = GET_DEV_SIZE(fsnod <<
302 <<
303 *result_position = this->position; <<
304 switch (whence) <<
305 { <<
306 case SOS_SEEK_SET: <<
307 ref_offs = 0; <<
308 break; <<
309 <<
310 case SOS_SEEK_CUR: <<
311 ref_offs = this->position; <<
312 break; <<
313 <<
314 case SOS_SEEK_END: <<
315 ref_offs = dev_size; <<
316 break; <<
317 <<
318 default: <<
319 return -SOS_EINVAL; <<
320 } <<
321 <<
322 <<
323 if (offset < -ref_offs) <<
324 return -SOS_EINVAL; <<
325 <<
326 <<
327 else if (ref_offs + offset > dev_size) <<
328 return -SOS_EINVAL; <<
329 <<
330 this->position = ref_offs + offset; <<
331 *result_position = this->position; <<
332 return SOS_OK; <<
333 } <<
334 <<
335 <<
336 typedef enum { DO_READ, DO_WRITE } dev_mem_acc <<
337 static sos_ret_t dev_mem_fs_access(struct sos_ <<
338 sos_uaddr_t <<
339 sos_size_t <<
340 dev_mem_acc <<
341 { <<
342 struct sos_fs_node * fsnode = sos_fs_nscache <<
343 sos_vaddr_t physmem_transfer_kernel_page = <<
344 sos_uoffset_t offs; <<
345 sos_size_t accesslen = 0; <<
346 <<
347 <<
348 if (this->position + *len >= GET_DEV_SIZE(fs <<
349 *len = GET_DEV_SIZE(fsnode) - this->positi <<
350 <<
351 <<
352 if (*len <= 0) <<
353 return SOS_OK; <<
354 <<
355 <<
356 <<
357 if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode->dev <<
358 { <<
359 physmem_transfer_kernel_page = sos_kmem_ <<
360 if (! physmem_transfer_kernel_page) <<
361 return -SOS_ENOMEM; <<
362 } <<
363 <<
364 <<
365 offs = this->position; <<
366 while (offs < this->position + *len) <<
367 { <<
368 <<
369 sos_uoffset_t page_boundary = SOS_PAGE_A <<
370 sos_vaddr_t page_vaddr; <<
371 sos_uoffset_t offset_in_page; <<
372 sos_uoffset_t accesslen_in_page; <<
373 sos_ret_t retval; <<
374 <<
375 <<
376 <<
377 if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode- <<
378 { <<
379 retval = sos_paging_map(page_boundar <<
380 physmem_tran <<
381 FALSE, <<
382 (access_type <<
383 SOS_VM_MAP <<
384 :SOS_VM_MA <<
385 if (SOS_OK != retval) <<
386 break; <<
387 <<
388 page_vaddr = physmem_transfer_kernel <<
389 } <<
390 <<
391 else if (! sos_kmem_vmm_is_valid_vaddr(p <<
392 break; <<
393 else <<
394 page_vaddr = page_boundary; <<
395 <<
396 <<
397 offset_in_page = offs - page_boundary; <<
398 accesslen_in_page = SOS_PAGE_SIZE - off <<
399 if (accesslen + accesslen_in_page > *len <<
400 accesslen_in_page = *len - accesslen; <<
401 <<
402 if (access_type==DO_WRITE) <<
403 retval = sos_memcpy_from_user(page_vad <<
404 user_buf <<
405 accessle <<
406 else <<
407 retval = sos_memcpy_to_user(user_buf + <<
408 page_vaddr <<
409 accesslen_ <<
410 <<
411 <<
412 if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode- <<
413 sos_paging_unmap(physmem_transfer_kern <<
414 <<
415 <<
416 if (retval < 0) <<
417 break; <<
418 <<
419 accesslen += retval; <<
420 <<
421 if (retval < (sos_ret_t)accesslen_in_pag <<
422 break; <<
423 <<
424 <<
425 offs = page_boundary + SOS_PAGE_SIZE; <<
426 } <<
427 <<
428 <<
429 if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode->dev <<
430 sos_kmem_vmm_free(physmem_transfer_kernel_ <<
431 <<
432 <<
433 *len = accesslen; <<
434 this->position += accesslen; <<
435 return SOS_OK; <<
436 } <<
437 <<
438 <<
439 static sos_ret_t dev_mem_fs_read(struct sos_fs <<
440 sos_uaddr_t <<
441 sos_size_t <<
442 { <<
443 return dev_mem_fs_access(this, dest_buf, len <<
444 } <<
445 <<
446 <<
447 static sos_ret_t dev_mem_fs_write(struct sos_f <<
448 sos_uaddr_t <<
449 sos_size_t * <<
450 { <<
451 return dev_mem_fs_access(this, src_buf, len, <<
452 } <<
453 <<
454 <<
455 static sos_ret_t dev_mem_fs_mmap(struct sos_fs <<
456 sos_uaddr_t * <<
457 sos_ui32_t ac <<
458 sos_ui32_t fl <<
459 sos_luoffset_ <<
460 { <<
461 struct sos_fs_node * fsnode = sos_fs_nscache <<
462 if (SOS_CHARDEV_PHYSMEM_MINOR == fsnode->dev <<
463 return sos_dev_physmem_map(sos_process_get <<
464 uaddr, size, of <<
465 <<
466 return sos_dev_kmem_map(sos_process_get_addr <<
467 uaddr, size, offset, <<
468 } <<
469 <<
470 <<
471 static struct sos_chardev_ops dev_mem_fs_ops <<
472 = (struct sos_chardev_ops) { <<
473 .open = dev_mem_fs_open, <<
474 .close = NULL, <<
475 .seek = dev_mem_fs_seek, <<
476 .read = dev_mem_fs_read, <<
477 .write = dev_mem_fs_write, <<
478 .mmap = dev_mem_fs_mmap, <<
479 .fcntl = NULL, <<
480 .ioctl = NULL <<
481 }; <<
482 <<
483 <<
484 sos_ret_t sos_dev_mem_chardev_setup() <<
485 { <<
486 return sos_chardev_register_class(SOS_CHARDE <<
487 & dev_mem_ <<
488 NULL); <<
489 } 241 }