← Back to context

Comment by my123

8 hours ago

FYI: https://patchew.org/QEMU/20260324204855.29759-1-mohamed@unpr...

There's some randomness around Tahoe for FileVault and it crashing because Data is detected as not encrypted (and that's not OK on bare metal). If hitting that case you might need to enable FileVault inside the VM (and remember to sync aux storage afterwards if not done)

Looks like someone beat me to it! Thanks!

I see the author of this patch set has run into a few similar issues as me. Strangely, not all of them: I don't see patches for the new PCI MSI-X device introduced somewhere in Sequoia (IIRC), a source of kernel panics for me; and there's still a bug in the PG MMIO path that casts all writes to 32-bit, this one caused me a lot of headaches (no errors but no video adapter detected). I'm somewhat surprised to hear that this works!

There's two significant problems that we both have came across:

- LLVM now favoring pre-indexed load/stores which trap with ISV=0 for MMIO accesses, and those ending up in the GIC initialization path of the newer macOS kernels (looks like there's a separate patch set for this [0]),

- Hypervisor.framework trapping PAC HVC calls.

It seems like the latter has been worked around here by signing QEMU with an Apple-private entitlement and running with SIP off, but there's actually a different way! While some HVCs are trapped right in the host kernel, the PAC trapping happens within Hypervisor.framework itself (at least in the host OSes I tested). It's possible to patch out this functionality without special privileges or talk to the in-kernel hypervisor directly. I originally tested with the former, and chose to implement the latter as a separate accel in the code I was planning to submit upstream, but the complexity of it exploded and, besides confirming that it would have worked, I haven't managed to finish my implementation.

Does the Tahoe crash you mentioned manifest itself in stage 2 iBoot panics? I must admit 26 was never quite my priority so I haven't looked into it, but if so, it might have been closer to booting than I thought :)

[0] https://lists.nongnu.org/archive/html/qemu-devel/2026-04/msg...

  • It was a kernel panic for Tahoe. Anything between macOS 12 and 26 wasn't tested so releases in-between might have more issues.

    The userspace reboot after FileVault password entry acts a bit oddly with QEMU input devices so you might need to attach a new USB tablet or kbd from the monitor.

    > looks like there's a separate patch set for this

    Yup and it's a bit of a problem to figure out the right thing to do for it on the upstreaming side as normal guests aren't supposed to do that.

    > It's possible to patch out this functionality without special privileges or talk to the in-kernel hypervisor directly

    Or pre-patch them all to HVC #1 works too. Patching the host Hypervisor.framework sounds quite brittle especially after they moved to a pile of C++

    • > It was a kernel panic for Tahoe.

      Ah, must be something else then.

      > normal guests aren't supposed to do that

      Oh how I wish Arm didn't let anything like this slip into the architecture spec to begin with! Massive source of pain, especially with protected memory/CCA guests. It's not macOS triggering this in isolation either. Most start up binaries for QNX do this too, somehow also in the GIC init path.

      I've looked at how different hypervisors/VMMs handle this and, if this makes that patch set any less hacky, Virtualization.framework, QNX Hypervisor, and (I think) VMware all decode and emulate those instructions in software. Virtualization.framework is a remarkable spaghetti in this regard :)

      > Or pre-patch them all to HVC #1 works too. Patching the host Hypervisor.framework sounds quite brittle especially after they moved to a pile of C++

      Possibly! IIRC, if HCR_EL2.HCD==1, HVC should trap as undefined instruction. Not sure how much of HCR_EL2 can be set from the user-space, but perhaps this could be the least invasive way.

      Simply ignoring the instruction, though, is not enough. I remember in my setup, with HVC handling stubbed out, secondary cores would always fail to start. I suspect this to be the culprit.

      The SMP bring-up code would fail to pass pointer authentication on the first indirect branch. It would then immediately pivot into FLEH->SLEH->panic(). panic() shortly would attempt to make an indirect jump itself, hoping to crash the other processors, but instead, getting stuck in a loop of calling itself. This would eventually get caught by a stack overflow guard somewhere in FLEH/SLEH, which would place the core in an infinite loop, and... the system would continue to run with just the boot core. Yo dawg, I heard you like panics :)

      4 replies →