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 /sos/physmem.c (Article 6.5) and /sos/physmem.c (Article 5)


001 /* Copyright (C) 2004  David Decotigny            001 /* Copyright (C) 2004  David Decotigny
002    Copyright (C) 2000  The KOS Team            << 
003                                                   002 
004    This program is free software; you can redi    003    This program is free software; you can redistribute it and/or
005    modify it under the terms of the GNU Genera    004    modify it under the terms of the GNU General Public License
006    as published by the Free Software Foundatio    005    as published by the Free Software Foundation; either version 2
007    of the License, or (at your option) any lat    006    of the License, or (at your option) any later version.
008                                                   007    
009    This program is distributed in the hope tha    008    This program is distributed in the hope that it will be useful,
010    but WITHOUT ANY WARRANTY; without even the     009    but WITHOUT ANY WARRANTY; without even the implied warranty of
011    MERCHANTABILITY or FITNESS FOR A PARTICULAR    010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012    GNU General Public License for more details    011    GNU General Public License for more details.
013                                                   012    
014    You should have received a copy of the GNU     013    You should have received a copy of the GNU General Public License
015    along with this program; if not, write to t    014    along with this program; if not, write to the Free Software
016    Foundation, Inc., 59 Temple Place - Suite 3    015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
017    USA.                                           016    USA. 
018 */                                                017 */
019 #include <sos/list.h>                             018 #include <sos/list.h>
020 #include <sos/macros.h>                           019 #include <sos/macros.h>
021 #include <sos/assert.h>                           020 #include <sos/assert.h>
022 #include <sos/klibc.h>                            021 #include <sos/klibc.h>
023                                                   022 
024 #include "physmem.h"                              023 #include "physmem.h"
025                                                   024 
026 /** A descriptor for a physical page in SOS */    025 /** A descriptor for a physical page in SOS */
027 struct physical_page_descr                        026 struct physical_page_descr
028 {                                                 027 {
029   /** The physical base address for the page *    028   /** The physical base address for the page */
030   sos_paddr_t paddr;                              029   sos_paddr_t paddr;
031                                                   030 
032   /** The reference count for this physical pa    031   /** The reference count for this physical page. > 0 means that the
033      page is in the used list. */                 032      page is in the used list. */
034   sos_count_t ref_cnt;                            033   sos_count_t ref_cnt;
035                                                   034 
036   /** Some data associated with the page when     035   /** Some data associated with the page when it is mapped in kernel space */
037   struct sos_kmem_range *kernel_range;            036   struct sos_kmem_range *kernel_range;
038                                                   037 
039   /** The other pages on the list (used, free)    038   /** The other pages on the list (used, free) */
040   struct physical_page_descr *prev, *next;        039   struct physical_page_descr *prev, *next;
041 };                                                040 };
042                                                   041 
043 /** These are some markers present in the exec    042 /** These are some markers present in the executable file (see sos.lds) */
044 extern char __b_kernel, __e_kernel;               043 extern char __b_kernel, __e_kernel;
045                                                   044 
046 /** The array of ppage descriptors will be loc    045 /** The array of ppage descriptors will be located at this address */
047 #define PAGE_DESCR_ARRAY_ADDR \                   046 #define PAGE_DESCR_ARRAY_ADDR \
048   SOS_PAGE_ALIGN_SUP((sos_paddr_t) (& __e_kern    047   SOS_PAGE_ALIGN_SUP((sos_paddr_t) (& __e_kernel))
049 static struct physical_page_descr * physical_p    048 static struct physical_page_descr * physical_page_descr_array;
050                                                   049 
051 /** The list of physical pages currently avail    050 /** The list of physical pages currently available */
052 static struct physical_page_descr *free_ppage;    051 static struct physical_page_descr *free_ppage;
053                                                   052 
054 /** The list of physical pages currently in us    053 /** The list of physical pages currently in use */
055 static struct physical_page_descr *used_ppage;    054 static struct physical_page_descr *used_ppage;
056                                                   055 
057 /** We will store here the interval of valid p    056 /** We will store here the interval of valid physical addresses */
058 static sos_paddr_t physmem_base, physmem_top;     057 static sos_paddr_t physmem_base, physmem_top;
059                                                   058 
060 /** We store the number of pages used/free */     059 /** We store the number of pages used/free */
061 static sos_count_t physmem_total_pages, physme    060 static sos_count_t physmem_total_pages, physmem_used_pages;
062                                                   061 
063 sos_ret_t sos_physmem_subsystem_setup(sos_size !! 062 sos_ret_t sos_physmem_setup(sos_size_t ram_size,
064                                       /* out * !! 063                             /* out */sos_paddr_t *kernel_core_base,
065                                       /* out * !! 064                             /* out */sos_paddr_t *kernel_core_top)
066 {                                                 065 {
067   /* The iterator over the page descriptors */    066   /* The iterator over the page descriptors */
068   struct physical_page_descr *ppage_descr;        067   struct physical_page_descr *ppage_descr;
069                                                   068 
070   /* The iterator over the physical addresses     069   /* The iterator over the physical addresses */
071   sos_paddr_t ppage_addr;                         070   sos_paddr_t ppage_addr;
072                                                   071 
073   /* Make sure ram size is aligned on a page b    072   /* Make sure ram size is aligned on a page boundary */
074   ram_size = SOS_PAGE_ALIGN_INF(ram_size);/* Y    073   ram_size = SOS_PAGE_ALIGN_INF(ram_size);/* Yes, we may lose at most a page */
075                                                   074 
076   /* Reset the used/free page lists before bui    075   /* Reset the used/free page lists before building them */
077   free_ppage = used_ppage = NULL;                 076   free_ppage = used_ppage = NULL;
078   physmem_total_pages = physmem_used_pages = 0    077   physmem_total_pages = physmem_used_pages = 0;
079                                                   078 
080   /* Make sure that there is enough memory to     079   /* Make sure that there is enough memory to store the array of page
081      descriptors */                               080      descriptors */
082   *kernel_core_base = SOS_PAGE_ALIGN_INF((sos_    081   *kernel_core_base = SOS_PAGE_ALIGN_INF((sos_paddr_t)(& __b_kernel));
083   *kernel_core_top                                082   *kernel_core_top
084     = PAGE_DESCR_ARRAY_ADDR                       083     = PAGE_DESCR_ARRAY_ADDR
085       + SOS_PAGE_ALIGN_SUP( (ram_size >> SOS_P    084       + SOS_PAGE_ALIGN_SUP( (ram_size >> SOS_PAGE_SHIFT)
086                             * sizeof(struct ph    085                             * sizeof(struct physical_page_descr));
087   if (*kernel_core_top > ram_size)                086   if (*kernel_core_top > ram_size)
088     return -SOS_ENOMEM;                           087     return -SOS_ENOMEM;
089                                                   088 
090   /* Page 0-4kB is not available in order to r    089   /* Page 0-4kB is not available in order to return address 0 as a
091      means to signal "no page available" */       090      means to signal "no page available" */
092   physmem_base = SOS_PAGE_SIZE;                   091   physmem_base = SOS_PAGE_SIZE;
093   physmem_top  = ram_size;                        092   physmem_top  = ram_size;
094                                                   093 
095   /* Setup the page descriptor arrray */          094   /* Setup the page descriptor arrray */
096   physical_page_descr_array                       095   physical_page_descr_array
097     = (struct physical_page_descr*)PAGE_DESCR_    096     = (struct physical_page_descr*)PAGE_DESCR_ARRAY_ADDR;
098                                                   097 
099   /* Scan the list of physical pages */           098   /* Scan the list of physical pages */
100   for (ppage_addr = 0,                            099   for (ppage_addr = 0,
101          ppage_descr = physical_page_descr_arr    100          ppage_descr = physical_page_descr_array ;
102        ppage_addr < physmem_top ;                 101        ppage_addr < physmem_top ;
103        ppage_addr += SOS_PAGE_SIZE,               102        ppage_addr += SOS_PAGE_SIZE,
104          ppage_descr ++)                          103          ppage_descr ++)
105     {                                             104     {
106       enum { PPAGE_MARK_RESERVED, PPAGE_MARK_F    105       enum { PPAGE_MARK_RESERVED, PPAGE_MARK_FREE,
107              PPAGE_MARK_KERNEL, PPAGE_MARK_HWM    106              PPAGE_MARK_KERNEL, PPAGE_MARK_HWMAP } todo;
108                                                   107 
109       memset(ppage_descr, 0x0, sizeof(struct p    108       memset(ppage_descr, 0x0, sizeof(struct physical_page_descr));
110                                                   109 
111       /* Init the page descriptor for this pag    110       /* Init the page descriptor for this page */
112       ppage_descr->paddr = ppage_addr;            111       ppage_descr->paddr = ppage_addr;
113                                                   112 
114       /* Reserved : 0 ... base */                 113       /* Reserved : 0 ... base */
115       if (ppage_addr < physmem_base)              114       if (ppage_addr < physmem_base)
116         todo = PPAGE_MARK_RESERVED;               115         todo = PPAGE_MARK_RESERVED;
117                                                   116 
118       /* Free : base ... BIOS */                  117       /* Free : base ... BIOS */
119       else if ((ppage_addr >= physmem_base)       118       else if ((ppage_addr >= physmem_base)
120                && (ppage_addr < BIOS_N_VIDEO_S    119                && (ppage_addr < BIOS_N_VIDEO_START))
121         todo = PPAGE_MARK_FREE;                   120         todo = PPAGE_MARK_FREE;
122                                                   121 
123       /* Used : BIOS */                           122       /* Used : BIOS */
124       else if ((ppage_addr >= BIOS_N_VIDEO_STA    123       else if ((ppage_addr >= BIOS_N_VIDEO_START)
125                && (ppage_addr < BIOS_N_VIDEO_E    124                && (ppage_addr < BIOS_N_VIDEO_END))
126         todo = PPAGE_MARK_HWMAP;                  125         todo = PPAGE_MARK_HWMAP;
127                                                   126 
128       /* Free : BIOS ... kernel */                127       /* Free : BIOS ... kernel */
129       else if ((ppage_addr >= BIOS_N_VIDEO_END    128       else if ((ppage_addr >= BIOS_N_VIDEO_END)
130                && (ppage_addr < (sos_paddr_t)     129                && (ppage_addr < (sos_paddr_t) (& __b_kernel)))
131         todo = PPAGE_MARK_FREE;                   130         todo = PPAGE_MARK_FREE;
132                                                   131 
133       /* Used : Kernel code/data/bss + physcal    132       /* Used : Kernel code/data/bss + physcal page descr array */
134       else if ((ppage_addr >= *kernel_core_bas    133       else if ((ppage_addr >= *kernel_core_base)
135                 && (ppage_addr < *kernel_core_    134                 && (ppage_addr < *kernel_core_top))
136         todo = PPAGE_MARK_KERNEL;                 135         todo = PPAGE_MARK_KERNEL;
137                                                   136 
138       /* Free : first page of descr ... end of    137       /* Free : first page of descr ... end of RAM */
139       else                                        138       else
140         todo = PPAGE_MARK_FREE;                   139         todo = PPAGE_MARK_FREE;
141                                                   140 
142       /* Actually does the insertion in the us    141       /* Actually does the insertion in the used/free page lists */
143       physmem_total_pages ++;                     142       physmem_total_pages ++;
144       switch (todo)                               143       switch (todo)
145         {                                         144         {
146         case PPAGE_MARK_FREE:                     145         case PPAGE_MARK_FREE:
147           ppage_descr->ref_cnt = 0;               146           ppage_descr->ref_cnt = 0;
148           list_add_head(free_ppage, ppage_desc    147           list_add_head(free_ppage, ppage_descr);
149           break;                                  148           break;
150                                                   149 
151         case PPAGE_MARK_KERNEL:                   150         case PPAGE_MARK_KERNEL:
152         case PPAGE_MARK_HWMAP:                    151         case PPAGE_MARK_HWMAP:
153           ppage_descr->ref_cnt = 1;               152           ppage_descr->ref_cnt = 1;
154           list_add_head(used_ppage, ppage_desc    153           list_add_head(used_ppage, ppage_descr);
155           physmem_used_pages ++;                  154           physmem_used_pages ++;
156           break;                                  155           break;
157                                                   156 
158         default:                                  157         default:
159           /* Reserved page: nop */                158           /* Reserved page: nop */
160           break;                                  159           break;
161         }                                         160         }
162     }                                             161     }
163                                                   162 
164   return SOS_OK;                                  163   return SOS_OK;
165 }                                                 164 }
166                                                   165 
167                                                   166 
168 sos_paddr_t sos_physmem_ref_physpage_new(sos_b    167 sos_paddr_t sos_physmem_ref_physpage_new(sos_bool_t can_block)
169 {                                                 168 {
170   struct physical_page_descr *ppage_descr;        169   struct physical_page_descr *ppage_descr;
171                                                   170 
172   if (! free_ppage)                               171   if (! free_ppage)
173     return (sos_paddr_t)NULL;                     172     return (sos_paddr_t)NULL;
174                                                   173 
175   /* Retrieve a page in the free list */          174   /* Retrieve a page in the free list */
176   ppage_descr = list_pop_head(free_ppage);        175   ppage_descr = list_pop_head(free_ppage);
177                                                   176 
178   /* The page is assumed not to be already use    177   /* The page is assumed not to be already used */
179   SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0);    178   SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0);
180                                                   179 
181   /* Mark the page as used (this of course set    180   /* Mark the page as used (this of course sets the ref count to 1) */
182   ppage_descr->ref_cnt ++;                        181   ppage_descr->ref_cnt ++;
183                                                   182 
184   /* No associated kernel range by default */     183   /* No associated kernel range by default */
185   ppage_descr->kernel_range = NULL;               184   ppage_descr->kernel_range = NULL;
186                                                   185   
187   /* Put the page in the used list */             186   /* Put the page in the used list */
188   list_add_tail(used_ppage, ppage_descr);         187   list_add_tail(used_ppage, ppage_descr);
189   physmem_used_pages ++;                          188   physmem_used_pages ++;
190                                                   189 
191   return ppage_descr->paddr;                      190   return ppage_descr->paddr;
192 }                                                 191 }
193                                                   192 
194                                                   193 
195 /**                                               194 /**
196  * Helper function to get the physical page de    195  * Helper function to get the physical page descriptor for the given
197  * physical page address.                         196  * physical page address.
198  *                                                197  *
199  * @return NULL when out-of-bounds or non-page    198  * @return NULL when out-of-bounds or non-page-aligned
200  */                                               199  */
201 inline static struct physical_page_descr *        200 inline static struct physical_page_descr *
202 get_page_descr_at_paddr(sos_paddr_t ppage_padd    201 get_page_descr_at_paddr(sos_paddr_t ppage_paddr)
203 {                                                 202 {
204   /* Don't handle non-page-aligned addresses *    203   /* Don't handle non-page-aligned addresses */
205   if (ppage_paddr & SOS_PAGE_MASK)                204   if (ppage_paddr & SOS_PAGE_MASK)
206     return NULL;                                  205     return NULL;
207                                                   206   
208   /* Don't support out-of-bounds requests */      207   /* Don't support out-of-bounds requests */
209   if ((ppage_paddr < physmem_base) || (ppage_p    208   if ((ppage_paddr < physmem_base) || (ppage_paddr >= physmem_top))
210     return NULL;                                  209     return NULL;
211                                                   210 
212   return physical_page_descr_array + (ppage_pa    211   return physical_page_descr_array + (ppage_paddr >> SOS_PAGE_SHIFT);
213 }                                                 212 }
214                                                   213 
215                                                   214 
216 sos_ret_t sos_physmem_ref_physpage_at(sos_padd    215 sos_ret_t sos_physmem_ref_physpage_at(sos_paddr_t ppage_paddr)
217 {                                                 216 {
218   struct physical_page_descr *ppage_descr         217   struct physical_page_descr *ppage_descr
219     = get_page_descr_at_paddr(ppage_paddr);       218     = get_page_descr_at_paddr(ppage_paddr);
220                                                   219 
221   if (! ppage_descr)                              220   if (! ppage_descr)
222     return -SOS_EINVAL;                           221     return -SOS_EINVAL;
223                                                   222 
224   /* Increment the reference count for the pag    223   /* Increment the reference count for the page */
225   ppage_descr->ref_cnt ++;                        224   ppage_descr->ref_cnt ++;
226                                                   225 
227   /* If the page is newly referenced (ie we ar    226   /* If the page is newly referenced (ie we are the only owners of the
228      page => ref cnt == 1), transfer it in the    227      page => ref cnt == 1), transfer it in the used pages list */
229   if (ppage_descr->ref_cnt == 1)                  228   if (ppage_descr->ref_cnt == 1)
230     {                                             229     {
231       list_delete(free_ppage, ppage_descr);       230       list_delete(free_ppage, ppage_descr);
232                                                   231 
233       /* No associated kernel range by default    232       /* No associated kernel range by default */
234       ppage_descr->kernel_range = NULL;           233       ppage_descr->kernel_range = NULL;
235                                                   234   
236       list_add_tail(used_ppage, ppage_descr);     235       list_add_tail(used_ppage, ppage_descr);
237       physmem_used_pages ++;                      236       physmem_used_pages ++;
238                                                   237 
239       /* The page is newly referenced */          238       /* The page is newly referenced */
240       return FALSE;                               239       return FALSE;
241     }                                             240     }
242                                                   241 
243   /* The page was already referenced by someon    242   /* The page was already referenced by someone */
244   return TRUE;                                    243   return TRUE;
245 }                                                 244 }
246                                                   245 
247                                                   246 
248 sos_ret_t                                         247 sos_ret_t
249 sos_physmem_unref_physpage(sos_paddr_t ppage_p    248 sos_physmem_unref_physpage(sos_paddr_t ppage_paddr)
250 {                                                 249 {
251   /* By default the return value indicates tha    250   /* By default the return value indicates that the page is still
252      used */                                      251      used */
253   sos_ret_t retval = FALSE;                       252   sos_ret_t retval = FALSE;
254                                                   253 
255   struct physical_page_descr *ppage_descr         254   struct physical_page_descr *ppage_descr
256     = get_page_descr_at_paddr(ppage_paddr);       255     = get_page_descr_at_paddr(ppage_paddr);
257                                                   256 
258   if (! ppage_descr)                              257   if (! ppage_descr)
259     return -SOS_EINVAL;                           258     return -SOS_EINVAL;
260                                                   259 
261   /* Don't do anything if the page is not in t    260   /* Don't do anything if the page is not in the used list */
262   if (ppage_descr->ref_cnt <= 0)                  261   if (ppage_descr->ref_cnt <= 0)
263     return -SOS_EINVAL;                           262     return -SOS_EINVAL;
264                                                   263 
265   /* Unreference the page, and, when no mappin    264   /* Unreference the page, and, when no mapping is active anymore, put
266      the page in the free list */                 265      the page in the free list */
267   ppage_descr->ref_cnt--;                         266   ppage_descr->ref_cnt--;
268   if (ppage_descr->ref_cnt <= 0)                  267   if (ppage_descr->ref_cnt <= 0)
269     {                                             268     {
270       /* Reset associated kernel range */         269       /* Reset associated kernel range */
271       ppage_descr->kernel_range = NULL;           270       ppage_descr->kernel_range = NULL;
272                                                   271   
273       /* Transfer the page, considered USED, t    272       /* Transfer the page, considered USED, to the free list */
274       list_delete(used_ppage, ppage_descr);       273       list_delete(used_ppage, ppage_descr);
275       physmem_used_pages --;                      274       physmem_used_pages --;
276       list_add_head(free_ppage, ppage_descr);     275       list_add_head(free_ppage, ppage_descr);
277                                                   276 
278       /* Indicate that the page is now unrefer    277       /* Indicate that the page is now unreferenced */
279       retval = TRUE;                              278       retval = TRUE;
280     }                                             279     }
281                                                   280 
282   return retval;                                  281   return retval;
283 }                                                 282 }
284                                                   283 
285                                                   284 
286 struct sos_kmem_range* sos_physmem_get_kmem_ra    285 struct sos_kmem_range* sos_physmem_get_kmem_range(sos_paddr_t ppage_paddr)
287 {                                                 286 {
288   struct physical_page_descr *ppage_descr         287   struct physical_page_descr *ppage_descr
289     = get_page_descr_at_paddr(ppage_paddr);       288     = get_page_descr_at_paddr(ppage_paddr);
290                                                   289 
291   if (! ppage_descr)                              290   if (! ppage_descr)
292     return NULL;                                  291     return NULL;
293                                                   292 
294   return ppage_descr->kernel_range;               293   return ppage_descr->kernel_range;
295 }                                                 294 }
296                                                   295 
297                                                   296 
298 sos_ret_t sos_physmem_set_kmem_range(sos_paddr    297 sos_ret_t sos_physmem_set_kmem_range(sos_paddr_t ppage_paddr,
299                                      struct so    298                                      struct sos_kmem_range *range)
300 {                                                 299 {
301   struct physical_page_descr *ppage_descr         300   struct physical_page_descr *ppage_descr
302     = get_page_descr_at_paddr(ppage_paddr);       301     = get_page_descr_at_paddr(ppage_paddr);
303                                                   302 
304   if (! ppage_descr)                              303   if (! ppage_descr)
305     return -SOS_EINVAL;                           304     return -SOS_EINVAL;
306                                                   305 
307   ppage_descr->kernel_range = range;              306   ppage_descr->kernel_range = range;
308   return SOS_OK;                                  307   return SOS_OK;
309 }                                                 308 }
310                                                   309 
311 sos_ret_t sos_physmem_get_state(/* out */sos_c    310 sos_ret_t sos_physmem_get_state(/* out */sos_count_t *total_ppages,
312                                 /* out */sos_c    311                                 /* out */sos_count_t *used_ppages)
313 {                                                 312 {
314   if (total_ppages)                               313   if (total_ppages)
315     *total_ppages = physmem_total_pages;          314     *total_ppages = physmem_total_pages;
316   if (used_ppages)                                315   if (used_ppages)
317     *used_ppages = physmem_used_pages;            316     *used_ppages = physmem_used_pages;
318   return SOS_OK;                                  317   return SOS_OK;
319 }                                                 318 }
                                                      

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