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 <sys/lockdoc.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <machine/pcpu.h>

//#define DEBUG_TRAPS
#ifdef LOCKDOC_RECORD
/*
 * 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 (curthread == NULL) {
		return 0;
	} else if (curthread->td_intr_nesting_level) {
		return -1;
	} else {
		return curthread->td_tid;
	}
}

void lockdoc_send_current_task_addr(void) {
	register_t flags;

	flags = lockdoc_intr_disable();

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

	la_buffer.action = LOCKDOC_CURRENT_TASK;
	la_buffer.ptr = (uint32_t)PCPU_PTR(curthread);
	__outb(PING_CHAR,IO_PORT_LOG);

	lockdoc_intr_restore(flags);
}

void lockdoc_send_irq_nest_offset(void) {
	register_t flags;

	flags = lockdoc_intr_disable();

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

	la_buffer.action = LOCKDOC_IRQ_NEST_OFFSET;
	la_buffer.ptr = offsetof(struct thread, td_intr_nesting_level);
	__outb(PING_CHAR,IO_PORT_LOG);

	lockdoc_intr_restore(flags);
}

void lockdoc_send_pid_offset(void) {
	register_t flags;

	flags = lockdoc_intr_disable();

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

	la_buffer.action = LOCKDOC_PID_OFFSET;
	la_buffer.ptr = offsetof(struct thread, td_tid);
	__outb(PING_CHAR,IO_PORT_LOG);

	lockdoc_intr_restore(flags);
}

void lockdoc_send_kernel_version(void) {
	register_t flags;

	flags = lockdoc_intr_disable();

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

	snprintf((char*)&la_buffer.type, LOG_CHAR_BUFFER_LEN, "%s", lockdoc_version);
	la_buffer.action = LOCKDOC_KERNEL_VERSION;
	__outb(PING_CHAR,IO_PORT_LOG);

	lockdoc_intr_restore(flags);
}

void trace_irqs_on(struct trapframe *frame) {
	register_t cur_eflags;
	cur_eflags = read_eflags();
	if ((frame->tf_eflags & (1 << 9)) && !(cur_eflags & (1 << 9))) {
#ifdef DEBUG_TRAPS
		log_lock(V_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, __FILE__, __LINE__, frame->tf_trapno);
#else
		log_lock(V_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, __FILE__, __LINE__, LOCK_NONE);
#endif
	}
}

void trace_irqs_off(struct trapframe *frame) {
	register_t cur_eflags;
	cur_eflags = read_eflags();
	if ((frame->tf_eflags & (1 << 9)) && !(cur_eflags & (1 << 9))) {
#ifdef DEBUG_TRAPS
		log_lock(P_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, __FILE__, __LINE__, frame->tf_trapno);
#else
		log_lock(P_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, __FILE__, __LINE__, LOCK_NONE);
#endif
	}
}

register_t __intr_disable(const char *file, int line, const char *func) {
	register_t eflags;

	eflags = read_eflags();
	lockdoc_disable_intr();
	if (eflags & (1 << 9)) {
		log_lock(P_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, file, line, 0); 
	}
	return (eflags);
}

void __intr_restore(register_t old_eflags, const char *file, int line, const char *func) {
	register_t cur_eflags;

	cur_eflags = read_eflags();
	// IRQ OFF (cur_eflags) --> IRQS ON (old_eflags)
	if (!(cur_eflags & (1 << 9)) && (old_eflags & (1 << 9))) {
		log_lock(V_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, file, line, 0); 
	// IRQS ON (cur_eflags) --> IRQS OFF (old_eflags)
	} else if ((cur_eflags & (1 << 9)) && !(old_eflags & (1 << 9))) {
		log_lock(P_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, file, line, 0); 
	}
	write_eflags(old_eflags);
}

void __disable_intr(const char *file, int line, const char *func) {
	register_t eflags;

	eflags = read_eflags();
	__asm __volatile("cli" : : : "memory");
	if (eflags & (1 << 9)) {
		log_lock(P_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, file, line, 0); 
	}
}

void __enable_intr(const char *file, int line, const char *func) {
	register_t eflags;

	eflags = read_eflags();
	if (!(eflags & (1 << 9))) {
		log_lock(V_WRITE, (struct lock_object*)PSEUDOLOCK_ADDR_HARDIRQ, file, line, 0); 
	}
	__asm __volatile("sti");
}
#endif //LOCKDOC_RECORD