Jump to content
559 posts in this topic

Recommended Posts

DIAG[Plane] — AppleIntelPlane

All pointer/ID fields zero — expected. Apple's init() only sets the MMIO addresses; fController, fPath, fIGPlaneID are wired later by allocatePlane. The ccont write from our init hook is also wasted here (ccont is still NULL this early) — the real protection comes from the per-method fixups.

The two non-zero items are the important ones:

Field Value Verdict
mmioAddr_PLANE_CTL(+0x98) 0x70180 PLANE_CTL_1_A pipe A plane 1 ✓
mmioAddr_PLANE_STRIDE(+0x9C) 0x701CC real MMIO addr, +0x4C from CTL base
raw +0xF8 0x701C8 mmioAddr_00F8 is a real plane reg ✓
raw +0xFC 0x701A8 mmioAddr_00A8 companion, +0x28 from CTL ✓

Struct offsets correct for all mmioAddr fields.

NootedGreen    ngreen: @ DIAG[Plane] that=0xffffff86a035ae00 pipeIndex=0
NootedGreen    ngreen: @ DIAG[Plane] fController(+0x68)=0 fPath(+0x70)=0
NootedGreen    ngreen: @ DIAG[Plane] fPipeIdx(+0x78)=0 fIGPlaneID(+0x7C)=0 fPlaneIdx(+0x80)=0 fEnabled(+0x84)=0
NootedGreen    ngreen: @ DIAG[Plane] fRegCache(+0x88)=0 fWriteAccessor(+0x90)=0
NootedGreen    ngreen: @ DIAG[Plane] mmio: CTL=0x70180 STRIDE=0x701cc
NootedGreen    ngreen: @ DIAG[Plane] shadows: CTL=0x0 STRIDE=0x0 COLOR_CTL=0x0
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x60: 00000000 00000000
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x68: 00000000 00000000
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x70: 00000000 00000000
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x78: 00000000 00000000
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x80: 00000000 00000000
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x88: 00000000 00000000
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x90: 00000000 00000000
NootedGreen    ngreen: @ DIAG[Plane-raw] +0xf8: 000701c8 000701a8
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x100: 00000000 00000000
NootedGreen    ngreen: @ DIAG[Plane-raw] +0x108: 00000000 00000000

 

DIAG[PowerWell]fController == param_1 match=1 ✓. Offset +0x10 verified correct. DIAG can be removed.

DIAG[ScalerRC] — confirms the 5 shadow fields of AppleIntelScaler:

  • shadow_0044=0x200 → PS_CTRL (ENABLE bit) ✓
  • shadow_0048=0x0 → PS_WIN_POS (0,0 pre-setup) ✓
  • shadow_004C=0x0 → PS_WIN_SZ ✓
  • shadow_0050=0x0 → PS_HPHASE (matches mmioAddr_0040=0x68194) ✓
  • shadow_0054=0x0 → unknown, no mmioAddr pair

 

NootedGreen    ngreen: @ DIAG[PowerWell] fController=0xffffff9305e5f000 param_1=0xffffff9305e5f000 match=1

NootedGreen    ngreen: @ DIAG[ScalerRC] that=0xffffff97d23e63e0 mmioAddr: 30=0x68180 34=0x68170 38=0x68174 3C=0x60020 40=0x68194
NootedGreen    ngreen: @ DIAG[ScalerRC] shadows: 44=0x200 48=0x0 4C=0x0 50=0x0 54=0x0

Fully verified (DIAG removed):

Struct Key findings
AppleIntelBaseController fMMIO, flags_ig, fInfoFlags2, fRegCachePool, unk_0C60 ✓
CRTCParams All fields ✓
AppleIntelFramebuffer fController, fPipeIndex, unk_01C8, fInitFlag ✓
AppleIntelDisplayPath unk_0284, unk_32A4 ✓
AppleIntelScaler All mmioAddrs + 5 shadows ✓
PLANEPARAMS 5 fields incl. PLANE_SIZE ✓
SCALERPARAMS 3 fields ✓
AppleIntelPowerWell fController, fAlwaysOn, fPGBase, fDDI[], fAUX[], fMMIO ✓
AppleIntelPlane All back-ptrs, mmioAddrs, PLANE_STRIDE/SIZE shadows ✓
AppleIntelPlaneRegCache fController +0x10, fWriteAccessor +0x28, seam-scaler mmioAddrs +0x30..+0x3C ✓
AppleIntelScalerRegCache All 3 fields + 2 extra shadows ✓

Still active / unresolved:

Struct Status
FlipTransactionArgs DIAG[Flip] still in code — always zeros during boot (black screen = no real flips). Likely embedded at AppleIntelPlane+0x10. Blocked until display reaches login.
AppleIntelPlane.mmioAddr_00_9C 0x701CC, renamed from PLANE_STRIDE — identity unconfirmed (may be PLANE_COLOR_CTL or AUX stride)
AppleIntelPlane.unk_01C8 / BC.unk_0C60 Identity TBD, need Ghidra cross-reference
IntelAccelerator Not yet validated
IGAccelTask / blit3d structs Not yet validated
LinkConfig No hook receives it directly — inaccessible without Ghidra offset into port object

The blocking issue is the black screen — without reaching login, FlipTransactionArgs is always zeroed and IntelAccelerator/3D structs never carry real data either. That's the priority.


Now for your question: how can we solve the black screen?

From the logs we have all the key signals:

  • V401[4]: NEW CTL=0x94000408 tile=0x1 STRIDE=0x14 SURF=0x412be000 — first real surface appears
  • V405[5]: param2=0 — pipeline disabled immediately after
  • V401[5]: NEW SURF=0x0 — surface cleared right away
  • PIPE_MISC bpc[5:3]=2→2 (6bpc) — this is abnormal, should be 8bpc (value 0) for standard output

The 6bpc encoding (bpc field=2 in PIPE_MISC[5:3]) is suspicious — it means the hardware is outputting 6-bit color which many panels reject, showing black. This could be why: Apple's pipeline sets 6bpc for ADL-P because of a display capability read it doesn't understand.

Want me to dig deeper into the PIPE_MISC bpc path and compare with what we'd need to force 8bpc?

 

Here we are, sotomayor

Yes, it's worth it. From the logs the bpc transition is clear:

  • V405[1]: PIPE_MISC: 0x1000000→0x1000000 bpc[5:3]=0→0 — 8bpc ✓
  • V405[2]: PIPE_MISC: 0x1000010→0x1000010 bpc[5:3]=2→2  6bpc, stays there permanently

0x1000010 = 0x1000000 | 0x10. Bit 4 set → bits[5:3]=0b010=2=6bpc. Apple's original configureColorPipeLine sets this between calls 1 and 2.

But 6bpc alone doesn't cause black screen — many panels accept dithered output. The more suspicious signal is:

  • V401[4]: NEW SURF=0x412be000 — first real surface appears
  • V405[5]: param2=0 — pipeline disabled immediately after
  • V401[5]: NEW SURF=0x0 — surface immediately cleared

The surface gets committed and torn down in back-to-back calls. That's the black screen: plane is enabled → surface committed → plane immediately disabled before any scanout.

Two things to investigate in parallel:

  1. Why does param2=0 fire right after the first real surface? — something is calling configureColorPipeLine(plane, args, false) immediately after the first flip. This disable call is the proximate cause.
  2. What drives the 6bpc decision? — Apple reads bpc from a connector capability; on ADL-P the DPCD/display-info path may be wrong.

For #1: the disable call at V405[5] might come from configurePlane failing (e.g., tiling mismatch) and tearing down the plane. V401[4] shows tile=0x1 (Y-tiled) which matches TilingEnum=1. But if the DSB flush fails or the scaler rejects the surface, Apple's error path disables the plane.

For #2: we can just force-clear bits[5:3] in PIPE_MISC post-callthrough — one-liner in the existing hook.

Which angle do you want to pursue first?

6bpc question answered: Call 1: PIPE_MISC=0x1000000, bpc=0 (8bpc) — initial setup before DPCD is read. Call 2+: PIPE_MISC=0x1000010, bpc=2 (6bpc) + bit4=dithering. Apple read the panel's DPCD after call 1 and decided 6bpc+dither. This is driven by the connector properties chain (DPCD panel descriptor), completely outside our hooks. Whether this is correct or wrong depends on what the panel actually reports.

V405[5] param2=0 explained — NOT a seam abort: Look at what changes between [5] and [6]: PIPE_MISC goes from 0x10000100x1800010 (bit 23 added). Apple is deliberately doing disable plane → change PIPE_MISC → re-enable plane. That's the standard sequence for any pipe-level register that requires the plane to be off. Not a hardware abort.

The suspicious part — V401[4→5]:

V401[4]: OLD SURF=0x0 → NEW SURF=0x412be000   ← first real IOSurface committed
V401[5]: OLD SURF=0x412be000 → NEW SURF=0x0   ← immediately removed, back to null

Apple presents a real frame to 0x412be000, then one flip later yanks it back to 0x0. Then at V401[8] a different surface 0x40396000 arrives. This oscillation — real surface appears, gets retired immediately, another one comes later — is abnormal. WindowServer is either immediately retiring presented frames or the surface lifetimes are extremely short.

The counters are capped at 8 and the recycling is happening after. We can't see the trigger from these logs.

Most likely remaining cause of the visual recycle: The real IOSurface allocations (0x412be000, 0x40396000) are Tile4 format — Apple's GPU allocator chose Tile4 because it thinks it's a TGL device. We're telling the display engine they're X-tiled (tile=0x1). The display engine scans Tile4 memory as X-tile → garbled/black → Apple's display watchdog detects no valid output → display reset → repeat.

Immediate action: increase the log cap from 8 to 20 in both hooks, boot, and share the full sequence — particularly what happens after SURF=0x40396000 arrives at V401[8]. That's where the recycling trigger should appear.

Want me to bump both caps to 20 now?

Posted (edited)

I was not talking about gambling.... I was talking like push the Botton and spend money.. ia is not gambling.. it's like show machine as a drug

On the i915 code your friend shared: this confirms ADL-P is Gen12 (GRAPHICS_VER=12, IP_VER(12,0)), not XEHP (IP_VER(12,55)). The relevance to us is about surface tiling format:

  • XEHP+ (Alchemist+) uses explicit Tile4 in the new memory model
  • Gen12 (TGL, ADL-P) uses the legacy Y-tile path for both render and display — the display engine PLANE_CTL bits[12:10]=100 is what i915 calls "Y-tile" on Gen12, even though it's physically the same 4KB swizzle as Tile4

Apple's TGL driver almost certainly allocates IOSurfaces as Y-tiled (TilingEnum=1 → PLANE_CTL 0x1000). Our V408 patch strips that and forces X-tile (0x400). That's the black screen.

Edited by Stezza88
Posted (edited)

u will eventually find what is missing for your display. i just found this code in linux at icl_set_pipe_chicken()

dam ai. your display is 13 its on linux log!! but yes were on gen12 graph ver so xe code doesnt apply. any i got wrong no problem

 

image.png.5bdc2664c8e3fcbdb5c444b9f827c8c5.png

 

try check apple pipe functions. u are almost running out of apple code to check

some here not all

image.png.c6805bac8a2bb142416ed9c17cb8921d.png

 

if that bot was working properly we can ask to verify __intel_display_wa() vs apple code

 

 

Edited by jalavoui
On 5/16/2026 at 8:18 PM, jalavoui said:

go back and read what i wrote

ure just doing someting i already solved

 

so in this part u have.

image.png.807e02a02f81a7d414d3be6c430d1e19.png

 

but it look to bs to me. so i bother to see apple code

image.png.63f31e060cc3db1d2b0243e1c6373a67.png

 

apple code is fine. no bs plz

probably linux as better answer as code there consider display=13, etc

 

but this helped as i have random hangs maybe relates to this

linux as

void intel_psr_enable_source(struct intel_dp *intel_dp,    const struct intel_crtc_state *crtc_state)

yep linux as code like this. just need find it as much more is there

image.png.aa9ebeacde1f52f07cf507f28b6e988e.png

 

better just follow linux log -> void intel_pps_on_unlocked(struct intel_dp *intel_dp)

none of this is working in apple code

Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.357944] i915 0000:00:02.0: [drm:intel_opregion_get_panel_type [i915]] Ignoring OpRegion panel type (0)
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.358056] i915 0000:00:02.0: [drm:get_panel_type [i915]] Panel type (VBT): 2
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.358168] i915 0000:00:02.0: [drm:get_panel_type [i915]] Selected panel type (VBT): 2
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.358272] i915 0000:00:02.0: [drm:intel_bios_init_panel [i915]] DRRS supported mode is seamless
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.358371] i915 0000:00:02.0: [drm:parse_lfp_data [i915]] Found panel mode in BIOS VBT legacy lfp table: "1024x768": 60 65000 1024 1048 1184 1344 768 771 777 806 0x8 0xa
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.358563] i915 0000:00:02.0: [drm:dump_pnp_id [i915]] Panel PNPID mfg: MS_ (0x7f36), prod: 3, serial: 3, week: 0, year: 2002
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.358655] i915 0000:00:02.0: [drm:parse_lfp_data [i915]] Panel name: LFP_PanelName
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.359384] i915 0000:00:02.0: [drm:pps_init_delays [i915]] panel power up delay 200, power down delay 50, power cycle delay 600
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.359636] i915 0000:00:02.0: [drm:pps_init_registers [i915]] panel power sequencer register settings: PP_ON 0x7d00001, PP_OFF 0x1f40001, PP_DIV 0x60
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.366776] i915 0000:00:02.0: [drm:intel_panel_add_edid_fixed_modes [i915]] [CONNECTOR:308:eDP-1] using preferred EDID fixed mode: "1920x1080": 60 142000 1920 2028 2076 2100 1080 1090 1100 1126 0x48 0xa
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.367377] i915 0000:00:02.0: [drm:intel_panel_init [i915]] [CONNECTOR:308:eDP-1] DRRS type: none
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.368057] i915 0000:00:02.0: [drm:pps_init_delays [i915]] panel power up delay 200, power down delay 50, power cycle delay 600
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.368308] i915 0000:00:02.0: [drm:pps_init_registers [i915]] panel power sequencer register settings: PP_ON 0x7d00001, PP_OFF 0x1f40001, PP_DIV 0x60
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.372615] i915 0000:00:02.0: [drm:intel_edp_fixup_vbt_bpp [i915]] pipe has 24 bpp for eDP panel, overriding BIOS-provided max 18 bpp
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.609599] i915 0000:00:02.0: [drm:intel_pps_off_unlocked [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 turn panel power off
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.610011] i915 0000:00:02.0: [drm:intel_pps_off_unlocked [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 wait for panel power off time
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.610390] i915 0000:00:02.0: [drm:wait_panel_status [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 mask: 0xb0000000 value: 0x00000000 PP_STATUS: 0xa0000002 PP_CONTROL: 0x00000060
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.665344] i915 0000:00:02.0: [drm:wait_panel_status [i915]] Wait complete
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.671712] i915 0000:00:02.0: [drm:intel_pps_on_unlocked [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 turn panel power on
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    1.672068] i915 0000:00:02.0: [drm:wait_panel_power_cycle [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 wait for panel power cycle
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    2.290730] i915 0000:00:02.0: [drm:wait_panel_status [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 mask: 0xb800000f value: 0x00000000 PP_STATUS: 0x00000000 PP_CONTROL: 0x00000060
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    2.291157] i915 0000:00:02.0: [drm:wait_panel_status [i915]] Wait complete
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    2.291546] i915 0000:00:02.0: [drm:intel_pps_on_unlocked [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 wait for panel power on
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    2.291933] i915 0000:00:02.0: [drm:wait_panel_status [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 mask: 0xb000000f value: 0x80000008 PP_STATUS: 0x9000000a PP_CONTROL: 0x00000063
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    2.502577] i915 0000:00:02.0: [drm:wait_panel_status [i915]] Wait complete
Feb 22 19:46:31 linuxlite-iMacPro1-1 kernel: [    6.983630] i915 0000:00:02.0: [drm:intel_panel_actually_set_backlight [i915]] [CONNECTOR:308:eDP-1] set backlight level = 11520
Feb 22 19:47:17 linuxlite-iMacPro1-1 kernel: [   58.563069] i915 0000:00:02.0: [drm:intel_pps_off_unlocked [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 turn panel power off
Feb 22 19:47:17 linuxlite-iMacPro1-1 kernel: [   58.563460] i915 0000:00:02.0: [drm:intel_pps_off_unlocked [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 wait for panel power off time
Feb 22 19:47:17 linuxlite-iMacPro1-1 kernel: [   58.563829] i915 0000:00:02.0: [drm:wait_panel_status [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 mask: 0xb0000000 value: 0x00000000 PP_STATUS: 0xa0000002 PP_CONTROL: 0x00000060
Feb 22 19:47:17 linuxlite-iMacPro1-1 kernel: [   58.616259] i915 0000:00:02.0: [drm:wait_panel_status [i915]] Wait complete
Feb 22 19:47:17 linuxlite-iMacPro1-1 kernel: [   58.654571] i915 0000:00:02.0: [drm:intel_pps_on_unlocked [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 turn panel power on
Feb 22 19:47:17 linuxlite-iMacPro1-1 kernel: [   58.654685] i915 0000:00:02.0: [drm:wait_panel_power_cycle [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 wait for panel power cycle
Feb 22 19:47:18 linuxlite-iMacPro1-1 kernel: [   59.250898] i915 0000:00:02.0: [drm:wait_panel_status [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 mask: 0xb800000f value: 0x00000000 PP_STATUS: 0x00000000 PP_CONTROL: 0x00000060
Feb 22 19:47:18 linuxlite-iMacPro1-1 kernel: [   59.251251] i915 0000:00:02.0: [drm:wait_panel_status [i915]] Wait complete
Feb 22 19:47:18 linuxlite-iMacPro1-1 kernel: [   59.251576] i915 0000:00:02.0: [drm:intel_pps_on_unlocked [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 wait for panel power on
Feb 22 19:47:18 linuxlite-iMacPro1-1 kernel: [   59.251906] i915 0000:00:02.0: [drm:wait_panel_status [i915]] [ENCODER:307:DDI A/PHY A] PPS 0 mask: 0xb000000f value: 0x80000008 PP_STATUS: 0x9000000a PP_CONTROL: 0x00000063
Feb 22 19:47:18 linuxlite-iMacPro1-1 kernel: [   59.462849] i915 0000:00:02.0: [drm:wait_panel_status [i915]] Wait complete

ofc acel will hang

 

hmmm i dont have display 13 but someone else might have

image.png.cfc228f1b513c55011e9b96ba7495f79.png

 

linux lib allow check callers so going back shows

image.png.89919cdcff1a4340f30bc6ba586140ba.png

 

very interesting

 

  • PSR is already cleared early, stays at 0 throughout — PSR is NOT the issue
  • V105 is still doing useful work: it caught and cleared legacy PSR2=0x4811 at 0x60900
  • V205 is catching the EFI residue PSR1=0x100001 (bit 31 clear = not actually enabled, just leftover bits from firmware)
Posted (edited)

wonder what this code is doing for you

image.png.d2d51fbc260ca60e0999022172658fc9.png

 

found a bug

#define HAS_PSR_TRANS_PUSH_FRAME_CHANGE(__display) (DISPLAY_VER(__display) >= 20)

image.png.8de12a3b85cde4278df0185a442a2197.png

 

since #define   DSB_FORCE_DEWAKE REG_BIT(23) = DSB_CHICKEN_SKIP_WAITS_EN

this is wrongly set so if no vrr chicken=0;

 

code is at _intel_dsb_chain()

static void _intel_dsb_chain(struct intel_atomic_state *state,
			     struct intel_dsb *dsb,
			     struct intel_dsb *chained_dsb,
			     u32 ctrl)
{
	struct intel_display *display = to_intel_display(state->base.dev);
	struct intel_crtc *crtc = dsb->crtc;
	enum pipe pipe = crtc->pipe;

	if (drm_WARN_ON(display->drm, dsb->id == chained_dsb->id))
		return;

	if (!assert_dsb_tail_is_aligned(chained_dsb))
		return;

	intel_dsb_reg_write(dsb, DSB_CTRL(pipe, chained_dsb->id),
			    ctrl | DSB_ENABLE);

	intel_dsb_reg_write(dsb, DSB_CHICKEN(pipe, chained_dsb->id),
			    dsb_chicken(state, crtc));

	intel_dsb_reg_write(dsb, DSB_INTERRUPT(pipe, chained_dsb->id),
			    dsb_error_int_status(display) | DSB_PROG_INT_STATUS |
			    dsb_error_int_en(display) | DSB_PROG_INT_EN);

	if (ctrl & DSB_WAIT_FOR_VBLANK) {
		int dewake_scanline = dsb_dewake_scanline_start(state, crtc);
		int hw_dewake_scanline = dsb_scanline_to_hw(state, crtc, dewake_scanline);

		intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id),
				    DSB_ENABLE_DEWAKE |
				    DSB_SCANLINE_FOR_DEWAKE(hw_dewake_scanline));
	} else {
		intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id), 0);
	}

	intel_dsb_reg_write(dsb, DSB_HEAD(pipe, chained_dsb->id),
			    intel_dsb_head(chained_dsb));

	intel_dsb_reg_write(dsb, DSB_TAIL(pipe, chained_dsb->id),
			    intel_dsb_tail(chained_dsb));

	if (ctrl & DSB_WAIT_FOR_VBLANK) {
		/*
		 * Keep DEwake alive via the first DSB, in
		 * case we're already past dewake_scanline,
		 * and thus DSB_ENABLE_DEWAKE on the second
		 * DSB won't do its job.
		 */
		intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(pipe, dsb->id),
					   DSB_FORCE_DEWAKE, DSB_FORCE_DEWAKE);

		intel_dsb_wait_scanline_out(state, dsb,
					    dsb_dewake_scanline_start(state, crtc),
					    dsb_dewake_scanline_end(state, crtc));

		/*
		 * DSB_FORCE_DEWAKE remains active even after DSB is
		 * disabled, so make sure to clear it.
		 */
		intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id),
					   DSB_FORCE_DEWAKE, 0);
	}
}

better just disable this pipe write as i doubt dsb is working

 

time to do a check to this dsb thing

enable dsb if 

#define HAS_DOUBLE_BUFFERED_LUT(__display) (DISPLAY_VER(__display) >= 30)

is used for this 3 checks

if (intel_color_uses_chained_dsb(new_crtc_state))

else if (intel_color_uses_gosub_dsb(new_crtc_state))

and also if (new_crtc_state->use_dsb && !intel_color_uses_chained_dsb(new_crtc_state))

 

final call is

void intel_dsb_finish(struct intel_dsb *dsb)

{

intel_dsb_align_tail(dsb);

 

dsb_buffer_flush_map(dsb);

}

 

so we dont have (DISPLAY_VER(__display) >= 30

gonna clean dsb code if apple doesnt crash

 

done hookcase tested and on github

Edited by jalavoui

This means the corruption source is upstream of PLANE_CTL/STRIDE — something in the FB kext's plane or pipe configuration that's wrong for ADL-P regardless of tiling. Most likely candidates:

  1. Pipe scaler — V400 (setupPipeScaler) may be applying wrong scale factor or wrong source window size. If it's scaling from the wrong source dimensions, the image repeats/tiles.
  2. PLANE_SIZE / PLANE_POS — plane dimensions might be set for a smaller surface than the actual display area.
  3. PIPE_SRCSZ mismatch — source size in CRTCParams doesn't match actual framebuffer size.

The 8-shapes-per-side pattern specifically suggests a scaler tiling artifact — like the scaler is treating a quarter-size buffer as the source and tiling it 8 times to fill the screen.

NootedGreen    ngreen: @ V400[1]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[1]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[2]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[2]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[3]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[3]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[4]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[4]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x412be000 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[5]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[5]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x412be000 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[6]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[6]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[7]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[7]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[8]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[8]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x40396000 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[9]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[9]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x40396000 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[10]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[10]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[11]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[11]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V400[12]: setupPipeScaler base-ok gates[+0x1E3,+0x1E5]=(0x00,0x00) PRE: SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 | POST: SRC=2560x1600 SEAM=0x0 WINSZ=0x0 WINPOS=0x0 HPHASE=0x0 HTOTAL=0xa9f09ff VTOTAL=0x6d5063f TRANS_CONF=0xc0000024
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[12]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x4035e000 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[13]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x4035e000 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[14]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[15]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[16]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x4035e000 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[17]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x4035e000 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[18]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V401, original ret [1]
NootedGreen    ngreen: @ V401[19]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
NootedGreen    ngreen: @ V401, original ret [0]
NootedGreen    ngreen: @ V401[20]: paramsSurfCompare ret=1 | OLD: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x0 SRC=0x9ff063f | NEW: CTL=0x94000008 tile=0 STRIDE=0xa0 SURF=0x4035e000 SRC=0x9ff063f | NAT_CTL=0x94000008 nat_tile_pl1=0 NAT_CTL=0x94000408 nat_tile_pl2=1 nat_stride_pl1=0xa0 nat_stride_pl2=0x14
 

Posted (edited)

did u test the production frameb?

code not the same as debug

 

check xlog if u have this then

display firmware is using correct registers

if zero it will use phyB

same logic as in icl

image.png.e492becc4150e26221dec16d3b55b29a.png

 

here in my ghidra

linux as macros for this regs i hope all ok

in cstate

image.png.27af663f2e27461a135977c2aeb073fe.png

 

and here

image.png.66251041f57c2d8e276697c8e593042a.png

 

w8 i think i swap the value. gonna do a test

pci hardware log line is

image.png.d08dfbf882cd9eb07428b61fc6cf5e54.png

Edited by jalavoui

V205 at line 515 (after cycle 5): SURF=412be000 LIVE=412be000 — the surface DID get written to hardware briefly.
V205 at line 546 (cycle 7): SURF=00000000 LIVE=00000000 — and it was reset back to black.
V401[5]: OLD=0x412be000, NEW=0x0 — Apple immediately REMOVES the surface it just showed.

The display is doing the correct blank → real → blank init sequence — the "disabling black black" pattern — but it never exits that loop.

There's also a logging bug in V401 (kern_gen11.cpp:1801) — nat_tile_pl2 is passed twice, shifting all subsequent NAT args. The real signal buried in there: nat_tile_pl2=1 (original pl2 has X-tiling), which we patch away to linear. That may cause CoreDisplay to see garbled content and restart.

But the user is right: the problem is earlier. Here's what's driving the restart loop:

V71[2]: post-stop ERR=0x7b cleared
V71[3]: post-stop ERR=0x7b cleared   ← every single stop after the first
V71[4]: post-stop ERR=0x7b cleared
...

ERROR_GEN6=0x7b fires on every stop from cycle 2 onward (cycle 1 is clean). 0x7b = bits 0,1,3,4,5,6 — instruction error + master error + several others — consistently generated whenever Apple's stop sequence runs with an active EXECLIST context (EXEC=0x18001). Our V71 clears them, but Apple may check ERROR_GEN6 during its stop (before our V71 POST runs), see the errors, and schedule a full display reinit.

The second driver: the frame counter jump between cycles 5→6: FRM 7912 → 17898 — a gap of ~10000 frames. The V97C comment says exactly this: "checkLinkStatus detects ~10 s later and tears down the display." Something after V97C's suppression is still allowing the link alignment to be lost on the second pass through init.

So there are two triggers working together:

  1. ERROR_GEN6=0x7b every stop → Apple's stop path sees GPU errors → reinit cycle
  2. DP link checkLinkStatus fires after ~10s of the first "stable" period → tears down, reinit

The user's message "no stop triggers, only start fires" in the newer version suggests the GPU error path may now be causing Apple to skip the stop entirely and just call start repeatedly — a degenerate recovery mode.

What specific things are we logging about the V53[1] first stop that's CLEAN vs V53[2] which generates 0x7b? The first stop happens before any GPU context has run. After the first startGraphicsEngine, the EXECLIST context (0x18001) is active. Every subsequent stop hits that context mid-flight and generates the errors.

Posted (edited)

I'm in the perfect commit to start to study... for prod version is too early for me... need to solve various situation

Lilu_fb+hw-recycling.txt.txt Lilu_fbonly_notrecycling.txt fbonly.log

x-fbonly..log.zip

Edited by Stezza88

wrapFBStart()
  └─ orig FBController::start() → returns 1          ← line 109
  └─ service->registerService()                       ← line 110
       └─ IOKit synchronous match → Gen11::start()
            ├─ V44: inject GraphicsSchedulerSelect    ← line 111-112
            ├─ inject MultiForceWakeSelect=1          ← line 113
            ├─ Pre-start: acquire ForceWake           ← line 114
            ├─ GGTT PTE dump                          ← lines 116-125
            ├─ GDRST + TLB flush
            └─ orig IntelAccelerator::start()
Posted (edited)

CoreDisplay IS running after startup. It IS trying to flip:

  • V401[4]: SURF=0x0 → 0x412be000 — real framebuffer address assigned
  • V205[c=30]: SURF=412be000 LIVE=412be000 — one successful flip
  • Then back to SURF=0x0 LIVE=0x0 every subsequent cycle

The GPU pipeline IS alive. The stamp issue caused a delayed start but the display loop IS running. The problem is the surface address cycling back to zero — that is the dp0/PLANE_SURF corruption issue from your prior work, not the interrupt delivery.

why does SURF go 0→real→0 repeatedly instead of sticking at 0x412be000. That's where the black screen lives

 

 

There are three smoking guns in this cycle. Let me lay them out:

Gun 1 — original ret [0] at lines 494 and 517: paramsSurfCompare returns false = planes are identical except SURF. Apple only wants a SURF-only fast-path (just write PLANE_SURF, skip full reprogram). Our hook forces ret=true when SURF changes, which is correct. But this means the cycle is Apple-driven — Apple is the one passing SURF=0x0 at V401[5].

Gun 2 — idx=255 and tl=deadbeef at line 490:

V201[4]: surf=0x412be000 idx=255 tile=0 | tl=deadbeef ctr=deadbeef bar=deadbeef mid=deadbeef

Every prior call had idx=0. idx=255 = 0xFF = likely a fallback/emergency allocation Apple takes when normal framebuffer allocation fails. The buffer contains deadbeef — our debug fill, confirming it's freshly allocated and never written with real pixel data.

Gun 3 — param2=0 abort fires immediately after startGraphicsEngine (line 500):

V163: startGraphicsEngine (ret=1323798017)
DIAG[BM]: bitmask 0x200 param2=0           ← teardown
V405[5]: configureColorPipeLine param2=0   ← pipeline abort
DIAG[BM]: bitmask 0x100 param2=1           ← immediate re-enable

The abort happens because the display hardware cannot read from SURF=0x412be000. The most likely reason: the GGTT PTE for page 0x412be is missing the LLC-coherency bit (bit[3]) that the display controller requires for plane surface access — the CPU can read from it (hence deadbeef visible via V201) but the display engine can't.

The cycle explained:

Apple allocates idx=255 emergency surface at 0x412be000
  → GGTT PTE lacks LLC-coherency for display
  → display controller fails to scan out
  → startGraphicsEngine fires (internal retry)
  → param2=0 abort triggered
  → Apple resets SURF → 0x0 and retries from scratch
  → loops indefinitely
Edited by Stezza88

uint32_t tlCtr = 0xDEADBEEF, ctr = 0xDEADBEEF, bar = 0xDEADBEEF, mid = 0xDEADBEEF;
if (NGreen::callback->aperturePtr && surfAddr + 0xA00000 <= NGreen::callback->apertureLen) {

The aperture is 0x10000000 (256MB, logged at startup). The condition for V201[4]:

0x412be000 + 0xA00000 = 0x4B2BE000 > 0x10000000  →  CONDITION FAILS

The deadbeef values are NOT pixel data — they're the unread sentinel. The surface at 0x412be000 is outside the CPU aperture (BAR2). We never read the buffer at all.

The stolen memory layout is now clear. fStolenMemorySize = 4000000 is hex = 0x4000000 = 64MB, exactly matching StolenMemorySize = 67108864. Apple's FB manager owns GGTT 0x0→0x4000000. The surface at 0x412be000 is ~1.04GB into GGTT — completely outside stolen memory — and needs real system-memory GGTT PTEs set up by Metal/GPU on allocation.

The V201 PTE=0 is almost certainly a ForceWake readback artifact. The proof: surf=0x0 (stolen base, must be mapped) also shows PTE=0. GGTT reads at 0x800000+ need GT ForceWake held, and wrapHwSetupMemory runs in FB controller context with no ForceWake.

We already have ForceWake inside HANGCHECK (lines 8230–8305). Let me add PTE reads there — first for GGTT page 0 (will prove the ForceWake hypothesis) then for current PLANE_SURF

Here's what V202 will tell us on the next boot:

HANGCHECK V202: GGTT[0] — This is the gold standard sanity check. GGTT page 0 is the very first 4KB of stolen memory, mapped by BIOS/UEFI before macOS boots. It must show present=1. If it shows present=0 here — with ForceWake confirmed held — the GGTT base address 0x800000 is wrong for this chip revision and every PTE read we've ever done has been garbage.

HANGCHECK V202: PLANE_SURF — This reads the live display register and then the PTE for whatever surface the display engine is currently trying to scan from. Two outcomes matter:

  • present=1 llc=1 → PTEs are there, DMA should work, the pipeline abort is from something else entirely
  • present=0 → PTEs are genuinely absent for the surface the display engine is pointed at — the display DMA is faulting, which directly causes configureColorPipeLine(param2=false)

The stolen memory layout from Apple's debug output confirms the surface at 0x412be000 (~1.04GB GGTT) is far outside the 64MB stolen region and needs Metal/GPU to map system RAM pages into GGTT. The idx=255 at fb+0x4288 suggests hwSetupMemory is taking an error path rather than completing a proper GGTT setup — that field normally holds the stolen memory slot index, and 255 means it fell through without finding one.

×
×
  • Create New...