Index: sys/dev/vt/vt_buf.c =================================================================== --- sys/dev/vt/vt_buf.c +++ sys/dev/vt/vt_buf.c @@ -433,17 +433,22 @@ vtbuf_do_fill(vb, &rect, VTBUF_SPACE_CHAR(ch)); } -void -vtbuf_init_early(struct vt_buf *vb) +static void +vtbuf_reset_scrollback(struct vt_buf *vb) { - vb->vb_flags |= VBF_CURSOR; vb->vb_roffset = 0; vb->vb_curroffset = 0; vb->vb_mark_start.tp_row = 0; vb->vb_mark_start.tp_col = 0; vb->vb_mark_end.tp_row = 0; vb->vb_mark_end.tp_col = 0; +} +void +vtbuf_init_early(struct vt_buf *vb) +{ + vb->vb_flags |= VBF_CURSOR; + vtbuf_reset_scrollback(vb); vtbuf_init_rows(vb); vtbuf_do_clearhistory(vb); vtbuf_make_undirty(vb); @@ -477,6 +482,8 @@ { VTBUF_LOCK(vb); vtbuf_do_clearhistory(vb); + vtbuf_reset_scrollback(vb); + vb->vb_flags &= ~VBF_HISTORY_FULL; VTBUF_UNLOCK(vb); } Index: sys/dev/vt/vt_core.c =================================================================== --- sys/dev/vt/vt_core.c +++ sys/dev/vt/vt_core.c @@ -2332,6 +2332,16 @@ return (0); case CONS_CLRHIST: vtbuf_clearhistory(&vd->vd_curwindow->vw_buf); + /* + * Invalidate the entire visible window; it is not guaranteed + * that this operation will be immediately followed by a scroll + * event, so it would otherwise be possible for prior artifacts + * to remain visible. + */ + VT_LOCK(vd); + vd->vd_flags |= VDF_INVALID; + VT_UNLOCK(vd); + vt_resume_flush_timer(vd->vd_curwindow, 0); return (0); case CONS_GET: /* XXX */ Index: sys/kern/subr_terminal.c =================================================================== --- sys/kern/subr_terminal.c +++ sys/kern/subr_terminal.c @@ -480,6 +480,21 @@ tty_unlock(tp); error = tm->tm_class->tc_ioctl(tm, cmd, data, td); tty_lock(tp); + if (error != 0) + return (error); + switch (cmd) { + case CONS_CLRHIST: { + /* + * Scrollback history has been successfully cleared, + * so reset the cursor position to the top left of the screen. + */ + teken_pos_t p; + p.tp_row = 0; + p.tp_col = 0; + teken_set_cursor(&tm->tm_emulator, &p); + break; + } + } return (error); }