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


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

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