aboutsummaryrefslogtreecommitdiffstats
path: root/nvdebug_entry.c
blob: 0854b8b138d46dbca6b57ea8c5fcc413bed5357d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* Copyright 2021 Joshua Bakita
 * SPDX-License-Identifier: MIT
 */

/* TODO
 * - Add sysfs trigger for a preemption
 */

#include <linux/device.h>  // For struct device, bus_find_device*(), struct bus_type
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h> // So we can set up entries in /proc

#include "nvdebug.h"

// LIAR. But without this we can't use GPL-only exported symbols like
// platform_bus_type or bus_find_device_by_name...
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joshua Bakita");
MODULE_DESCRIPTION("A scheduling debugging module for NVIDIA GPUs");
MODULE_SOFTDEP("pre: nvgpu"); // We only support the Jetson boards for now

extern const struct file_operations runlist_file_ops;
extern const struct file_operations preempt_tsg_file_ops;
extern const struct file_operations disable_channel_file_ops;
extern const struct file_operations enable_channel_file_ops;
extern const struct file_operations switch_to_tsg_file_ops;

int __init nvdebug_init(void) {
	struct proc_dir_entry *rl_entry, *preempt_entry, *disable_channel_entry,
			      *enable_channel_entry, *switch_to_tsg_entry;
	// Create file `/proc/preempt_tsg`, world readable
	rl_entry = proc_create("runlist", 0444, NULL, &runlist_file_ops);
	// Create file `/proc/preempt_tsg`, world writable
	preempt_entry = proc_create("preempt_tsg", 0222, NULL, &preempt_tsg_file_ops);
	// Create file `/proc/disable_channel`, world writable
	disable_channel_entry = proc_create("disable_channel", 0222, NULL, &disable_channel_file_ops);
	// Create file `/proc/enable_channel`, world writable
	enable_channel_entry = proc_create("enable_channel", 0222, NULL, &enable_channel_file_ops);
	// Create file `/proc/switch_to_tsg`, world writable
	switch_to_tsg_entry = proc_create("switch_to_tsg", 0222, NULL, &switch_to_tsg_file_ops);
	// ProcFS entry creation only fails if out of memory
	if (!rl_entry || !preempt_entry || !disable_channel_entry || !enable_channel_entry || !switch_to_tsg_entry) {
		remove_proc_entry("runlist", NULL);
		remove_proc_entry("preempt_tsg", NULL);
		remove_proc_entry("disable_channel", NULL);
		remove_proc_entry("enable_channel", NULL);
		remove_proc_entry("switch_to_tsg", NULL);
		printk(KERN_ERR "[nvdebug] Unable to initialize procfs entries!\n");
		return -ENOMEM;
	}
	printk(KERN_INFO "[nvdebug] Module version "GIT_HASH" initialized\n");
	return 0;
}

static void __exit nvdebug_exit(void) {
	remove_proc_entry("runlist", NULL);
	remove_proc_entry("preempt_tsg", NULL);
	remove_proc_entry("disable_channel", NULL);
	remove_proc_entry("enable_channel", NULL);
	remove_proc_entry("switch_to_tsg", NULL);
	printk(KERN_INFO "[nvdebug] Exiting...\n");
}

module_init(nvdebug_init);
module_exit(nvdebug_exit);