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