mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #61] ppc: NVRAM address wrap and hardcoded MPIC table break New World / QEMU mac99 boots #52
Labels
No labels
bug
documentation
enhancement
enhancement
good first issue
help wanted
help wanted
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
github-starred/RhapsodiOS#52
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @raynorpat on GitHub (Oct 17, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/61
Booting the Mac OS X Server 1.2v3 ppc disk (kernel 5.6) on QEMU's
mac99machine (OpenBIOS, reported as a "Sawtooth" G4) hits two problems. Both are in code we carry in our tree.1.
/dev/nvramaddress wraps past 4 GBsrc/kernel-7/bsd/dev/ppc/nvram.c(nvprobe, lines 86–95) computes the NVRAM address asPCI_IO_BASE_PHYS + regs[0].address. That works on old-world Macs, where the nvram node sits under mac-io andregis relative. On New World firmware (and QEMU/OpenBIOS) the node is/nvram@fff04000, with an absoluteregoffff04000 4000. The sum wraps to0x7ff04000.What happens:
/etc/startup/0200_Tunerunsnvram boot-args, and the kernel takesUnresolved kernel trap: 0x0300 Data access DSISR=0x40000000 DAR=0x7ff04000in the device read (read→spec_read→ nvram read).The PE's own
ReadNVRAMpath (called duringDeviceTreeProbe) usesregas an absolute address. Rewriting the OF property to7ff04000to satisfynvprobetherefore makesReadNVRAMfault on the same address instead. The two consumers disagree, so this has to be fixed in the kernel, not with a device-tree tweak.Fix: treat
regas absolute when the node is not under mac-io (or iscompatible "nvram,flash"). New World flash NVRAM probably needs the PE's NVRAM access path rather than the byte-stridenvram_data[offset << 4]accessor.2. PCI interrupts outside the hardcoded Sawtooth MPIC table
src/drivers-ppc/bus/drvPExpert/powermac/families/sawtooth.chardcodes PCI slots at MPIC sources 21–24 and marks 25–31 reserved. Nothing in kernel-7 or drivers-ppc readsinterrupt-map. QEMU's UniNorth gives PCI childreninterrupts = 1(the pin) plus aninterrupt-maprouting it to MPIC0x1b–0x1e. Results:-device sungem, and the default USB OHCI: endless{MPIC INT 30}frommpic_interrupt, with no handler for the source.-device tulip(DEC 21143):panic: mpic_register_int: Interrupt 136 not foundduringprobeNativeDevices. This happens even after rewriting the node'sinterruptsto1d 1at the OF prompt.ata-3bus:{MPIC INT 14}while hc1 says it registered irq 22, and the probe stalls.Fix: build the MPIC device table from the device tree (resolving
interrupt-mapfor PCI children) instead of trusting a per-family hardcoded table, or at least map unknown sources to the device that owns them.Repro
vm/ppc-guest.py(coming with the ppc QEMU guest setup) boots this image onmac99,usb=off -nodefaults. It works around problem 1 by replacingnvramwithfalsein0200_Tuneon the guest's overlay disk. Problem 2 currently leaves the guest with no working NIC.@raynorpat commented on GitHub (Oct 17, 2026):
Update: branch
ppc-qemufixes both problems for our kernel. A RhapsodiOS ppc kernel built from it boots the Mac OS X Server 1.2v3 disk on QEMUmac99through multi-user to the Setup Assistant. Cuda/ADB, the display, ATA root and driverLoader all work.A correction first: the issue body says nothing in our tree reads
interrupt-map. That was wrong.driverkit-3/libDriver/ppc/IODeviceTreeBus.mdoes, butIOTreeDeviceonly used it whenIsYosemite(), and it assumed one-cell interrupt specifiers.What it took, in commit order:
1222e3954:nvprobesends Sawtooth throughReadNVRAM/WriteNVRAM(NVRAM_PMU), which already handle Core99 flash NVRAM.ade4b9620: an allocation-free subtree search next toDTFindEntry.b25b3c196: New World meansIsYosemite() || IsSawtooth(). The mapper reads the controller's real#interrupt-cells(2 on an MPIC), stops at the controller, and keeps only the source cell. The tulip now gets MPIC source 0x1d.e7cf0f798:keylargo_find_i2cran fromconfigure_machine, beforekalloc_init(). It used a kalloc'd DT iterator, and the free blocked inkmem_free.eb4b43dd9:identify_machine2()added the mac-io base to the absolute/nvram@fff04000reg; it wrapped to 0x7ff04000 inInitCore99NVRAM.get_int_cntlr_base_addr()returned the open-picreg(0x40000, mac-io relative) as-is. Every MPIC access hit low RAM, andFM_MPIC_CTRL(memory controller base 0 on Sawtooth) scribbled at 0x160 in the vector page. 5.6 adds the mac-io base on Sawtooth and only touches FM on Power Express.86f2501c5:mpic_interrupt_initializenow follows the 5.6 kernel: reset, mask all, spurious 0xff, cascade, then load the table.sawtooth_int_mapping_tblnow matches the 5.6 binary: priority 8, level/active-low for 16–18 and 22–63 (VIA cascade and PCI included). The old table had the cascade edge-triggered.Still open:
/etc/startup/0700_Devicesloads the Floppy driver, whosePMAC_DEV_FLOPPYisn't in the Sawtooth MPIC table (in 5.6 either), sompic_register_intpanics "Interrupt 136 not found".vm/ppc-guest.pycomments it out on the guest disk.sawtooth_interruptsdevice numbering still differs from 5.6's table. It doesn't block anything, because DT-routed drivers resolve through the same table.pci1011,19added to its match) reads zeroed TX descriptors. drvPPCGem (withgmacadded) spins on the GEM status register. Being looked at next.@raynorpat commented on GitHub (Oct 18, 2026):
Networking now works on branch
ppc-qemu.vm/ppc-guest.py runtelnets into the guest on our kernel about six minutes after a fresh boot:Rhapsody 5.6,en010.0.2.15, default route via 10.0.2.2.The blocker was in our driverkit, not the NIC drivers.
IOMacRiscPCIBridge -setConfigAddress:offset:always accessedconfigData + 0. UniNorth, unlike Bandit/Chaos, takes offset bit 2 from the data access rather than the address cycle; Linux handles this withcfg_data + (offset & 7)underhas_uninorth. So every config register with bit 2 set hit the wrong register. The NIC drivers' write of0x16to the command register (offset 4) landed on offset 0, bus mastering was never enabled, and DMA read zeros. That explains both the tulip's and sungem's "zeroed descriptors". Fixed ind4e78b61d. It applies to real Sawtooth hardware too.The guest disk also needed two patches to the stock
drvPPCGemloadable:gmac, so it drives QEMU's sungem.MAC_RXMASK, and the driver never clears it, so it caused an interrupt storm.The longer-term route is to build
drvUniNEnet(Apple's GMAC driver, which 5.6 has built in) into our kernel; see #63.@raynorpat commented on GitHub (Oct 18, 2026):
Progress on branch
ppc-qemusince the last update (still local, not pushed):c14acd573), source for source. The "numbering still differs" item above is closed.b6e11b19d), sovm/ppc-guest.pyno longer patchesdrvPPCGem(326603484).en0comes up at 100 Mb full duplex on QEMU's sungem, and telnet works.97dc15f7f).The two bugs this issue covers, NVRAM wrap and the MPIC table/base, are fixed on the branch. Leaving it open until
ppc-qemuis merged.@raynorpat commented on GitHub (Oct 23, 2026):
Closing. Everything this issue covers is fixed on branch
ppc-qemu(not pushed yet):1222e3954,eb4b43dd9.eb4b43dd9,86f2501c5,c14acd573.b25b3c196.d4e78b61d.Our ppc kernel boots the 1.2v3 disk on QEMU
mac99to multi-user, anden0(built-in UniNEnet on the sungem) carries telnet.The same branch also boots QEMU
g3beige(Gossamer). There the built-in DEC21x4 drives the tulip, and telnet and ping work. That needed79679149d(matchpci1011,19) and2f4326b96, a Heathrow handler fix: it now dispatches level-triggered PCI slot interrupts that stay asserted. Otherwise a held card interrupt storms with nothing dispatched.vm/ppc-guest.py start --machine g3beigeboots it.