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