diff options
-rw-r--r-- | arch/ia64/kernel/efi.c | 489 |
1 files changed, 266 insertions, 223 deletions
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 242d79341120..9e5910920da6 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Extensible Firmware Interface | 2 | * Extensible Firmware Interface |
3 | * | 3 | * |
4 | * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999 | 4 | * Based on Extensible Firmware Interface Specification version 0.9 |
5 | * April 30, 1999 | ||
5 | * | 6 | * |
6 | * Copyright (C) 1999 VA Linux Systems | 7 | * Copyright (C) 1999 VA Linux Systems |
7 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | 8 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> |
@@ -48,145 +49,157 @@ static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; | |||
48 | 49 | ||
49 | #define efi_call_virt(f, args...) (*(f))(args) | 50 | #define efi_call_virt(f, args...) (*(f))(args) |
50 | 51 | ||
51 | #define STUB_GET_TIME(prefix, adjust_arg) \ | 52 | #define STUB_GET_TIME(prefix, adjust_arg) \ |
52 | static efi_status_t \ | 53 | static efi_status_t \ |
53 | prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ | 54 | prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ |
54 | { \ | 55 | { \ |
55 | struct ia64_fpreg fr[6]; \ | 56 | struct ia64_fpreg fr[6]; \ |
56 | efi_time_cap_t *atc = NULL; \ | 57 | efi_time_cap_t *atc = NULL; \ |
57 | efi_status_t ret; \ | 58 | efi_status_t ret; \ |
58 | \ | 59 | \ |
59 | if (tc) \ | 60 | if (tc) \ |
60 | atc = adjust_arg(tc); \ | 61 | atc = adjust_arg(tc); \ |
61 | ia64_save_scratch_fpregs(fr); \ | 62 | ia64_save_scratch_fpregs(fr); \ |
62 | ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), atc); \ | 63 | ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), \ |
63 | ia64_load_scratch_fpregs(fr); \ | 64 | adjust_arg(tm), atc); \ |
64 | return ret; \ | 65 | ia64_load_scratch_fpregs(fr); \ |
66 | return ret; \ | ||
65 | } | 67 | } |
66 | 68 | ||
67 | #define STUB_SET_TIME(prefix, adjust_arg) \ | 69 | #define STUB_SET_TIME(prefix, adjust_arg) \ |
68 | static efi_status_t \ | 70 | static efi_status_t \ |
69 | prefix##_set_time (efi_time_t *tm) \ | 71 | prefix##_set_time (efi_time_t *tm) \ |
70 | { \ | 72 | { \ |
71 | struct ia64_fpreg fr[6]; \ | 73 | struct ia64_fpreg fr[6]; \ |
72 | efi_status_t ret; \ | 74 | efi_status_t ret; \ |
73 | \ | 75 | \ |
74 | ia64_save_scratch_fpregs(fr); \ | 76 | ia64_save_scratch_fpregs(fr); \ |
75 | ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \ | 77 | ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), \ |
76 | ia64_load_scratch_fpregs(fr); \ | 78 | adjust_arg(tm)); \ |
77 | return ret; \ | 79 | ia64_load_scratch_fpregs(fr); \ |
80 | return ret; \ | ||
78 | } | 81 | } |
79 | 82 | ||
80 | #define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \ | 83 | #define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \ |
81 | static efi_status_t \ | 84 | static efi_status_t \ |
82 | prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \ | 85 | prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, \ |
83 | { \ | 86 | efi_time_t *tm) \ |
84 | struct ia64_fpreg fr[6]; \ | 87 | { \ |
85 | efi_status_t ret; \ | 88 | struct ia64_fpreg fr[6]; \ |
86 | \ | 89 | efi_status_t ret; \ |
87 | ia64_save_scratch_fpregs(fr); \ | 90 | \ |
88 | ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \ | 91 | ia64_save_scratch_fpregs(fr); \ |
89 | adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \ | 92 | ret = efi_call_##prefix( \ |
90 | ia64_load_scratch_fpregs(fr); \ | 93 | (efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \ |
91 | return ret; \ | 94 | adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \ |
95 | ia64_load_scratch_fpregs(fr); \ | ||
96 | return ret; \ | ||
92 | } | 97 | } |
93 | 98 | ||
94 | #define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \ | 99 | #define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \ |
95 | static efi_status_t \ | 100 | static efi_status_t \ |
96 | prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ | 101 | prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ |
97 | { \ | 102 | { \ |
98 | struct ia64_fpreg fr[6]; \ | 103 | struct ia64_fpreg fr[6]; \ |
99 | efi_time_t *atm = NULL; \ | 104 | efi_time_t *atm = NULL; \ |
100 | efi_status_t ret; \ | 105 | efi_status_t ret; \ |
101 | \ | 106 | \ |
102 | if (tm) \ | 107 | if (tm) \ |
103 | atm = adjust_arg(tm); \ | 108 | atm = adjust_arg(tm); \ |
104 | ia64_save_scratch_fpregs(fr); \ | 109 | ia64_save_scratch_fpregs(fr); \ |
105 | ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \ | 110 | ret = efi_call_##prefix( \ |
106 | enabled, atm); \ | 111 | (efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \ |
107 | ia64_load_scratch_fpregs(fr); \ | 112 | enabled, atm); \ |
108 | return ret; \ | 113 | ia64_load_scratch_fpregs(fr); \ |
114 | return ret; \ | ||
109 | } | 115 | } |
110 | 116 | ||
111 | #define STUB_GET_VARIABLE(prefix, adjust_arg) \ | 117 | #define STUB_GET_VARIABLE(prefix, adjust_arg) \ |
112 | static efi_status_t \ | 118 | static efi_status_t \ |
113 | prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ | 119 | prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ |
114 | unsigned long *data_size, void *data) \ | 120 | unsigned long *data_size, void *data) \ |
115 | { \ | 121 | { \ |
116 | struct ia64_fpreg fr[6]; \ | 122 | struct ia64_fpreg fr[6]; \ |
117 | u32 *aattr = NULL; \ | 123 | u32 *aattr = NULL; \ |
118 | efi_status_t ret; \ | 124 | efi_status_t ret; \ |
119 | \ | 125 | \ |
120 | if (attr) \ | 126 | if (attr) \ |
121 | aattr = adjust_arg(attr); \ | 127 | aattr = adjust_arg(attr); \ |
122 | ia64_save_scratch_fpregs(fr); \ | 128 | ia64_save_scratch_fpregs(fr); \ |
123 | ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \ | 129 | ret = efi_call_##prefix( \ |
124 | adjust_arg(name), adjust_arg(vendor), aattr, \ | 130 | (efi_get_variable_t *) __va(runtime->get_variable), \ |
125 | adjust_arg(data_size), adjust_arg(data)); \ | 131 | adjust_arg(name), adjust_arg(vendor), aattr, \ |
126 | ia64_load_scratch_fpregs(fr); \ | 132 | adjust_arg(data_size), adjust_arg(data)); \ |
127 | return ret; \ | 133 | ia64_load_scratch_fpregs(fr); \ |
134 | return ret; \ | ||
128 | } | 135 | } |
129 | 136 | ||
130 | #define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \ | 137 | #define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \ |
131 | static efi_status_t \ | 138 | static efi_status_t \ |
132 | prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \ | 139 | prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, \ |
133 | { \ | 140 | efi_guid_t *vendor) \ |
134 | struct ia64_fpreg fr[6]; \ | 141 | { \ |
135 | efi_status_t ret; \ | 142 | struct ia64_fpreg fr[6]; \ |
136 | \ | 143 | efi_status_t ret; \ |
137 | ia64_save_scratch_fpregs(fr); \ | 144 | \ |
138 | ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \ | 145 | ia64_save_scratch_fpregs(fr); \ |
139 | adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \ | 146 | ret = efi_call_##prefix( \ |
140 | ia64_load_scratch_fpregs(fr); \ | 147 | (efi_get_next_variable_t *) __va(runtime->get_next_variable), \ |
141 | return ret; \ | 148 | adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \ |
149 | ia64_load_scratch_fpregs(fr); \ | ||
150 | return ret; \ | ||
142 | } | 151 | } |
143 | 152 | ||
144 | #define STUB_SET_VARIABLE(prefix, adjust_arg) \ | 153 | #define STUB_SET_VARIABLE(prefix, adjust_arg) \ |
145 | static efi_status_t \ | 154 | static efi_status_t \ |
146 | prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long attr, \ | 155 | prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, \ |
147 | unsigned long data_size, void *data) \ | 156 | unsigned long attr, unsigned long data_size, \ |
148 | { \ | 157 | void *data) \ |
149 | struct ia64_fpreg fr[6]; \ | 158 | { \ |
150 | efi_status_t ret; \ | 159 | struct ia64_fpreg fr[6]; \ |
151 | \ | 160 | efi_status_t ret; \ |
152 | ia64_save_scratch_fpregs(fr); \ | 161 | \ |
153 | ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \ | 162 | ia64_save_scratch_fpregs(fr); \ |
154 | adjust_arg(name), adjust_arg(vendor), attr, data_size, \ | 163 | ret = efi_call_##prefix( \ |
155 | adjust_arg(data)); \ | 164 | (efi_set_variable_t *) __va(runtime->set_variable), \ |
156 | ia64_load_scratch_fpregs(fr); \ | 165 | adjust_arg(name), adjust_arg(vendor), attr, data_size, \ |
157 | return ret; \ | 166 | adjust_arg(data)); \ |
167 | ia64_load_scratch_fpregs(fr); \ | ||
168 | return ret; \ | ||
158 | } | 169 | } |
159 | 170 | ||
160 | #define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \ | 171 | #define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \ |
161 | static efi_status_t \ | 172 | static efi_status_t \ |
162 | prefix##_get_next_high_mono_count (u32 *count) \ | 173 | prefix##_get_next_high_mono_count (u32 *count) \ |
163 | { \ | 174 | { \ |
164 | struct ia64_fpreg fr[6]; \ | 175 | struct ia64_fpreg fr[6]; \ |
165 | efi_status_t ret; \ | 176 | efi_status_t ret; \ |
166 | \ | 177 | \ |
167 | ia64_save_scratch_fpregs(fr); \ | 178 | ia64_save_scratch_fpregs(fr); \ |
168 | ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \ | 179 | ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \ |
169 | __va(runtime->get_next_high_mono_count), adjust_arg(count)); \ | 180 | __va(runtime->get_next_high_mono_count), \ |
170 | ia64_load_scratch_fpregs(fr); \ | 181 | adjust_arg(count)); \ |
171 | return ret; \ | 182 | ia64_load_scratch_fpregs(fr); \ |
183 | return ret; \ | ||
172 | } | 184 | } |
173 | 185 | ||
174 | #define STUB_RESET_SYSTEM(prefix, adjust_arg) \ | 186 | #define STUB_RESET_SYSTEM(prefix, adjust_arg) \ |
175 | static void \ | 187 | static void \ |
176 | prefix##_reset_system (int reset_type, efi_status_t status, \ | 188 | prefix##_reset_system (int reset_type, efi_status_t status, \ |
177 | unsigned long data_size, efi_char16_t *data) \ | 189 | unsigned long data_size, efi_char16_t *data) \ |
178 | { \ | 190 | { \ |
179 | struct ia64_fpreg fr[6]; \ | 191 | struct ia64_fpreg fr[6]; \ |
180 | efi_char16_t *adata = NULL; \ | 192 | efi_char16_t *adata = NULL; \ |
181 | \ | 193 | \ |
182 | if (data) \ | 194 | if (data) \ |
183 | adata = adjust_arg(data); \ | 195 | adata = adjust_arg(data); \ |
184 | \ | 196 | \ |
185 | ia64_save_scratch_fpregs(fr); \ | 197 | ia64_save_scratch_fpregs(fr); \ |
186 | efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \ | 198 | efi_call_##prefix( \ |
187 | reset_type, status, data_size, adata); \ | 199 | (efi_reset_system_t *) __va(runtime->reset_system), \ |
188 | /* should not return, but just in case... */ \ | 200 | reset_type, status, data_size, adata); \ |
189 | ia64_load_scratch_fpregs(fr); \ | 201 | /* should not return, but just in case... */ \ |
202 | ia64_load_scratch_fpregs(fr); \ | ||
190 | } | 203 | } |
191 | 204 | ||
192 | #define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg)) | 205 | #define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg)) |
@@ -223,7 +236,8 @@ efi_gettimeofday (struct timespec *ts) | |||
223 | return; | 236 | return; |
224 | } | 237 | } |
225 | 238 | ||
226 | ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); | 239 | ts->tv_sec = mktime(tm.year, tm.month, tm.day, |
240 | tm.hour, tm.minute, tm.second); | ||
227 | ts->tv_nsec = tm.nanosecond; | 241 | ts->tv_nsec = tm.nanosecond; |
228 | } | 242 | } |
229 | 243 | ||
@@ -297,8 +311,8 @@ walk (efi_freemem_callback_t callback, void *arg, u64 attr) | |||
297 | } | 311 | } |
298 | 312 | ||
299 | /* | 313 | /* |
300 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that | 314 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory |
301 | * has memory that is available for OS use. | 315 | * descriptor that has memory that is available for OS use. |
302 | */ | 316 | */ |
303 | void | 317 | void |
304 | efi_memmap_walk (efi_freemem_callback_t callback, void *arg) | 318 | efi_memmap_walk (efi_freemem_callback_t callback, void *arg) |
@@ -307,8 +321,8 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) | |||
307 | } | 321 | } |
308 | 322 | ||
309 | /* | 323 | /* |
310 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that | 324 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory |
311 | * has memory that is available for uncached allocator. | 325 | * descriptor that has memory that is available for uncached allocator. |
312 | */ | 326 | */ |
313 | void | 327 | void |
314 | efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) | 328 | efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) |
@@ -321,7 +335,6 @@ efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) | |||
321 | * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor | 335 | * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor |
322 | * Abstraction Layer chapter 11 in ADAG | 336 | * Abstraction Layer chapter 11 in ADAG |
323 | */ | 337 | */ |
324 | |||
325 | void * | 338 | void * |
326 | efi_get_pal_addr (void) | 339 | efi_get_pal_addr (void) |
327 | { | 340 | { |
@@ -341,32 +354,33 @@ efi_get_pal_addr (void) | |||
341 | continue; | 354 | continue; |
342 | 355 | ||
343 | if (++pal_code_count > 1) { | 356 | if (++pal_code_count > 1) { |
344 | printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n", | 357 | printk(KERN_ERR "Too many EFI Pal Code memory ranges, " |
345 | md->phys_addr); | 358 | "dropped @ %lx\n", md->phys_addr); |
346 | continue; | 359 | continue; |
347 | } | 360 | } |
348 | /* | 361 | /* |
349 | * The only ITLB entry in region 7 that is used is the one installed by | 362 | * The only ITLB entry in region 7 that is used is the one |
350 | * __start(). That entry covers a 64MB range. | 363 | * installed by __start(). That entry covers a 64MB range. |
351 | */ | 364 | */ |
352 | mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1); | 365 | mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1); |
353 | vaddr = PAGE_OFFSET + md->phys_addr; | 366 | vaddr = PAGE_OFFSET + md->phys_addr; |
354 | 367 | ||
355 | /* | 368 | /* |
356 | * We must check that the PAL mapping won't overlap with the kernel | 369 | * We must check that the PAL mapping won't overlap with the |
357 | * mapping. | 370 | * kernel mapping. |
358 | * | 371 | * |
359 | * PAL code is guaranteed to be aligned on a power of 2 between 4k and | 372 | * PAL code is guaranteed to be aligned on a power of 2 between |
360 | * 256KB and that only one ITR is needed to map it. This implies that the | 373 | * 4k and 256KB and that only one ITR is needed to map it. This |
361 | * PAL code is always aligned on its size, i.e., the closest matching page | 374 | * implies that the PAL code is always aligned on its size, |
362 | * size supported by the TLB. Therefore PAL code is guaranteed never to | 375 | * i.e., the closest matching page size supported by the TLB. |
363 | * cross a 64MB unless it is bigger than 64MB (very unlikely!). So for | 376 | * Therefore PAL code is guaranteed never to cross a 64MB unless |
364 | * now the following test is enough to determine whether or not we need a | 377 | * it is bigger than 64MB (very unlikely!). So for now the |
365 | * dedicated ITR for the PAL code. | 378 | * following test is enough to determine whether or not we need |
379 | * a dedicated ITR for the PAL code. | ||
366 | */ | 380 | */ |
367 | if ((vaddr & mask) == (KERNEL_START & mask)) { | 381 | if ((vaddr & mask) == (KERNEL_START & mask)) { |
368 | printk(KERN_INFO "%s: no need to install ITR for PAL code\n", | 382 | printk(KERN_INFO "%s: no need to install ITR for " |
369 | __FUNCTION__); | 383 | "PAL code\n", __FUNCTION__); |
370 | continue; | 384 | continue; |
371 | } | 385 | } |
372 | 386 | ||
@@ -376,10 +390,11 @@ efi_get_pal_addr (void) | |||
376 | #if EFI_DEBUG | 390 | #if EFI_DEBUG |
377 | mask = ~((1 << IA64_GRANULE_SHIFT) - 1); | 391 | mask = ~((1 << IA64_GRANULE_SHIFT) - 1); |
378 | 392 | ||
379 | printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n", | 393 | printk(KERN_INFO "CPU %d: mapping PAL code " |
380 | smp_processor_id(), md->phys_addr, | 394 | "[0x%lx-0x%lx) into [0x%lx-0x%lx)\n", |
381 | md->phys_addr + efi_md_size(md), | 395 | smp_processor_id(), md->phys_addr, |
382 | vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE); | 396 | md->phys_addr + efi_md_size(md), |
397 | vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE); | ||
383 | #endif | 398 | #endif |
384 | return __va(md->phys_addr); | 399 | return __va(md->phys_addr); |
385 | } | 400 | } |
@@ -401,7 +416,8 @@ efi_map_pal_code (void) | |||
401 | * Cannot write to CRx with PSR.ic=1 | 416 | * Cannot write to CRx with PSR.ic=1 |
402 | */ | 417 | */ |
403 | psr = ia64_clear_ic(); | 418 | psr = ia64_clear_ic(); |
404 | ia64_itr(0x1, IA64_TR_PALCODE, GRANULEROUNDDOWN((unsigned long) pal_vaddr), | 419 | ia64_itr(0x1, IA64_TR_PALCODE, |
420 | GRANULEROUNDDOWN((unsigned long) pal_vaddr), | ||
405 | pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)), | 421 | pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)), |
406 | IA64_GRANULE_SHIFT); | 422 | IA64_GRANULE_SHIFT); |
407 | ia64_set_psr(psr); /* restore psr */ | 423 | ia64_set_psr(psr); /* restore psr */ |
@@ -418,7 +434,10 @@ efi_init (void) | |||
418 | char *cp, vendor[100] = "unknown"; | 434 | char *cp, vendor[100] = "unknown"; |
419 | int i; | 435 | int i; |
420 | 436 | ||
421 | /* it's too early to be able to use the standard kernel command line support... */ | 437 | /* |
438 | * it's too early to be able to use the standard kernel command line | ||
439 | * support... | ||
440 | */ | ||
422 | for (cp = boot_command_line; *cp; ) { | 441 | for (cp = boot_command_line; *cp; ) { |
423 | if (memcmp(cp, "mem=", 4) == 0) { | 442 | if (memcmp(cp, "mem=", 4) == 0) { |
424 | mem_limit = memparse(cp + 4, &cp); | 443 | mem_limit = memparse(cp + 4, &cp); |
@@ -434,9 +453,11 @@ efi_init (void) | |||
434 | } | 453 | } |
435 | } | 454 | } |
436 | if (min_addr != 0UL) | 455 | if (min_addr != 0UL) |
437 | printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20); | 456 | printk(KERN_INFO "Ignoring memory below %luMB\n", |
457 | min_addr >> 20); | ||
438 | if (max_addr != ~0UL) | 458 | if (max_addr != ~0UL) |
439 | printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20); | 459 | printk(KERN_INFO "Ignoring memory above %luMB\n", |
460 | max_addr >> 20); | ||
440 | 461 | ||
441 | efi.systab = __va(ia64_boot_param->efi_systab); | 462 | efi.systab = __va(ia64_boot_param->efi_systab); |
442 | 463 | ||
@@ -464,7 +485,8 @@ efi_init (void) | |||
464 | } | 485 | } |
465 | 486 | ||
466 | printk(KERN_INFO "EFI v%u.%.02u by %s:", | 487 | printk(KERN_INFO "EFI v%u.%.02u by %s:", |
467 | efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); | 488 | efi.systab->hdr.revision >> 16, |
489 | efi.systab->hdr.revision & 0xffff, vendor); | ||
468 | 490 | ||
469 | efi.mps = EFI_INVALID_TABLE_ADDR; | 491 | efi.mps = EFI_INVALID_TABLE_ADDR; |
470 | efi.acpi = EFI_INVALID_TABLE_ADDR; | 492 | efi.acpi = EFI_INVALID_TABLE_ADDR; |
@@ -519,9 +541,12 @@ efi_init (void) | |||
519 | efi_memory_desc_t *md; | 541 | efi_memory_desc_t *md; |
520 | void *p; | 542 | void *p; |
521 | 543 | ||
522 | for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { | 544 | for (i = 0, p = efi_map_start; p < efi_map_end; |
545 | ++i, p += efi_desc_size) | ||
546 | { | ||
523 | md = p; | 547 | md = p; |
524 | printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", | 548 | printk("mem%02u: type=%u, attr=0x%lx, " |
549 | "range=[0x%016lx-0x%016lx) (%luMB)\n", | ||
525 | i, md->type, md->attribute, md->phys_addr, | 550 | i, md->type, md->attribute, md->phys_addr, |
526 | md->phys_addr + efi_md_size(md), | 551 | md->phys_addr + efi_md_size(md), |
527 | md->num_pages >> (20 - EFI_PAGE_SHIFT)); | 552 | md->num_pages >> (20 - EFI_PAGE_SHIFT)); |
@@ -549,8 +574,8 @@ efi_enter_virtual_mode (void) | |||
549 | md = p; | 574 | md = p; |
550 | if (md->attribute & EFI_MEMORY_RUNTIME) { | 575 | if (md->attribute & EFI_MEMORY_RUNTIME) { |
551 | /* | 576 | /* |
552 | * Some descriptors have multiple bits set, so the order of | 577 | * Some descriptors have multiple bits set, so the |
553 | * the tests is relevant. | 578 | * order of the tests is relevant. |
554 | */ | 579 | */ |
555 | if (md->attribute & EFI_MEMORY_WB) { | 580 | if (md->attribute & EFI_MEMORY_WB) { |
556 | md->virt_addr = (u64) __va(md->phys_addr); | 581 | md->virt_addr = (u64) __va(md->phys_addr); |
@@ -558,21 +583,26 @@ efi_enter_virtual_mode (void) | |||
558 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 583 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
559 | } else if (md->attribute & EFI_MEMORY_WC) { | 584 | } else if (md->attribute & EFI_MEMORY_WC) { |
560 | #if 0 | 585 | #if 0 |
561 | md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P | 586 | md->virt_addr = ia64_remap(md->phys_addr, |
562 | | _PAGE_D | 587 | (_PAGE_A | |
563 | | _PAGE_MA_WC | 588 | _PAGE_P | |
564 | | _PAGE_PL_0 | 589 | _PAGE_D | |
565 | | _PAGE_AR_RW)); | 590 | _PAGE_MA_WC | |
591 | _PAGE_PL_0 | | ||
592 | _PAGE_AR_RW)); | ||
566 | #else | 593 | #else |
567 | printk(KERN_INFO "EFI_MEMORY_WC mapping\n"); | 594 | printk(KERN_INFO "EFI_MEMORY_WC mapping\n"); |
568 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 595 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
569 | #endif | 596 | #endif |
570 | } else if (md->attribute & EFI_MEMORY_WT) { | 597 | } else if (md->attribute & EFI_MEMORY_WT) { |
571 | #if 0 | 598 | #if 0 |
572 | md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P | 599 | md->virt_addr = ia64_remap(md->phys_addr, |
573 | | _PAGE_D | _PAGE_MA_WT | 600 | (_PAGE_A | |
574 | | _PAGE_PL_0 | 601 | _PAGE_P | |
575 | | _PAGE_AR_RW)); | 602 | _PAGE_D | |
603 | _PAGE_MA_WT | | ||
604 | _PAGE_PL_0 | | ||
605 | _PAGE_AR_RW)); | ||
576 | #else | 606 | #else |
577 | printk(KERN_INFO "EFI_MEMORY_WT mapping\n"); | 607 | printk(KERN_INFO "EFI_MEMORY_WT mapping\n"); |
578 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 608 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
@@ -583,16 +613,18 @@ efi_enter_virtual_mode (void) | |||
583 | 613 | ||
584 | status = efi_call_phys(__va(runtime->set_virtual_address_map), | 614 | status = efi_call_phys(__va(runtime->set_virtual_address_map), |
585 | ia64_boot_param->efi_memmap_size, | 615 | ia64_boot_param->efi_memmap_size, |
586 | efi_desc_size, ia64_boot_param->efi_memdesc_version, | 616 | efi_desc_size, |
617 | ia64_boot_param->efi_memdesc_version, | ||
587 | ia64_boot_param->efi_memmap); | 618 | ia64_boot_param->efi_memmap); |
588 | if (status != EFI_SUCCESS) { | 619 | if (status != EFI_SUCCESS) { |
589 | printk(KERN_WARNING "warning: unable to switch EFI into virtual mode " | 620 | printk(KERN_WARNING "warning: unable to switch EFI into " |
590 | "(status=%lu)\n", status); | 621 | "virtual mode (status=%lu)\n", status); |
591 | return; | 622 | return; |
592 | } | 623 | } |
593 | 624 | ||
594 | /* | 625 | /* |
595 | * Now that EFI is in virtual mode, we call the EFI functions more efficiently: | 626 | * Now that EFI is in virtual mode, we call the EFI functions more |
627 | * efficiently: | ||
596 | */ | 628 | */ |
597 | efi.get_time = virt_get_time; | 629 | efi.get_time = virt_get_time; |
598 | efi.set_time = virt_set_time; | 630 | efi.set_time = virt_set_time; |
@@ -606,8 +638,8 @@ efi_enter_virtual_mode (void) | |||
606 | } | 638 | } |
607 | 639 | ||
608 | /* | 640 | /* |
609 | * Walk the EFI memory map looking for the I/O port range. There can only be one entry of | 641 | * Walk the EFI memory map looking for the I/O port range. There can only be |
610 | * this type, other I/O port ranges should be described via ACPI. | 642 | * one entry of this type, other I/O port ranges should be described via ACPI. |
611 | */ | 643 | */ |
612 | u64 | 644 | u64 |
613 | efi_get_iobase (void) | 645 | efi_get_iobase (void) |
@@ -678,7 +710,6 @@ efi_memmap_intersects (unsigned long phys_addr, unsigned long size) | |||
678 | 710 | ||
679 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 711 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
680 | md = p; | 712 | md = p; |
681 | |||
682 | if (md->phys_addr < end && efi_md_end(md) > phys_addr) | 713 | if (md->phys_addr < end && efi_md_end(md) > phys_addr) |
683 | return 1; | 714 | return 1; |
684 | } | 715 | } |
@@ -883,7 +914,7 @@ efi_uart_console_only(void) | |||
883 | return 1; | 914 | return 1; |
884 | uart = 0; | 915 | uart = 0; |
885 | } | 916 | } |
886 | hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + hdr->length); | 917 | hdr = (struct efi_generic_dev_path *)((u8 *) hdr + hdr->length); |
887 | } | 918 | } |
888 | printk(KERN_ERR "Malformed %s value\n", name); | 919 | printk(KERN_ERR "Malformed %s value\n", name); |
889 | return 0; | 920 | return 0; |
@@ -921,10 +952,12 @@ find_memmap_space (void) | |||
921 | if (!efi_wb(md)) { | 952 | if (!efi_wb(md)) { |
922 | continue; | 953 | continue; |
923 | } | 954 | } |
924 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { | 955 | if (pmd == NULL || !efi_wb(pmd) || |
956 | efi_md_end(pmd) != md->phys_addr) { | ||
925 | contig_low = GRANULEROUNDUP(md->phys_addr); | 957 | contig_low = GRANULEROUNDUP(md->phys_addr); |
926 | contig_high = efi_md_end(md); | 958 | contig_high = efi_md_end(md); |
927 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { | 959 | for (q = p + efi_desc_size; q < efi_map_end; |
960 | q += efi_desc_size) { | ||
928 | check_md = q; | 961 | check_md = q; |
929 | if (!efi_wb(check_md)) | 962 | if (!efi_wb(check_md)) |
930 | break; | 963 | break; |
@@ -988,8 +1021,9 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
988 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { | 1021 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { |
989 | md = p; | 1022 | md = p; |
990 | if (!efi_wb(md)) { | 1023 | if (!efi_wb(md)) { |
991 | if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY || | 1024 | if (efi_uc(md) && |
992 | md->type == EFI_BOOT_SERVICES_DATA)) { | 1025 | (md->type == EFI_CONVENTIONAL_MEMORY || |
1026 | md->type == EFI_BOOT_SERVICES_DATA)) { | ||
993 | k->attribute = EFI_MEMORY_UC; | 1027 | k->attribute = EFI_MEMORY_UC; |
994 | k->start = md->phys_addr; | 1028 | k->start = md->phys_addr; |
995 | k->num_pages = md->num_pages; | 1029 | k->num_pages = md->num_pages; |
@@ -997,10 +1031,12 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
997 | } | 1031 | } |
998 | continue; | 1032 | continue; |
999 | } | 1033 | } |
1000 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { | 1034 | if (pmd == NULL || !efi_wb(pmd) || |
1035 | efi_md_end(pmd) != md->phys_addr) { | ||
1001 | contig_low = GRANULEROUNDUP(md->phys_addr); | 1036 | contig_low = GRANULEROUNDUP(md->phys_addr); |
1002 | contig_high = efi_md_end(md); | 1037 | contig_high = efi_md_end(md); |
1003 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { | 1038 | for (q = p + efi_desc_size; q < efi_map_end; |
1039 | q += efi_desc_size) { | ||
1004 | check_md = q; | 1040 | check_md = q; |
1005 | if (!efi_wb(check_md)) | 1041 | if (!efi_wb(check_md)) |
1006 | break; | 1042 | break; |
@@ -1025,13 +1061,17 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
1025 | if (md->phys_addr < contig_low) { | 1061 | if (md->phys_addr < contig_low) { |
1026 | lim = min(efi_md_end(md), contig_low); | 1062 | lim = min(efi_md_end(md), contig_low); |
1027 | if (efi_uc(md)) { | 1063 | if (efi_uc(md)) { |
1028 | if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC && | 1064 | if (k > kern_memmap && |
1065 | (k-1)->attribute == EFI_MEMORY_UC && | ||
1029 | kmd_end(k-1) == md->phys_addr) { | 1066 | kmd_end(k-1) == md->phys_addr) { |
1030 | (k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT; | 1067 | (k-1)->num_pages += |
1068 | (lim - md->phys_addr) | ||
1069 | >> EFI_PAGE_SHIFT; | ||
1031 | } else { | 1070 | } else { |
1032 | k->attribute = EFI_MEMORY_UC; | 1071 | k->attribute = EFI_MEMORY_UC; |
1033 | k->start = md->phys_addr; | 1072 | k->start = md->phys_addr; |
1034 | k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT; | 1073 | k->num_pages = (lim - md->phys_addr) |
1074 | >> EFI_PAGE_SHIFT; | ||
1035 | k++; | 1075 | k++; |
1036 | } | 1076 | } |
1037 | } | 1077 | } |
@@ -1049,7 +1089,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
1049 | } else { | 1089 | } else { |
1050 | k->attribute = EFI_MEMORY_UC; | 1090 | k->attribute = EFI_MEMORY_UC; |
1051 | k->start = lim; | 1091 | k->start = lim; |
1052 | k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT; | 1092 | k->num_pages = (efi_md_end(md) - lim) |
1093 | >> EFI_PAGE_SHIFT; | ||
1053 | k++; | 1094 | k++; |
1054 | } | 1095 | } |
1055 | } | 1096 | } |
@@ -1151,8 +1192,10 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
1151 | break; | 1192 | break; |
1152 | } | 1193 | } |
1153 | 1194 | ||
1154 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { | 1195 | if ((res = kzalloc(sizeof(struct resource), |
1155 | printk(KERN_ERR "failed to alocate resource for iomem\n"); | 1196 | GFP_KERNEL)) == NULL) { |
1197 | printk(KERN_ERR | ||
1198 | "failed to alocate resource for iomem\n"); | ||
1156 | return; | 1199 | return; |
1157 | } | 1200 | } |
1158 | 1201 | ||
@@ -1187,44 +1230,44 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
1187 | rsvd_regions are sorted | 1230 | rsvd_regions are sorted |
1188 | */ | 1231 | */ |
1189 | unsigned long __init | 1232 | unsigned long __init |
1190 | kdump_find_rsvd_region (unsigned long size, | 1233 | kdump_find_rsvd_region (unsigned long size, struct rsvd_region *r, int n) |
1191 | struct rsvd_region *r, int n) | ||
1192 | { | 1234 | { |
1193 | int i; | 1235 | int i; |
1194 | u64 start, end; | 1236 | u64 start, end; |
1195 | u64 alignment = 1UL << _PAGE_SIZE_64M; | 1237 | u64 alignment = 1UL << _PAGE_SIZE_64M; |
1196 | void *efi_map_start, *efi_map_end, *p; | 1238 | void *efi_map_start, *efi_map_end, *p; |
1197 | efi_memory_desc_t *md; | 1239 | efi_memory_desc_t *md; |
1198 | u64 efi_desc_size; | 1240 | u64 efi_desc_size; |
1199 | 1241 | ||
1200 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 1242 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
1201 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 1243 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
1202 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 1244 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
1203 | 1245 | ||
1204 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 1246 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
1205 | md = p; | 1247 | md = p; |
1206 | if (!efi_wb(md)) | 1248 | if (!efi_wb(md)) |
1207 | continue; | 1249 | continue; |
1208 | start = ALIGN(md->phys_addr, alignment); | 1250 | start = ALIGN(md->phys_addr, alignment); |
1209 | end = efi_md_end(md); | 1251 | end = efi_md_end(md); |
1210 | for (i = 0; i < n; i++) { | 1252 | for (i = 0; i < n; i++) { |
1211 | if (__pa(r[i].start) >= start && __pa(r[i].end) < end) { | 1253 | if (__pa(r[i].start) >= start && __pa(r[i].end) < end) { |
1212 | if (__pa(r[i].start) > start + size) | 1254 | if (__pa(r[i].start) > start + size) |
1213 | return start; | 1255 | return start; |
1214 | start = ALIGN(__pa(r[i].end), alignment); | 1256 | start = ALIGN(__pa(r[i].end), alignment); |
1215 | if (i < n-1 && __pa(r[i+1].start) < start + size) | 1257 | if (i < n-1 && |
1216 | continue; | 1258 | __pa(r[i+1].start) < start + size) |
1217 | else | 1259 | continue; |
1218 | break; | 1260 | else |
1261 | break; | ||
1262 | } | ||
1219 | } | 1263 | } |
1220 | } | 1264 | if (end > start + size) |
1221 | if (end > start + size) | 1265 | return start; |
1222 | return start; | 1266 | } |
1223 | } | 1267 | |
1224 | 1268 | printk(KERN_WARNING | |
1225 | printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n", | 1269 | "Cannot reserve 0x%lx byte of memory for crashdump\n", size); |
1226 | size); | 1270 | return ~0UL; |
1227 | return ~0UL; | ||
1228 | } | 1271 | } |
1229 | #endif | 1272 | #endif |
1230 | 1273 | ||