⬢ DragonFlyBSD Kernel Audit
DF-5135 / i915_probe.c
← back to finding ↓ download raw
/*
 * i915_probe.c -- kmod PoC helper for DF-5135
 * (TUNABLE_bool() in sys/dev/drm/include/linux/moduleparam.h casts a 1-byte
 *  _Bool param to (int *) and kgetenv_int() stores 4 bytes, corrupting the
 *  following params in struct i915_params).
 *
 * Reads the real i915_modparams symbol out of i915.ko at the offsets of the
 * trailing bool block (identical ABI to the struct in i915_params.h).
 *
 * Must be kldload'ed AFTER i915.ko.
 */
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/stdint.h>

/* exact replica of struct i915_params member order (i915_params.h) */
struct probe_params {
	char *vbt_firmware;
	int modeset, lvds_channel_mode, panel_use_ssc, vbt_sdvo_panel_type;
	int enable_dc, enable_fbc, enable_ppgtt, enable_psr, disable_power_well;
	int enable_ips, invert_brightness, enable_guc, guc_log_level;
	char *guc_firmware_path, *huc_firmware_path, *dmc_firmware_path;
	int mmio_debug, edp_vswing, reset;
	unsigned int inject_load_failure;
	_Bool alpha_support, enable_hangcheck, fastboot, prefault_disable,
	    load_detect_test, force_reset_modeset_test, error_capture,
	    disable_display, verbose_state_checks, nuclear_pageflip,
	    enable_dp_mst, enable_dpcd_backlight, enable_gvt;
};

extern unsigned char i915_modparams[];	/* the real thing, from i915.ko */

#define POFF(m)	((int)(unsigned long)&((struct probe_params *)0)->m)

static int
probe_show(SYSCTL_HANDLER_ARGS)
{
	unsigned char *p = i915_modparams;
	int out = p[POFF(verbose_state_checks)];

	kprintf("dmabug: i915_modparams @ %p (sizeof=%zu)\n",
		i915_modparams, sizeof(struct probe_params));
	kprintf("dmabug:   error_capture=%d  disable_display=%d  "
		"verbose_state_checks=%d  nuclear_pageflip=%d\n"
		"dmabug:   (defaults were:            1               0"
		"                 1                    0)\n",
		p[POFF(error_capture)], p[POFF(disable_display)],
		p[POFF(verbose_state_checks)], p[POFF(nuclear_pageflip)]);
	kprintf("dmabug:   enable_dp_mst=%d enable_dpcd_backlight=%d "
		"enable_gvt=%d (last member; 4-byte store ends in padding)\n",
		p[POFF(enable_dp_mst)], p[POFF(enable_dpcd_backlight)],
		p[POFF(enable_gvt)]);
	kprintf("dmabug:   enable_hangcheck=%d fastboot=%d "
		"prefault_disable=%d load_detect_test=%d\n",
		p[POFF(enable_hangcheck)], p[POFF(fastboot)],
		p[POFF(prefault_disable)], p[POFF(load_detect_test)]);
	return sysctl_handle_int(oidp, &out, 0, req);
}

SYSCTL_NODE(_hw, OID_AUTO, i915probe, CTLFLAG_RW, 0, "i915 param probe");
SYSCTL_PROC(_hw_i915probe, OID_AUTO, params,
	CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_ANYBODY,
	NULL, 0, probe_show, "I", "dump trailing bool block of i915_modparams");

static int
probe_modevent(module_t mod, int type, void *data)
{
	switch (type) {
	case MOD_LOAD:
		kprintf("dmabug: i915 probe loaded; i915_modparams=%p "
			"(error_capture@%d verbose_state_checks@%d "
			"enable_gvt@%d)\n", i915_modparams,
			POFF(error_capture), POFF(verbose_state_checks),
			POFF(enable_gvt));
		return 0;
	case MOD_UNLOAD:
		return 0;
	}
	return 0;
}

static moduledata_t probe_mod = { "i915probe", probe_modevent, NULL };
DECLARE_MODULE(i915probe, probe_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);