PowerMac G5 hangs/crashes on boot: 10.2, 11.0-RCx

Nathan Whitehorn nwhitehorn at freebsd.org
Tue Sep 13 03:33:10 UTC 2016



On 09/12/16 14:50, Mark Millard wrote:
> On 2016-Sep-12, at 2:00 PM, Nathan Whitehorn <nwhitehorn at freebsd.org> wrote:
>
>> On 09/11/16 12:04, Krzysztof Parzyszek wrote:
>>> On 9/10/2016 7:12 PM, Mark Millard wrote:
>>>> Your report that you have some sort of failure after booting during the likes of buildkernel is new as far as I know. Sending the list (and/or a bugzilla report) about the failure mode and related information may be appropriate and help in the future. (May be I missed an already existing report.)
>>> I think the issues with hangs are related to the temperature sensors.  I was getting console messages that the media temp sensor was reporting 120C! I realized that as I replaced the hard drive, I changed the position of the drive in a way that exposed the sensor to the wind from the fans (it used to be angled a bit). Following this line of thought, I stuck a piece of paper in front of the sensor and things seem to work. At least work better than before. I have ordered a replacement sensor from eBay, so hopefully that problem will go away.
>>>
>>> Regarding your "hack": it works perfectly! So far, my system (10.3 at the moment) has booted every single time, no exceptions, traps, unexpected conditions. This is too good to remain as a "hack". I have no experience debugging the kernel and I don't know ABI the OFW follows, but I wouldn't mind digging a bit deeper into it, if someone shared some pointers.
>> I've finally understood why this helps. 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.
> Actual theory of operation material! Great! I've no clue how I would have figured out the Apple Open Firmware side of the context so I'd still be stuck with just observation of the overall change in behavior.
>
> Presuming that you are correct: no longer "just a hack". That is great news.
>
> It does sound like the Open Firmware side gets some risk of picking up the wrong address map with the change. So avoiding Open Firmware in the kernel via the usefdt=1 sounds like it would still be appropriate.
>
>> I believe that OF's SPRG0 is maintained only for compatibility with some G4 Apple hardware, the eMac in particular, but will check and we can move on with this. I think it should be safe to wrap this in an #ifdef __powerpc64__.
>> -Nathan
> Again I've no clue how I would figure such a thing out. But, if some powerpc Macs are the only reason GENERIC preserves SPRG0 and preserving works for the other powerpcs so that detecting PowerMac vs. not is not really required to decide on the SPRG0 handling (at least for powerpc64), that too is great news.
>
>
> Thanks for continuing to look into why the SPRG0 change might have a solid justification!

Here's a patch that I think is commitable. I've tested it on a PowerMac 
11,2 with no ill effect. I would appreciate testing on any other models 
of PowerMac G5 (or iMac G5) before committing. This only changes 
behavior on powerpc64 kernels running on Apple-branded systems, so no 
need for testing on non-Apple or non-G5 hardware.
-Nathan
-------------- next part --------------
Index: sys/powerpc/ofw/ofw_machdep.c
===================================================================
--- sys/powerpc/ofw/ofw_machdep.c	(revision 305719)
+++ sys/powerpc/ofw/ofw_machdep.c	(working copy)
@@ -98,7 +98,12 @@
 
 /*
  * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
+ * Applies only to work around some broken on a few 32-bit Apple systems.
+ * Harmful on 64-bit systems, as this code can tread on registers used by
+ * the SLB fault handler, which can be invoked from inside firmware.
  */
+
+#ifndef __powerpc64__
 register_t	ofw_sprg0_save;
 
 static __inline void
@@ -140,6 +145,8 @@
 }
 #endif
 
+#endif
+
 static int
 parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
 {
@@ -344,11 +351,12 @@
 	ofmsr[0] = mfmsr();
 	#ifdef __powerpc64__
 	ofmsr[0] &= ~PSL_SF;
-	#endif
+	#else
 	__asm __volatile("mfsprg0 %0" : "=&r"(ofmsr[1]));
 	__asm __volatile("mfsprg1 %0" : "=&r"(ofmsr[2]));
 	__asm __volatile("mfsprg2 %0" : "=&r"(ofmsr[3]));
 	__asm __volatile("mfsprg3 %0" : "=&r"(ofmsr[4]));
+	#endif
 	openfirmware_entry = openfirm;
 
 	if (ofmsr[0] & PSL_DR)
@@ -440,7 +448,9 @@
 	 */
 	oldmsr = intr_disable();
 
+#ifndef __powerpc64__
 	ofw_sprg_prepare();
+#endif
 
 	/* Save trap vectors */
 	ofw_save_trap_vec(save_trap_of);
@@ -463,7 +473,9 @@
 	/* Restore trap vecotrs */
 	ofw_restore_trap_vec(save_trap_of);
 
+#ifndef __powerpc64__
 	ofw_sprg_restore();
+#endif
 
 	intr_restore(oldmsr);
 


More information about the freebsd-ppc mailing list