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 ]

Diff markup

Differences between /hwcore/mm_context.c (Article 9.5) and /hwcore/mm_context.c (Article 7)


001 /* Copyright (C) 2005  David Decotigny            001 /* Copyright (C) 2005  David Decotigny
002                                                   002 
003    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
007                                                   007    
008    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details    011    GNU General Public License for more details.
012                                                   012    
013    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA.                                           016    USA. 
017 */                                                017 */
018                                                   018 
019 #include <hwcore/paging.h>                        019 #include <hwcore/paging.h>
020 #include <hwcore/irq.h>                           020 #include <hwcore/irq.h>
021                                                   021 
022 #include <sos/assert.h>                           022 #include <sos/assert.h>
023 #include <sos/list.h>                             023 #include <sos/list.h>
024 #include <sos/klibc.h>                            024 #include <sos/klibc.h>
025 #include <sos/physmem.h>                          025 #include <sos/physmem.h>
026 #include <sos/kmem_slab.h>                        026 #include <sos/kmem_slab.h>
027 #include <sos/kmem_vmm.h>                         027 #include <sos/kmem_vmm.h>
028                                                   028 
029 #include "mm_context.h"                           029 #include "mm_context.h"
030                                                   030 
031                                                   031 
032 /**                                               032 /**
033  * Definition of an MMU context.                  033  * Definition of an MMU context.
034  */                                               034  */
035 struct sos_mm_context                             035 struct sos_mm_context
036 {                                                 036 {
037   /** Physical address of the PD for this MMU     037   /** Physical address of the PD for this MMU context */
038   sos_paddr_t paddr_PD;                           038   sos_paddr_t paddr_PD;
039                                                   039 
040   /** Virtual address where it is mapped into     040   /** Virtual address where it is mapped into the Kernel space */
041   sos_vaddr_t vaddr_PD;                           041   sos_vaddr_t vaddr_PD;
042                                                   042 
043   /** Reference counter for this mm_context */    043   /** Reference counter for this mm_context */
044   sos_ui32_t  ref_cnt;                            044   sos_ui32_t  ref_cnt;
045                                                   045 
046   /** List of MMU contexts in the system */       046   /** List of MMU contexts in the system */
047   struct sos_mm_context *prev, *next;             047   struct sos_mm_context *prev, *next;
048 };                                                048 };
049                                                   049 
050                                                   050 
051 /**                                               051 /**
052  * The cache of mm_context structures             052  * The cache of mm_context structures
053  */                                               053  */
054 struct sos_kslab_cache * cache_struct_mm_conte    054 struct sos_kslab_cache * cache_struct_mm_context;
055                                                   055 
056                                                   056 
057 /**                                               057 /**
058  * The current MMU context corresponding to th    058  * The current MMU context corresponding to the current configuration
059  * of the MMU.                                    059  * of the MMU.
060  */                                               060  */
061 static struct sos_mm_context *current_mm_conte    061 static struct sos_mm_context *current_mm_context = NULL;
062                                                   062 
063                                                   063 
064 /**                                               064 /**
065  * System-wide list of all the mm_contexts in     065  * System-wide list of all the mm_contexts in the system
066  */                                               066  */
067 static struct sos_mm_context *list_mm_context     067 static struct sos_mm_context *list_mm_context = NULL;
068 /* The "= NULL" here is FUNDAMENTAL, because p    068 /* The "= NULL" here is FUNDAMENTAL, because paging.c must work
069    correctly, ie synch_PDE below must behave r    069    correctly, ie synch_PDE below must behave reasonably (eg do
070    nothing), until the mm_context subsystem ha    070    nothing), until the mm_context subsystem has been initialized. */
071                                                   071 
072                                                   072 
073 sos_ret_t sos_mm_context_subsystem_setup()        073 sos_ret_t sos_mm_context_subsystem_setup()
074 {                                                 074 {
075   struct sos_mm_context * initial_mm_context;     075   struct sos_mm_context * initial_mm_context;
076   sos_ret_t retval;                               076   sos_ret_t retval;
077                                                   077 
078   /* Create the new mm_context cache */           078   /* Create the new mm_context cache */
079   cache_struct_mm_context = sos_kmem_cache_cre    079   cache_struct_mm_context = sos_kmem_cache_create("struct mm_context",
080                                                   080                                                   sizeof(struct sos_mm_context),
081                                                   081                                                   1, 0,
082                                                   082                                                   SOS_KSLAB_CREATE_MAP);
083   if (NULL == cache_struct_mm_context)            083   if (NULL == cache_struct_mm_context)
084     return -SOS_ENOMEM;                           084     return -SOS_ENOMEM;
085                                                   085 
086   /*                                              086   /*
087    * Allocate the initial mm_context structure    087    * Allocate the initial mm_context structure
088    */                                             088    */
089   initial_mm_context                              089   initial_mm_context
090     = (struct sos_mm_context*) sos_kmem_cache_    090     = (struct sos_mm_context*) sos_kmem_cache_alloc(cache_struct_mm_context,
091                                                   091                                                     SOS_KSLAB_ALLOC_ATOMIC);
092   if (NULL == initial_mm_context)                 092   if (NULL == initial_mm_context)
093     return -SOS_ENOMEM;                           093     return -SOS_ENOMEM;
094                                                   094 
095   /* Retrieve the address of the current page     095   /* Retrieve the address of the current page where the PD lies */
096   initial_mm_context->paddr_PD = sos_paging_ge    096   initial_mm_context->paddr_PD = sos_paging_get_current_PD_paddr();
097                                                   097 
098   /*                                              098   /*
099    * Map it somewhere in kernel virtual memory    099    * Map it somewhere in kernel virtual memory
100    */                                             100    */
101                                                   101 
102   /* Allocate 1 page of kernel Virtual memory     102   /* Allocate 1 page of kernel Virtual memory */
103   initial_mm_context->vaddr_PD = sos_kmem_vmm_    103   initial_mm_context->vaddr_PD = sos_kmem_vmm_alloc(1, 0);
104   if (initial_mm_context->vaddr_PD == 0)          104   if (initial_mm_context->vaddr_PD == 0)
105     return -SOS_ENOMEM;                           105     return -SOS_ENOMEM;
106                                                   106 
107   /* Map the PD at this virtual address: it wi    107   /* Map the PD at this virtual address: it will thus be mapped 2
108      times (1 time for the mirroring, 1 time f    108      times (1 time for the mirroring, 1 time for mm_context) ! */
109   retval = sos_paging_map(initial_mm_context->    109   retval = sos_paging_map(initial_mm_context->paddr_PD,
110                           initial_mm_context->    110                           initial_mm_context->vaddr_PD,
111                           FALSE,                  111                           FALSE,
112                           SOS_VM_MAP_PROT_READ    112                           SOS_VM_MAP_PROT_READ
113                           | SOS_VM_MAP_PROT_WR    113                           | SOS_VM_MAP_PROT_WRITE);
114   if (SOS_OK != retval)                           114   if (SOS_OK != retval)
115     return retval;                                115     return retval;
116                                                   116 
117   /* Initialize the initial list of mm_context    117   /* Initialize the initial list of mm_contexts */
118   list_singleton(list_mm_context, initial_mm_c    118   list_singleton(list_mm_context, initial_mm_context);
119                                                   119 
120   /* We just created this mm_context: mark it     120   /* We just created this mm_context: mark it as "referenced" */
121   initial_mm_context->ref_cnt ++;                 121   initial_mm_context->ref_cnt ++;
122                                                   122 
123   /* We are actually already using it ! */        123   /* We are actually already using it ! */
124   initial_mm_context->ref_cnt ++; /* ie refere    124   initial_mm_context->ref_cnt ++; /* ie reference it a 2nd time ! */
125   current_mm_context = initial_mm_context;        125   current_mm_context = initial_mm_context;
126                                                   126 
127   return SOS_OK;                                  127   return SOS_OK;
128 }                                                 128 }
129                                                   129 
130                                                   130 
131 struct sos_mm_context * sos_mm_context_create(    131 struct sos_mm_context * sos_mm_context_create(void)
132 {                                                 132 {
133   sos_ui32_t flags;                               133   sos_ui32_t flags;
134   struct sos_mm_context *mmctxt;                  134   struct sos_mm_context *mmctxt;
135                                                   135 
136   /*                                              136   /*
137    * Allocate the initial mm_context structure    137    * Allocate the initial mm_context structure
138    */                                             138    */
139   mmctxt = (struct sos_mm_context*) sos_kmem_c    139   mmctxt = (struct sos_mm_context*) sos_kmem_cache_alloc(cache_struct_mm_context, 0);
140   if (NULL == mmctxt)                             140   if (NULL == mmctxt)
141     return NULL;                                  141     return NULL;
142                                                   142 
143   /* Allocate a new page for the new PD and ma    143   /* Allocate a new page for the new PD and map it into the kernel */
144   mmctxt->vaddr_PD = sos_kmem_vmm_alloc(1, SOS    144   mmctxt->vaddr_PD = sos_kmem_vmm_alloc(1, SOS_KMEM_VMM_MAP);
145   if (mmctxt->vaddr_PD == 0)                      145   if (mmctxt->vaddr_PD == 0)
146     {                                             146     {
147       sos_kmem_cache_free((sos_vaddr_t) mmctxt    147       sos_kmem_cache_free((sos_vaddr_t) mmctxt);
148       return NULL;                                148       return NULL;
149     }                                             149     }
150                                                   150 
151   /* Retrieve its physical address */             151   /* Retrieve its physical address */
152   mmctxt->paddr_PD = sos_paging_get_paddr(mmct    152   mmctxt->paddr_PD = sos_paging_get_paddr(mmctxt->vaddr_PD);
153   if (mmctxt->paddr_PD == 0)                      153   if (mmctxt->paddr_PD == 0)
154     {                                             154     {
155       sos_kmem_cache_free((sos_vaddr_t) mmctxt << 
156       sos_kmem_cache_free((sos_vaddr_t) mmctxt    155       sos_kmem_cache_free((sos_vaddr_t) mmctxt);
157       return NULL;                                156       return NULL;
158     }                                             157     }
159                                                   158 
160   /* Copy the current hardware MMU address tra    159   /* Copy the current hardware MMU address translation tables */
161   if (SOS_OK != sos_paging_copy_kernel_space(m    160   if (SOS_OK != sos_paging_copy_kernel_space(mmctxt->vaddr_PD,
162                                              c    161                                              current_mm_context->vaddr_PD))
163     {                                             162     {
164       sos_kmem_cache_free((sos_vaddr_t) mmctxt << 
165       sos_kmem_cache_free((sos_vaddr_t) mmctxt    163       sos_kmem_cache_free((sos_vaddr_t) mmctxt);
166       return NULL;                                164       return NULL;
167     }                                             165     }
168                                                   166 
169   /* Mark the mm_context as "referenced" */       167   /* Mark the mm_context as "referenced" */
170   mmctxt->ref_cnt = 1;                            168   mmctxt->ref_cnt = 1;
171                                                   169 
172   /* Add it to the list of MMU contexts */        170   /* Add it to the list of MMU contexts */
173   sos_disable_IRQs(flags);                        171   sos_disable_IRQs(flags);
174   list_add_tail(list_mm_context, mmctxt);         172   list_add_tail(list_mm_context, mmctxt);
175   sos_restore_IRQs(flags);                        173   sos_restore_IRQs(flags);
176                                                   174 
177   return mmctxt;                                  175   return mmctxt;
178 }                                                 176 }
179                                                   177 
180                                                   178 
181 struct sos_mm_context *                        << 
182 sos_mm_context_duplicate(const struct sos_mm_c << 
183 {                                              << 
184   struct sos_mm_context *mmctxt;               << 
185                                                << 
186   /* Create an mm_context, the kernel space wi << 
187   mmctxt = sos_mm_context_create();            << 
188   if (NULL == mmctxt)                          << 
189     return NULL;                               << 
190                                                << 
191   /* Copy the user-space configuration of the  << 
192   if (SOS_OK != sos_paging_copy_user_space(mmc << 
193                                            mod << 
194     {                                          << 
195       sos_mm_context_unref(mmctxt);            << 
196       return NULL;                             << 
197     }                                          << 
198                                                << 
199   return mmctxt;                               << 
200 }                                              << 
201                                                << 
202                                                << 
203 sos_ret_t sos_mm_context_unref(struct sos_mm_c    179 sos_ret_t sos_mm_context_unref(struct sos_mm_context *mmctxt)
204 {                                                 180 {
205   sos_ui32_t flags;                               181   sos_ui32_t flags;
206                                                   182 
207   sos_disable_IRQs(flags);                        183   sos_disable_IRQs(flags);
208                                                   184 
209   /* A valid mmctxt is one which is not yet un    185   /* A valid mmctxt is one which is not yet unreferenced */
210   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);          186   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);
211                                                   187 
212   /* Unreference it */                            188   /* Unreference it */
213   mmctxt->ref_cnt --;                             189   mmctxt->ref_cnt --;
214                                                   190 
215   /* If somebody is still using it, don't rele    191   /* If somebody is still using it, don't release it now */
216   if (mmctxt->ref_cnt > 0)                        192   if (mmctxt->ref_cnt > 0)
217     {                                             193     {
218       sos_restore_IRQs(flags);                    194       sos_restore_IRQs(flags);
219       return SOS_OK;                              195       return SOS_OK;
220     }                                             196     }
221                                                   197 
222   /* If nobody uses it, then it cannot be the     198   /* If nobody uses it, then it cannot be the current mm_context ! */
223   SOS_ASSERT_FATAL(mmctxt != current_mm_contex    199   SOS_ASSERT_FATAL(mmctxt != current_mm_context);
224                                                   200 
225   /* Remove it from the list of mm_contexts */    201   /* Remove it from the list of mm_contexts */
226   list_delete(list_mm_context, mmctxt);           202   list_delete(list_mm_context, mmctxt);
227                                                   203 
228   sos_restore_IRQs(flags);                        204   sos_restore_IRQs(flags);
229                                                   205 
230   /* Remove all user mappings (if any) */         206   /* Remove all user mappings (if any) */
231   sos_paging_dispose(mmctxt->vaddr_PD);           207   sos_paging_dispose(mmctxt->vaddr_PD);
232                                                   208 
233   /* Unmap the PD from the kernel */              209   /* Unmap the PD from the kernel */
234   sos_kmem_vmm_free(mmctxt->vaddr_PD);            210   sos_kmem_vmm_free(mmctxt->vaddr_PD);
235                                                   211 
236   memset(mmctxt, 0x0, sizeof(*mmctxt));           212   memset(mmctxt, 0x0, sizeof(*mmctxt));
237                                                   213 
238   return SOS_OK;                                  214   return SOS_OK;
239 }                                                 215 }
240                                                   216 
241                                                   217 
242 sos_ret_t sos_mm_context_ref(struct sos_mm_con    218 sos_ret_t sos_mm_context_ref(struct sos_mm_context *mmctxt)
243 {                                                 219 {
244   sos_ui32_t flags;                               220   sos_ui32_t flags;
245                                                   221 
246   sos_disable_IRQs(flags);                        222   sos_disable_IRQs(flags);
247                                                   223 
248   /* A valid mmctxt is one which is not yet un    224   /* A valid mmctxt is one which is not yet unreferenced */
249   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);          225   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);
250                                                   226 
251   /* Reference it once again */                   227   /* Reference it once again */
252   mmctxt->ref_cnt ++;                             228   mmctxt->ref_cnt ++;
253                                                   229 
254   sos_restore_IRQs(flags);                        230   sos_restore_IRQs(flags);
255                                                   231 
256   return SOS_OK;                                  232   return SOS_OK;
257 }                                                 233 }
258                                                   234 
259                                                   235 
260 sos_ret_t sos_mm_context_switch_to(struct sos_    236 sos_ret_t sos_mm_context_switch_to(struct sos_mm_context *mmctxt)
261 {                                                 237 {
262   SOS_ASSERT_FATAL(NULL != mmctxt);               238   SOS_ASSERT_FATAL(NULL != mmctxt);
263   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);          239   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);
264   SOS_ASSERT_FATAL(current_mm_context->ref_cnt    240   SOS_ASSERT_FATAL(current_mm_context->ref_cnt > 0);
265   if (mmctxt != current_mm_context)               241   if (mmctxt != current_mm_context)
266     {                                             242     {
267       sos_ui32_t flags;                           243       sos_ui32_t flags;
268       struct sos_mm_context * prev_mm_context     244       struct sos_mm_context * prev_mm_context = current_mm_context;
269                                                   245 
270       /* This is the most dangerous part of th    246       /* This is the most dangerous part of the whole thing. If we set
271          the wrong MMU configuration in mmctxt    247          the wrong MMU configuration in mmctxt, this will hang or
272          reboot the machine... */                 248          reboot the machine... */
273       sos_paging_set_current_PD_paddr(mmctxt->    249       sos_paging_set_current_PD_paddr(mmctxt->paddr_PD);
274                                                   250 
275       /* Exchange the mm_contexts */              251       /* Exchange the mm_contexts */
276       current_mm_context = mmctxt;                252       current_mm_context = mmctxt;
277                                                   253 
278       /* Update the reference counts */           254       /* Update the reference counts */
279       sos_disable_IRQs(flags);                    255       sos_disable_IRQs(flags);
280       mmctxt->ref_cnt ++;                         256       mmctxt->ref_cnt ++;
281       sos_mm_context_unref(prev_mm_context);      257       sos_mm_context_unref(prev_mm_context);
282       sos_restore_IRQs(flags);                    258       sos_restore_IRQs(flags);
283     }                                             259     }
284                                                   260 
285   return SOS_OK;                                  261   return SOS_OK;
286 }                                                 262 }
287                                                   263 
288                                                   264 
289 struct sos_mm_context *get_current_mm_context( !! 265 struct sos_mm_context *get_current_mm_context()
290 {                                                 266 {
291   SOS_ASSERT_FATAL(current_mm_context->ref_cnt    267   SOS_ASSERT_FATAL(current_mm_context->ref_cnt > 0);
292   return current_mm_context;                      268   return current_mm_context;
293 }                                                 269 }
294                                                   270 
295                                                   271 
296 /* *******************************************    272 /* ******************************************************
297  * Reserved functions                             273  * Reserved functions
298  */                                               274  */
299                                                   275 
300                                                   276 
301 sos_ret_t sos_mm_context_synch_kernel_PDE(unsi    277 sos_ret_t sos_mm_context_synch_kernel_PDE(unsigned int index_in_pd,
302                                           sos_    278                                           sos_ui32_t pde)
303 {                                                 279 {
304   sos_ui32_t flags;                               280   sos_ui32_t flags;
305   struct sos_mm_context * dest_mm_context;        281   struct sos_mm_context * dest_mm_context;
306   int nb_mm_contexts;                             282   int nb_mm_contexts;
307                                                   283 
308   sos_disable_IRQs(flags);                        284   sos_disable_IRQs(flags);
309   list_foreach_forward(list_mm_context, dest_m    285   list_foreach_forward(list_mm_context, dest_mm_context, nb_mm_contexts)
310     {                                             286     {
311       sos_ui32_t * dest_pd;                       287       sos_ui32_t * dest_pd;
312                                                   288 
313       SOS_ASSERT_FATAL(dest_mm_context->ref_cn    289       SOS_ASSERT_FATAL(dest_mm_context->ref_cnt > 0);
314                                                   290 
315       dest_pd = (sos_ui32_t*) dest_mm_context-    291       dest_pd = (sos_ui32_t*) dest_mm_context->vaddr_PD;
316       dest_pd[index_in_pd] = pde;                 292       dest_pd[index_in_pd] = pde;
317     }                                             293     }
318   sos_restore_IRQs(flags);                        294   sos_restore_IRQs(flags);
319                                                   295 
320   return SOS_OK;                                  296   return SOS_OK;
321 }                                                 297 }
                                                      

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