Diff markup
001 001
002 002
003 003
004 004
005 005
006 006
007 007
008 008
009 009
010 010
011 011
012 012
013 013
014 014
015 015
016 016
017 017
018 018
019 #include <sos/list.h> 019 #include <sos/list.h>
020 #include <sos/macros.h> 020 #include <sos/macros.h>
021 #include <sos/assert.h> 021 #include <sos/assert.h>
022 #include <sos/klibc.h> 022 #include <sos/klibc.h>
023 023
024 #include "physmem.h" 024 #include "physmem.h"
025 025
026 026
027 struct physical_page_descr 027 struct physical_page_descr
028 { 028 {
029 029
030 sos_paddr_t paddr; 030 sos_paddr_t paddr;
031 031
032 032
033 !! 033
034 sos_count_t ref_cnt; 034 sos_count_t ref_cnt;
035 035
>> 036
>> 037
>> 038
>> 039
>> 040
>> 041
>> 042
>> 043
>> 044
>> 045 sos_count_t occupation_cnt;
>> 046
>> 047
036 048
037 struct sos_kmem_range *kernel_range; 049 struct sos_kmem_range *kernel_range;
038 050
039 !! 051
040 struct physical_page_descr *prev, *next; 052 struct physical_page_descr *prev, *next;
041 }; 053 };
042 054
043 055
044 extern char __b_kernel, __e_kernel; 056 extern char __b_kernel, __e_kernel;
045 057
046 058
047 #define PAGE_DESCR_ARRAY_ADDR \ 059 #define PAGE_DESCR_ARRAY_ADDR \
048 SOS_PAGE_ALIGN_SUP((sos_paddr_t) (& __e_kern 060 SOS_PAGE_ALIGN_SUP((sos_paddr_t) (& __e_kernel))
049 static struct physical_page_descr * physical_p 061 static struct physical_page_descr * physical_page_descr_array;
050 062
051 063
052 static struct physical_page_descr *free_ppage; 064 static struct physical_page_descr *free_ppage;
053 065
054 !! 066
055 static struct physical_page_descr *used_ppage; !! 067 static struct physical_page_descr *nonfree_ppage;
056 068
057 069
058 static sos_paddr_t physmem_base, physmem_top; 070 static sos_paddr_t physmem_base, physmem_top;
059 071
060 !! 072
061 static sos_count_t physmem_total_pages, physme !! 073 static sos_count_t physmem_total_pages, physmem_nonfree_pages;
062 074
063 sos_ret_t sos_physmem_subsystem_setup(sos_size 075 sos_ret_t sos_physmem_subsystem_setup(sos_size_t ram_size,
064 076 sos_paddr_t *kernel_core_base,
065 077 sos_paddr_t *kernel_core_top)
066 { 078 {
067 079
068 struct physical_page_descr *ppage_descr; 080 struct physical_page_descr *ppage_descr;
069 081
070 082
071 sos_paddr_t ppage_addr; 083 sos_paddr_t ppage_addr;
072 084
073 085
074 ram_size = SOS_PAGE_ALIGN_INF(ram_size); 086 ram_size = SOS_PAGE_ALIGN_INF(ram_size);
075 087
076 !! 088
077 free_ppage = used_ppage = NULL; !! 089 free_ppage = nonfree_ppage = NULL;
078 physmem_total_pages = physmem_used_pages = 0 !! 090 physmem_total_pages = physmem_nonfree_pages = 0;
079 091
080 092
081 093
082 *kernel_core_base = SOS_PAGE_ALIGN_INF((sos_ 094 *kernel_core_base = SOS_PAGE_ALIGN_INF((sos_paddr_t)(& __b_kernel));
083 *kernel_core_top 095 *kernel_core_top
084 = PAGE_DESCR_ARRAY_ADDR 096 = PAGE_DESCR_ARRAY_ADDR
085 + SOS_PAGE_ALIGN_SUP( (ram_size >> SOS_P 097 + SOS_PAGE_ALIGN_SUP( (ram_size >> SOS_PAGE_SHIFT)
086 * sizeof(struct ph 098 * sizeof(struct physical_page_descr));
087 if (*kernel_core_top > ram_size) 099 if (*kernel_core_top > ram_size)
088 return -SOS_ENOMEM; 100 return -SOS_ENOMEM;
089 101
090 102
091 103
092 physmem_base = SOS_PAGE_SIZE; 104 physmem_base = SOS_PAGE_SIZE;
093 physmem_top = ram_size; 105 physmem_top = ram_size;
094 106
095 107
096 physical_page_descr_array 108 physical_page_descr_array
097 = (struct physical_page_descr*)PAGE_DESCR_ 109 = (struct physical_page_descr*)PAGE_DESCR_ARRAY_ADDR;
098 110
099 111
100 for (ppage_addr = 0, 112 for (ppage_addr = 0,
101 ppage_descr = physical_page_descr_arr 113 ppage_descr = physical_page_descr_array ;
102 ppage_addr < physmem_top ; 114 ppage_addr < physmem_top ;
103 ppage_addr += SOS_PAGE_SIZE, 115 ppage_addr += SOS_PAGE_SIZE,
104 ppage_descr ++) 116 ppage_descr ++)
105 { 117 {
106 enum { PPAGE_MARK_RESERVED, PPAGE_MARK_F 118 enum { PPAGE_MARK_RESERVED, PPAGE_MARK_FREE,
107 PPAGE_MARK_KERNEL, PPAGE_MARK_HWM 119 PPAGE_MARK_KERNEL, PPAGE_MARK_HWMAP } todo;
108 120
109 memset(ppage_descr, 0x0, sizeof(struct p 121 memset(ppage_descr, 0x0, sizeof(struct physical_page_descr));
110 122
111 123
112 ppage_descr->paddr = ppage_addr; 124 ppage_descr->paddr = ppage_addr;
113 125
114 126
115 if (ppage_addr < physmem_base) 127 if (ppage_addr < physmem_base)
116 todo = PPAGE_MARK_RESERVED; 128 todo = PPAGE_MARK_RESERVED;
117 129
118 130
119 else if ((ppage_addr >= physmem_base) 131 else if ((ppage_addr >= physmem_base)
120 && (ppage_addr < BIOS_N_VIDEO_S 132 && (ppage_addr < BIOS_N_VIDEO_START))
121 todo = PPAGE_MARK_FREE; 133 todo = PPAGE_MARK_FREE;
122 134
123 135
124 else if ((ppage_addr >= BIOS_N_VIDEO_STA 136 else if ((ppage_addr >= BIOS_N_VIDEO_START)
125 && (ppage_addr < BIOS_N_VIDEO_E 137 && (ppage_addr < BIOS_N_VIDEO_END))
126 todo = PPAGE_MARK_HWMAP; 138 todo = PPAGE_MARK_HWMAP;
127 139
128 140
129 else if ((ppage_addr >= BIOS_N_VIDEO_END 141 else if ((ppage_addr >= BIOS_N_VIDEO_END)
130 && (ppage_addr < (sos_paddr_t) 142 && (ppage_addr < (sos_paddr_t) (& __b_kernel)))
131 todo = PPAGE_MARK_FREE; 143 todo = PPAGE_MARK_FREE;
132 144
133 145
134 else if ((ppage_addr >= *kernel_core_bas 146 else if ((ppage_addr >= *kernel_core_base)
135 && (ppage_addr < *kernel_core_ 147 && (ppage_addr < *kernel_core_top))
136 todo = PPAGE_MARK_KERNEL; 148 todo = PPAGE_MARK_KERNEL;
137 149
138 150
139 else 151 else
140 todo = PPAGE_MARK_FREE; 152 todo = PPAGE_MARK_FREE;
141 153
142 !! 154
143 physmem_total_pages ++; 155 physmem_total_pages ++;
144 switch (todo) 156 switch (todo)
145 { 157 {
146 case PPAGE_MARK_FREE: 158 case PPAGE_MARK_FREE:
147 ppage_descr->ref_cnt = 0; 159 ppage_descr->ref_cnt = 0;
148 list_add_head(free_ppage, ppage_desc 160 list_add_head(free_ppage, ppage_descr);
149 break; 161 break;
150 162
151 case PPAGE_MARK_KERNEL: 163 case PPAGE_MARK_KERNEL:
152 case PPAGE_MARK_HWMAP: 164 case PPAGE_MARK_HWMAP:
153 ppage_descr->ref_cnt = 1; 165 ppage_descr->ref_cnt = 1;
154 list_add_head(used_ppage, ppage_desc !! 166 list_add_head(nonfree_ppage, ppage_descr);
155 physmem_used_pages ++; !! 167 physmem_nonfree_pages ++;
156 break; 168 break;
157 169
158 default: 170 default:
159 171
160 break; 172 break;
161 } 173 }
162 } 174 }
163 175
164 return SOS_OK; 176 return SOS_OK;
165 } 177 }
166 178
167 179
168 sos_paddr_t sos_physmem_ref_physpage_new(sos_b 180 sos_paddr_t sos_physmem_ref_physpage_new(sos_bool_t can_block)
169 { 181 {
170 struct physical_page_descr *ppage_descr; 182 struct physical_page_descr *ppage_descr;
171 183
172 if (! free_ppage) 184 if (! free_ppage)
173 return (sos_paddr_t)NULL; 185 return (sos_paddr_t)NULL;
174 186
175 187
176 ppage_descr = list_pop_head(free_ppage); 188 ppage_descr = list_pop_head(free_ppage);
177 189
178 !! 190
179 SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0); 191 SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0);
180 192
181 !! 193
182 ppage_descr->ref_cnt ++; 194 ppage_descr->ref_cnt ++;
183 195
184 !! 196
185 ppage_descr->kernel_range = NULL; !! 197
>> 198
>> 199 SOS_ASSERT_FATAL(ppage_descr->occupation_cnt == 0);
>> 200 SOS_ASSERT_FATAL(ppage_descr->kernel_range == NULL);
186 201
187 !! 202
188 list_add_tail(used_ppage, ppage_descr); !! 203 list_add_tail(nonfree_ppage, ppage_descr);
189 physmem_used_pages ++; !! 204 physmem_nonfree_pages ++;
190 205
191 return ppage_descr->paddr; 206 return ppage_descr->paddr;
192 } 207 }
193 208
194 209
195 210
196 211
197 212
198 213
199 214
200 215
201 inline static struct physical_page_descr * 216 inline static struct physical_page_descr *
202 get_page_descr_at_paddr(sos_paddr_t ppage_padd 217 get_page_descr_at_paddr(sos_paddr_t ppage_paddr)
203 { 218 {
204 219
205 if (ppage_paddr & SOS_PAGE_MASK) 220 if (ppage_paddr & SOS_PAGE_MASK)
206 return NULL; 221 return NULL;
207 222
208 223
209 if ((ppage_paddr < physmem_base) || (ppage_p 224 if ((ppage_paddr < physmem_base) || (ppage_paddr >= physmem_top))
210 return NULL; 225 return NULL;
211 226
212 return physical_page_descr_array + (ppage_pa 227 return physical_page_descr_array + (ppage_paddr >> SOS_PAGE_SHIFT);
213 } 228 }
214 229
215 230
216 sos_ret_t sos_physmem_ref_physpage_at(sos_padd 231 sos_ret_t sos_physmem_ref_physpage_at(sos_paddr_t ppage_paddr)
217 { 232 {
218 struct physical_page_descr *ppage_descr 233 struct physical_page_descr *ppage_descr
219 = get_page_descr_at_paddr(ppage_paddr); 234 = get_page_descr_at_paddr(ppage_paddr);
220 235
221 if (! ppage_descr) 236 if (! ppage_descr)
222 return -SOS_EINVAL; 237 return -SOS_EINVAL;
223 238
224 239
225 ppage_descr->ref_cnt ++; 240 ppage_descr->ref_cnt ++;
226 241
227 242
228 !! 243
229 if (ppage_descr->ref_cnt == 1) 244 if (ppage_descr->ref_cnt == 1)
230 { 245 {
>> 246
>> 247
>> 248
>> 249 SOS_ASSERT_FATAL(ppage_descr->occupation_cnt == 0);
>> 250 SOS_ASSERT_FATAL(ppage_descr->kernel_range == NULL);
>> 251
231 list_delete(free_ppage, ppage_descr); 252 list_delete(free_ppage, ppage_descr);
232 !! 253 list_add_tail(nonfree_ppage, ppage_descr);
233 !! 254 physmem_nonfree_pages ++;
234 ppage_descr->kernel_range = NULL; <<
235 <<
236 list_add_tail(used_ppage, ppage_descr); <<
237 physmem_used_pages ++; <<
238 255
239 256
240 return FALSE; 257 return FALSE;
241 } 258 }
242 !! 259
243 260
244 return TRUE; 261 return TRUE;
245 } 262 }
246 263
247 264
248 sos_ret_t 265 sos_ret_t
249 sos_physmem_unref_physpage(sos_paddr_t ppage_p 266 sos_physmem_unref_physpage(sos_paddr_t ppage_paddr)
250 { 267 {
251 268
252 269
253 sos_ret_t retval = FALSE; 270 sos_ret_t retval = FALSE;
254 271
255 struct physical_page_descr *ppage_descr 272 struct physical_page_descr *ppage_descr
256 = get_page_descr_at_paddr(ppage_paddr); 273 = get_page_descr_at_paddr(ppage_paddr);
257 274
258 if (! ppage_descr) 275 if (! ppage_descr)
259 return -SOS_EINVAL; 276 return -SOS_EINVAL;
260 277
261 !! 278
262 if (ppage_descr->ref_cnt <= 0) 279 if (ppage_descr->ref_cnt <= 0)
263 return -SOS_EINVAL; 280 return -SOS_EINVAL;
264 281
265 282
266 283
267 ppage_descr->ref_cnt--; 284 ppage_descr->ref_cnt--;
268 if (ppage_descr->ref_cnt <= 0) !! 285 if (ppage_descr->ref_cnt == 0)
269 { 286 {
>> 287
>> 288 SOS_ASSERT_FATAL(ppage_descr->occupation_cnt == 0);
>> 289
270 290
271 ppage_descr->kernel_range = NULL; 291 ppage_descr->kernel_range = NULL;
272 292
273 !! 293
274 list_delete(used_ppage, ppage_descr); !! 294 list_delete(nonfree_ppage, ppage_descr);
275 physmem_used_pages --; !! 295 physmem_nonfree_pages --;
>> 296
276 list_add_head(free_ppage, ppage_descr); 297 list_add_head(free_ppage, ppage_descr);
277 298
278 299
279 retval = TRUE; 300 retval = TRUE;
280 } 301 }
281 302
>> 303
282 return retval; 304 return retval;
283 } 305 }
284 306
285 307
>> 308 sos_ret_t sos_physmem_get_physpage_refcount(sos_paddr_t ppage_paddr)
>> 309 {
>> 310 struct physical_page_descr *ppage_descr
>> 311 = get_page_descr_at_paddr(ppage_paddr);
>> 312
>> 313 if (! ppage_descr)
>> 314 return -SOS_EINVAL;
>> 315
>> 316 return ppage_descr->ref_cnt;
>> 317 }
>> 318
>> 319
>> 320 sos_ret_t sos_physmem_inc_physpage_occupation(sos_paddr_t ppage_paddr)
>> 321 {
>> 322 struct physical_page_descr *ppage_descr
>> 323 = get_page_descr_at_paddr(ppage_paddr);
>> 324
>> 325 if (! ppage_descr)
>> 326 return -SOS_EINVAL;
>> 327
>> 328
>> 329 SOS_ASSERT_FATAL(ppage_descr->ref_cnt > 0);
>> 330
>> 331 ppage_descr->occupation_cnt ++;
>> 332 return (ppage_descr->occupation_cnt > 1);
>> 333 }
>> 334
>> 335
>> 336 sos_ret_t sos_physmem_dec_physpage_occupation(sos_paddr_t ppage_paddr)
>> 337 {
>> 338 struct physical_page_descr *ppage_descr
>> 339 = get_page_descr_at_paddr(ppage_paddr);
>> 340
>> 341 if (! ppage_descr)
>> 342 return -SOS_EINVAL;
>> 343
>> 344
>> 345 SOS_ASSERT_FATAL(ppage_descr->ref_cnt > 0);
>> 346 SOS_ASSERT_FATAL(ppage_descr->occupation_cnt > 0);
>> 347
>> 348 ppage_descr->occupation_cnt --;
>> 349 return (ppage_descr->occupation_cnt == 0);
>> 350 }
>> 351
>> 352
286 struct sos_kmem_range* sos_physmem_get_kmem_ra 353 struct sos_kmem_range* sos_physmem_get_kmem_range(sos_paddr_t ppage_paddr)
287 { 354 {
288 struct physical_page_descr *ppage_descr 355 struct physical_page_descr *ppage_descr
289 = get_page_descr_at_paddr(ppage_paddr); 356 = get_page_descr_at_paddr(ppage_paddr);
290 357
291 if (! ppage_descr) 358 if (! ppage_descr)
292 return NULL; 359 return NULL;
293 360
294 return ppage_descr->kernel_range; 361 return ppage_descr->kernel_range;
295 } 362 }
296 363
297 364
298 sos_ret_t sos_physmem_set_kmem_range(sos_paddr 365 sos_ret_t sos_physmem_set_kmem_range(sos_paddr_t ppage_paddr,
299 struct so 366 struct sos_kmem_range *range)
300 { 367 {
301 struct physical_page_descr *ppage_descr 368 struct physical_page_descr *ppage_descr
302 = get_page_descr_at_paddr(ppage_paddr); 369 = get_page_descr_at_paddr(ppage_paddr);
303 370
304 if (! ppage_descr) 371 if (! ppage_descr)
305 return -SOS_EINVAL; 372 return -SOS_EINVAL;
306 373
307 ppage_descr->kernel_range = range; 374 ppage_descr->kernel_range = range;
308 return SOS_OK; 375 return SOS_OK;
309 } 376 }
310 377
311 sos_ret_t sos_physmem_get_state(sos_c 378 sos_ret_t sos_physmem_get_state(sos_count_t *total_ppages,
312 sos_c !! 379 sos_count_t *nonfree_ppages)
313 { 380 {
314 if (total_ppages) 381 if (total_ppages)
315 *total_ppages = physmem_total_pages; 382 *total_ppages = physmem_total_pages;
316 if (used_ppages) !! 383 if (nonfree_ppages)
317 *used_ppages = physmem_used_pages; !! 384 *nonfree_ppages = physmem_nonfree_pages;
318 return SOS_OK; 385 return SOS_OK;
319 } 386 }