Serialize multiline printks

A lot of times the kernel will do a series of printks as part of a larger
call.  Backtraces, tabs for formatting, ASCII giraffes, you name it.

To prevent these prints from interleaving with other (atomic) printks, we
can use the print_lock().  There were at least two cases where the
print_lock() replaced an already-existing spinlock that served a similar
purpose.

Additionally, there were a few places that just lacked a \n, which would be
hard to read.  Those usually needed to be warn() anyway.  And of course
there was a printk("YOU SHOULD PANIC (stuff)"), which is now a panic.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/arch/x86/bitmask.h b/kern/arch/x86/bitmask.h
index be6e6be..f3c8798 100644
--- a/kern/arch/x86/bitmask.h
+++ b/kern/arch/x86/bitmask.h
@@ -91,6 +91,7 @@
 #define PRINT_BITMASK(name, size) { \
 	int i;	\
 	int _size = size; \
+	print_lock(); \
 	for (i = 0; i < BYTES_FOR_BITMASK(size); i++) { \
 		int j;	\
 		for (j = 0; j < MIN(8, _size); j++) { \
@@ -99,4 +100,5 @@
 		} \
 	} \
 	printk("\n"); \
+	print_unlock(); \
 }
diff --git a/kern/arch/x86/ioapic.c b/kern/arch/x86/ioapic.c
index 31df9cf..c4d760c 100644
--- a/kern/arch/x86/ioapic.c
+++ b/kern/arch/x86/ioapic.c
@@ -450,14 +450,14 @@
 {
 	struct Rdt *rdt;
 	if (apic_vector < IdtIOAPIC || apic_vector > MaxIdtIOAPIC) {
-		printk("ioapic vector %d out of range", apic_vector);
+		warn("ioapic vector %d out of range", apic_vector);
 		return 0;
 	}
 	/* Fortunately rdtvecno[vecno] is static once assigned. o/w, we'll need some
 	 * global sync for the callers, both for lookup and keeping rdt valid. */
 	rdt = rdtvecno[apic_vector];
 	if (!rdt) {
-		printk("vector %d has no RDT! (did you enable it?)", apic_vector);
+		warn("vector %d has no RDT! (did you enable it?)", apic_vector);
 		return 0;
 	}
 	return rdt;
@@ -588,7 +588,7 @@
 		case BusPCI:
 			pcidev = pci_match_tbdf(irq_h->tbdf);
 			if (!pcidev) {
-				printk("No PCI dev for tbdf %p!", irq_h->tbdf);
+				warn("No PCI dev for tbdf %p!", irq_h->tbdf);
 				return -1;
 			}
 			if ((vecno = msi_irq_enable(irq_h, pcidev)) != -1)
diff --git a/kern/arch/x86/kdebug.c b/kern/arch/x86/kdebug.c
index 7042d26..3b740f8 100644
--- a/kern/arch/x86/kdebug.c
+++ b/kern/arch/x86/kdebug.c
@@ -400,6 +400,7 @@
 /* Assumes 32-bit header */
 void print_fpu_state(struct ancillary_state *fpu)
 {
+	print_lock();
 	printk("fcw:        0x%04x\n", fpu->fp_head_n64.fcw);
 	printk("fsw:        0x%04x\n", fpu->fp_head_n64.fsw);
 	printk("ftw:          0x%02x\n", fpu->fp_head_n64.ftw);
@@ -417,4 +418,5 @@
 		printk("%02x ", *((uint8_t*)fpu + i));
 	}
 	printk("\n");
+	print_unlock();
 }
diff --git a/kern/arch/x86/pmap64.c b/kern/arch/x86/pmap64.c
index 69a653f..ea1924a 100644
--- a/kern/arch/x86/pmap64.c
+++ b/kern/arch/x86/pmap64.c
@@ -561,7 +561,7 @@
 
 	if (memcpy_from_user(p, &pte, &u_pml[PMLx(gva, pml_shift)],
 	                     sizeof(kpte_t))) {
-		printk("Buggy pml %p, tried %p\n", u_pml, &u_pml[PMLx(gva, pml_shift)]);
+		warn("Buggy pml %p, tried %p\n", u_pml, &u_pml[PMLx(gva, pml_shift)]);
 		return 0;
 	}
 	if (walk_is_complete(&pte, pml_shift, flags))
@@ -721,6 +721,7 @@
 {
 	if (kpte_is_unmapped(kpte))
 		return 0;
+	print_lock();
 	switch (shift) {
 		case (PML1_SHIFT):
 			printk("\t");
@@ -733,6 +734,7 @@
 	}
 	printk("KVA: %p, PTE val %p, shift %d, visit %d%s\n", kva, *kpte, shift,
 	       visited_subs, (*kpte & PTE_PS ? " (jumbo)" : ""));
+	print_unlock();
 	return 0;
 }
 
diff --git a/kern/arch/x86/trap.c b/kern/arch/x86/trap.c
index 82089b4..01b0dd5 100644
--- a/kern/arch/x86/trap.c
+++ b/kern/arch/x86/trap.c
@@ -209,9 +209,11 @@
 {
 	uint16_t fpcw, fpsw;
 	uint32_t mxcsr;
+
 	asm volatile ("fnstcw %0" : "=m"(fpcw));
 	asm volatile ("fnstsw %0" : "=m"(fpsw));
 	asm volatile ("stmxcsr %0" : "=m"(mxcsr));
+	print_lock();
 	print_trapframe(hw_tf);
 	printk("Core %d: FP ERR, CW: 0x%04x, SW: 0x%04x, MXCSR 0x%08x\n", core_id(),
 	       fpcw, fpsw, mxcsr);
@@ -237,6 +239,7 @@
 		printk("\tNumeric Underflow\n");
 	if (fpsw & ~fpcw & FP_EXCP_PE)
 		printk("\tInexact result (precision)\n");
+	print_unlock();
 }
 
 static bool __handler_user_page_fault(struct hw_trapframe *hw_tf,
diff --git a/kern/arch/x86/trap.h b/kern/arch/x86/trap.h
index e8820b6..0f9a7a8 100644
--- a/kern/arch/x86/trap.h
+++ b/kern/arch/x86/trap.h
@@ -270,7 +270,7 @@
 
 
 	if (err) {
-		printk("Error restoring fp state!");
+		printk("Error restoring fp state!\n");
 		printk("Likely a bad ancillary_state argument.\n");
 		printk("Re-initializing fp state to default due to error.\n");
 		init_fp_state();
diff --git a/kern/arch/x86/vmm/intel/vmx.c b/kern/arch/x86/vmm/intel/vmx.c
index b925d6d..abe3b2f 100644
--- a/kern/arch/x86/vmm/intel/vmx.c
+++ b/kern/arch/x86/vmm/intel/vmx.c
@@ -212,6 +212,8 @@
 	int crnr = val & 0xf;
 	int type = (val >> 4) & 3;
 	int reg = (val >> 11) & 0xf;
+
+	print_lock();
 	printk("%s: %d: ", cr_access_type[type], crnr);
 	if (type < 2) {
 		printk("%s", cr_gpr[reg]);
@@ -220,6 +222,7 @@
 		}
 	}
 	printk("\n");
+	print_unlock();
 }
 
 void
diff --git a/kern/drivers/dev/kfs.c b/kern/drivers/dev/kfs.c
index b701a1d..3a5541e 100644
--- a/kern/drivers/dev/kfs.c
+++ b/kern/drivers/dev/kfs.c
@@ -224,8 +224,8 @@
 		break;
 	default:
 		cclose(c);
-		printk("Unknown file type %d in the CPIO!",
-		       c_bhdr->c_mode & CPIO_FILE_MASK);
+		warn("Unknown file type %d in the CPIO!",
+		     c_bhdr->c_mode & CPIO_FILE_MASK);
 		return -1;
 	}
 	if (!c)
diff --git a/kern/drivers/net/mlx4/en_main.c b/kern/drivers/net/mlx4/en_main.c
index f1c7911..f8667c0 100644
--- a/kern/drivers/net/mlx4/en_main.c
+++ b/kern/drivers/net/mlx4/en_main.c
@@ -95,6 +95,7 @@
 #else
 	va_list args;
 
+	print_lock();
 	va_start(args, format);
 	if (priv->registered)
 		printk("%s%s: %s: ", level, DRV_NAME, priv->dev->name);
@@ -103,6 +104,7 @@
 		       dev_name(&priv->mdev->pdev->dev), priv->port);
 	vcprintf(format, args);
 	va_end(args);
+	print_unlock();
 #endif
 }
 
diff --git a/kern/drivers/net/r8169.c b/kern/drivers/net/r8169.c
index 52844a2..93f0113 100644
--- a/kern/drivers/net/r8169.c
+++ b/kern/drivers/net/r8169.c
@@ -8664,7 +8664,7 @@
 	spin_unlock(&rtl_9ns_lock);
 
 	if (rtl_open(edev)) {
-		printk("Unable to attach rtl8169!");
+		warn("Unable to attach rtl8169!");
 		return;
 	}
 	/* If we want an rproc, nows the time to ktask it */
diff --git a/kern/src/hexdump.c b/kern/src/hexdump.c
index 6b81d42..547979a 100644
--- a/kern/src/hexdump.c
+++ b/kern/src/hexdump.c
@@ -39,6 +39,7 @@
 	uintptr_t memory = (uintptr_t) v;
 	int all_zero = 0;
 
+	print_lock();
 	for (i = 0; i < length; i += 16) {
 		int j;
 
@@ -62,6 +63,7 @@
 			printk("...\n");
 		}
 	}
+	print_unlock();
 }
 
 /* easier in monitor */
diff --git a/kern/src/kdebug.c b/kern/src/kdebug.c
index 6937d6d..9841484 100644
--- a/kern/src/kdebug.c
+++ b/kern/src/kdebug.c
@@ -95,8 +95,6 @@
 	tab_depth = 0;
 }
 
-static spinlock_t lock = SPINLOCK_INITIALIZER_IRQSAVE;
-
 static void __print_hdr(void)
 {
 	struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
@@ -117,14 +115,15 @@
 {
 	char tentabs[] = "\t\t\t\t\t\t\t\t\t\t"; // ten tabs and a \0
 	char *ourtabs = &tentabs[10 - MIN(tab_depth, 10)];
+
 	if (!printx_on)
 		return;
 	if (is_blacklisted(func))
 		return;
-	spin_lock_irqsave(&lock);
+	print_lock();
 	__print_hdr();
 	printk("%s%s() in %s\n", ourtabs, func, file);
-	spin_unlock_irqsave(&lock);
+	print_unlock();
 	tab_depth++;
 }
 
@@ -132,16 +131,17 @@
 {
 	char tentabs[] = "\t\t\t\t\t\t\t\t\t\t"; // ten tabs and a \0
 	char *ourtabs;
+
 	if (!printx_on)
 		return;
 	if (is_blacklisted(func))
 		return;
 	tab_depth--;
 	ourtabs = &tentabs[10 - MIN(tab_depth, 10)];
-	spin_lock_irqsave(&lock);
+	print_lock();
 	__print_hdr();
 	printk("%s---- %s()\n", ourtabs, func);
-	spin_unlock_irqsave(&lock);
+	print_unlock();
 }
 
 bool printx_on = FALSE;
@@ -215,8 +215,10 @@
 
 void backtrace(void)
 {
+	print_lock();
 	printk("Stack Backtrace on Core %d:\n", core_id());
 	gen_backtrace(&printk_func, NULL);
+	print_unlock();
 }
 
 void backtrace_frame(uintptr_t eip, uintptr_t ebp)
@@ -224,8 +226,10 @@
 	uintptr_t pcs[MAX_BT_DEPTH];
 	size_t nr_pcs = backtrace_list(eip, ebp, pcs, MAX_BT_DEPTH);
 
+	print_lock();
 	printk("\nBacktrace of kernel context on Core %d:\n", core_id());
 	print_backtrace_list(pcs, nr_pcs, &printk_func, NULL);
+	print_unlock();
 }
 
 /* TODO: change debug_addr_proc() to allow print redirection like
@@ -233,8 +237,10 @@
 void backtrace_user_frame(uintptr_t eip, uintptr_t ebp)
 {
 	uintptr_t pcs[MAX_BT_DEPTH];
+	/* TODO: this assumes we have the user's address space loaded (current). */
 	size_t nr_pcs = backtrace_user_list(eip, ebp, pcs, MAX_BT_DEPTH);
 
+	print_lock();
 	printk("\nBacktrace of user context on Core %d:\n", core_id());
 	printk("\tOffsets only matter for shared libraries\n");
 	/* This formatting is consumed by scripts/bt-akaros.sh. */
@@ -243,23 +249,19 @@
 		/* TODO: user backtraces all assume we're working on 'current' */
 		debug_addr_proc(current, pcs[i]);
 	}
+	print_unlock();
 }
 
 void backtrace_hwtf(struct hw_trapframe *hw_tf)
 {
-	struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-
-	pcpui->__lock_checking_enabled--;
 	if (in_kernel(hw_tf))
 		backtrace_frame(get_hwtf_pc(hw_tf), get_hwtf_fp(hw_tf));
 	else
 		backtrace_user_frame(get_hwtf_pc(hw_tf), get_hwtf_fp(hw_tf));
-	pcpui->__lock_checking_enabled++;
 }
 
 void backtrace_user_ctx(struct proc *p, struct user_context *ctx)
 {
-	struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
 	uintptr_t st_save;
 
 	if (!ctx) {
@@ -267,9 +269,7 @@
 		return;
 	}
 	st_save = switch_to(p);
-	pcpui->__lock_checking_enabled--;
 	backtrace_user_frame(get_user_ctx_pc(ctx), get_user_ctx_fp(ctx));
-	pcpui->__lock_checking_enabled++;
 	switch_back(p, st_save);
 }
 
diff --git a/kern/src/mm.c b/kern/src/mm.c
index fc5dc4f..8d51536 100644
--- a/kern/src/mm.c
+++ b/kern/src/mm.c
@@ -602,6 +602,8 @@
 {
 	int count = 0;
 	struct vm_region *vmr;
+
+	print_lock();
 	printk("VM Regions for proc %d\n", p->pid);
 	printk("NR:"
 	       "                                     Range:"
@@ -613,6 +615,7 @@
 		printk("%02d: (%p - %p): 0x%08x, 0x%08x, %p, %p\n", count++,
 		       vmr->vm_base, vmr->vm_end, vmr->vm_prot, vmr->vm_flags,
 		       foc_pointer(vmr->__vm_foc), vmr->vm_foff);
+	print_unlock();
 }
 
 void enumerate_vmrs(struct proc *p,
diff --git a/kern/src/monitor.c b/kern/src/monitor.c
index 6a5fcaf..be56b11 100644
--- a/kern/src/monitor.c
+++ b/kern/src/monitor.c
@@ -120,8 +120,10 @@
 	}
 	pc = strtol(argv[1], 0, 16);
 	fp = strtol(argv[2], 0, 16);
+	print_lock();
 	printk("Backtrace from instruction %p, with frame pointer %p\n", pc, fp);
 	backtrace_frame(pc, fp);
+	print_unlock();
 	return 0;
 }
 
@@ -187,13 +189,11 @@
 	return __showmapping(argc, argv, hw_tf);
 }
 
-static spinlock_t print_info_lock = SPINLOCK_INITIALIZER_IRQSAVE;
-
 static void print_info_handler(struct hw_trapframe *hw_tf, void *data)
 {
 	uint64_t tsc = read_tsc();
 
-	spin_lock_irqsave(&print_info_lock);
+	print_lock();
 	cprintf("----------------------------\n");
 	cprintf("This is Core %d\n", core_id());
 	cprintf("Timestamp = %lld\n", tsc);
@@ -218,7 +218,7 @@
 	        read_msr(0x20e), read_msr(0x20f));
 #endif // CONFIG_X86
 	cprintf("----------------------------\n");
-	spin_unlock_irqsave(&print_info_lock);
+	print_unlock();
 }
 
 static bool print_all_info(void)
@@ -254,6 +254,7 @@
 	/* Borrowed with love from http://www.geocities.com/SoHo/7373/zoo.htm
 	 * (http://www.ascii-art.com/).  Slightly modified to make it 25 lines tall.
 	 */
+	print_lock();
 	printk("\n");
 	printk("             .-.  .-.\n");
 	printk("             |  \\/  |\n");
@@ -278,6 +279,7 @@
 	printk("                                \\'   .\\#\n");
 	printk("                             jgs \\   ::\\#\n");
 	printk("                                  \\      \n");
+	print_unlock();
 	return 0;
 }
 
@@ -681,6 +683,7 @@
 static void emit_hwtf_backtrace(struct hw_trapframe *hw_tf)
 {
 	if (mon_verbose_trace) {
+		printk("\n");
 		print_trapframe(hw_tf);
 		backtrace_hwtf(hw_tf);
 	}
@@ -690,8 +693,10 @@
 
 static void emit_vmtf_backtrace(struct vm_trapframe *vm_tf)
 {
-	if (mon_verbose_trace)
+	if (mon_verbose_trace) {
+		printk("\n");
 		print_vmtrapframe(vm_tf);
+	}
 	printk("Core %d is at %p\n", core_id(), get_vmtf_pc(vm_tf));
 }
 
@@ -700,22 +705,18 @@
  * doesn't deal in contexts (yet) */
 void emit_monitor_backtrace(int type, void *tf)
 {
-	struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-
 	if (!PERCPU_VAR(mon_nmi_trace))
 		return;
 	/* To prevent a spew of output during a lot of perf NMIs, we'll turn off the
 	 * monitor output as soon as any NMI hits our core. */
 	PERCPU_VAR(mon_nmi_trace) = FALSE;
-	/* Temporarily disable deadlock detection when we print.  We could
-	 * deadlock if we were printing when we NMIed. */
-	pcpui->__lock_checking_enabled--;
+	print_lock();
 	if (type == ROS_HW_CTX)
 		emit_hwtf_backtrace((struct hw_trapframe*)tf);
 	else
 		emit_vmtf_backtrace((struct vm_trapframe*)tf);
 	print_kmsgs(core_id());
-	pcpui->__lock_checking_enabled++;
+	print_unlock();
 }
 
 
diff --git a/kern/src/ns/allocb.c b/kern/src/ns/allocb.c
index 427cd13..f02ae7a 100644
--- a/kern/src/ns/allocb.c
+++ b/kern/src/ns/allocb.c
@@ -312,6 +312,7 @@
 		return;
 	}
 
+	print_lock();
 	printk("block of BLEN = %d, with %d header and %d data in %d extras\n",
 	       BLEN(b), BHLEN(b), b->extra_len, b->nr_extra_bufs);
 
@@ -345,4 +346,5 @@
 		}
 	}
 	printk("\n");
+	print_unlock();
 }
diff --git a/kern/src/ns/convM2D.c b/kern/src/ns/convM2D.c
index 1492751..bbc027c 100644
--- a/kern/src/ns/convM2D.c
+++ b/kern/src/ns/convM2D.c
@@ -48,10 +48,8 @@
 	ebuf = buf + nbuf;
 
 	if (nbuf < STAT_FIX_LEN_9P || nbuf != BIT16SZ + GBIT16(buf)) {
-		printk("nbuf %d, STAT_FIX_LEN_9P %d ", nbuf, STAT_FIX_LEN_9P);
-		printk("BIT16SZ %d, GBIT16(buf) %d ",
-			BIT16SZ, GBIT16(buf));
-		printk("This is bad!\n");
+		warn("nbuf %d, STAT_FIX_LEN_9P %d BIT16SZ %d, GBIT16(buf) %d ",
+		     nbuf, STAT_FIX_LEN_9P, BIT16SZ, GBIT16(buf));
 		return -1;
 	}
 
diff --git a/kern/src/ns/sysfile.c b/kern/src/ns/sysfile.c
index dc6cf1f..af8340a 100644
--- a/kern/src/ns/sysfile.c
+++ b/kern/src/ns/sysfile.c
@@ -1393,6 +1393,7 @@
 	bool has_dev = c->type != -1;
 	bool has_chaninfo = has_dev && devtab[c->type].chaninfo;
 
+	print_lock();
 	printk("Chan flags: %p, pathname: %s, ref: %d, Dev: %s, Devinfo: %s",
 		   c->flag,
 		   c->name ? c->name->s : "no cname",
@@ -1402,6 +1403,7 @@
 	if (!has_chaninfo)
 		printk("qid.path: %p\n", c->qid.path);
 	printk("\n");
+	print_unlock();
 }
 
 /* TODO: 9ns ns inheritance flags: Shared, copied, or empty.  The old fgrp is
diff --git a/kern/src/ns/tree_file.c b/kern/src/ns/tree_file.c
index be21d2b..14e5f8d 100644
--- a/kern/src/ns/tree_file.c
+++ b/kern/src/ns/tree_file.c
@@ -1176,6 +1176,7 @@
 	    !!(tf->file.dir.qid.type & QTSYMLINK))
 		warn("%s has differing symlink bits", tree_file_to_name(tf));
 
+	print_lock();
 	for (int i = 0; i < tabs; i++)
 		printk("    ");
 	print_tf(tf);
@@ -1186,6 +1187,7 @@
 		list_for_each_entry(child, &tf->children, siblings)
 			dump_tf(child, tabs + 1);
 	}
+	print_unlock();
 }
 
 void __tfs_dump(struct tree_filesystem *tfs)
diff --git a/kern/src/process.c b/kern/src/process.c
index 336eeba..7c69f77 100644
--- a/kern/src/process.c
+++ b/kern/src/process.c
@@ -2390,6 +2390,7 @@
 		return;
 	}
 	vcpd = &p->procdata->vcore_preempt_data[0];
+	print_lock();
 	spinlock_debug(&p->proc_lock);
 	//spin_lock(&p->proc_lock); // No locking!!
 	printk("struct proc: %p\n", p);
@@ -2441,6 +2442,7 @@
 	if (spin_locked(&files->lock)) {
 		spinlock_debug(&files->lock);
 		printk("FILE LOCK HELD, ABORTING\n");
+		print_unlock();
 		proc_decref(p);
 		return;
 	}
@@ -2456,6 +2458,7 @@
 	printk("Children: (PID (struct proc *))\n");
 	TAILQ_FOREACH(child, &p->children, sibling_link)
 		printk("\t%d (%p)\n", child->pid, child);
+	print_unlock();
 	/* no locking / unlocking or refcnting */
 	// spin_unlock(&p->proc_lock);
 	proc_decref(p);
diff --git a/kern/src/rcu_tree_helper.c b/kern/src/rcu_tree_helper.c
index 4ba1db0..5c99032 100644
--- a/kern/src/rcu_tree_helper.c
+++ b/kern/src/rcu_tree_helper.c
@@ -249,6 +249,7 @@
 	int level = 0;
 	struct rcu_node *rnp;
 
+	print_lock();
 	printk("rcu_node tree layout dump\n");
 	printk(" ");
 	rcu_for_each_node_breadth_first(rsp, rnp) {
@@ -260,4 +261,5 @@
 		printk("%d:%d ^%d ", rnp->grplo, rnp->grphi, rnp->grpnum);
 	}
 	printk("\n");
+	print_unlock();
 }
diff --git a/kern/src/smp.c b/kern/src/smp.c
index 43ba748..55beb2f 100644
--- a/kern/src/smp.c
+++ b/kern/src/smp.c
@@ -191,9 +191,11 @@
 		func_name = get_fn_name(lock_addr);
 	else
 		func_name = "Dynamic lock";
+	print_lock();
 	printk("Time %uus, lock %p (%s)\n", te->arg0, lock_addr, func_name);
 	printk("\t");
 	spinlock_debug((spinlock_t*)lock_addr);
+	print_unlock();
 }
 
 /* Add specific trace handlers here: */
diff --git a/kern/src/syscall.c b/kern/src/syscall.c
index 27e770a..0b63102 100644
--- a/kern/src/syscall.c
+++ b/kern/src/syscall.c
@@ -2534,7 +2534,7 @@
 		       sc_num, syscall_table[sc_num].name, a0, a1, a2, a3,
 		       a4, a5, p->pid);
 		if (sc_num != SYS_fork)
-			printk("YOU SHOULD PANIC: errstack mismatch");
+			panic("errstack mismatch");
 	}
 	return ret;
 }