From 62c6b30e5c0e0f7b9c90850081b1054028d6aace Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Tue, 7 Mar 2017 22:11:57 +0000 Subject: [PATCH] Fix booting with >4GB RAM on PowerMac G5 hardware === From Nathan Whitehorn: Open Firmware runs in virtual mode on the Powermac G5. This runs inside the kernel page table, which preserves all address translations made by OF before the kernel starts; as a result, the kernel address space is a strict superset of OF's. Where this explodes is if OF uses an unmapped SLB entry. The SLB fault handler runs in real mode and refers to the PCPU pointer in SPRG0, which blows up the kernel. Having a value of SPRG0 that works for the kernel is less fatal than preserving OF's value in this case. === The result of this is seemingly random panics from NULL dereferences, or hangs immediately upon boot. By not restoring SPRG0 for Open Firmware entry the kernel PCPU pointer is preserved and SLB faults are successful, resulting in a stable kernel. PR: 205458 Reported by: several (over bugzilla, lists, IRC) Reviewed by: andreast Tested by: many (various forms) MFC after: 2 weeks --- sys/powerpc/ofw/ofw_machdep.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sys/powerpc/ofw/ofw_machdep.c b/sys/powerpc/ofw/ofw_machdep.c index 3051eb3fc20d..55ad00643c61 100644 --- a/sys/powerpc/ofw/ofw_machdep.c +++ b/sys/powerpc/ofw/ofw_machdep.c @@ -111,6 +111,15 @@ ofw_sprg_prepare(void) * Assume that interrupt are disabled at this point, or * SPRG1-3 could be trashed */ +#ifdef __powerpc64__ + __asm __volatile("mtsprg1 %0\n\t" + "mtsprg2 %1\n\t" + "mtsprg3 %2\n\t" + : + : "r"(ofmsr[2]), + "r"(ofmsr[3]), + "r"(ofmsr[4])); +#else __asm __volatile("mfsprg0 %0\n\t" "mtsprg0 %1\n\t" "mtsprg1 %2\n\t" @@ -121,6 +130,7 @@ ofw_sprg_prepare(void) "r"(ofmsr[2]), "r"(ofmsr[3]), "r"(ofmsr[4])); +#endif } static __inline void @@ -136,7 +146,9 @@ ofw_sprg_restore(void) * * PCPU data cannot be used until this routine is called ! */ +#ifndef __powerpc64__ __asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save)); +#endif } #endif @@ -344,8 +356,9 @@ OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *)) ofmsr[0] = mfmsr(); #ifdef __powerpc64__ ofmsr[0] &= ~PSL_SF; - #endif + #else __asm __volatile("mfsprg0 %0" : "=&r"(ofmsr[1])); + #endif __asm __volatile("mfsprg1 %0" : "=&r"(ofmsr[2])); __asm __volatile("mfsprg2 %0" : "=&r"(ofmsr[3])); __asm __volatile("mfsprg3 %0" : "=&r"(ofmsr[4]));