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