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
036 struct sos_kmem_range *kernel_range; 037 struct sos_kmem_range *kernel_range;
037 038
038 039
039 struct physical_page_descr *prev, *next; 040 struct physical_page_descr *prev, *next;
040 }; 041 };
041 042
042 043
043 extern char __b_kernel, __e_kernel; 044 extern char __b_kernel, __e_kernel;
044 045
045 046
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 051
051 static struct physical_page_descr *free_ppage; 052 static struct physical_page_descr *free_ppage;
052 053
053 054
054 static struct physical_page_descr *used_ppage; 055 static struct physical_page_descr *used_ppage;
055 056
056 057
057 static sos_paddr_t physmem_base, physmem_top; 058 static sos_paddr_t physmem_base, physmem_top;
058 059
059 060
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_subsystem_setup(sos_size 063 sos_ret_t sos_physmem_subsystem_setup(sos_size_t ram_size,
063 064 sos_paddr_t *kernel_core_base,
064 065 sos_paddr_t *kernel_core_top)
065 { 066 {
066 067
067 struct physical_page_descr *ppage_descr; 068 struct physical_page_descr *ppage_descr;
068 069
069 070
070 sos_paddr_t ppage_addr; 071 sos_paddr_t ppage_addr;
071 072
072 073
073 ram_size = SOS_PAGE_ALIGN_INF(ram_size); 074 ram_size = SOS_PAGE_ALIGN_INF(ram_size);
074 075
075 076
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 080
080 081
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 090
090 091
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 095
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 099
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 111
111 ppage_descr->paddr = ppage_addr; 112 ppage_descr->paddr = ppage_addr;
112 113
113 114
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 118
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 123
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 128
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 133
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 138
138 else 139 else
139 todo = PPAGE_MARK_FREE; 140 todo = PPAGE_MARK_FREE;
140 141
141 142
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 159
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 175
175 ppage_descr = list_pop_head(free_ppage); 176 ppage_descr = list_pop_head(free_ppage);
176 177
177 178
178 SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0); 179 SOS_ASSERT_FATAL(ppage_descr->ref_cnt == 0);
179 180
180 181
181 ppage_descr->ref_cnt ++; 182 ppage_descr->ref_cnt ++;
182 183
183 184
184 ppage_descr->kernel_range = NULL; 185 ppage_descr->kernel_range = NULL;
185 186
186 187
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 196
196 197
197 198
198 199
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 204
204 if (ppage_paddr & SOS_PAGE_MASK) 205 if (ppage_paddr & SOS_PAGE_MASK)
205 return NULL; 206 return NULL;
206 207
207 208
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 224
224 ppage_descr->ref_cnt ++; 225 ppage_descr->ref_cnt ++;
225 226
226 227
227 228
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 233
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 239
239 return FALSE; 240 return FALSE;
240 } 241 }
241 242
242 243
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 251
251 252
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 261
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 265
265 266
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 270
270 ppage_descr->kernel_range = NULL; 271 ppage_descr->kernel_range = NULL;
271 272
272 273
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 278
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(sos_c 311 sos_ret_t sos_physmem_get_state(sos_count_t *total_ppages,
311 sos_c 312 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 }