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