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