};
struct mem_map_entry {
- unsigned long base;
- unsigned long size;
+ u64 base;
+ u64 size;
};
typedef u32 cell_t;
static unsigned long __initdata prom_tce_alloc_end;
#endif
+/* Platforms codes are now obsolete in the kernel. Now only used within this
+ * file and ultimately gone too. Feel free to change them if you need, they
+ * are not shared with anything outside of this file anymore
+ */
+#define PLATFORM_PSERIES 0x0100
+#define PLATFORM_PSERIES_LPAR 0x0101
+#define PLATFORM_LPAR 0x0001
+#define PLATFORM_POWERMAC 0x0400
+#define PLATFORM_GENERIC 0x0500
+
static int __initdata of_platform;
static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
static unsigned long __initdata rmo_top;
static unsigned long __initdata ram_top;
+#ifdef CONFIG_KEXEC
+static unsigned long __initdata prom_crashk_base;
+static unsigned long __initdata prom_crashk_size;
+#endif
+
static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
static int __initdata mem_reserve_cnt;
#define MAX_CPU_THREADS 2
-/* TO GO */
-#ifdef CONFIG_HMT
-struct {
- unsigned int pir;
- unsigned int threadid;
-} hmt_thread_data[NR_CPUS];
-#endif /* CONFIG_HMT */
-
/*
* Error results ... some OF calls will return "-1" on error, some
* will return 0, some will return either. To simplify, here are
reason = PTRRELOC(reason);
#endif
prom_print(reason);
+ /* Do not call exit because it clears the screen on pmac
+ * it also causes some sort of double-fault on early pmacs */
+ if (RELOC(of_platform) == PLATFORM_POWERMAC)
+ asm("trap\n");
+
/* ToDo: should put up an SRC here on p/iSeries */
call_prom("exit", 0, 0);
static void __init early_cmdline_parse(void)
{
struct prom_t *_prom = &RELOC(prom);
- char *opt, *p;
+ const char *opt;
+ char *p;
int l = 0;
RELOC(prom_cmd_line[0]) = 0;
RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
#endif
}
+
+#ifdef CONFIG_KEXEC
+ /*
+ * crashkernel=size@addr specifies the location to reserve for
+ * crash kernel.
+ */
+ opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel="));
+ if (opt) {
+ opt += 12;
+ RELOC(prom_crashk_size) =
+ prom_memparse(opt, (const char **)&opt);
+
+ if (ALIGN(RELOC(prom_crashk_size), 0x1000000) !=
+ RELOC(prom_crashk_size)) {
+ prom_printf("Warning: crashkernel size is not "
+ "aligned to 16MB\n");
+ }
+
+ /*
+ * At present, the crash kernel always run at 32MB.
+ * Just ignore whatever user passed.
+ */
+ RELOC(prom_crashk_base) = 0x2000000;
+ if (*opt == '@') {
+ prom_printf("Warning: PPC64 kdump kernel always runs "
+ "at 32 MB\n");
+ }
+ }
+#endif
}
#ifdef CONFIG_PPC_PSERIES
* If problems seem to show up, it would be a good start to track
* them down.
*/
-static void reserve_mem(unsigned long base, unsigned long size)
+static void reserve_mem(u64 base, u64 size)
{
- unsigned long top = base + size;
+ u64 top = base + size;
unsigned long cnt = RELOC(mem_reserve_cnt);
if (size == 0)
if (size == 0)
continue;
prom_debug(" %x %x\n", base, size);
- if (base == 0)
+ if (base == 0 && (RELOC(of_platform) & PLATFORM_LPAR))
RELOC(rmo_top) = size;
if ((base + size) > RELOC(ram_top))
RELOC(ram_top) = base + size;
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
prom_printf(" rmo_top : %x\n", RELOC(rmo_top));
prom_printf(" ram_top : %x\n", RELOC(ram_top));
+#ifdef CONFIG_KEXEC
+ if (RELOC(prom_crashk_base)) {
+ prom_printf(" crashk_base : %x\n", RELOC(prom_crashk_base));
+ prom_printf(" crashk_size : %x\n", RELOC(prom_crashk_size));
+ }
+#endif
}
*/
*spinloop = 0;
-#ifdef CONFIG_HMT
- for (i = 0; i < NR_CPUS; i++)
- RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
-#endif
/* look for cpus */
for (node = 0; prom_next_node(&node); ) {
type[0] = 0;
/* Reserve cpu #s for secondary threads. They start later. */
cpuid += cpu_threads;
}
-#ifdef CONFIG_HMT
- /* Only enable HMT on processors that provide support. */
- if (__is_processor(PV_PULSAR) ||
- __is_processor(PV_ICESTAR) ||
- __is_processor(PV_SSTAR)) {
- prom_printf(" starting secondary threads\n");
-
- for (i = 0; i < NR_CPUS; i += 2) {
- if (!cpu_online(i))
- continue;
-
- if (i == 0) {
- unsigned long pir = mfspr(SPRN_PIR);
- if (__is_processor(PV_PULSAR)) {
- RELOC(hmt_thread_data)[i].pir =
- pir & 0x1f;
- } else {
- RELOC(hmt_thread_data)[i].pir =
- pir & 0x3ff;
- }
- }
- }
- } else {
- prom_printf("Processor is not HMT capable\n");
- }
-#endif
if (cpuid > NR_CPUS)
prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
int len, i = 0;
#ifdef CONFIG_PPC64
phandle rtas;
+ int x;
#endif
+
+ /* Look for a PowerMac */
len = prom_getprop(_prom->root, "compatible",
compat, sizeof(compat)-1);
if (len > 0) {
if (strstr(p, RELOC("Power Macintosh")) ||
strstr(p, RELOC("MacRISC")))
return PLATFORM_POWERMAC;
-#ifdef CONFIG_PPC64
- if (strstr(p, RELOC("Momentum,Maple")))
- return PLATFORM_MAPLE;
-#endif
i += sl + 1;
}
}
#ifdef CONFIG_PPC64
+ /* If not a mac, try to figure out if it's an IBM pSeries or any other
+ * PAPR compliant platform. We assume it is if :
+ * - /device_type is "chrp" (please, do NOT use that for future
+ * non-IBM designs !
+ * - it has /rtas
+ */
+ len = prom_getprop(_prom->root, "device_type",
+ compat, sizeof(compat)-1);
+ if (len <= 0)
+ return PLATFORM_GENERIC;
+ if (strncmp(compat, RELOC("chrp"), 4))
+ return PLATFORM_GENERIC;
+
/* Default to pSeries. We need to know if we are running LPAR */
rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
- if (PHANDLE_VALID(rtas)) {
- int x = prom_getproplen(rtas, "ibm,hypertas-functions");
- if (x != PROM_ERROR) {
- prom_printf("Hypertas detected, assuming LPAR !\n");
- return PLATFORM_PSERIES_LPAR;
- }
+ if (!PHANDLE_VALID(rtas))
+ return PLATFORM_GENERIC;
+ x = prom_getproplen(rtas, "ibm,hypertas-functions");
+ if (x != PROM_ERROR) {
+ prom_printf("Hypertas detected, assuming LPAR !\n");
+ return PLATFORM_PSERIES_LPAR;
}
return PLATFORM_PSERIES;
#else
- return PLATFORM_CHRP;
+ return PLATFORM_GENERIC;
#endif
}
if (r3 && r4 && r4 != 0xdeadbeef) {
unsigned long val;
- RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
+ RELOC(prom_initrd_start) = is_kernel_addr(r3) ? __pa(r3) : r3;
RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
val = RELOC(prom_initrd_start);
{
struct prom_t *_prom;
unsigned long hdr;
- u32 getprop_rval;
unsigned long offset = reloc_offset();
#ifdef CONFIG_PPC32
*/
prom_init_stdout();
- /*
- * Check for an initrd
- */
- prom_check_initrd(r3, r4);
-
/*
* Get default machine type. At this point, we do not differentiate
* between pSeries SMP and pSeries LPAR
*/
RELOC(of_platform) = prom_find_machine_type();
- getprop_rval = RELOC(of_platform);
- prom_setprop(_prom->chosen, "/chosen", "linux,platform",
- &getprop_rval, sizeof(getprop_rval));
+
+ /* Bail if this is a kdump kernel. */
+ if (PHYSICAL_START > 0)
+ prom_panic("Error: You can't boot a kdump kernel from OF!\n");
+
+ /*
+ * Check for an initrd
+ */
+ prom_check_initrd(r3, r4);
#ifdef CONFIG_PPC_PSERIES
/*
*/
prom_init_mem();
+#ifdef CONFIG_KEXEC
+ if (RELOC(prom_crashk_base))
+ reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size));
+#endif
/*
* Determine which cpu is actually running right _now_
*/
}
#endif
+#ifdef CONFIG_KEXEC
+ if (RELOC(prom_crashk_base)) {
+ prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base",
+ PTRRELOC(&prom_crashk_base),
+ sizeof(RELOC(prom_crashk_base)));
+ prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size",
+ PTRRELOC(&prom_crashk_size),
+ sizeof(RELOC(prom_crashk_size)));
+ }
+#endif
/*
* Fixup any known bugs in the device-tree
*/