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