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


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

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