SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2005 David Decotigny
002 
003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any later version.
007    
008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details.
012    
013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA. 
017 */
018 
019 #include <sos/assert.h>
020 #include <sos/kmalloc.h>
021 #include <sos/physmem.h>
022 #include <hwcore/paging.h>
023 #include <sos/kmem_slab.h>
024 #include <sos/list.h>
025 #include <hwcore/paging.h>
026 
027 #include "mem.h"
028 
029 
030 /**
031  * A mapped mem/kmem resource
032  */
033 struct kernel_remapped_resource
034 {
035   int ref_cnt;
036   struct sos_umem_vmm_mapped_resource mr;
037 };
038 
039 
040 /** Called after the virtual region has been inserted inside its
041     address space */
042 static void resource_ref(struct sos_umem_vmm_vr * vr)
043 {
044   /* Retrieve the mem/kmem structure associated with the mapped resource */
045   struct kernel_remapped_resource * resource;
046   resource
047     = (struct kernel_remapped_resource*)
048     sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
049 
050   /* Increment ref counter */
051   resource->ref_cnt ++;
052 }
053 
054 
055 /** Called when the virtual region is removed from its address
056     space */
057 static void resource_unref(struct sos_umem_vmm_vr * vr)
058 {
059   /* Retrieve the mem/kmem structure associated with the mapped resource */
060   struct kernel_remapped_resource * resource;
061   resource
062     = (struct kernel_remapped_resource*)
063     sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
064   
065   /* Decrement ref coutner */
066   SOS_ASSERT_FATAL(resource->ref_cnt > 0);
067   resource->ref_cnt --;
068 
069   /* Free the resource if it becomes unused */
070   if (resource->ref_cnt == 0)
071     sos_kfree((sos_vaddr_t)resource);
072 }
073 
074 
075 /** MOST IMPORTANT callback ! Called when a thread page faults on the
076     resource's mapping */
077 static sos_ret_t kmem_page_in(struct sos_umem_vmm_vr * vr,
078                               sos_uaddr_t uaddr,
079                               sos_bool_t write_access)
080 {
081   sos_vaddr_t vaddr;
082   sos_ret_t retval = SOS_OK;
083   sos_paddr_t ppage_paddr;
084 
085   /* Compute address of kernel page */
086   vaddr = uaddr - sos_umem_vmm_get_start_of_vr(vr)
087     + sos_umem_vmm_get_offset_in_resource(vr);
088 
089   /* Don't allow demand paging of non kernel pages */
090   if (vaddr >= SOS_PAGING_BASE_USER_ADDRESS)
091     return -SOS_EFAULT;
092 
093   /* Lookup physical kernel page */
094   ppage_paddr = sos_paging_get_paddr(SOS_PAGE_ALIGN_INF(vaddr));
095 
096   /* Cannot access unmapped kernel pages */
097   if (! ppage_paddr)
098     return -SOS_EFAULT;
099   
100   /* Remap it in user space */
101   retval = sos_paging_map(ppage_paddr,
102                           SOS_PAGE_ALIGN_INF(uaddr),
103                           TRUE,
104                           sos_umem_vmm_get_prot_of_vr(vr));
105 
106   return retval;
107 }
108 
109 
110 /** The callbacks for a mapped kmem resource */
111 static struct sos_umem_vmm_vr_ops kmem_ops = (struct sos_umem_vmm_vr_ops)
112 {
113   .ref     = resource_ref,
114   .unref   = resource_unref,
115   .page_in = kmem_page_in,
116 };
117 
118 
119 /** The callback that gets called when the resource gets mapped */
120 static sos_ret_t kmem_mmap(struct sos_umem_vmm_vr *vr)
121 {
122   return sos_umem_vmm_set_ops_of_vr(vr, &kmem_ops);
123 }
124 
125 
126 /** The function responsible for mapping the /dev/kmem resource in
127     user space */
128 sos_ret_t sos_dev_kmem_map(struct sos_umem_vmm_as * dest_as,
129                            sos_uaddr_t *uaddr,
130                            sos_size_t size,
131                            sos_vaddr_t offset,
132                            sos_ui32_t access_rights,
133                            sos_ui32_t flags)
134 {
135   sos_ret_t retval;
136   struct kernel_remapped_resource * kmem_resource;
137 
138   /* Allocate a new "descriptor" for the resource */
139   kmem_resource
140     = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*kmem_resource),
141                                                      0);
142   if (! kmem_resource)
143     return -SOS_ENOMEM;
144 
145   memset(kmem_resource, 0x0, sizeof(*kmem_resource));
146   kmem_resource->mr.allowed_access_rights 
147     = SOS_VM_MAP_PROT_READ
148     | SOS_VM_MAP_PROT_WRITE
149     | SOS_VM_MAP_PROT_EXEC;
150   kmem_resource->mr.custom_data    = kmem_resource;
151   kmem_resource->mr.mmap           = kmem_mmap;
152 
153   /* Map it in user space */
154   retval = sos_umem_vmm_map(dest_as, uaddr, size,
155                             access_rights, flags,
156                             & kmem_resource->mr, offset);
157   if (SOS_OK != retval)
158     {
159       sos_kfree((sos_vaddr_t)kmem_resource);
160       return retval;
161     }
162 
163   return SOS_OK;
164 }
165 
166 
167 /** MOST IMPORTANT callback ! Called when a thread page faults on the
168     resource's mapping */
169 static sos_ret_t physmem_page_in(struct sos_umem_vmm_vr * vr,
170                                  sos_uaddr_t uaddr,
171                                  sos_bool_t write_access)
172 {
173   sos_ret_t retval = SOS_OK;
174   sos_paddr_t ppage_paddr;
175 
176   /* Compute address of kernel page */
177   ppage_paddr = uaddr - sos_umem_vmm_get_start_of_vr(vr)
178     + sos_umem_vmm_get_offset_in_resource(vr);
179 
180   /* Remap page in user space */
181   retval = sos_paging_map(SOS_PAGE_ALIGN_INF(ppage_paddr),
182                           SOS_PAGE_ALIGN_INF(uaddr),
183                           TRUE,
184                           sos_umem_vmm_get_prot_of_vr(vr));
185   return retval;
186 }
187 
188 
189 /** The callbacks for a mapped physmem resource */
190 static struct sos_umem_vmm_vr_ops physmem_ops = (struct sos_umem_vmm_vr_ops)
191 {
192   .ref     = resource_ref,
193   .unref   = resource_unref,
194   .page_in = physmem_page_in,
195 };
196 
197 
198 /** The callback that gets called when the resource gets mapped */
199 static sos_ret_t physmem_mmap(struct sos_umem_vmm_vr *vr)
200 {
201   return sos_umem_vmm_set_ops_of_vr(vr, &physmem_ops);
202 }
203 
204 
205 /** The function responsible for mapping the /dev/mem resource in
206     user space */
207 sos_ret_t sos_dev_physmem_map(struct sos_umem_vmm_as * dest_as,
208                               sos_uaddr_t *uaddr,
209                               sos_size_t size,
210                               sos_paddr_t offset,
211                               sos_ui32_t access_rights,
212                               sos_ui32_t flags)
213 {
214   sos_ret_t retval;
215   struct kernel_remapped_resource * physmem_resource;
216 
217   physmem_resource
218     = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*physmem_resource),
219                                                      0);
220   if (! physmem_resource)
221     return -SOS_ENOMEM;
222 
223   memset(physmem_resource, 0x0, sizeof(*physmem_resource));
224   physmem_resource->mr.allowed_access_rights 
225     = SOS_VM_MAP_PROT_READ
226     | SOS_VM_MAP_PROT_WRITE
227     | SOS_VM_MAP_PROT_EXEC;
228   physmem_resource->mr.custom_data    = physmem_resource;
229   physmem_resource->mr.mmap           = physmem_mmap;
230 
231   retval = sos_umem_vmm_map(dest_as, uaddr, size,
232                             access_rights, flags,
233                             & physmem_resource->mr, offset);
234   if (SOS_OK != retval)
235     {
236       sos_kfree((sos_vaddr_t)physmem_resource);
237       return retval;
238     }
239 
240   return SOS_OK;
241 }

source navigation ] diff markup ] identifier search ] general search ]