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