Index: sys/dev/vt/colors/vt_termcolors.h
===================================================================
--- sys/dev/vt/colors/vt_termcolors.h
+++ sys/dev/vt/colors/vt_termcolors.h
@@ -46,7 +46,18 @@
         COLOR_FORMAT_MAX = 15,
 };
 
+#define NCOLORS	16
+
+/*
+ * Between console's palette and VGA's one:
+ *   - blue and red are swapped (1 <-> 4)
+ *   - yellow and cyan are swapped (3 <-> 6)
+ */
+static const int cons_to_vga_colors[NCOLORS] = {
+	0,  4,  2,  6,  1,  5,  3,  7,
+	8, 12, 10, 14,  9, 13, 11, 15
+};
+
 /* Helper to fill color map used by driver */
 int vt_generate_cons_palette(uint32_t *palette, int format, uint32_t rmax,
     int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset);
-
Index: sys/dev/vt/colors/vt_termcolors.c
===================================================================
--- sys/dev/vt/colors/vt_termcolors.c
+++ sys/dev/vt/colors/vt_termcolors.c
@@ -38,8 +38,6 @@
 
 #include <dev/vt/colors/vt_termcolors.h>
 
-#define NCOLORS	16
-
 static struct {
 	unsigned char r;	/* Red percentage value. */
 	unsigned char g;	/* Green percentage value. */
@@ -64,16 +62,6 @@
 	{100,	100,	100},	/* white */
 };
 
-/*
- * Between console's palette and VGA's one:
- *   - blue and red are swapped (1 <-> 4)
- *   - yellow ad cyan are swapped (3 <-> 6)
- */
-static const int cons_to_vga_colors[NCOLORS] = {
-	0, 4, 2, 6, 1, 5, 3, 7,
-	0, 4, 2, 6, 1, 5, 3, 7
-};
-
 static int
 vt_parse_rgb_triplet(const char *rgb, unsigned char *r,
     unsigned char *g, unsigned char *b)
@@ -171,21 +159,21 @@
 {
 	int i;
 
-	vt_palette_init();
-
-#define	CF(_f, _i) ((_f ## max * color_def[(_i)]._f / 100) << _f ## offset)
-	for (i = 0; i < NCOLORS; i++) {
-		switch (format) {
-		case COLOR_FORMAT_VGA:
+	switch (format) {
+	case COLOR_FORMAT_VGA:
+		for (i = 0; i < NCOLORS; i++)
 			palette[i] = cons_to_vga_colors[i];
-			break;
-		case COLOR_FORMAT_RGB:
+		break;
+	case COLOR_FORMAT_RGB:
+		vt_palette_init();
+#define	CF(_f, _i) ((_f ## max * color_def[(_i)]._f / 100) << _f ## offset)
+		for (i = 0; i < NCOLORS; i++)
 			palette[i] = CF(r, i) | CF(g, i) | CF(b, i);
-			break;
-		default:
-			return (ENODEV);
-		}
-	}
 #undef	CF
+		break;
+	default:
+		return (ENODEV);
+	}
+
 	return (0);
 }
Index: sys/dev/vt/hw/vga/vt_vga.c
===================================================================
--- sys/dev/vt/hw/vga/vt_vga.c
+++ sys/dev/vt/hw/vga/vt_vga.c
@@ -43,6 +43,7 @@
 #include <sys/rman.h>
 
 #include <dev/vt/vt.h>
+#include <dev/vt/colors/vt_termcolors.h>
 #include <dev/vt/hw/vga/vt_vga_reg.h>
 #include <dev/pci/pcivar.h>
 
@@ -152,7 +153,7 @@
 		return;
 
 	REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_SET_RESET);
-	REG_WRITE1(sc, VGA_GC_DATA, color);
+	REG_WRITE1(sc, VGA_GC_DATA, cons_to_vga_colors[color]);
 	sc->vga_curfg = color;
 }
 
@@ -167,7 +168,7 @@
 		return;
 
 	REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_SET_RESET);
-	REG_WRITE1(sc, VGA_GC_DATA, color);
+	REG_WRITE1(sc, VGA_GC_DATA, cons_to_vga_colors[color]);
 
 	/*
 	 * Write 8 pixels using the background color to an off-screen
@@ -888,7 +889,9 @@
 			ch = vga_get_cp437(TCHAR_CHARACTER(c));
 
 			/* Convert colors to VGA attributes. */
-			attr = bg << 4 | fg;
+			attr =
+			    cons_to_vga_colors[bg] << 4 |
+			    cons_to_vga_colors[fg];
 
 			MEM_WRITE1(sc, (row * 80 + col) * 2 + 0,
 			    ch);
@@ -1114,43 +1117,45 @@
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(0));
 	REG_WRITE1(sc, VGA_AC_WRITE, 0);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(1));
-	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_R);
+	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_B);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(2));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_G);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(3));
-	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SG | VGA_AC_PAL_R);
+	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_G | VGA_AC_PAL_B);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(4));
-	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_B);
+	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_R);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(5));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_R | VGA_AC_PAL_B);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(6));
-	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_G | VGA_AC_PAL_B);
+	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SG | VGA_AC_PAL_R);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(7));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_R | VGA_AC_PAL_G | VGA_AC_PAL_B);
+
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(8));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
 	    VGA_AC_PAL_SB);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(9));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
-	    VGA_AC_PAL_SB | VGA_AC_PAL_R);
+	    VGA_AC_PAL_SB | VGA_AC_PAL_B);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(10));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
 	    VGA_AC_PAL_SB | VGA_AC_PAL_G);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(11));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
-	    VGA_AC_PAL_SB | VGA_AC_PAL_R | VGA_AC_PAL_G);
+	    VGA_AC_PAL_SB | VGA_AC_PAL_G | VGA_AC_PAL_B);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(12));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
-	    VGA_AC_PAL_SB | VGA_AC_PAL_B);
+	    VGA_AC_PAL_SB | VGA_AC_PAL_R);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(13));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
 	    VGA_AC_PAL_SB | VGA_AC_PAL_R | VGA_AC_PAL_B);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(14));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
-	    VGA_AC_PAL_SB | VGA_AC_PAL_G | VGA_AC_PAL_B);
+	    VGA_AC_PAL_SB | VGA_AC_PAL_R | VGA_AC_PAL_G);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(15));
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
 	    VGA_AC_PAL_SB | VGA_AC_PAL_R | VGA_AC_PAL_G | VGA_AC_PAL_B);
+
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_OVERSCAN_COLOR);
 	REG_WRITE1(sc, VGA_AC_WRITE, 0);
 	REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_COLOR_PLANE_ENABLE);
Index: sys/dev/vt/vt.h
===================================================================
--- sys/dev/vt/vt.h
+++ sys/dev/vt/vt.h
@@ -172,7 +172,7 @@
 #define	VT_LOCK_ASSERT(vd, what)	mtx_assert(&(vd)->vd_lock, what)
 
 void vt_resume(struct vt_device *vd);
-void vt_resume_flush_timer(struct vt_device *vd, int ms);
+void vt_resume_flush_timer(struct vt_window *vw, int ms);
 void vt_suspend(struct vt_device *vd);
 
 /*
@@ -213,16 +213,18 @@
 #define	VBF_DEFAULT_HISTORY_SIZE	500
 #endif
 
-void vtbuf_copy(struct vt_buf *, const term_rect_t *, const term_pos_t *);
+void vtbuf_lock(struct vt_buf *);
+void vtbuf_unlock(struct vt_buf *);
+void vtbuf_copy_locked(struct vt_buf *, const term_rect_t *, const term_pos_t *);
 void vtbuf_fill_locked(struct vt_buf *, const term_rect_t *, term_char_t);
 void vtbuf_init_early(struct vt_buf *);
 void vtbuf_init(struct vt_buf *, const term_pos_t *);
 void vtbuf_grow(struct vt_buf *, const term_pos_t *, unsigned int);
-void vtbuf_putchar(struct vt_buf *, const term_pos_t *, term_char_t);
-void vtbuf_cursor_position(struct vt_buf *, const term_pos_t *);
+void vtbuf_putchar_locked(struct vt_buf *, const term_pos_t *, term_char_t);
+void vtbuf_cursor_position_locked(struct vt_buf *, const term_pos_t *);
 void vtbuf_scroll_mode(struct vt_buf *vb, int yes);
-void vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area);
-void vtbuf_undirty(struct vt_buf *, term_rect_t *);
+void vtbuf_dirty_locked(struct vt_buf *vb, const term_rect_t *area);
+void vtbuf_undirty_locked(struct vt_buf *, term_rect_t *);
 void vtbuf_sethistory_size(struct vt_buf *, unsigned int);
 int vtbuf_iscursor(const struct vt_buf *vb, int row, int col);
 void vtbuf_cursor_visibility(struct vt_buf *, int);
Index: sys/dev/vt/vt_buf.c
===================================================================
--- sys/dev/vt/vt_buf.c
+++ sys/dev/vt/vt_buf.c
@@ -49,6 +49,8 @@
 
 #define	VTBUF_LOCK(vb)		mtx_lock_spin(&(vb)->vb_lock)
 #define	VTBUF_UNLOCK(vb)	mtx_unlock_spin(&(vb)->vb_lock)
+//#define	VTBUF_IS_LOCKED(vb)	mtx_assert(&(vb)->vb_lock, MA_OWNED);
+#define	VTBUF_IS_LOCKED(vb)
 
 #define POS_INDEX(c, r) (((r) << 12) + (c))
 #define	POS_COPY(d, s)	do {	\
@@ -253,10 +255,26 @@
 	return (0);
 }
 
-static inline void
+void
+vtbuf_lock(struct vt_buf *vb)
+{
+
+	VTBUF_LOCK(vb);
+}
+
+void
+vtbuf_unlock(struct vt_buf *vb)
+{
+
+	VTBUF_UNLOCK(vb);
+}
+
+void
 vtbuf_dirty_locked(struct vt_buf *vb, const term_rect_t *area)
 {
 
+	VTBUF_IS_LOCKED(vb);
+
 	if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row)
 		vb->vb_dirtyrect.tr_begin.tp_row = area->tr_begin.tp_row;
 	if (vb->vb_dirtyrect.tr_begin.tp_col > area->tr_begin.tp_col)
@@ -267,15 +285,6 @@
 		vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col;
 }
 
-void
-vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area)
-{
-
-	VTBUF_LOCK(vb);
-	vtbuf_dirty_locked(vb, area);
-	VTBUF_UNLOCK(vb);
-}
-
 static inline void
 vtbuf_dirty_cell_locked(struct vt_buf *vb, const term_pos_t *p)
 {
@@ -296,23 +305,25 @@
 }
 
 void
-vtbuf_undirty(struct vt_buf *vb, term_rect_t *r)
+vtbuf_undirty_locked(struct vt_buf *vb, term_rect_t *r)
 {
 
-	VTBUF_LOCK(vb);
+	VTBUF_IS_LOCKED(vb);
+
 	*r = vb->vb_dirtyrect;
 	vtbuf_make_undirty(vb);
-	VTBUF_UNLOCK(vb);
 }
 
 void
-vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2)
+vtbuf_copy_locked(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2)
 {
 	const term_pos_t *p1 = &r->tr_begin;
 	term_rect_t area;
 	unsigned int rows, cols;
 	int pr, rdiff;
 
+	VTBUF_IS_LOCKED(vb);
+
 	KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row,
 	    ("vtbuf_copy begin.tp_row %d must be less than screen width %d",
 		r->tr_begin.tp_row, vb->vb_scr_size.tp_row));
@@ -362,11 +373,11 @@
 	area.tr_begin = *p2;
 	area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row);
 	area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col);
-	vtbuf_dirty(vb, &area);
+	vtbuf_dirty_locked(vb, &area);
 }
 
 static void
-vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c)
+vtbuf_do_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c)
 {
 	unsigned int pr, pc;
 	term_char_t *row;
@@ -383,6 +394,9 @@
 void
 vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c)
 {
+
+	VTBUF_IS_LOCKED(vb);
+
 	KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row,
 	    ("vtbuf_fill_locked begin.tp_row %d must be < screen height %d",
 		r->tr_begin.tp_row, vb->vb_scr_size.tp_row));
@@ -397,10 +411,9 @@
 	    ("vtbuf_fill_locked end.tp_col %d must be <= screen width %d",
 		r->tr_end.tp_col, vb->vb_scr_size.tp_col));
 
-	VTBUF_LOCK(vb);
-	vtbuf_fill(vb, r, c);
+	vtbuf_do_fill(vb, r, c);
+
 	vtbuf_dirty_locked(vb, r);
-	VTBUF_UNLOCK(vb);
 }
 
 static void
@@ -431,7 +444,7 @@
 	rect.tr_begin.tp_row = rect.tr_begin.tp_col = 0;
 	rect.tr_end.tp_col = vb->vb_scr_size.tp_col;
 	rect.tr_end.tp_row = vb->vb_history_size;
-	vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR));
+	vtbuf_do_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR));
 	vtbuf_make_undirty(vb);
 	if ((vb->vb_flags & VBF_MTX_INIT) == 0) {
 		mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN);
@@ -631,10 +644,12 @@
 }
 
 void
-vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c)
+vtbuf_putchar_locked(struct vt_buf *vb, const term_pos_t *p, term_char_t c)
 {
 	term_char_t *row;
 
+	VTBUF_IS_LOCKED(vb);
+
 	KASSERT(p->tp_row < vb->vb_scr_size.tp_row,
 	    ("vtbuf_putchar tp_row %d must be less than screen width %d",
 		p->tp_row, vb->vb_scr_size.tp_row));
@@ -645,23 +660,20 @@
 	row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) %
 	    VTBUF_MAX_HEIGHT(vb)];
 	if (row[p->tp_col] != c) {
-		VTBUF_LOCK(vb);
 		row[p->tp_col] = c;
 		vtbuf_dirty_cell_locked(vb, p);
-		VTBUF_UNLOCK(vb);
 	}
 }
 
 void
-vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p)
+vtbuf_cursor_position_locked(struct vt_buf *vb, const term_pos_t *p)
 {
+	VTBUF_IS_LOCKED(vb);
 
 	if (vb->vb_flags & VBF_CURSOR) {
-		VTBUF_LOCK(vb);
 		vtbuf_dirty_cell_locked(vb, &vb->vb_cursor);
 		vb->vb_cursor = *p;
 		vtbuf_dirty_cell_locked(vb, &vb->vb_cursor);
-		VTBUF_UNLOCK(vb);
 	} else {
 		vb->vb_cursor = *p;
 	}
@@ -687,7 +699,9 @@
 		area.tr_end.tp_col = vb->vb_scr_size.tp_col;
 		area.tr_end.tp_row = MAX(s, e) + 1;
 
-		vtbuf_dirty(vb, &area);
+		vtbuf_lock(vb);
+		vtbuf_dirty_locked(vb, &area);
+		vtbuf_unlock(vb);
 	}
 }
 
@@ -853,4 +867,3 @@
 		vtbuf_dirty_cell_locked(vb, &vb->vb_cursor);
 	VTBUF_UNLOCK(vb);
 }
-
Index: sys/dev/vt/vt_core.c
===================================================================
--- sys/dev/vt/vt_core.c
+++ sys/dev/vt/vt_core.c
@@ -61,6 +61,7 @@
 #include <machine/frame.h>
 #endif
 
+static tc_prepare_t	vtterm_prepare;
 static tc_bell_t	vtterm_bell;
 static tc_cursor_t	vtterm_cursor;
 static tc_putchar_t	vtterm_putchar;
@@ -80,6 +81,7 @@
 static tc_mmap_t	vtterm_mmap;
 
 const struct terminal_class vt_termclass = {
+	.tc_prepare	= vtterm_prepare,
 	.tc_bell	= vtterm_bell,
 	.tc_cursor	= vtterm_cursor,
 	.tc_putchar	= vtterm_putchar,
@@ -285,8 +287,12 @@
 }
 
 void
-vt_resume_flush_timer(struct vt_device *vd, int ms)
+vt_resume_flush_timer(struct vt_window *vw, int ms)
 {
+	struct vt_device *vd = vw->vw_device;
+
+	if (vd->vd_curwindow != vw)
+		return;
 
 	if (!(vd->vd_flags & VDF_ASYNC) ||
 	    !atomic_cmpset_int(&vd->vd_timer_armed, 0, 1))
@@ -531,14 +537,14 @@
 			return (0);
 		if (!(vw->vw_flags & (VWF_OPENED|VWF_CONSOLE)))
 			return (EINVAL);
-		
+
 		vd->vd_curwindow = vw;
 		vd->vd_flags |= VDF_INVALID;
 		if (vd->vd_driver->vd_postswitch)
 			vd->vd_driver->vd_postswitch(vd);
 		return (0);
 	}
-		
+
 	VT_LOCK(vd);
 	if (curvw == vw) {
 		/* Nothing to do. */
@@ -560,7 +566,7 @@
 	if (vd->vd_driver->vd_postswitch)
 		vd->vd_driver->vd_postswitch(vd);
 
-	vt_resume_flush_timer(vd, 0);
+	vt_resume_flush_timer(vw, 0);
 
 	/* Restore per-window keyboard mode. */
 	mtx_lock(&Giant);
@@ -680,7 +686,7 @@
 	diff = vthistory_seek(&vw->vw_buf, offset, whence);
 	if (diff)
 		vw->vw_device->vd_flags |= VDF_INVALID;
-	vt_resume_flush_timer(vw->vw_device, 0);
+	vt_resume_flush_timer(vw, 0);
 }
 
 static int
@@ -1035,8 +1041,7 @@
 {
 	struct vt_window *vw = tm->tm_softc;
 
-	vtbuf_cursor_position(&vw->vw_buf, p);
-	vt_resume_flush_timer(vw->vw_device, 0);
+	vtbuf_cursor_position_locked(&vw->vw_buf, p);
 }
 
 static void
@@ -1044,8 +1049,7 @@
 {
 	struct vt_window *vw = tm->tm_softc;
 
-	vtbuf_putchar(&vw->vw_buf, p, c);
-	vt_resume_flush_timer(vw->vw_device, 0);
+	vtbuf_putchar_locked(&vw->vw_buf, p, c);
 }
 
 static void
@@ -1054,7 +1058,6 @@
 	struct vt_window *vw = tm->tm_softc;
 
 	vtbuf_fill_locked(&vw->vw_buf, r, c);
-	vt_resume_flush_timer(vw->vw_device, 0);
 }
 
 static void
@@ -1063,8 +1066,7 @@
 {
 	struct vt_window *vw = tm->tm_softc;
 
-	vtbuf_copy(&vw->vw_buf, r, p);
-	vt_resume_flush_timer(vw->vw_device, 0);
+	vtbuf_copy_locked(&vw->vw_buf, r, p);
 }
 
 static void
@@ -1084,7 +1086,7 @@
 		/* FALLTHROUGH */
 	case TP_SHOWCURSOR:
 		vtbuf_cursor_visibility(&vw->vw_buf, arg);
-		vt_resume_flush_timer(vw->vw_device, 0);
+		vt_resume_flush_timer(vw, 0);
 		break;
 	case TP_MOUSE:
 		vw->vw_mouse_level = arg;
@@ -1142,7 +1144,7 @@
 }
 
 static void
-vt_mark_mouse_position_as_dirty(struct vt_device *vd)
+vt_mark_mouse_position_as_dirty(struct vt_device *vd, int locked)
 {
 	term_rect_t area;
 	struct vt_window *vw;
@@ -1175,7 +1177,11 @@
 		area.tr_end.tp_row = y + 2;
 	}
 
-	vtbuf_dirty(&vw->vw_buf, &area);
+	if (!locked)
+		vtbuf_lock(&vw->vw_buf);
+	vtbuf_dirty_locked(&vw->vw_buf, &area);
+	if (!locked)
+		vtbuf_unlock(&vw->vw_buf);
 }
 #endif
 
@@ -1230,6 +1236,8 @@
 	if (((vd->vd_flags & VDF_TEXTMODE) == 0) && (vf == NULL))
 		return (0);
 
+	vtbuf_lock(&vw->vw_buf);
+
 #ifndef SC_NO_CUTPASTE
 	cursor_was_shown = vd->vd_mshown;
 	cursor_moved = (vd->vd_mx != vd->vd_mx_drawn ||
@@ -1250,7 +1258,7 @@
 	 */
 	if (cursor_was_shown != vd->vd_mshown ||
 	    (vd->vd_mshown && cursor_moved))
-		vt_mark_mouse_position_as_dirty(vd);
+		vt_mark_mouse_position_as_dirty(vd, true);
 
 	/*
          * Save position of the mouse cursor. It's used by backends to
@@ -1265,10 +1273,10 @@
 	 * mark the new position as dirty.
 	 */
 	if (vd->vd_mshown && cursor_moved)
-		vt_mark_mouse_position_as_dirty(vd);
+		vt_mark_mouse_position_as_dirty(vd, true);
 #endif
 
-	vtbuf_undirty(&vw->vw_buf, &tarea);
+	vtbuf_undirty_locked(&vw->vw_buf, &tarea);
 
 	/* Force a full redraw when the screen contents are invalid. */
 	if (vd->vd_flags & VDF_INVALID) {
@@ -1282,9 +1290,11 @@
 
 	if (tarea.tr_begin.tp_col < tarea.tr_end.tp_col) {
 		vd->vd_driver->vd_bitblt_text(vd, vw, &tarea);
+		vtbuf_unlock(&vw->vw_buf);
 		return (1);
 	}
 
+	vtbuf_unlock(&vw->vw_buf);
 	return (0);
 }
 
@@ -1306,6 +1316,16 @@
 }
 
 static void
+vtterm_prepare(struct terminal *tm)
+{
+	struct vt_window *vw = tm->tm_softc;
+
+	if (!kdb_active && panicstr == NULL) {
+		vtbuf_lock(&vw->vw_buf);
+	}
+}
+
+static void
 vtterm_done(struct terminal *tm)
 {
 	struct vt_window *vw = tm->tm_softc;
@@ -1322,7 +1342,11 @@
 		vd->vd_flags &= ~VDF_SPLASH;
 		vt_flush(vd);
 	} else if (!(vd->vd_flags & VDF_ASYNC)) {
+		vtbuf_unlock(&vw->vw_buf);
 		vt_flush(vd);
+	} else {
+		vtbuf_unlock(&vw->vw_buf);
+		vt_resume_flush_timer(vw, 0);
 	}
 }
 
@@ -1655,7 +1679,7 @@
 	/* Force a full redraw the next timer tick. */
 	if (vd->vd_curwindow == vw) {
 		vd->vd_flags |= VDF_INVALID;
-		vt_resume_flush_timer(vw->vw_device, 0);
+		vt_resume_flush_timer(vw, 0);
 	}
 	vw->vw_flags &= ~VWF_BUSY;
 	VT_UNLOCK(vd);
@@ -1882,7 +1906,7 @@
 			    vd->vd_mx / vf->vf_width,
 			    vd->vd_my / vf->vf_height);
 
-		vt_resume_flush_timer(vw->vw_device, 0);
+		vt_resume_flush_timer(vw, 0);
 		return; /* Done */
 	case MOUSE_BUTTON_EVENT:
 		/* Buttons */
@@ -1946,7 +1970,7 @@
 		 * We have something marked to copy, so update pointer to
 		 * window with selection.
 		 */
-		vt_resume_flush_timer(vw->vw_device, 0);
+		vt_resume_flush_timer(vw, 0);
 
 		switch (mark) {
 		case VTB_MARK_END:
@@ -2000,8 +2024,8 @@
 	}
 
 	/* Mark mouse position as dirty. */
-	vt_mark_mouse_position_as_dirty(vd);
-	vt_resume_flush_timer(vw->vw_device, 0);
+	vt_mark_mouse_position_as_dirty(vd, false);
+	vt_resume_flush_timer(vw, 0);
 }
 #endif
 
@@ -2779,7 +2803,7 @@
 		/* Allow to put chars now. */
 		terminal_mute(vd->vd_curwindow->vw_terminal, 0);
 		/* Rerun timer for screen updates. */
-		vt_resume_flush_timer(vd, 0);
+		vt_resume_flush_timer(vd->vd_curwindow, 0);
 	}
 
 	/*
Index: sys/dev/vt/vt_cpulogos.c
===================================================================
--- sys/dev/vt/vt_cpulogos.c
+++ sys/dev/vt/vt_cpulogos.c
@@ -194,7 +194,7 @@
 
 		if (vd->vd_curwindow == vw) {
 			vd->vd_flags |= VDF_INVALID;
-			vt_resume_flush_timer(vd, 0);
+			vt_resume_flush_timer(vw, 0);
 		}
 		VT_UNLOCK(vd);
 	}
@@ -253,7 +253,7 @@
 
 	if (vd->vd_curwindow == vw) {
 		vd->vd_flags |= VDF_INVALID;
-		vt_resume_flush_timer(vd, 0);
+		vt_resume_flush_timer(vw, 0);
 	}
 
 	callout_init(&vt_splash_cpu_callout, 1);
Index: sys/kern/subr_terminal.c
===================================================================
--- sys/kern/subr_terminal.c
+++ sys/kern/subr_terminal.c
@@ -392,17 +392,18 @@
 	size_t olen;
 	unsigned int flags = 0;
 
+	TERMINAL_LOCK_TTY(tm);
+	if (!(tm->tm_flags & TF_MUTE))
+		tm->tm_class->tc_prepare(tm);
+
 	while ((olen = ttydisc_getc(tp, obuf, sizeof obuf)) > 0) {
-		TERMINAL_LOCK_TTY(tm);
 		if (!(tm->tm_flags & TF_MUTE)) {
 			tm->tm_flags &= ~TF_BELL;
 			teken_input(&tm->tm_emulator, obuf, olen);
 			flags |= tm->tm_flags;
 		}
-		TERMINAL_UNLOCK_TTY(tm);
 	}
 
-	TERMINAL_LOCK_TTY(tm);
 	if (!(tm->tm_flags & TF_MUTE))
 		tm->tm_class->tc_done(tm);
 	TERMINAL_UNLOCK_TTY(tm);
@@ -571,6 +572,7 @@
 
 	TERMINAL_LOCK_CONS(tm);
 	if (!(tm->tm_flags & TF_MUTE)) {
+		tm->tm_class->tc_prepare(tm);
 		backup = *teken_get_curattr(&tm->tm_emulator);
 		teken_set_curattr(&tm->tm_emulator, &kernel_message);
 		teken_input(&tm->tm_emulator, &cv, 1);
Index: sys/sys/terminal.h
===================================================================
--- sys/sys/terminal.h
+++ sys/sys/terminal.h
@@ -144,6 +144,7 @@
 typedef teken_pos_t term_pos_t;
 typedef teken_rect_t term_rect_t;
 
+typedef void tc_prepare_t(struct terminal *tm);
 typedef void tc_cursor_t(struct terminal *tm, const term_pos_t *p);
 typedef void tc_putchar_t(struct terminal *tm, const term_pos_t *p,
     term_char_t c);
@@ -169,6 +170,7 @@
 
 struct terminal_class {
 	/* Terminal emulator. */
+	tc_prepare_t	*tc_prepare;
 	tc_cursor_t	*tc_cursor;
 	tc_putchar_t	*tc_putchar;
 	tc_fill_t	*tc_fill;