diff options
author | Jean-Sébastien Pédron <dumbbell@FreeBSD.org> | 2023-11-24 17:30:33 +0000 |
---|---|---|
committer | Jean-Sébastien Pédron <dumbbell@FreeBSD.org> | 2023-11-24 17:31:33 +0000 |
commit | 049e3fba04e82f840cc43080edade0ed415fee72 (patch) | |
tree | 3771c266efca4bbd29afa3c2c4caebce91012cf8 | |
parent | 14dcd40983748596d116d91acb934a8a95ac76bc (diff) | |
download | src-049e3fba04e82f840cc43080edade0ed415fee72.tar.gz src-049e3fba04e82f840cc43080edade0ed415fee72.zip |
vt(4): Skip vt_flush() for nested panics
[Why]
If there is a problem with DRM drivers or in their integration with
vt(4) and displaying something on the console triggers a panic, there is
a high chance that displaying that panic will trigger another one,
recursively.
[How]
If vt_flush() is called and it detects is is called resursively from
another panic, it return immediately, doing nothing, to avoid the risk
of triggering another panic.
Reviewed by: manu
Approved by: manu
Differential Revision: https://reviews.freebsd.org/D42056
-rw-r--r-- | sys/dev/vt/vt_core.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index c97cb80ca3f1..406472a8fbf6 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -274,6 +274,8 @@ SYSINIT(vt_update_static, SI_SUB_KMEM, SI_ORDER_ANY, vt_update_static, SYSINIT(vt_early_cons, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, vt_upgrade, &vt_consdev); +static bool inside_vt_flush = false; + /* Initialize locks/mem depended members. */ static void vt_update_static(void *dummy) @@ -1344,6 +1346,9 @@ vt_flush(struct vt_device *vd) int cursor_was_shown, cursor_moved; #endif + if (inside_vt_flush && KERNEL_PANICKED()) + return (0); + vw = vd->vd_curwindow; if (vw == NULL) return (0); @@ -1357,6 +1362,8 @@ vt_flush(struct vt_device *vd) vtbuf_lock(&vw->vw_buf); + inside_vt_flush = true; + #ifndef SC_NO_CUTPASTE cursor_was_shown = vd->vd_mshown; cursor_moved = (vd->vd_mx != vd->vd_mx_drawn || @@ -1414,10 +1421,12 @@ vt_flush(struct vt_device *vd) if (tarea.tr_begin.tp_col < tarea.tr_end.tp_col) { vd->vd_driver->vd_bitblt_text(vd, vw, &tarea); + inside_vt_flush = false; vtbuf_unlock(&vw->vw_buf); return (1); } + inside_vt_flush = false; vtbuf_unlock(&vw->vw_buf); return (0); } @@ -1444,6 +1453,9 @@ vtterm_pre_input(struct terminal *tm) { struct vt_window *vw = tm->tm_softc; + if (inside_vt_flush && KERNEL_PANICKED()) + return; + vtbuf_lock(&vw->vw_buf); } @@ -1452,6 +1464,9 @@ vtterm_post_input(struct terminal *tm) { struct vt_window *vw = tm->tm_softc; + if (inside_vt_flush && KERNEL_PANICKED()) + return; + vtbuf_unlock(&vw->vw_buf); vt_resume_flush_timer(vw, 0); } |