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


001 /* Copyright (C) 2004  David Decotigny            001 /* Copyright (C) 2004  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 #include <sos/list.h>                             018 #include <sos/list.h>
019 #include <sos/macros.h>                           019 #include <sos/macros.h>
020 #include <sos/assert.h>                           020 #include <sos/assert.h>
021 #include <sos/klibc.h>                            021 #include <sos/klibc.h>
022                                                   022 
023 #include "physmem.h"                              023 #include "physmem.h"
024                                                   024 
025 /** A descriptor for a physical page in SOS */    025 /** A descriptor for a physical page in SOS */
026 struct physical_page_descr                        026 struct physical_page_descr
027 {                                                 027 {
028   /** The physical base address for the page *    028   /** The physical base address for the page */
029   sos_paddr_t paddr;                              029   sos_paddr_t paddr;
030                                                   030 
031   /** The reference count for this physical pa    031   /** The reference count for this physical page. > 0 means that the
032      page is in the used list. */                 032      page is in the used list. */
033   sos_count_t ref_cnt;                            033   sos_count_t ref_cnt;
034                                                   034 
035   /** The other pages on the list (used, free)    035   /** The other pages on the list (used, free) */
036   struct physical_page_descr *prev, *next;        036   struct physical_page_descr *prev, *next;
037 };                                                037 };
038                                                   038 
039 /** These are some markers present in the exec    039 /** These are some markers present in the executable file (see sos.lds) */
040 extern char __b_kernel, __e_kernel;               040 extern char __b_kernel, __e_kernel;
041                                                   041 
042 /** The array of ppage descriptors will be loc    042 /** The array of ppage descriptors will be located at this address */
043 #define PAGE_DESCR_ARRAY_ADDR \                   043 #define PAGE_DESCR_ARRAY_ADDR \
044   SOS_PAGE_ALIGN_SUP((sos_paddr_t) (& __e_kern    044   SOS_PAGE_ALIGN_SUP((sos_paddr_t) (& __e_kernel))
045 static struct physical_page_descr * physical_p    045 static struct physical_page_descr * physical_page_descr_array;
046                                                   046 
047 /** The list of physical pages currently avail    047 /** The list of physical pages currently available */
048 static struct physical_page_descr *free_ppage;    048 static struct physical_page_descr *free_ppage;
049                                                   049 
050 /** The list of physical pages currently in us    050 /** The list of physical pages currently in use */
051 static struct physical_page_descr *used_ppage;    051 static struct physical_page_descr *used_ppage;
052                                                   052 
053 /** We will store here the interval of valid p    053 /** We will store here the interval of valid physical addresses */
054 static sos_paddr_t physmem_base, physmem_top;     054 static sos_paddr_t physmem_base, physmem_top;
055                                                   055 
056 /** We store the number of pages used/free */     056 /** We store the number of pages used/free */
057 static sos_count_t physmem_total_pages, physme    057 static sos_count_t physmem_total_pages, physmem_used_pages;
058                                                   058 
059 sos_ret_t sos_physmem_setup(sos_size_t ram_siz    059 sos_ret_t sos_physmem_setup(sos_size_t ram_size,
060                             /* out */sos_paddr    060                             /* out */sos_paddr_t *kernel_core_base,
061                             /* out */sos_paddr    061                             /* out */sos_paddr_t *kernel_core_top)
062 {                                                 062 {
063   /* The iterator over the page descriptors */    063   /* The iterator over the page descriptors */
064   struct physical_page_descr *ppage_descr;        064   struct physical_page_descr *ppage_descr;
065                                                   065 
066   /* The iterator over the physical addresses     066   /* The iterator over the physical addresses */
067   sos_paddr_t ppage_addr;                         067   sos_paddr_t ppage_addr;
068                                                   068 
069   /* Make sure ram size is aligned on a page b    069   /* Make sure ram size is aligned on a page boundary */
070   ram_size = SOS_PAGE_ALIGN_INF(ram_size);/* Y    070   ram_size = SOS_PAGE_ALIGN_INF(ram_size);/* Yes, we may lose at most a page */
071                                                   071 
072   /* Reset the used/free page lists before bui    072   /* Reset the used/free page lists before building them */
073   free_ppage = used_ppage = NULL;                 073   free_ppage = used_ppage = NULL;
074   physmem_total_pages = physmem_used_pages = 0    074   physmem_total_pages = physmem_used_pages = 0;
075                                                   075 
076   /* Make sure that there is enough memory to     076   /* Make sure that there is enough memory to store the array of page
077      descriptors */                               077      descriptors */
078   *kernel_core_base = SOS_PAGE_ALIGN_INF((sos_    078   *kernel_core_base = SOS_PAGE_ALIGN_INF((sos_paddr_t)(& __b_kernel));
079   *kernel_core_top                                079   *kernel_core_top
080     = PAGE_DESCR_ARRAY_ADDR                       080     = PAGE_DESCR_ARRAY_ADDR
081       + SOS_PAGE_ALIGN_SUP( (ram_size >> SOS_P    081       + SOS_PAGE_ALIGN_SUP( (ram_size >> SOS_PAGE_SHIFT)
082                             * sizeof(struct ph    082                             * sizeof(struct physical_page_descr));
083   if (*kernel_core_top > ram_size)                083   if (*kernel_core_top > ram_size)
084     return -SOS_ENOMEM;                           084     return -SOS_ENOMEM;
085                                                   085 
086   /* Page 0-4kB is not available in order to r    086   /* Page 0-4kB is not available in order to return address 0 as a
087      means to signal "no page available" */       087      means to signal "no page available" */
088   physmem_base = SOS_PAGE_SIZE;                   088   physmem_base = SOS_PAGE_SIZE;
089   physmem_top  = ram_size;                        089   physmem_top  = ram_size;
090                                                   090 
091   /* Setup the page descriptor arrray */          091   /* Setup the page descriptor arrray */
092   physical_page_descr_array                       092   physical_page_descr_array
093     = (struct physical_page_descr*)PAGE_DESCR_    093     = (struct physical_page_descr*)PAGE_DESCR_ARRAY_ADDR;
094                                                   094 
095   /* Scan the list of physical pages */           095   /* Scan the list of physical pages */
096   for (ppage_addr = 0,                            096   for (ppage_addr = 0,
097          ppage_descr = physical_page_descr_arr    097          ppage_descr = physical_page_descr_array ;
098        ppage_addr < physmem_top ;                 098        ppage_addr < physmem_top ;
099        ppage_addr += SOS_PAGE_SIZE,               099        ppage_addr += SOS_PAGE_SIZE,
100          ppage_descr ++)                          100          ppage_descr ++)
101     {                                             101     {
102       enum { PPAGE_MARK_RESERVED, PPAGE_MARK_F    102       enum { PPAGE_MARK_RESERVED, PPAGE_MARK_FREE,
103              PPAGE_MARK_KERNEL, PPAGE_MARK_HWM    103              PPAGE_MARK_KERNEL, PPAGE_MARK_HWMAP } todo;
104                                                   104 
105       memset(ppage_descr, 0x0, sizeof(struct p    105       memset(ppage_descr, 0x0, sizeof(struct physical_page_descr));
106                                                   106 
107       /* Init the page descriptor for this pag    107       /* Init the page descriptor for this page */
108       ppage_descr->paddr = ppage_addr;            108       ppage_descr->paddr = ppage_addr;
109                                                   109 
110       /* Reserved : 0 ... base */                 110       /* Reserved : 0 ... base */
111       if (ppage_addr < physmem_base)              111       if (ppage_addr < physmem_base)
112         todo = PPAGE_MARK_RESERVED;               112         todo = PPAGE_MARK_RESERVED;
113                                                   113 
114       /* Free : base ... BIOS */                  114       /* Free : base ... BIOS */
115       else if ((ppage_addr >= physmem_base)       115       else if ((ppage_addr >= physmem_base)
116                && (ppage_addr < BIOS_N_VIDEO_S    116                && (ppage_addr < BIOS_N_VIDEO_START))
117         todo = PPAGE_MARK_FREE;                   117         todo = PPAGE_MARK_FREE;
118                                                   118 
119       /* Used : BIOS */                           119       /* Used : BIOS */
120       else if ((ppage_addr >= BIOS_N_VIDEO_STA    120       else if ((ppage_addr >= BIOS_N_VIDEO_START)
121                && (ppage_addr < BIOS_N_VIDEO_E    121                && (ppage_addr < BIOS_N_VIDEO_END))
122         todo = PPAGE_MARK_HWMAP;                  122         todo = PPAGE_MARK_HWMAP;
123                                                   123 
124       /* Free : BIOS ... kernel */                124       /* Free : BIOS ... kernel */
125       else if ((ppage_addr >= BIOS_N_VIDEO_END    125       else if ((ppage_addr >= BIOS_N_VIDEO_END)
126                && (ppage_addr < (sos_paddr_t)     126                && (ppage_addr < (sos_paddr_t) (& __b_kernel)))
127         todo = PPAGE_MARK_FREE;                   127         todo = PPAGE_MARK_FREE;
128                                                   128 
129       /* Used : Kernel code/data/bss + physcal    129       /* Used : Kernel code/data/bss + physcal page descr array */
130       else if ((ppage_addr >= *kernel_core_bas    130       else if ((ppage_addr >= *kernel_core_base)
131                 && (ppage_addr < *kernel_core_    131                 && (ppage_addr < *kernel_core_top))
132         todo = PPAGE_MARK_KERNEL;                 132         todo = PPAGE_MARK_KERNEL;
133                                                   133 
134       /* Free : first page of descr ... end of    134       /* Free : first page of descr ... end of RAM */
135       else                                        135       else
136         todo = PPAGE_MARK_FREE;                   136         todo = PPAGE_MARK_FREE;
137                                                   137 
138       /* Actually does the insertion in the us    138       /* Actually does the insertion in the used/free page lists */
139       physmem_total_pages ++;                     139       physmem_total_pages ++;
140       switch (todo)                               140       switch (todo)
141         {                                         141         {
142         case PPAGE_MARK_FREE:                     142         case PPAGE_MARK_FREE:
143           ppage_descr->ref_cnt = 0;               143           ppage_descr->ref_cnt = 0;
144           list_add_head(free_ppage, ppage_desc    144           list_add_head(free_ppage, ppage_descr);
145           break;                                  145           break;
146                                                   146 
147         case PPAGE_MARK_KERNEL:                   147         case PPAGE_MARK_KERNEL:
148         case PPAGE_MARK_HWMAP:                    148         case PPAGE_MARK_HWMAP:
149           ppage_descr->ref_cnt = 1;               149           ppage_descr->ref_cnt = 1;
150           list_add_head(used_ppage, ppage_desc    150           list_add_head(used_ppage, ppage_descr);
151           physmem_used_pages ++;                  151           physmem_used_pages ++;
152           break;                                  152           break;
153                                                   153 
154         default:                                  154         default:
155           /* Reserved page: nop */                155           /* Reserved page: nop */
156           break;                                  156           break;
157         }                                         157         }
158     }                                             158     }
159                                                   159 
160   return SOS_OK;                                  160   return SOS_OK;
161 }                                                 161 }
162                                                   162 
163                                                   163 
164 sos_paddr_t sos_physmem_ref_physpage_new(sos_b    164 sos_paddr_t sos_physmem_ref_physpage_new(sos_bool_t can_block)
165 {                                                 165 {
166   struct physical_page_descr *ppage_descr;        166   struct physical_page_descr *ppage_descr;
167                                                   167 
168   if (! free_ppage)                               168   if (! free_ppage)
169     return (sos_paddr_t)NULL;                     169     return (sos_paddr_t)NULL;
170                                                   170 
171   /* Retrieve a page in the free list */          171   /* Retrieve a page in the free list */
172   ppage_descr = list_pop_head(free_ppage);        172   ppage_descr = list_pop_head(free_ppage);
173                                                   173 
174   /* The page is assumed not to be already use    174   /* The page is assumed not to be already used */
175   SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0);    175   SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0);
176                                                   176 
177   /* Mark the page as used (this of course set    177   /* Mark the page as used (this of course sets the ref count to 1) */
178   ppage_descr->ref_cnt ++;                        178   ppage_descr->ref_cnt ++;
179                                                   179 
180   /* Put the page in the used list */             180   /* Put the page in the used list */
181   list_add_tail(used_ppage, ppage_descr);         181   list_add_tail(used_ppage, ppage_descr);
182   physmem_used_pages ++;                          182   physmem_used_pages ++;
183                                                   183 
184   return ppage_descr->paddr;                      184   return ppage_descr->paddr;
185 }                                                 185 }
186                                                   186 
187                                                   187 
188 /**                                               188 /**
189  * Helper function to get the physical page de    189  * Helper function to get the physical page descriptor for the given
190  * physical page address.                         190  * physical page address.
191  *                                                191  *
192  * @return NULL when out-of-bounds or non-page    192  * @return NULL when out-of-bounds or non-page-aligned
193  */                                               193  */
194 inline static struct physical_page_descr *        194 inline static struct physical_page_descr *
195 get_page_descr_at_paddr(sos_paddr_t ppage_padd    195 get_page_descr_at_paddr(sos_paddr_t ppage_paddr)
196 {                                                 196 {
197   /* Don't handle non-page-aligned addresses *    197   /* Don't handle non-page-aligned addresses */
198   if (ppage_paddr & SOS_PAGE_MASK)                198   if (ppage_paddr & SOS_PAGE_MASK)
199     return NULL;                                  199     return NULL;
200                                                   200   
201   /* Don't support out-of-bounds requests */      201   /* Don't support out-of-bounds requests */
202   if ((ppage_paddr < physmem_base) || (ppage_p    202   if ((ppage_paddr < physmem_base) || (ppage_paddr >= physmem_top))
203     return NULL;                                  203     return NULL;
204                                                   204 
205   return physical_page_descr_array + (ppage_pa    205   return physical_page_descr_array + (ppage_paddr >> SOS_PAGE_SHIFT);
206 }                                                 206 }
207                                                   207 
208                                                   208 
209 sos_ret_t sos_physmem_ref_physpage_at(sos_padd    209 sos_ret_t sos_physmem_ref_physpage_at(sos_paddr_t ppage_paddr)
210 {                                                 210 {
211   struct physical_page_descr *ppage_descr         211   struct physical_page_descr *ppage_descr
212     = get_page_descr_at_paddr(ppage_paddr);       212     = get_page_descr_at_paddr(ppage_paddr);
213                                                   213 
214   if (! ppage_descr)                              214   if (! ppage_descr)
215     return -SOS_EINVAL;                           215     return -SOS_EINVAL;
216                                                   216 
217   /* Increment the reference count for the pag    217   /* Increment the reference count for the page */
218   ppage_descr->ref_cnt ++;                        218   ppage_descr->ref_cnt ++;
219                                                   219 
220   /* If the page is newly referenced (ie we ar    220   /* If the page is newly referenced (ie we are the only owners of the
221      page => ref cnt == 1), transfer it in the    221      page => ref cnt == 1), transfer it in the used pages list */
222   if (ppage_descr->ref_cnt == 1)                  222   if (ppage_descr->ref_cnt == 1)
223     {                                             223     {
224       list_delete(free_ppage, ppage_descr);       224       list_delete(free_ppage, ppage_descr);
225       list_add_tail(used_ppage, ppage_descr);     225       list_add_tail(used_ppage, ppage_descr);
226       physmem_used_pages ++;                      226       physmem_used_pages ++;
227                                                   227 
228       /* The page is newly referenced */          228       /* The page is newly referenced */
229       return FALSE;                               229       return FALSE;
230     }                                             230     }
231                                                   231 
232   /* The page was already referenced by someon    232   /* The page was already referenced by someone */
233   return TRUE;                                    233   return TRUE;
234 }                                                 234 }
235                                                   235 
236                                                   236 
237 sos_ret_t                                         237 sos_ret_t
238 sos_physmem_unref_physpage(sos_paddr_t ppage_p    238 sos_physmem_unref_physpage(sos_paddr_t ppage_paddr)
239 {                                                 239 {
240   /* By default the return value indicates tha    240   /* By default the return value indicates that the page is still
241      used */                                      241      used */
242   sos_ret_t retval = FALSE;                       242   sos_ret_t retval = FALSE;
243                                                   243 
244   struct physical_page_descr *ppage_descr         244   struct physical_page_descr *ppage_descr
245     = get_page_descr_at_paddr(ppage_paddr);       245     = get_page_descr_at_paddr(ppage_paddr);
246                                                   246 
247   if (! ppage_descr)                              247   if (! ppage_descr)
248     return -SOS_EINVAL;                           248     return -SOS_EINVAL;
249                                                   249 
250   /* Don't do anything if the page is not in t    250   /* Don't do anything if the page is not in the used list */
251   if (ppage_descr->ref_cnt <= 0)                  251   if (ppage_descr->ref_cnt <= 0)
252     return -SOS_EINVAL;                           252     return -SOS_EINVAL;
253                                                   253 
254   /* Unreference the page, and, when no mappin    254   /* Unreference the page, and, when no mapping is active anymore, put
255      the page in the free list */                 255      the page in the free list */
256   ppage_descr->ref_cnt--;                         256   ppage_descr->ref_cnt--;
257   if (ppage_descr->ref_cnt <= 0)                  257   if (ppage_descr->ref_cnt <= 0)
258     {                                             258     {
259       /* Transfer the page, considered USED, t    259       /* Transfer the page, considered USED, to the free list */
260       list_delete(used_ppage, ppage_descr);       260       list_delete(used_ppage, ppage_descr);
261       physmem_used_pages --;                      261       physmem_used_pages --;
262       list_add_head(free_ppage, ppage_descr);     262       list_add_head(free_ppage, ppage_descr);
263                                                   263 
264       /* Indicate that the page is now unrefer    264       /* Indicate that the page is now unreferenced */
265       retval = TRUE;                              265       retval = TRUE;
266     }                                             266     }
267                                                   267 
268   return retval;                                  268   return retval;
269 }                                                 269 }
                                                      

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