| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Procedures for interfacing to Open Firmware. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * |
|---|
| 7 | 8 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. |
|---|
| 8 | 9 | * {engebret|bergner}@us.ibm.com |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or |
|---|
| 11 | | - * modify it under the terms of the GNU General Public License |
|---|
| 12 | | - * as published by the Free Software Foundation; either version |
|---|
| 13 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 14 | 10 | */ |
|---|
| 15 | 11 | |
|---|
| 16 | 12 | #undef DEBUG_PROM |
|---|
| .. | .. |
|---|
| 30 | 26 | #include <linux/delay.h> |
|---|
| 31 | 27 | #include <linux/initrd.h> |
|---|
| 32 | 28 | #include <linux/bitops.h> |
|---|
| 29 | +#include <linux/pgtable.h> |
|---|
| 33 | 30 | #include <asm/prom.h> |
|---|
| 34 | 31 | #include <asm/rtas.h> |
|---|
| 35 | 32 | #include <asm/page.h> |
|---|
| .. | .. |
|---|
| 38 | 35 | #include <asm/io.h> |
|---|
| 39 | 36 | #include <asm/smp.h> |
|---|
| 40 | 37 | #include <asm/mmu.h> |
|---|
| 41 | | -#include <asm/pgtable.h> |
|---|
| 42 | 38 | #include <asm/iommu.h> |
|---|
| 43 | 39 | #include <asm/btext.h> |
|---|
| 44 | 40 | #include <asm/sections.h> |
|---|
| 45 | 41 | #include <asm/machdep.h> |
|---|
| 46 | | -#include <asm/opal.h> |
|---|
| 47 | 42 | #include <asm/asm-prototypes.h> |
|---|
| 43 | +#include <asm/ultravisor-api.h> |
|---|
| 48 | 44 | |
|---|
| 49 | 45 | #include <linux/linux_logo.h> |
|---|
| 46 | + |
|---|
| 47 | +/* All of prom_init bss lives here */ |
|---|
| 48 | +#define __prombss __section(".bss.prominit") |
|---|
| 50 | 49 | |
|---|
| 51 | 50 | /* |
|---|
| 52 | 51 | * Eventually bump that one up |
|---|
| .. | .. |
|---|
| 87 | 86 | #define OF_WORKAROUNDS 0 |
|---|
| 88 | 87 | #else |
|---|
| 89 | 88 | #define OF_WORKAROUNDS of_workarounds |
|---|
| 90 | | -int of_workarounds; |
|---|
| 89 | +static int of_workarounds __prombss; |
|---|
| 91 | 90 | #endif |
|---|
| 92 | 91 | |
|---|
| 93 | 92 | #define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */ |
|---|
| .. | .. |
|---|
| 96 | 95 | #define PROM_BUG() do { \ |
|---|
| 97 | 96 | prom_printf("kernel BUG at %s line 0x%x!\n", \ |
|---|
| 98 | 97 | __FILE__, __LINE__); \ |
|---|
| 99 | | - __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \ |
|---|
| 98 | + __builtin_trap(); \ |
|---|
| 100 | 99 | } while (0) |
|---|
| 101 | 100 | |
|---|
| 102 | 101 | #ifdef DEBUG_PROM |
|---|
| .. | .. |
|---|
| 148 | 147 | unsigned long size, unsigned long offset); |
|---|
| 149 | 148 | |
|---|
| 150 | 149 | /* prom structure */ |
|---|
| 151 | | -static struct prom_t __initdata prom; |
|---|
| 150 | +static struct prom_t __prombss prom; |
|---|
| 152 | 151 | |
|---|
| 153 | | -static unsigned long prom_entry __initdata; |
|---|
| 152 | +static unsigned long __prombss prom_entry; |
|---|
| 154 | 153 | |
|---|
| 155 | | -#define PROM_SCRATCH_SIZE 256 |
|---|
| 154 | +static char __prombss of_stdout_device[256]; |
|---|
| 155 | +static char __prombss prom_scratch[256]; |
|---|
| 156 | 156 | |
|---|
| 157 | | -static char __initdata of_stdout_device[256]; |
|---|
| 158 | | -static char __initdata prom_scratch[PROM_SCRATCH_SIZE]; |
|---|
| 157 | +static unsigned long __prombss dt_header_start; |
|---|
| 158 | +static unsigned long __prombss dt_struct_start, dt_struct_end; |
|---|
| 159 | +static unsigned long __prombss dt_string_start, dt_string_end; |
|---|
| 159 | 160 | |
|---|
| 160 | | -static unsigned long __initdata dt_header_start; |
|---|
| 161 | | -static unsigned long __initdata dt_struct_start, dt_struct_end; |
|---|
| 162 | | -static unsigned long __initdata dt_string_start, dt_string_end; |
|---|
| 163 | | - |
|---|
| 164 | | -static unsigned long __initdata prom_initrd_start, prom_initrd_end; |
|---|
| 161 | +static unsigned long __prombss prom_initrd_start, prom_initrd_end; |
|---|
| 165 | 162 | |
|---|
| 166 | 163 | #ifdef CONFIG_PPC64 |
|---|
| 167 | | -static int __initdata prom_iommu_force_on; |
|---|
| 168 | | -static int __initdata prom_iommu_off; |
|---|
| 169 | | -static unsigned long __initdata prom_tce_alloc_start; |
|---|
| 170 | | -static unsigned long __initdata prom_tce_alloc_end; |
|---|
| 164 | +static int __prombss prom_iommu_force_on; |
|---|
| 165 | +static int __prombss prom_iommu_off; |
|---|
| 166 | +static unsigned long __prombss prom_tce_alloc_start; |
|---|
| 167 | +static unsigned long __prombss prom_tce_alloc_end; |
|---|
| 171 | 168 | #endif |
|---|
| 172 | 169 | |
|---|
| 173 | | -static bool prom_radix_disable __initdata = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); |
|---|
| 170 | +#ifdef CONFIG_PPC_PSERIES |
|---|
| 171 | +static bool __prombss prom_radix_disable; |
|---|
| 172 | +static bool __prombss prom_radix_gtse_disable; |
|---|
| 173 | +static bool __prombss prom_xive_disable; |
|---|
| 174 | +#endif |
|---|
| 175 | + |
|---|
| 176 | +#ifdef CONFIG_PPC_SVM |
|---|
| 177 | +static bool __prombss prom_svm_enable; |
|---|
| 178 | +#endif |
|---|
| 174 | 179 | |
|---|
| 175 | 180 | struct platform_support { |
|---|
| 176 | 181 | bool hash_mmu; |
|---|
| .. | .. |
|---|
| 188 | 193 | #define PLATFORM_LPAR 0x0001 |
|---|
| 189 | 194 | #define PLATFORM_POWERMAC 0x0400 |
|---|
| 190 | 195 | #define PLATFORM_GENERIC 0x0500 |
|---|
| 191 | | -#define PLATFORM_OPAL 0x0600 |
|---|
| 192 | 196 | |
|---|
| 193 | | -static int __initdata of_platform; |
|---|
| 197 | +static int __prombss of_platform; |
|---|
| 194 | 198 | |
|---|
| 195 | | -static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; |
|---|
| 199 | +static char __prombss prom_cmd_line[COMMAND_LINE_SIZE]; |
|---|
| 196 | 200 | |
|---|
| 197 | | -static unsigned long __initdata prom_memory_limit; |
|---|
| 201 | +static unsigned long __prombss prom_memory_limit; |
|---|
| 198 | 202 | |
|---|
| 199 | | -static unsigned long __initdata alloc_top; |
|---|
| 200 | | -static unsigned long __initdata alloc_top_high; |
|---|
| 201 | | -static unsigned long __initdata alloc_bottom; |
|---|
| 202 | | -static unsigned long __initdata rmo_top; |
|---|
| 203 | | -static unsigned long __initdata ram_top; |
|---|
| 203 | +static unsigned long __prombss alloc_top; |
|---|
| 204 | +static unsigned long __prombss alloc_top_high; |
|---|
| 205 | +static unsigned long __prombss alloc_bottom; |
|---|
| 206 | +static unsigned long __prombss rmo_top; |
|---|
| 207 | +static unsigned long __prombss ram_top; |
|---|
| 204 | 208 | |
|---|
| 205 | | -static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; |
|---|
| 206 | | -static int __initdata mem_reserve_cnt; |
|---|
| 209 | +static struct mem_map_entry __prombss mem_reserve_map[MEM_RESERVE_MAP_SIZE]; |
|---|
| 210 | +static int __prombss mem_reserve_cnt; |
|---|
| 207 | 211 | |
|---|
| 208 | | -static cell_t __initdata regbuf[1024]; |
|---|
| 212 | +static cell_t __prombss regbuf[1024]; |
|---|
| 209 | 213 | |
|---|
| 210 | | -static bool rtas_has_query_cpu_stopped; |
|---|
| 214 | +static bool __prombss rtas_has_query_cpu_stopped; |
|---|
| 211 | 215 | |
|---|
| 212 | 216 | |
|---|
| 213 | 217 | /* |
|---|
| .. | .. |
|---|
| 221 | 225 | #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) |
|---|
| 222 | 226 | #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) |
|---|
| 223 | 227 | |
|---|
| 228 | +/* Copied from lib/string.c and lib/kstrtox.c */ |
|---|
| 229 | + |
|---|
| 230 | +static int __init prom_strcmp(const char *cs, const char *ct) |
|---|
| 231 | +{ |
|---|
| 232 | + unsigned char c1, c2; |
|---|
| 233 | + |
|---|
| 234 | + while (1) { |
|---|
| 235 | + c1 = *cs++; |
|---|
| 236 | + c2 = *ct++; |
|---|
| 237 | + if (c1 != c2) |
|---|
| 238 | + return c1 < c2 ? -1 : 1; |
|---|
| 239 | + if (!c1) |
|---|
| 240 | + break; |
|---|
| 241 | + } |
|---|
| 242 | + return 0; |
|---|
| 243 | +} |
|---|
| 244 | + |
|---|
| 245 | +static char __init *prom_strcpy(char *dest, const char *src) |
|---|
| 246 | +{ |
|---|
| 247 | + char *tmp = dest; |
|---|
| 248 | + |
|---|
| 249 | + while ((*dest++ = *src++) != '\0') |
|---|
| 250 | + /* nothing */; |
|---|
| 251 | + return tmp; |
|---|
| 252 | +} |
|---|
| 253 | + |
|---|
| 254 | +static int __init prom_strncmp(const char *cs, const char *ct, size_t count) |
|---|
| 255 | +{ |
|---|
| 256 | + unsigned char c1, c2; |
|---|
| 257 | + |
|---|
| 258 | + while (count) { |
|---|
| 259 | + c1 = *cs++; |
|---|
| 260 | + c2 = *ct++; |
|---|
| 261 | + if (c1 != c2) |
|---|
| 262 | + return c1 < c2 ? -1 : 1; |
|---|
| 263 | + if (!c1) |
|---|
| 264 | + break; |
|---|
| 265 | + count--; |
|---|
| 266 | + } |
|---|
| 267 | + return 0; |
|---|
| 268 | +} |
|---|
| 269 | + |
|---|
| 270 | +static size_t __init prom_strlen(const char *s) |
|---|
| 271 | +{ |
|---|
| 272 | + const char *sc; |
|---|
| 273 | + |
|---|
| 274 | + for (sc = s; *sc != '\0'; ++sc) |
|---|
| 275 | + /* nothing */; |
|---|
| 276 | + return sc - s; |
|---|
| 277 | +} |
|---|
| 278 | + |
|---|
| 279 | +static int __init prom_memcmp(const void *cs, const void *ct, size_t count) |
|---|
| 280 | +{ |
|---|
| 281 | + const unsigned char *su1, *su2; |
|---|
| 282 | + int res = 0; |
|---|
| 283 | + |
|---|
| 284 | + for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) |
|---|
| 285 | + if ((res = *su1 - *su2) != 0) |
|---|
| 286 | + break; |
|---|
| 287 | + return res; |
|---|
| 288 | +} |
|---|
| 289 | + |
|---|
| 290 | +static char __init *prom_strstr(const char *s1, const char *s2) |
|---|
| 291 | +{ |
|---|
| 292 | + size_t l1, l2; |
|---|
| 293 | + |
|---|
| 294 | + l2 = prom_strlen(s2); |
|---|
| 295 | + if (!l2) |
|---|
| 296 | + return (char *)s1; |
|---|
| 297 | + l1 = prom_strlen(s1); |
|---|
| 298 | + while (l1 >= l2) { |
|---|
| 299 | + l1--; |
|---|
| 300 | + if (!prom_memcmp(s1, s2, l2)) |
|---|
| 301 | + return (char *)s1; |
|---|
| 302 | + s1++; |
|---|
| 303 | + } |
|---|
| 304 | + return NULL; |
|---|
| 305 | +} |
|---|
| 306 | + |
|---|
| 307 | +static size_t __init prom_strlcat(char *dest, const char *src, size_t count) |
|---|
| 308 | +{ |
|---|
| 309 | + size_t dsize = prom_strlen(dest); |
|---|
| 310 | + size_t len = prom_strlen(src); |
|---|
| 311 | + size_t res = dsize + len; |
|---|
| 312 | + |
|---|
| 313 | + /* This would be a bug */ |
|---|
| 314 | + if (dsize >= count) |
|---|
| 315 | + return count; |
|---|
| 316 | + |
|---|
| 317 | + dest += dsize; |
|---|
| 318 | + count -= dsize; |
|---|
| 319 | + if (len >= count) |
|---|
| 320 | + len = count-1; |
|---|
| 321 | + memcpy(dest, src, len); |
|---|
| 322 | + dest[len] = 0; |
|---|
| 323 | + return res; |
|---|
| 324 | + |
|---|
| 325 | +} |
|---|
| 326 | + |
|---|
| 327 | +#ifdef CONFIG_PPC_PSERIES |
|---|
| 328 | +static int __init prom_strtobool(const char *s, bool *res) |
|---|
| 329 | +{ |
|---|
| 330 | + if (!s) |
|---|
| 331 | + return -EINVAL; |
|---|
| 332 | + |
|---|
| 333 | + switch (s[0]) { |
|---|
| 334 | + case 'y': |
|---|
| 335 | + case 'Y': |
|---|
| 336 | + case '1': |
|---|
| 337 | + *res = true; |
|---|
| 338 | + return 0; |
|---|
| 339 | + case 'n': |
|---|
| 340 | + case 'N': |
|---|
| 341 | + case '0': |
|---|
| 342 | + *res = false; |
|---|
| 343 | + return 0; |
|---|
| 344 | + case 'o': |
|---|
| 345 | + case 'O': |
|---|
| 346 | + switch (s[1]) { |
|---|
| 347 | + case 'n': |
|---|
| 348 | + case 'N': |
|---|
| 349 | + *res = true; |
|---|
| 350 | + return 0; |
|---|
| 351 | + case 'f': |
|---|
| 352 | + case 'F': |
|---|
| 353 | + *res = false; |
|---|
| 354 | + return 0; |
|---|
| 355 | + default: |
|---|
| 356 | + break; |
|---|
| 357 | + } |
|---|
| 358 | + default: |
|---|
| 359 | + break; |
|---|
| 360 | + } |
|---|
| 361 | + |
|---|
| 362 | + return -EINVAL; |
|---|
| 363 | +} |
|---|
| 364 | +#endif |
|---|
| 224 | 365 | |
|---|
| 225 | 366 | /* This is the one and *ONLY* place where we actually call open |
|---|
| 226 | 367 | * firmware. |
|---|
| .. | .. |
|---|
| 498 | 639 | } |
|---|
| 499 | 640 | } |
|---|
| 500 | 641 | |
|---|
| 501 | | -static inline int prom_getprop(phandle node, const char *pname, |
|---|
| 502 | | - void *value, size_t valuelen) |
|---|
| 642 | +static inline int __init prom_getprop(phandle node, const char *pname, |
|---|
| 643 | + void *value, size_t valuelen) |
|---|
| 503 | 644 | { |
|---|
| 504 | 645 | return call_prom("getprop", 4, 1, node, ADDR(pname), |
|---|
| 505 | 646 | (u32)(unsigned long) value, (u32) valuelen); |
|---|
| 506 | 647 | } |
|---|
| 507 | 648 | |
|---|
| 508 | | -static inline int prom_getproplen(phandle node, const char *pname) |
|---|
| 649 | +static inline int __init prom_getproplen(phandle node, const char *pname) |
|---|
| 509 | 650 | { |
|---|
| 510 | 651 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); |
|---|
| 511 | 652 | } |
|---|
| .. | .. |
|---|
| 522 | 663 | |
|---|
| 523 | 664 | static char *tohex(unsigned int x) |
|---|
| 524 | 665 | { |
|---|
| 525 | | - static char digits[] = "0123456789abcdef"; |
|---|
| 526 | | - static char result[9]; |
|---|
| 666 | + static const char digits[] __initconst = "0123456789abcdef"; |
|---|
| 667 | + static char result[9] __prombss; |
|---|
| 527 | 668 | int i; |
|---|
| 528 | 669 | |
|---|
| 529 | 670 | result[8] = 0; |
|---|
| .. | .. |
|---|
| 552 | 693 | add_string(&p, tohex((u32)(unsigned long) value)); |
|---|
| 553 | 694 | add_string(&p, tohex(valuelen)); |
|---|
| 554 | 695 | add_string(&p, tohex(ADDR(pname))); |
|---|
| 555 | | - add_string(&p, tohex(strlen(pname))); |
|---|
| 696 | + add_string(&p, tohex(prom_strlen(pname))); |
|---|
| 556 | 697 | add_string(&p, "property"); |
|---|
| 557 | 698 | *p = 0; |
|---|
| 558 | 699 | return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd); |
|---|
| .. | .. |
|---|
| 628 | 769 | const char *opt; |
|---|
| 629 | 770 | |
|---|
| 630 | 771 | char *p; |
|---|
| 631 | | - int l __maybe_unused = 0; |
|---|
| 772 | + int l = 0; |
|---|
| 632 | 773 | |
|---|
| 633 | 774 | prom_cmd_line[0] = 0; |
|---|
| 634 | 775 | p = prom_cmd_line; |
|---|
| 635 | | - if ((long)prom.chosen > 0) |
|---|
| 776 | + |
|---|
| 777 | + if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && (long)prom.chosen > 0) |
|---|
| 636 | 778 | l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1); |
|---|
| 637 | | -#ifdef CONFIG_CMDLINE |
|---|
| 638 | | - if (l <= 0 || p[0] == '\0') /* dbl check */ |
|---|
| 639 | | - strlcpy(prom_cmd_line, |
|---|
| 640 | | - CONFIG_CMDLINE, sizeof(prom_cmd_line)); |
|---|
| 641 | | -#endif /* CONFIG_CMDLINE */ |
|---|
| 779 | + |
|---|
| 780 | + if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || l <= 0 || p[0] == '\0') |
|---|
| 781 | + prom_strlcat(prom_cmd_line, " " CONFIG_CMDLINE, |
|---|
| 782 | + sizeof(prom_cmd_line)); |
|---|
| 783 | + |
|---|
| 642 | 784 | prom_printf("command line: %s\n", prom_cmd_line); |
|---|
| 643 | 785 | |
|---|
| 644 | 786 | #ifdef CONFIG_PPC64 |
|---|
| 645 | | - opt = strstr(prom_cmd_line, "iommu="); |
|---|
| 787 | + opt = prom_strstr(prom_cmd_line, "iommu="); |
|---|
| 646 | 788 | if (opt) { |
|---|
| 647 | 789 | prom_printf("iommu opt is: %s\n", opt); |
|---|
| 648 | 790 | opt += 6; |
|---|
| 649 | 791 | while (*opt && *opt == ' ') |
|---|
| 650 | 792 | opt++; |
|---|
| 651 | | - if (!strncmp(opt, "off", 3)) |
|---|
| 793 | + if (!prom_strncmp(opt, "off", 3)) |
|---|
| 652 | 794 | prom_iommu_off = 1; |
|---|
| 653 | | - else if (!strncmp(opt, "force", 5)) |
|---|
| 795 | + else if (!prom_strncmp(opt, "force", 5)) |
|---|
| 654 | 796 | prom_iommu_force_on = 1; |
|---|
| 655 | 797 | } |
|---|
| 656 | 798 | #endif |
|---|
| 657 | | - opt = strstr(prom_cmd_line, "mem="); |
|---|
| 799 | + opt = prom_strstr(prom_cmd_line, "mem="); |
|---|
| 658 | 800 | if (opt) { |
|---|
| 659 | 801 | opt += 4; |
|---|
| 660 | 802 | prom_memory_limit = prom_memparse(opt, (const char **)&opt); |
|---|
| .. | .. |
|---|
| 664 | 806 | #endif |
|---|
| 665 | 807 | } |
|---|
| 666 | 808 | |
|---|
| 667 | | - opt = strstr(prom_cmd_line, "disable_radix"); |
|---|
| 809 | +#ifdef CONFIG_PPC_PSERIES |
|---|
| 810 | + prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); |
|---|
| 811 | + opt = prom_strstr(prom_cmd_line, "disable_radix"); |
|---|
| 668 | 812 | if (opt) { |
|---|
| 669 | 813 | opt += 13; |
|---|
| 670 | 814 | if (*opt && *opt == '=') { |
|---|
| 671 | 815 | bool val; |
|---|
| 672 | 816 | |
|---|
| 673 | | - if (kstrtobool(++opt, &val)) |
|---|
| 817 | + if (prom_strtobool(++opt, &val)) |
|---|
| 674 | 818 | prom_radix_disable = false; |
|---|
| 675 | 819 | else |
|---|
| 676 | 820 | prom_radix_disable = val; |
|---|
| .. | .. |
|---|
| 679 | 823 | } |
|---|
| 680 | 824 | if (prom_radix_disable) |
|---|
| 681 | 825 | prom_debug("Radix disabled from cmdline\n"); |
|---|
| 826 | + |
|---|
| 827 | + opt = prom_strstr(prom_cmd_line, "radix_hcall_invalidate=on"); |
|---|
| 828 | + if (opt) { |
|---|
| 829 | + prom_radix_gtse_disable = true; |
|---|
| 830 | + prom_debug("Radix GTSE disabled from cmdline\n"); |
|---|
| 831 | + } |
|---|
| 832 | + |
|---|
| 833 | + opt = prom_strstr(prom_cmd_line, "xive=off"); |
|---|
| 834 | + if (opt) { |
|---|
| 835 | + prom_xive_disable = true; |
|---|
| 836 | + prom_debug("XIVE disabled from cmdline\n"); |
|---|
| 837 | + } |
|---|
| 838 | +#endif /* CONFIG_PPC_PSERIES */ |
|---|
| 839 | + |
|---|
| 840 | +#ifdef CONFIG_PPC_SVM |
|---|
| 841 | + opt = prom_strstr(prom_cmd_line, "svm="); |
|---|
| 842 | + if (opt) { |
|---|
| 843 | + bool val; |
|---|
| 844 | + |
|---|
| 845 | + opt += sizeof("svm=") - 1; |
|---|
| 846 | + if (!prom_strtobool(opt, &val)) |
|---|
| 847 | + prom_svm_enable = val; |
|---|
| 848 | + } |
|---|
| 849 | +#endif /* CONFIG_PPC_SVM */ |
|---|
| 682 | 850 | } |
|---|
| 683 | 851 | |
|---|
| 684 | | -#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) |
|---|
| 852 | +#ifdef CONFIG_PPC_PSERIES |
|---|
| 685 | 853 | /* |
|---|
| 686 | 854 | * The architecture vector has an array of PVR mask/value pairs, |
|---|
| 687 | 855 | * followed by # option vectors - 1, followed by the option vectors. |
|---|
| .. | .. |
|---|
| 759 | 927 | } __packed; |
|---|
| 760 | 928 | |
|---|
| 761 | 929 | struct ibm_arch_vec { |
|---|
| 762 | | - struct { u32 mask, val; } pvrs[12]; |
|---|
| 930 | + struct { u32 mask, val; } pvrs[14]; |
|---|
| 763 | 931 | |
|---|
| 764 | 932 | u8 num_vectors; |
|---|
| 765 | 933 | |
|---|
| .. | .. |
|---|
| 782 | 950 | struct option_vector6 vec6; |
|---|
| 783 | 951 | } __packed; |
|---|
| 784 | 952 | |
|---|
| 785 | | -struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = { |
|---|
| 953 | +static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = { |
|---|
| 786 | 954 | .pvrs = { |
|---|
| 787 | 955 | { |
|---|
| 788 | 956 | .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */ |
|---|
| .. | .. |
|---|
| 813 | 981 | .val = cpu_to_be32(0x004e0000), |
|---|
| 814 | 982 | }, |
|---|
| 815 | 983 | { |
|---|
| 984 | + .mask = cpu_to_be32(0xffff0000), /* POWER10 */ |
|---|
| 985 | + .val = cpu_to_be32(0x00800000), |
|---|
| 986 | + }, |
|---|
| 987 | + { |
|---|
| 988 | + .mask = cpu_to_be32(0xffffffff), /* all 3.1-compliant */ |
|---|
| 989 | + .val = cpu_to_be32(0x0f000006), |
|---|
| 990 | + }, |
|---|
| 991 | + { |
|---|
| 816 | 992 | .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */ |
|---|
| 817 | 993 | .val = cpu_to_be32(0x0f000005), |
|---|
| 818 | 994 | }, |
|---|
| .. | .. |
|---|
| 841 | 1017 | .byte1 = 0, |
|---|
| 842 | 1018 | .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 | |
|---|
| 843 | 1019 | OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07, |
|---|
| 844 | | - .arch_versions3 = OV1_PPC_3_00, |
|---|
| 1020 | + .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1, |
|---|
| 845 | 1021 | }, |
|---|
| 846 | 1022 | |
|---|
| 847 | 1023 | .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)), |
|---|
| .. | .. |
|---|
| 893 | 1069 | #else |
|---|
| 894 | 1070 | 0, |
|---|
| 895 | 1071 | #endif |
|---|
| 896 | | - .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN), |
|---|
| 1072 | + .associativity = OV5_FEAT(OV5_FORM1_AFFINITY) | OV5_FEAT(OV5_PRRN) | |
|---|
| 1073 | + OV5_FEAT(OV5_FORM2_AFFINITY), |
|---|
| 897 | 1074 | .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT), |
|---|
| 898 | 1075 | .micro_checkpoint = 0, |
|---|
| 899 | 1076 | .reserved0 = 0, |
|---|
| .. | .. |
|---|
| 920 | 1097 | }, |
|---|
| 921 | 1098 | }; |
|---|
| 922 | 1099 | |
|---|
| 1100 | +static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned; |
|---|
| 1101 | + |
|---|
| 923 | 1102 | /* Old method - ELF header with PT_NOTE sections only works on BE */ |
|---|
| 924 | 1103 | #ifdef __BIG_ENDIAN__ |
|---|
| 925 | | -static struct fake_elf { |
|---|
| 1104 | +static const struct fake_elf { |
|---|
| 926 | 1105 | Elf32_Ehdr elfhdr; |
|---|
| 927 | 1106 | Elf32_Phdr phdr[2]; |
|---|
| 928 | 1107 | struct chrpnote { |
|---|
| .. | .. |
|---|
| 955 | 1134 | u32 ignore_me; |
|---|
| 956 | 1135 | } rpadesc; |
|---|
| 957 | 1136 | } rpanote; |
|---|
| 958 | | -} fake_elf = { |
|---|
| 1137 | +} fake_elf __initconst = { |
|---|
| 959 | 1138 | .elfhdr = { |
|---|
| 960 | 1139 | .e_ident = { 0x7f, 'E', 'L', 'F', |
|---|
| 961 | 1140 | ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, |
|---|
| .. | .. |
|---|
| 1020 | 1199 | type[0] = 0; |
|---|
| 1021 | 1200 | prom_getprop(node, "device_type", type, sizeof(type)); |
|---|
| 1022 | 1201 | |
|---|
| 1023 | | - if (strcmp(type, "cpu")) |
|---|
| 1202 | + if (prom_strcmp(type, "cpu")) |
|---|
| 1024 | 1203 | continue; |
|---|
| 1025 | 1204 | /* |
|---|
| 1026 | 1205 | * There is an entry for each smt thread, each entry being |
|---|
| .. | .. |
|---|
| 1084 | 1263 | switch (val) { |
|---|
| 1085 | 1264 | case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */ |
|---|
| 1086 | 1265 | prom_debug("XIVE - either mode supported\n"); |
|---|
| 1087 | | - support->xive = true; |
|---|
| 1266 | + support->xive = !prom_xive_disable; |
|---|
| 1088 | 1267 | break; |
|---|
| 1089 | 1268 | case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */ |
|---|
| 1090 | 1269 | prom_debug("XIVE - exploitation mode supported\n"); |
|---|
| 1270 | + if (prom_xive_disable) { |
|---|
| 1271 | + /* |
|---|
| 1272 | + * If we __have__ to do XIVE, we're better off ignoring |
|---|
| 1273 | + * the command line rather than not booting. |
|---|
| 1274 | + */ |
|---|
| 1275 | + prom_printf("WARNING: Ignoring cmdline option xive=off\n"); |
|---|
| 1276 | + } |
|---|
| 1091 | 1277 | support->xive = true; |
|---|
| 1092 | 1278 | break; |
|---|
| 1093 | 1279 | case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */ |
|---|
| .. | .. |
|---|
| 1107 | 1293 | prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support); |
|---|
| 1108 | 1294 | break; |
|---|
| 1109 | 1295 | case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */ |
|---|
| 1110 | | - if (val & OV5_FEAT(OV5_RADIX_GTSE)) { |
|---|
| 1111 | | - prom_debug("Radix - GTSE supported\n"); |
|---|
| 1112 | | - support->radix_gtse = true; |
|---|
| 1113 | | - } |
|---|
| 1296 | + if (val & OV5_FEAT(OV5_RADIX_GTSE)) |
|---|
| 1297 | + support->radix_gtse = !prom_radix_gtse_disable; |
|---|
| 1114 | 1298 | break; |
|---|
| 1115 | 1299 | case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */ |
|---|
| 1116 | 1300 | prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT), |
|---|
| .. | .. |
|---|
| 1129 | 1313 | }; |
|---|
| 1130 | 1314 | int prop_len = prom_getproplen(prom.chosen, |
|---|
| 1131 | 1315 | "ibm,arch-vec-5-platform-support"); |
|---|
| 1316 | + |
|---|
| 1317 | + /* |
|---|
| 1318 | + * First copy the architecture vec template |
|---|
| 1319 | + * |
|---|
| 1320 | + * use memcpy() instead of *vec = *vec_template so that GCC replaces it |
|---|
| 1321 | + * by __memcpy() when KASAN is active |
|---|
| 1322 | + */ |
|---|
| 1323 | + memcpy(&ibm_architecture_vec, &ibm_architecture_vec_template, |
|---|
| 1324 | + sizeof(ibm_architecture_vec)); |
|---|
| 1325 | + |
|---|
| 1132 | 1326 | if (prop_len > 1) { |
|---|
| 1133 | 1327 | int i; |
|---|
| 1134 | | - u8 vec[prop_len]; |
|---|
| 1328 | + u8 vec[8]; |
|---|
| 1135 | 1329 | prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n", |
|---|
| 1136 | 1330 | prop_len); |
|---|
| 1137 | | - prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", |
|---|
| 1138 | | - &vec, sizeof(vec)); |
|---|
| 1331 | + if (prop_len > sizeof(vec)) |
|---|
| 1332 | + prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n", |
|---|
| 1333 | + prop_len); |
|---|
| 1334 | + prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", &vec, sizeof(vec)); |
|---|
| 1139 | 1335 | for (i = 0; i < prop_len; i += 2) { |
|---|
| 1140 | | - prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2 |
|---|
| 1141 | | - , vec[i] |
|---|
| 1142 | | - , vec[i + 1]); |
|---|
| 1143 | | - prom_parse_platform_support(vec[i], vec[i + 1], |
|---|
| 1144 | | - &supported); |
|---|
| 1336 | + prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2, vec[i], vec[i + 1]); |
|---|
| 1337 | + prom_parse_platform_support(vec[i], vec[i + 1], &supported); |
|---|
| 1145 | 1338 | } |
|---|
| 1146 | 1339 | } |
|---|
| 1147 | 1340 | |
|---|
| 1148 | | - if (supported.radix_mmu && supported.radix_gtse && |
|---|
| 1149 | | - IS_ENABLED(CONFIG_PPC_RADIX_MMU)) { |
|---|
| 1150 | | - /* Radix preferred - but we require GTSE for now */ |
|---|
| 1151 | | - prom_debug("Asking for radix with GTSE\n"); |
|---|
| 1341 | + if (supported.radix_mmu && IS_ENABLED(CONFIG_PPC_RADIX_MMU)) { |
|---|
| 1342 | + /* Radix preferred - Check if GTSE is also supported */ |
|---|
| 1343 | + prom_debug("Asking for radix\n"); |
|---|
| 1152 | 1344 | ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX); |
|---|
| 1153 | | - ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE); |
|---|
| 1345 | + if (supported.radix_gtse) |
|---|
| 1346 | + ibm_architecture_vec.vec5.radix_ext = |
|---|
| 1347 | + OV5_FEAT(OV5_RADIX_GTSE); |
|---|
| 1348 | + else |
|---|
| 1349 | + prom_debug("Radix GTSE isn't supported\n"); |
|---|
| 1154 | 1350 | } else if (supported.hash_mmu) { |
|---|
| 1155 | 1351 | /* Default to hash mmu (if we can) */ |
|---|
| 1156 | 1352 | prom_debug("Asking for hash\n"); |
|---|
| .. | .. |
|---|
| 1225 | 1421 | } |
|---|
| 1226 | 1422 | #endif /* __BIG_ENDIAN__ */ |
|---|
| 1227 | 1423 | } |
|---|
| 1228 | | -#endif /* #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */ |
|---|
| 1424 | +#endif /* CONFIG_PPC_PSERIES */ |
|---|
| 1229 | 1425 | |
|---|
| 1230 | 1426 | /* |
|---|
| 1231 | 1427 | * Memory allocation strategy... our layout is normally: |
|---|
| .. | .. |
|---|
| 1266 | 1462 | unsigned long addr = 0; |
|---|
| 1267 | 1463 | |
|---|
| 1268 | 1464 | if (align) |
|---|
| 1269 | | - base = _ALIGN_UP(base, align); |
|---|
| 1465 | + base = ALIGN(base, align); |
|---|
| 1270 | 1466 | prom_debug("%s(%lx, %lx)\n", __func__, size, align); |
|---|
| 1271 | 1467 | if (ram_top == 0) |
|---|
| 1272 | 1468 | prom_panic("alloc_up() called with mem not initialized\n"); |
|---|
| 1273 | 1469 | |
|---|
| 1274 | 1470 | if (align) |
|---|
| 1275 | | - base = _ALIGN_UP(alloc_bottom, align); |
|---|
| 1471 | + base = ALIGN(alloc_bottom, align); |
|---|
| 1276 | 1472 | else |
|---|
| 1277 | 1473 | base = alloc_bottom; |
|---|
| 1278 | 1474 | |
|---|
| 1279 | 1475 | for(; (base + size) <= alloc_top; |
|---|
| 1280 | | - base = _ALIGN_UP(base + 0x100000, align)) { |
|---|
| 1476 | + base = ALIGN(base + 0x100000, align)) { |
|---|
| 1281 | 1477 | prom_debug(" trying: 0x%lx\n\r", base); |
|---|
| 1282 | 1478 | addr = (unsigned long)prom_claim(base, size, 0); |
|---|
| 1283 | 1479 | if (addr != PROM_ERROR && addr != 0) |
|---|
| .. | .. |
|---|
| 1317 | 1513 | |
|---|
| 1318 | 1514 | if (highmem) { |
|---|
| 1319 | 1515 | /* Carve out storage for the TCE table. */ |
|---|
| 1320 | | - addr = _ALIGN_DOWN(alloc_top_high - size, align); |
|---|
| 1516 | + addr = ALIGN_DOWN(alloc_top_high - size, align); |
|---|
| 1321 | 1517 | if (addr <= alloc_bottom) |
|---|
| 1322 | 1518 | return 0; |
|---|
| 1323 | 1519 | /* Will we bump into the RMO ? If yes, check out that we |
|---|
| .. | .. |
|---|
| 1335 | 1531 | goto bail; |
|---|
| 1336 | 1532 | } |
|---|
| 1337 | 1533 | |
|---|
| 1338 | | - base = _ALIGN_DOWN(alloc_top - size, align); |
|---|
| 1534 | + base = ALIGN_DOWN(alloc_top - size, align); |
|---|
| 1339 | 1535 | for (; base > alloc_bottom; |
|---|
| 1340 | | - base = _ALIGN_DOWN(base - 0x100000, align)) { |
|---|
| 1536 | + base = ALIGN_DOWN(base - 0x100000, align)) { |
|---|
| 1341 | 1537 | prom_debug(" trying: 0x%lx\n\r", base); |
|---|
| 1342 | 1538 | addr = (unsigned long)prom_claim(base, size, 0); |
|---|
| 1343 | 1539 | if (addr != PROM_ERROR && addr != 0) |
|---|
| .. | .. |
|---|
| 1403 | 1599 | * have our terminator with "size" set to 0 since we are |
|---|
| 1404 | 1600 | * dumb and just copy this entire array to the boot params |
|---|
| 1405 | 1601 | */ |
|---|
| 1406 | | - base = _ALIGN_DOWN(base, PAGE_SIZE); |
|---|
| 1407 | | - top = _ALIGN_UP(top, PAGE_SIZE); |
|---|
| 1602 | + base = ALIGN_DOWN(base, PAGE_SIZE); |
|---|
| 1603 | + top = ALIGN(top, PAGE_SIZE); |
|---|
| 1408 | 1604 | size = top - base; |
|---|
| 1409 | 1605 | |
|---|
| 1410 | 1606 | if (cnt >= (MEM_RESERVE_MAP_SIZE - 1)) |
|---|
| .. | .. |
|---|
| 1421 | 1617 | static void __init prom_init_mem(void) |
|---|
| 1422 | 1618 | { |
|---|
| 1423 | 1619 | phandle node; |
|---|
| 1424 | | -#ifdef DEBUG_PROM |
|---|
| 1425 | | - char *path; |
|---|
| 1426 | | -#endif |
|---|
| 1427 | 1620 | char type[64]; |
|---|
| 1428 | 1621 | unsigned int plen; |
|---|
| 1429 | 1622 | cell_t *p, *endp; |
|---|
| .. | .. |
|---|
| 1445 | 1638 | prom_debug("root_size_cells: %x\n", rsc); |
|---|
| 1446 | 1639 | |
|---|
| 1447 | 1640 | prom_debug("scanning memory:\n"); |
|---|
| 1448 | | -#ifdef DEBUG_PROM |
|---|
| 1449 | | - path = prom_scratch; |
|---|
| 1450 | | -#endif |
|---|
| 1451 | 1641 | |
|---|
| 1452 | 1642 | for (node = 0; prom_next_node(&node); ) { |
|---|
| 1453 | 1643 | type[0] = 0; |
|---|
| .. | .. |
|---|
| 1460 | 1650 | */ |
|---|
| 1461 | 1651 | prom_getprop(node, "name", type, sizeof(type)); |
|---|
| 1462 | 1652 | } |
|---|
| 1463 | | - if (strcmp(type, "memory")) |
|---|
| 1653 | + if (prom_strcmp(type, "memory")) |
|---|
| 1464 | 1654 | continue; |
|---|
| 1465 | 1655 | |
|---|
| 1466 | 1656 | plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf)); |
|---|
| .. | .. |
|---|
| 1472 | 1662 | endp = p + (plen / sizeof(cell_t)); |
|---|
| 1473 | 1663 | |
|---|
| 1474 | 1664 | #ifdef DEBUG_PROM |
|---|
| 1475 | | - memset(path, 0, PROM_SCRATCH_SIZE); |
|---|
| 1476 | | - call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); |
|---|
| 1477 | | - prom_debug(" node %s :\n", path); |
|---|
| 1665 | + memset(prom_scratch, 0, sizeof(prom_scratch)); |
|---|
| 1666 | + call_prom("package-to-path", 3, 1, node, prom_scratch, |
|---|
| 1667 | + sizeof(prom_scratch) - 1); |
|---|
| 1668 | + prom_debug(" node %s :\n", prom_scratch); |
|---|
| 1478 | 1669 | #endif /* DEBUG_PROM */ |
|---|
| 1479 | 1670 | |
|---|
| 1480 | 1671 | while ((endp - p) >= (rac + rsc)) { |
|---|
| .. | .. |
|---|
| 1562 | 1753 | } |
|---|
| 1563 | 1754 | } |
|---|
| 1564 | 1755 | |
|---|
| 1565 | | -#ifdef CONFIG_PPC_POWERNV |
|---|
| 1566 | | - |
|---|
| 1567 | | -#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL |
|---|
| 1568 | | -static u64 __initdata prom_opal_base; |
|---|
| 1569 | | -static u64 __initdata prom_opal_entry; |
|---|
| 1570 | | -#endif |
|---|
| 1571 | | - |
|---|
| 1572 | | -/* |
|---|
| 1573 | | - * Allocate room for and instantiate OPAL |
|---|
| 1574 | | - */ |
|---|
| 1575 | | -static void __init prom_instantiate_opal(void) |
|---|
| 1756 | +#ifdef CONFIG_PPC_SVM |
|---|
| 1757 | +static int prom_rtas_hcall(uint64_t args) |
|---|
| 1576 | 1758 | { |
|---|
| 1577 | | - phandle opal_node; |
|---|
| 1578 | | - ihandle opal_inst; |
|---|
| 1579 | | - u64 base, entry; |
|---|
| 1580 | | - u64 size = 0, align = 0x10000; |
|---|
| 1581 | | - __be64 val64; |
|---|
| 1582 | | - u32 rets[2]; |
|---|
| 1759 | + register uint64_t arg1 asm("r3") = H_RTAS; |
|---|
| 1760 | + register uint64_t arg2 asm("r4") = args; |
|---|
| 1583 | 1761 | |
|---|
| 1584 | | - prom_debug("prom_instantiate_opal: start...\n"); |
|---|
| 1585 | | - |
|---|
| 1586 | | - opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal")); |
|---|
| 1587 | | - prom_debug("opal_node: %x\n", opal_node); |
|---|
| 1588 | | - if (!PHANDLE_VALID(opal_node)) |
|---|
| 1589 | | - return; |
|---|
| 1590 | | - |
|---|
| 1591 | | - val64 = 0; |
|---|
| 1592 | | - prom_getprop(opal_node, "opal-runtime-size", &val64, sizeof(val64)); |
|---|
| 1593 | | - size = be64_to_cpu(val64); |
|---|
| 1594 | | - if (size == 0) |
|---|
| 1595 | | - return; |
|---|
| 1596 | | - val64 = 0; |
|---|
| 1597 | | - prom_getprop(opal_node, "opal-runtime-alignment", &val64,sizeof(val64)); |
|---|
| 1598 | | - align = be64_to_cpu(val64); |
|---|
| 1599 | | - |
|---|
| 1600 | | - base = alloc_down(size, align, 0); |
|---|
| 1601 | | - if (base == 0) { |
|---|
| 1602 | | - prom_printf("OPAL allocation failed !\n"); |
|---|
| 1603 | | - return; |
|---|
| 1604 | | - } |
|---|
| 1605 | | - |
|---|
| 1606 | | - opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal")); |
|---|
| 1607 | | - if (!IHANDLE_VALID(opal_inst)) { |
|---|
| 1608 | | - prom_printf("opening opal package failed (%x)\n", opal_inst); |
|---|
| 1609 | | - return; |
|---|
| 1610 | | - } |
|---|
| 1611 | | - |
|---|
| 1612 | | - prom_printf("instantiating opal at 0x%llx...", base); |
|---|
| 1613 | | - |
|---|
| 1614 | | - if (call_prom_ret("call-method", 4, 3, rets, |
|---|
| 1615 | | - ADDR("load-opal-runtime"), |
|---|
| 1616 | | - opal_inst, |
|---|
| 1617 | | - base >> 32, base & 0xffffffff) != 0 |
|---|
| 1618 | | - || (rets[0] == 0 && rets[1] == 0)) { |
|---|
| 1619 | | - prom_printf(" failed\n"); |
|---|
| 1620 | | - return; |
|---|
| 1621 | | - } |
|---|
| 1622 | | - entry = (((u64)rets[0]) << 32) | rets[1]; |
|---|
| 1623 | | - |
|---|
| 1624 | | - prom_printf(" done\n"); |
|---|
| 1625 | | - |
|---|
| 1626 | | - reserve_mem(base, size); |
|---|
| 1627 | | - |
|---|
| 1628 | | - prom_debug("opal base = 0x%llx\n", base); |
|---|
| 1629 | | - prom_debug("opal align = 0x%llx\n", align); |
|---|
| 1630 | | - prom_debug("opal entry = 0x%llx\n", entry); |
|---|
| 1631 | | - prom_debug("opal size = 0x%llx\n", size); |
|---|
| 1632 | | - |
|---|
| 1633 | | - prom_setprop(opal_node, "/ibm,opal", "opal-base-address", |
|---|
| 1634 | | - &base, sizeof(base)); |
|---|
| 1635 | | - prom_setprop(opal_node, "/ibm,opal", "opal-entry-address", |
|---|
| 1636 | | - &entry, sizeof(entry)); |
|---|
| 1637 | | - |
|---|
| 1638 | | -#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL |
|---|
| 1639 | | - prom_opal_base = base; |
|---|
| 1640 | | - prom_opal_entry = entry; |
|---|
| 1641 | | -#endif |
|---|
| 1642 | | - prom_debug("prom_instantiate_opal: end...\n"); |
|---|
| 1762 | + asm volatile("sc 1\n" : "=r" (arg1) : |
|---|
| 1763 | + "r" (arg1), |
|---|
| 1764 | + "r" (arg2) :); |
|---|
| 1765 | + return arg1; |
|---|
| 1643 | 1766 | } |
|---|
| 1644 | 1767 | |
|---|
| 1645 | | -#endif /* CONFIG_PPC_POWERNV */ |
|---|
| 1768 | +static struct rtas_args __prombss os_term_args; |
|---|
| 1769 | + |
|---|
| 1770 | +static void __init prom_rtas_os_term(char *str) |
|---|
| 1771 | +{ |
|---|
| 1772 | + phandle rtas_node; |
|---|
| 1773 | + __be32 val; |
|---|
| 1774 | + u32 token; |
|---|
| 1775 | + |
|---|
| 1776 | + prom_debug("%s: start...\n", __func__); |
|---|
| 1777 | + rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); |
|---|
| 1778 | + prom_debug("rtas_node: %x\n", rtas_node); |
|---|
| 1779 | + if (!PHANDLE_VALID(rtas_node)) |
|---|
| 1780 | + return; |
|---|
| 1781 | + |
|---|
| 1782 | + val = 0; |
|---|
| 1783 | + prom_getprop(rtas_node, "ibm,os-term", &val, sizeof(val)); |
|---|
| 1784 | + token = be32_to_cpu(val); |
|---|
| 1785 | + prom_debug("ibm,os-term: %x\n", token); |
|---|
| 1786 | + if (token == 0) |
|---|
| 1787 | + prom_panic("Could not get token for ibm,os-term\n"); |
|---|
| 1788 | + os_term_args.token = cpu_to_be32(token); |
|---|
| 1789 | + os_term_args.nargs = cpu_to_be32(1); |
|---|
| 1790 | + os_term_args.nret = cpu_to_be32(1); |
|---|
| 1791 | + os_term_args.args[0] = cpu_to_be32(__pa(str)); |
|---|
| 1792 | + prom_rtas_hcall((uint64_t)&os_term_args); |
|---|
| 1793 | +} |
|---|
| 1794 | +#endif /* CONFIG_PPC_SVM */ |
|---|
| 1646 | 1795 | |
|---|
| 1647 | 1796 | /* |
|---|
| 1648 | 1797 | * Allocate room for and instantiate RTAS |
|---|
| .. | .. |
|---|
| 1823 | 1972 | prom_getprop(node, "device_type", type, sizeof(type)); |
|---|
| 1824 | 1973 | prom_getprop(node, "model", model, sizeof(model)); |
|---|
| 1825 | 1974 | |
|---|
| 1826 | | - if ((type[0] == 0) || (strstr(type, "pci") == NULL)) |
|---|
| 1975 | + if ((type[0] == 0) || (prom_strstr(type, "pci") == NULL)) |
|---|
| 1827 | 1976 | continue; |
|---|
| 1828 | 1977 | |
|---|
| 1829 | 1978 | /* Keep the old logic intact to avoid regression. */ |
|---|
| 1830 | 1979 | if (compatible[0] != 0) { |
|---|
| 1831 | | - if ((strstr(compatible, "python") == NULL) && |
|---|
| 1832 | | - (strstr(compatible, "Speedwagon") == NULL) && |
|---|
| 1833 | | - (strstr(compatible, "Winnipeg") == NULL)) |
|---|
| 1980 | + if ((prom_strstr(compatible, "python") == NULL) && |
|---|
| 1981 | + (prom_strstr(compatible, "Speedwagon") == NULL) && |
|---|
| 1982 | + (prom_strstr(compatible, "Winnipeg") == NULL)) |
|---|
| 1834 | 1983 | continue; |
|---|
| 1835 | 1984 | } else if (model[0] != 0) { |
|---|
| 1836 | | - if ((strstr(model, "ython") == NULL) && |
|---|
| 1837 | | - (strstr(model, "peedwagon") == NULL) && |
|---|
| 1838 | | - (strstr(model, "innipeg") == NULL)) |
|---|
| 1985 | + if ((prom_strstr(model, "ython") == NULL) && |
|---|
| 1986 | + (prom_strstr(model, "peedwagon") == NULL) && |
|---|
| 1987 | + (prom_strstr(model, "innipeg") == NULL)) |
|---|
| 1839 | 1988 | continue; |
|---|
| 1840 | 1989 | } |
|---|
| 1841 | 1990 | |
|---|
| .. | .. |
|---|
| 1863 | 2012 | local_alloc_bottom = base; |
|---|
| 1864 | 2013 | |
|---|
| 1865 | 2014 | /* It seems OF doesn't null-terminate the path :-( */ |
|---|
| 1866 | | - memset(path, 0, PROM_SCRATCH_SIZE); |
|---|
| 2015 | + memset(path, 0, sizeof(prom_scratch)); |
|---|
| 1867 | 2016 | /* Call OF to setup the TCE hardware */ |
|---|
| 1868 | 2017 | if (call_prom("package-to-path", 3, 1, node, |
|---|
| 1869 | | - path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) { |
|---|
| 2018 | + path, sizeof(prom_scratch) - 1) == PROM_ERROR) { |
|---|
| 1870 | 2019 | prom_printf("package-to-path failed\n"); |
|---|
| 1871 | 2020 | } |
|---|
| 1872 | 2021 | |
|---|
| .. | .. |
|---|
| 1984 | 2133 | |
|---|
| 1985 | 2134 | type[0] = 0; |
|---|
| 1986 | 2135 | prom_getprop(node, "device_type", type, sizeof(type)); |
|---|
| 1987 | | - if (strcmp(type, "cpu") != 0) |
|---|
| 2136 | + if (prom_strcmp(type, "cpu") != 0) |
|---|
| 1988 | 2137 | continue; |
|---|
| 1989 | 2138 | |
|---|
| 1990 | 2139 | /* Skip non-configured cpus. */ |
|---|
| 1991 | 2140 | if (prom_getprop(node, "status", type, sizeof(type)) > 0) |
|---|
| 1992 | | - if (strcmp(type, "okay") != 0) |
|---|
| 2141 | + if (prom_strcmp(type, "okay") != 0) |
|---|
| 1993 | 2142 | continue; |
|---|
| 1994 | 2143 | |
|---|
| 1995 | 2144 | reg = cpu_to_be32(-1); /* make sparse happy */ |
|---|
| .. | .. |
|---|
| 2065 | 2214 | return; |
|---|
| 2066 | 2215 | version[sizeof(version) - 1] = 0; |
|---|
| 2067 | 2216 | /* XXX might need to add other versions here */ |
|---|
| 2068 | | - if (strcmp(version, "Open Firmware, 1.0.5") == 0) |
|---|
| 2217 | + if (prom_strcmp(version, "Open Firmware, 1.0.5") == 0) |
|---|
| 2069 | 2218 | of_workarounds = OF_WA_CLAIM; |
|---|
| 2070 | | - else if (strncmp(version, "FirmWorks,3.", 12) == 0) { |
|---|
| 2219 | + else if (prom_strncmp(version, "FirmWorks,3.", 12) == 0) { |
|---|
| 2071 | 2220 | of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL; |
|---|
| 2072 | 2221 | call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim"); |
|---|
| 2073 | 2222 | } else |
|---|
| .. | .. |
|---|
| 2100 | 2249 | call_prom("instance-to-path", 3, 1, prom.stdout, path, 255); |
|---|
| 2101 | 2250 | prom_printf("OF stdout device is: %s\n", of_stdout_device); |
|---|
| 2102 | 2251 | prom_setprop(prom.chosen, "/chosen", "linux,stdout-path", |
|---|
| 2103 | | - path, strlen(path) + 1); |
|---|
| 2252 | + path, prom_strlen(path) + 1); |
|---|
| 2104 | 2253 | |
|---|
| 2105 | 2254 | /* instance-to-package fails on PA-Semi */ |
|---|
| 2106 | 2255 | stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout); |
|---|
| .. | .. |
|---|
| 2110 | 2259 | /* If it's a display, note it */ |
|---|
| 2111 | 2260 | memset(type, 0, sizeof(type)); |
|---|
| 2112 | 2261 | prom_getprop(stdout_node, "device_type", type, sizeof(type)); |
|---|
| 2113 | | - if (strcmp(type, "display") == 0) |
|---|
| 2262 | + if (prom_strcmp(type, "display") == 0) |
|---|
| 2114 | 2263 | prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0); |
|---|
| 2115 | 2264 | } |
|---|
| 2116 | 2265 | } |
|---|
| .. | .. |
|---|
| 2131 | 2280 | compat[len] = 0; |
|---|
| 2132 | 2281 | while (i < len) { |
|---|
| 2133 | 2282 | char *p = &compat[i]; |
|---|
| 2134 | | - int sl = strlen(p); |
|---|
| 2283 | + int sl = prom_strlen(p); |
|---|
| 2135 | 2284 | if (sl == 0) |
|---|
| 2136 | 2285 | break; |
|---|
| 2137 | | - if (strstr(p, "Power Macintosh") || |
|---|
| 2138 | | - strstr(p, "MacRISC")) |
|---|
| 2286 | + if (prom_strstr(p, "Power Macintosh") || |
|---|
| 2287 | + prom_strstr(p, "MacRISC")) |
|---|
| 2139 | 2288 | return PLATFORM_POWERMAC; |
|---|
| 2140 | 2289 | #ifdef CONFIG_PPC64 |
|---|
| 2141 | 2290 | /* We must make sure we don't detect the IBM Cell |
|---|
| 2142 | 2291 | * blades as pSeries due to some firmware issues, |
|---|
| 2143 | 2292 | * so we do it here. |
|---|
| 2144 | 2293 | */ |
|---|
| 2145 | | - if (strstr(p, "IBM,CBEA") || |
|---|
| 2146 | | - strstr(p, "IBM,CPBW-1.0")) |
|---|
| 2294 | + if (prom_strstr(p, "IBM,CBEA") || |
|---|
| 2295 | + prom_strstr(p, "IBM,CPBW-1.0")) |
|---|
| 2147 | 2296 | return PLATFORM_GENERIC; |
|---|
| 2148 | 2297 | #endif /* CONFIG_PPC64 */ |
|---|
| 2149 | 2298 | i += sl + 1; |
|---|
| 2150 | 2299 | } |
|---|
| 2151 | 2300 | } |
|---|
| 2152 | 2301 | #ifdef CONFIG_PPC64 |
|---|
| 2153 | | - /* Try to detect OPAL */ |
|---|
| 2154 | | - if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal")))) |
|---|
| 2155 | | - return PLATFORM_OPAL; |
|---|
| 2156 | | - |
|---|
| 2157 | 2302 | /* Try to figure out if it's an IBM pSeries or any other |
|---|
| 2158 | 2303 | * PAPR compliant platform. We assume it is if : |
|---|
| 2159 | 2304 | * - /device_type is "chrp" (please, do NOT use that for future |
|---|
| .. | .. |
|---|
| 2164 | 2309 | compat, sizeof(compat)-1); |
|---|
| 2165 | 2310 | if (len <= 0) |
|---|
| 2166 | 2311 | return PLATFORM_GENERIC; |
|---|
| 2167 | | - if (strcmp(compat, "chrp")) |
|---|
| 2312 | + if (prom_strcmp(compat, "chrp")) |
|---|
| 2168 | 2313 | return PLATFORM_GENERIC; |
|---|
| 2169 | 2314 | |
|---|
| 2170 | 2315 | /* Default to pSeries. We need to know if we are running LPAR */ |
|---|
| .. | .. |
|---|
| 2202 | 2347 | ihandle ih; |
|---|
| 2203 | 2348 | int i; |
|---|
| 2204 | 2349 | |
|---|
| 2205 | | - static unsigned char default_colors[] = { |
|---|
| 2350 | + static const unsigned char default_colors[] __initconst = { |
|---|
| 2206 | 2351 | 0x00, 0x00, 0x00, |
|---|
| 2207 | 2352 | 0x00, 0x00, 0xaa, |
|---|
| 2208 | 2353 | 0x00, 0xaa, 0x00, |
|---|
| .. | .. |
|---|
| 2226 | 2371 | for (node = 0; prom_next_node(&node); ) { |
|---|
| 2227 | 2372 | memset(type, 0, sizeof(type)); |
|---|
| 2228 | 2373 | prom_getprop(node, "device_type", type, sizeof(type)); |
|---|
| 2229 | | - if (strcmp(type, "display") != 0) |
|---|
| 2374 | + if (prom_strcmp(type, "display") != 0) |
|---|
| 2230 | 2375 | continue; |
|---|
| 2231 | 2376 | |
|---|
| 2232 | 2377 | /* It seems OF doesn't null-terminate the path :-( */ |
|---|
| 2233 | 2378 | path = prom_scratch; |
|---|
| 2234 | | - memset(path, 0, PROM_SCRATCH_SIZE); |
|---|
| 2379 | + memset(path, 0, sizeof(prom_scratch)); |
|---|
| 2235 | 2380 | |
|---|
| 2236 | 2381 | /* |
|---|
| 2237 | 2382 | * leave some room at the end of the path for appending extra |
|---|
| 2238 | 2383 | * arguments |
|---|
| 2239 | 2384 | */ |
|---|
| 2240 | 2385 | if (call_prom("package-to-path", 3, 1, node, path, |
|---|
| 2241 | | - PROM_SCRATCH_SIZE-10) == PROM_ERROR) |
|---|
| 2386 | + sizeof(prom_scratch) - 10) == PROM_ERROR) |
|---|
| 2242 | 2387 | continue; |
|---|
| 2243 | 2388 | prom_printf("found display : %s, opening... ", path); |
|---|
| 2244 | 2389 | |
|---|
| .. | .. |
|---|
| 2274 | 2419 | u32 width, height, pitch, addr; |
|---|
| 2275 | 2420 | |
|---|
| 2276 | 2421 | prom_printf("Setting btext !\n"); |
|---|
| 2277 | | - prom_getprop(node, "width", &width, 4); |
|---|
| 2278 | | - prom_getprop(node, "height", &height, 4); |
|---|
| 2279 | | - prom_getprop(node, "linebytes", &pitch, 4); |
|---|
| 2280 | | - prom_getprop(node, "address", &addr, 4); |
|---|
| 2422 | + |
|---|
| 2423 | + if (prom_getprop(node, "width", &width, 4) == PROM_ERROR) |
|---|
| 2424 | + return; |
|---|
| 2425 | + |
|---|
| 2426 | + if (prom_getprop(node, "height", &height, 4) == PROM_ERROR) |
|---|
| 2427 | + return; |
|---|
| 2428 | + |
|---|
| 2429 | + if (prom_getprop(node, "linebytes", &pitch, 4) == PROM_ERROR) |
|---|
| 2430 | + return; |
|---|
| 2431 | + |
|---|
| 2432 | + if (prom_getprop(node, "address", &addr, 4) == PROM_ERROR) |
|---|
| 2433 | + return; |
|---|
| 2434 | + |
|---|
| 2281 | 2435 | prom_printf("W=%d H=%d LB=%d addr=0x%x\n", |
|---|
| 2282 | 2436 | width, height, pitch, addr); |
|---|
| 2283 | 2437 | btext_setup_display(width, height, 8, pitch, addr); |
|---|
| 2438 | + btext_prepare_BAT(); |
|---|
| 2284 | 2439 | } |
|---|
| 2285 | 2440 | #endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */ |
|---|
| 2286 | 2441 | } |
|---|
| .. | .. |
|---|
| 2293 | 2448 | { |
|---|
| 2294 | 2449 | void *ret; |
|---|
| 2295 | 2450 | |
|---|
| 2296 | | - *mem_start = _ALIGN(*mem_start, align); |
|---|
| 2451 | + *mem_start = ALIGN(*mem_start, align); |
|---|
| 2297 | 2452 | while ((*mem_start + needed) > *mem_end) { |
|---|
| 2298 | 2453 | unsigned long room, chunk; |
|---|
| 2299 | 2454 | |
|---|
| .. | .. |
|---|
| 2330 | 2485 | s = os = (char *)dt_string_start; |
|---|
| 2331 | 2486 | s += 4; |
|---|
| 2332 | 2487 | while (s < (char *)dt_string_end) { |
|---|
| 2333 | | - if (strcmp(s, str) == 0) |
|---|
| 2488 | + if (prom_strcmp(s, str) == 0) |
|---|
| 2334 | 2489 | return s - os; |
|---|
| 2335 | | - s += strlen(s) + 1; |
|---|
| 2490 | + s += prom_strlen(s) + 1; |
|---|
| 2336 | 2491 | } |
|---|
| 2337 | 2492 | return 0; |
|---|
| 2338 | 2493 | } |
|---|
| .. | .. |
|---|
| 2365 | 2520 | } |
|---|
| 2366 | 2521 | |
|---|
| 2367 | 2522 | /* skip "name" */ |
|---|
| 2368 | | - if (strcmp(namep, "name") == 0) { |
|---|
| 2523 | + if (prom_strcmp(namep, "name") == 0) { |
|---|
| 2369 | 2524 | *mem_start = (unsigned long)namep; |
|---|
| 2370 | 2525 | prev_name = "name"; |
|---|
| 2371 | 2526 | continue; |
|---|
| .. | .. |
|---|
| 2377 | 2532 | namep = sstart + soff; |
|---|
| 2378 | 2533 | } else { |
|---|
| 2379 | 2534 | /* Trim off some if we can */ |
|---|
| 2380 | | - *mem_start = (unsigned long)namep + strlen(namep) + 1; |
|---|
| 2535 | + *mem_start = (unsigned long)namep + prom_strlen(namep) + 1; |
|---|
| 2381 | 2536 | dt_string_end = *mem_start; |
|---|
| 2382 | 2537 | } |
|---|
| 2383 | 2538 | prev_name = namep; |
|---|
| .. | .. |
|---|
| 2398 | 2553 | char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; |
|---|
| 2399 | 2554 | unsigned long soff; |
|---|
| 2400 | 2555 | unsigned char *valp; |
|---|
| 2401 | | - static char pname[MAX_PROPERTY_NAME]; |
|---|
| 2556 | + static char pname[MAX_PROPERTY_NAME] __prombss; |
|---|
| 2402 | 2557 | int l, room, has_phandle = 0; |
|---|
| 2403 | 2558 | |
|---|
| 2404 | 2559 | dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); |
|---|
| .. | .. |
|---|
| 2429 | 2584 | *lp++ = *p; |
|---|
| 2430 | 2585 | } |
|---|
| 2431 | 2586 | *lp = 0; |
|---|
| 2432 | | - *mem_start = _ALIGN((unsigned long)lp + 1, 4); |
|---|
| 2587 | + *mem_start = ALIGN((unsigned long)lp + 1, 4); |
|---|
| 2433 | 2588 | } |
|---|
| 2434 | 2589 | |
|---|
| 2435 | 2590 | /* get it again for debugging */ |
|---|
| 2436 | 2591 | path = prom_scratch; |
|---|
| 2437 | | - memset(path, 0, PROM_SCRATCH_SIZE); |
|---|
| 2438 | | - call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); |
|---|
| 2592 | + memset(path, 0, sizeof(prom_scratch)); |
|---|
| 2593 | + call_prom("package-to-path", 3, 1, node, path, sizeof(prom_scratch) - 1); |
|---|
| 2439 | 2594 | |
|---|
| 2440 | 2595 | /* get and store all properties */ |
|---|
| 2441 | 2596 | prev_name = ""; |
|---|
| .. | .. |
|---|
| 2446 | 2601 | break; |
|---|
| 2447 | 2602 | |
|---|
| 2448 | 2603 | /* skip "name" */ |
|---|
| 2449 | | - if (strcmp(pname, "name") == 0) { |
|---|
| 2604 | + if (prom_strcmp(pname, "name") == 0) { |
|---|
| 2450 | 2605 | prev_name = "name"; |
|---|
| 2451 | 2606 | continue; |
|---|
| 2452 | 2607 | } |
|---|
| .. | .. |
|---|
| 2475 | 2630 | /* push property content */ |
|---|
| 2476 | 2631 | valp = make_room(mem_start, mem_end, l, 4); |
|---|
| 2477 | 2632 | call_prom("getprop", 4, 1, node, pname, valp, l); |
|---|
| 2478 | | - *mem_start = _ALIGN(*mem_start, 4); |
|---|
| 2633 | + *mem_start = ALIGN(*mem_start, 4); |
|---|
| 2479 | 2634 | |
|---|
| 2480 | | - if (!strcmp(pname, "phandle")) |
|---|
| 2635 | + if (!prom_strcmp(pname, "phandle")) |
|---|
| 2481 | 2636 | has_phandle = 1; |
|---|
| 2482 | 2637 | } |
|---|
| 2483 | 2638 | |
|---|
| 2484 | | - /* Add a "linux,phandle" property if no "phandle" property already |
|---|
| 2485 | | - * existed (can happen with OPAL) |
|---|
| 2486 | | - */ |
|---|
| 2639 | + /* Add a "phandle" property if none already exist */ |
|---|
| 2487 | 2640 | if (!has_phandle) { |
|---|
| 2488 | | - soff = dt_find_string("linux,phandle"); |
|---|
| 2641 | + soff = dt_find_string("phandle"); |
|---|
| 2489 | 2642 | if (soff == 0) |
|---|
| 2490 | | - prom_printf("WARNING: Can't find string index for" |
|---|
| 2491 | | - " <linux-phandle> node %s\n", path); |
|---|
| 2643 | + prom_printf("WARNING: Can't find string index for <phandle> node %s\n", path); |
|---|
| 2492 | 2644 | else { |
|---|
| 2493 | 2645 | dt_push_token(OF_DT_PROP, mem_start, mem_end); |
|---|
| 2494 | 2646 | dt_push_token(4, mem_start, mem_end); |
|---|
| .. | .. |
|---|
| 2537 | 2689 | prom_panic ("couldn't get device tree root\n"); |
|---|
| 2538 | 2690 | |
|---|
| 2539 | 2691 | /* Build header and make room for mem rsv map */ |
|---|
| 2540 | | - mem_start = _ALIGN(mem_start, 4); |
|---|
| 2692 | + mem_start = ALIGN(mem_start, 4); |
|---|
| 2541 | 2693 | hdr = make_room(&mem_start, &mem_end, |
|---|
| 2542 | 2694 | sizeof(struct boot_param_header), 4); |
|---|
| 2543 | 2695 | dt_header_start = (unsigned long)hdr; |
|---|
| .. | .. |
|---|
| 2548 | 2700 | dt_string_start = mem_start; |
|---|
| 2549 | 2701 | mem_start += 4; /* hole */ |
|---|
| 2550 | 2702 | |
|---|
| 2551 | | - /* Add "linux,phandle" in there, we'll need it */ |
|---|
| 2703 | + /* Add "phandle" in there, we'll need it */ |
|---|
| 2552 | 2704 | namep = make_room(&mem_start, &mem_end, 16, 1); |
|---|
| 2553 | | - strcpy(namep, "linux,phandle"); |
|---|
| 2554 | | - mem_start = (unsigned long)namep + strlen(namep) + 1; |
|---|
| 2705 | + prom_strcpy(namep, "phandle"); |
|---|
| 2706 | + mem_start = (unsigned long)namep + prom_strlen(namep) + 1; |
|---|
| 2555 | 2707 | |
|---|
| 2556 | 2708 | /* Build string array */ |
|---|
| 2557 | 2709 | prom_printf("Building dt strings...\n"); |
|---|
| .. | .. |
|---|
| 2873 | 3025 | rv = prom_getprop(node, "model", prop, sizeof(prop)); |
|---|
| 2874 | 3026 | if (rv == PROM_ERROR) |
|---|
| 2875 | 3027 | return; |
|---|
| 2876 | | - if (strcmp(prop, "EFIKA5K2")) |
|---|
| 3028 | + if (prom_strcmp(prop, "EFIKA5K2")) |
|---|
| 2877 | 3029 | return; |
|---|
| 2878 | 3030 | |
|---|
| 2879 | 3031 | prom_printf("Applying EFIKA device tree fixups\n"); |
|---|
| .. | .. |
|---|
| 2881 | 3033 | /* Claiming to be 'chrp' is death */ |
|---|
| 2882 | 3034 | node = call_prom("finddevice", 1, 1, ADDR("/")); |
|---|
| 2883 | 3035 | rv = prom_getprop(node, "device_type", prop, sizeof(prop)); |
|---|
| 2884 | | - if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0)) |
|---|
| 3036 | + if (rv != PROM_ERROR && (prom_strcmp(prop, "chrp") == 0)) |
|---|
| 2885 | 3037 | prom_setprop(node, "/", "device_type", "efika", sizeof("efika")); |
|---|
| 2886 | 3038 | |
|---|
| 2887 | 3039 | /* CODEGEN,description is exposed in /proc/cpuinfo so |
|---|
| 2888 | 3040 | fix that too */ |
|---|
| 2889 | 3041 | rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop)); |
|---|
| 2890 | | - if (rv != PROM_ERROR && (strstr(prop, "CHRP"))) |
|---|
| 3042 | + if (rv != PROM_ERROR && (prom_strstr(prop, "CHRP"))) |
|---|
| 2891 | 3043 | prom_setprop(node, "/", "CODEGEN,description", |
|---|
| 2892 | 3044 | "Efika 5200B PowerPC System", |
|---|
| 2893 | 3045 | sizeof("Efika 5200B PowerPC System")); |
|---|
| .. | .. |
|---|
| 3106 | 3258 | #endif |
|---|
| 3107 | 3259 | #endif |
|---|
| 3108 | 3260 | |
|---|
| 3261 | +#ifdef CONFIG_PPC_SVM |
|---|
| 3262 | +/* |
|---|
| 3263 | + * Perform the Enter Secure Mode ultracall. |
|---|
| 3264 | + */ |
|---|
| 3265 | +static int enter_secure_mode(unsigned long kbase, unsigned long fdt) |
|---|
| 3266 | +{ |
|---|
| 3267 | + register unsigned long r3 asm("r3") = UV_ESM; |
|---|
| 3268 | + register unsigned long r4 asm("r4") = kbase; |
|---|
| 3269 | + register unsigned long r5 asm("r5") = fdt; |
|---|
| 3270 | + |
|---|
| 3271 | + asm volatile("sc 2" : "+r"(r3) : "r"(r4), "r"(r5)); |
|---|
| 3272 | + |
|---|
| 3273 | + return r3; |
|---|
| 3274 | +} |
|---|
| 3275 | + |
|---|
| 3276 | +/* |
|---|
| 3277 | + * Call the Ultravisor to transfer us to secure memory if we have an ESM blob. |
|---|
| 3278 | + */ |
|---|
| 3279 | +static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt) |
|---|
| 3280 | +{ |
|---|
| 3281 | + int ret; |
|---|
| 3282 | + |
|---|
| 3283 | + if (!prom_svm_enable) |
|---|
| 3284 | + return; |
|---|
| 3285 | + |
|---|
| 3286 | + /* Switch to secure mode. */ |
|---|
| 3287 | + prom_printf("Switching to secure mode.\n"); |
|---|
| 3288 | + |
|---|
| 3289 | + /* |
|---|
| 3290 | + * The ultravisor will do an integrity check of the kernel image but we |
|---|
| 3291 | + * relocated it so the check will fail. Restore the original image by |
|---|
| 3292 | + * relocating it back to the kernel virtual base address. |
|---|
| 3293 | + */ |
|---|
| 3294 | + if (IS_ENABLED(CONFIG_RELOCATABLE)) |
|---|
| 3295 | + relocate(KERNELBASE); |
|---|
| 3296 | + |
|---|
| 3297 | + ret = enter_secure_mode(kbase, fdt); |
|---|
| 3298 | + |
|---|
| 3299 | + /* Relocate the kernel again. */ |
|---|
| 3300 | + if (IS_ENABLED(CONFIG_RELOCATABLE)) |
|---|
| 3301 | + relocate(kbase); |
|---|
| 3302 | + |
|---|
| 3303 | + if (ret != U_SUCCESS) { |
|---|
| 3304 | + prom_printf("Returned %d from switching to secure mode.\n", ret); |
|---|
| 3305 | + prom_rtas_os_term("Switch to secure mode failed.\n"); |
|---|
| 3306 | + } |
|---|
| 3307 | +} |
|---|
| 3308 | +#else |
|---|
| 3309 | +static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt) |
|---|
| 3310 | +{ |
|---|
| 3311 | +} |
|---|
| 3312 | +#endif /* CONFIG_PPC_SVM */ |
|---|
| 3313 | + |
|---|
| 3109 | 3314 | /* |
|---|
| 3110 | 3315 | * We enter here early on, when the Open Firmware prom is still |
|---|
| 3111 | 3316 | * handling exceptions and the MMU hash table for us. |
|---|
| .. | .. |
|---|
| 3172 | 3377 | */ |
|---|
| 3173 | 3378 | early_cmdline_parse(); |
|---|
| 3174 | 3379 | |
|---|
| 3175 | | -#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) |
|---|
| 3380 | +#ifdef CONFIG_PPC_PSERIES |
|---|
| 3176 | 3381 | /* |
|---|
| 3177 | 3382 | * On pSeries, inform the firmware about our capabilities |
|---|
| 3178 | 3383 | */ |
|---|
| .. | .. |
|---|
| 3216 | 3421 | * On non-powermacs, try to instantiate RTAS. PowerMacs don't |
|---|
| 3217 | 3422 | * have a usable RTAS implementation. |
|---|
| 3218 | 3423 | */ |
|---|
| 3219 | | - if (of_platform != PLATFORM_POWERMAC && |
|---|
| 3220 | | - of_platform != PLATFORM_OPAL) |
|---|
| 3424 | + if (of_platform != PLATFORM_POWERMAC) |
|---|
| 3221 | 3425 | prom_instantiate_rtas(); |
|---|
| 3222 | | - |
|---|
| 3223 | | -#ifdef CONFIG_PPC_POWERNV |
|---|
| 3224 | | - if (of_platform == PLATFORM_OPAL) |
|---|
| 3225 | | - prom_instantiate_opal(); |
|---|
| 3226 | | -#endif /* CONFIG_PPC_POWERNV */ |
|---|
| 3227 | 3426 | |
|---|
| 3228 | 3427 | #ifdef CONFIG_PPC64 |
|---|
| 3229 | 3428 | /* instantiate sml */ |
|---|
| .. | .. |
|---|
| 3237 | 3436 | * |
|---|
| 3238 | 3437 | * (This must be done after instanciating RTAS) |
|---|
| 3239 | 3438 | */ |
|---|
| 3240 | | - if (of_platform != PLATFORM_POWERMAC && |
|---|
| 3241 | | - of_platform != PLATFORM_OPAL) |
|---|
| 3439 | + if (of_platform != PLATFORM_POWERMAC) |
|---|
| 3242 | 3440 | prom_hold_cpus(); |
|---|
| 3243 | 3441 | |
|---|
| 3244 | 3442 | /* |
|---|
| .. | .. |
|---|
| 3282 | 3480 | /* |
|---|
| 3283 | 3481 | * in case stdin is USB and still active on IBM machines... |
|---|
| 3284 | 3482 | * Unfortunately quiesce crashes on some powermacs if we have |
|---|
| 3285 | | - * closed stdin already (in particular the powerbook 101). It |
|---|
| 3286 | | - * appears that the OPAL version of OFW doesn't like it either. |
|---|
| 3483 | + * closed stdin already (in particular the powerbook 101). |
|---|
| 3287 | 3484 | */ |
|---|
| 3288 | | - if (of_platform != PLATFORM_POWERMAC && |
|---|
| 3289 | | - of_platform != PLATFORM_OPAL) |
|---|
| 3485 | + if (of_platform != PLATFORM_POWERMAC) |
|---|
| 3290 | 3486 | prom_close_stdin(); |
|---|
| 3291 | 3487 | |
|---|
| 3292 | 3488 | /* |
|---|
| .. | .. |
|---|
| 3303 | 3499 | */ |
|---|
| 3304 | 3500 | hdr = dt_header_start; |
|---|
| 3305 | 3501 | |
|---|
| 3306 | | - /* Don't print anything after quiesce under OPAL, it crashes OFW */ |
|---|
| 3307 | | - if (of_platform != PLATFORM_OPAL) { |
|---|
| 3308 | | - prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase); |
|---|
| 3309 | | - prom_debug("->dt_header_start=0x%lx\n", hdr); |
|---|
| 3310 | | - } |
|---|
| 3502 | + prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase); |
|---|
| 3503 | + prom_debug("->dt_header_start=0x%lx\n", hdr); |
|---|
| 3311 | 3504 | |
|---|
| 3312 | 3505 | #ifdef CONFIG_PPC32 |
|---|
| 3313 | 3506 | reloc_got2(-offset); |
|---|
| .. | .. |
|---|
| 3315 | 3508 | unreloc_toc(); |
|---|
| 3316 | 3509 | #endif |
|---|
| 3317 | 3510 | |
|---|
| 3318 | | -#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL |
|---|
| 3319 | | - /* OPAL early debug gets the OPAL base & entry in r8 and r9 */ |
|---|
| 3320 | | - __start(hdr, kbase, 0, 0, 0, |
|---|
| 3321 | | - prom_opal_base, prom_opal_entry); |
|---|
| 3322 | | -#else |
|---|
| 3511 | + /* Move to secure memory if we're supposed to be secure guests. */ |
|---|
| 3512 | + setup_secure_guest(kbase, hdr); |
|---|
| 3513 | + |
|---|
| 3323 | 3514 | __start(hdr, kbase, 0, 0, 0, 0, 0); |
|---|
| 3324 | | -#endif |
|---|
| 3325 | 3515 | |
|---|
| 3326 | 3516 | return 0; |
|---|
| 3327 | 3517 | } |
|---|