Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

#include <linux/lockdoc.h>
#include <linux/preempt.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/utsname.h>
#include <linux/sched.h>
#include <linux/string.h>
#include "kernelversion.gen.h"
//#define DBG_ASM_IRQ_TRACE

/* Since we run our experiment in a single-core environment, 
 * we can safely use *only* one buffer.
 * If someone wants to run the experiment on a multi-core system some day,
 * he or she has to allocate #cores vars.
 */
struct log_action la_buffer;

int32_t lockdoc_get_ctx(void) {
	if (in_irq()) {
		return -2;
	} else if (in_softirq() || in_serving_softirq()) {
		return -1;
	} else {
		return current->pid;
	}
}

#ifdef CONFIG_LOCKDOC
__visible void trace_hardirqs_on_caller(unsigned long ip) {
#ifdef DBG_ASM_IRQ_TRACE
	__log_lock(V_WRITE, PSEUDOLOCK_VAR_HARDIRQ, (void*)PSEUDOLOCK_ADDR_HARDIRQ, __FILE__, __LINE__,  __func__, PSEUDOLOCK_NAME_HARDIRQ, ip, 0);
#else
	log_lock(V_WRITE, PSEUDOLOCK_VAR_HARDIRQ, (void*)PSEUDOLOCK_ADDR_HARDIRQ, __FILE__, __LINE__,  __func__,0);
#endif
}
EXPORT_SYMBOL(trace_hardirqs_on_caller)

__visible void trace_hardirqs_off_caller(unsigned long ip) {
#ifdef DBG_ASM_IRQ_TRACE
	__log_lock(P_WRITE, PSEUDOLOCK_VAR_HARDIRQ, (void*)PSEUDOLOCK_ADDR_HARDIRQ, __FILE__, __LINE__,  __func__, PSEUDOLOCK_NAME_HARDIRQ, ip, 0);
#else
	log_lock(P_WRITE, PSEUDOLOCK_VAR_HARDIRQ, (void*)PSEUDOLOCK_ADDR_HARDIRQ, __FILE__, __LINE__,  __func__,0);
#endif
}
EXPORT_SYMBOL(trace_hardirqs_off_caller)
#endif

int log_preempt_count(void) {
	return preempt_count();
}
EXPORT_SYMBOL(log_preempt_count);

void lockdoc_send_current_task_addr(void) {
	unsigned long eflags;

	raw_local_irq_save(eflags);

	memset(&la_buffer,0,sizeof(la_buffer));

	la_buffer.action = LOCKDOC_CURRENT_TASK;
	la_buffer.ptr = (unsigned long)per_cpu_ptr(&current_task,0);
	outb_(PING_CHAR,IO_PORT_LOG);

	raw_local_irq_restore(eflags);
}

void lockdoc_send_preempt_count_addr(void) {
	unsigned long eflags;

	raw_local_irq_save(eflags);

	memset(&la_buffer,0,sizeof(la_buffer));

	la_buffer.action = LOCKDOC_PREEMPT_COUNT;
	la_buffer.ptr = (unsigned long)per_cpu_ptr(&__preempt_count,0);
	outb_(PING_CHAR,IO_PORT_LOG);

	raw_local_irq_restore(eflags);
}

void lockdoc_send_pid_offset(void) {
	unsigned long eflags;

	raw_local_irq_save(eflags);

	memset(&la_buffer,0,sizeof(la_buffer));

	la_buffer.action = LOCKDOC_PID_OFFSET;
	la_buffer.ptr = offsetof(struct task_struct, pid);
	outb_(PING_CHAR,IO_PORT_LOG);

	raw_local_irq_restore(eflags);
}

void lockdoc_send_kernel_version(void) {
	unsigned long eflags;

	raw_local_irq_save(eflags);

	memset(&la_buffer,0,sizeof(la_buffer));

        strncat((char*)&la_buffer.type, utsname()->release, LOG_CHAR_BUFFER_LEN);
        strncat((char*)&la_buffer.type, KERNEL_VERSION_EXTENDED, LOG_CHAR_BUFFER_LEN);
	la_buffer.action = LOCKDOC_KERNEL_VERSION;
	outb_(PING_CHAR,IO_PORT_LOG);

	raw_local_irq_restore(eflags);
}