#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