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