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 8) and /hwcore/mm_context.c (Article 7.5)


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 *                           179 struct sos_mm_context *
182 sos_mm_context_duplicate(const struct sos_mm_c    180 sos_mm_context_duplicate(const struct sos_mm_context *model)
183 {                                                 181 {
184   struct sos_mm_context *mmctxt;                  182   struct sos_mm_context *mmctxt;
185                                                   183 
186   /* Create an mm_context, the kernel space wi    184   /* Create an mm_context, the kernel space will be copied in it */
187   mmctxt = sos_mm_context_create();               185   mmctxt = sos_mm_context_create();
188   if (NULL == mmctxt)                             186   if (NULL == mmctxt)
189     return NULL;                                  187     return NULL;
190                                                   188 
191   /* Copy the user-space configuration of the     189   /* Copy the user-space configuration of the MMU */
192   if (SOS_OK != sos_paging_copy_user_space(mmc    190   if (SOS_OK != sos_paging_copy_user_space(mmctxt->vaddr_PD,
193                                            mod    191                                            model->vaddr_PD))
194     {                                             192     {
195       sos_mm_context_unref(mmctxt);               193       sos_mm_context_unref(mmctxt);
196       return NULL;                                194       return NULL;
197     }                                             195     }
198                                                   196 
199   return mmctxt;                                  197   return mmctxt;
200 }                                                 198 }
201                                                   199 
202                                                   200 
203 sos_ret_t sos_mm_context_unref(struct sos_mm_c    201 sos_ret_t sos_mm_context_unref(struct sos_mm_context *mmctxt)
204 {                                                 202 {
205   sos_ui32_t flags;                               203   sos_ui32_t flags;
206                                                   204 
207   sos_disable_IRQs(flags);                        205   sos_disable_IRQs(flags);
208                                                   206 
209   /* A valid mmctxt is one which is not yet un    207   /* A valid mmctxt is one which is not yet unreferenced */
210   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);          208   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);
211                                                   209 
212   /* Unreference it */                            210   /* Unreference it */
213   mmctxt->ref_cnt --;                             211   mmctxt->ref_cnt --;
214                                                   212 
215   /* If somebody is still using it, don't rele    213   /* If somebody is still using it, don't release it now */
216   if (mmctxt->ref_cnt > 0)                        214   if (mmctxt->ref_cnt > 0)
217     {                                             215     {
218       sos_restore_IRQs(flags);                    216       sos_restore_IRQs(flags);
219       return SOS_OK;                              217       return SOS_OK;
220     }                                             218     }
221                                                   219 
222   /* If nobody uses it, then it cannot be the     220   /* If nobody uses it, then it cannot be the current mm_context ! */
223   SOS_ASSERT_FATAL(mmctxt != current_mm_contex    221   SOS_ASSERT_FATAL(mmctxt != current_mm_context);
224                                                   222 
225   /* Remove it from the list of mm_contexts */    223   /* Remove it from the list of mm_contexts */
226   list_delete(list_mm_context, mmctxt);           224   list_delete(list_mm_context, mmctxt);
227                                                   225 
228   sos_restore_IRQs(flags);                        226   sos_restore_IRQs(flags);
229                                                   227 
230   /* Remove all user mappings (if any) */         228   /* Remove all user mappings (if any) */
231   sos_paging_dispose(mmctxt->vaddr_PD);           229   sos_paging_dispose(mmctxt->vaddr_PD);
232                                                   230 
233   /* Unmap the PD from the kernel */              231   /* Unmap the PD from the kernel */
234   sos_kmem_vmm_free(mmctxt->vaddr_PD);            232   sos_kmem_vmm_free(mmctxt->vaddr_PD);
235                                                   233 
236   memset(mmctxt, 0x0, sizeof(*mmctxt));           234   memset(mmctxt, 0x0, sizeof(*mmctxt));
237                                                   235 
238   return SOS_OK;                                  236   return SOS_OK;
239 }                                                 237 }
240                                                   238 
241                                                   239 
242 sos_ret_t sos_mm_context_ref(struct sos_mm_con    240 sos_ret_t sos_mm_context_ref(struct sos_mm_context *mmctxt)
243 {                                                 241 {
244   sos_ui32_t flags;                               242   sos_ui32_t flags;
245                                                   243 
246   sos_disable_IRQs(flags);                        244   sos_disable_IRQs(flags);
247                                                   245 
248   /* A valid mmctxt is one which is not yet un    246   /* A valid mmctxt is one which is not yet unreferenced */
249   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);          247   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);
250                                                   248 
251   /* Reference it once again */                   249   /* Reference it once again */
252   mmctxt->ref_cnt ++;                             250   mmctxt->ref_cnt ++;
253                                                   251 
254   sos_restore_IRQs(flags);                        252   sos_restore_IRQs(flags);
255                                                   253 
256   return SOS_OK;                                  254   return SOS_OK;
257 }                                                 255 }
258                                                   256 
259                                                   257 
260 sos_ret_t sos_mm_context_switch_to(struct sos_    258 sos_ret_t sos_mm_context_switch_to(struct sos_mm_context *mmctxt)
261 {                                                 259 {
262   SOS_ASSERT_FATAL(NULL != mmctxt);               260   SOS_ASSERT_FATAL(NULL != mmctxt);
263   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);          261   SOS_ASSERT_FATAL(mmctxt->ref_cnt > 0);
264   SOS_ASSERT_FATAL(current_mm_context->ref_cnt    262   SOS_ASSERT_FATAL(current_mm_context->ref_cnt > 0);
265   if (mmctxt != current_mm_context)               263   if (mmctxt != current_mm_context)
266     {                                             264     {
267       sos_ui32_t flags;                           265       sos_ui32_t flags;
268       struct sos_mm_context * prev_mm_context     266       struct sos_mm_context * prev_mm_context = current_mm_context;
269                                                   267 
270       /* This is the most dangerous part of th    268       /* This is the most dangerous part of the whole thing. If we set
271          the wrong MMU configuration in mmctxt    269          the wrong MMU configuration in mmctxt, this will hang or
272          reboot the machine... */                 270          reboot the machine... */
273       sos_paging_set_current_PD_paddr(mmctxt->    271       sos_paging_set_current_PD_paddr(mmctxt->paddr_PD);
274                                                   272 
275       /* Exchange the mm_contexts */              273       /* Exchange the mm_contexts */
276       current_mm_context = mmctxt;                274       current_mm_context = mmctxt;
277                                                   275 
278       /* Update the reference counts */           276       /* Update the reference counts */
279       sos_disable_IRQs(flags);                    277       sos_disable_IRQs(flags);
280       mmctxt->ref_cnt ++;                         278       mmctxt->ref_cnt ++;
281       sos_mm_context_unref(prev_mm_context);      279       sos_mm_context_unref(prev_mm_context);
282       sos_restore_IRQs(flags);                    280       sos_restore_IRQs(flags);
283     }                                             281     }
284                                                   282 
285   return SOS_OK;                                  283   return SOS_OK;
286 }                                                 284 }
287                                                   285 
288                                                   286 
289 struct sos_mm_context *get_current_mm_context(    287 struct sos_mm_context *get_current_mm_context()
290 {                                                 288 {
291   SOS_ASSERT_FATAL(current_mm_context->ref_cnt    289   SOS_ASSERT_FATAL(current_mm_context->ref_cnt > 0);
292   return current_mm_context;                      290   return current_mm_context;
293 }                                                 291 }
294                                                   292 
295                                                   293 
296 /* *******************************************    294 /* ******************************************************
297  * Reserved functions                             295  * Reserved functions
298  */                                               296  */
299                                                   297 
300                                                   298 
301 sos_ret_t sos_mm_context_synch_kernel_PDE(unsi    299 sos_ret_t sos_mm_context_synch_kernel_PDE(unsigned int index_in_pd,
302                                           sos_    300                                           sos_ui32_t pde)
303 {                                                 301 {
304   sos_ui32_t flags;                               302   sos_ui32_t flags;
305   struct sos_mm_context * dest_mm_context;        303   struct sos_mm_context * dest_mm_context;
306   int nb_mm_contexts;                             304   int nb_mm_contexts;
307                                                   305 
308   sos_disable_IRQs(flags);                        306   sos_disable_IRQs(flags);
309   list_foreach_forward(list_mm_context, dest_m    307   list_foreach_forward(list_mm_context, dest_mm_context, nb_mm_contexts)
310     {                                             308     {
311       sos_ui32_t * dest_pd;                       309       sos_ui32_t * dest_pd;
312                                                   310 
313       SOS_ASSERT_FATAL(dest_mm_context->ref_cn    311       SOS_ASSERT_FATAL(dest_mm_context->ref_cnt > 0);
314                                                   312 
315       dest_pd = (sos_ui32_t*) dest_mm_context-    313       dest_pd = (sos_ui32_t*) dest_mm_context->vaddr_PD;
316       dest_pd[index_in_pd] = pde;                 314       dest_pd[index_in_pd] = pde;
317     }                                             315     }
318   sos_restore_IRQs(flags);                        316   sos_restore_IRQs(flags);
319                                                   317 
320   return SOS_OK;                                  318   return SOS_OK;
321 }                                                 319 }
                                                      

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