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 | 24d6f256f825e5d7f8ca6b5d16499f13614f9cdd (patch) | |
tree | e9671a37c88cbb9fa33071b74ced22dfcc405762 | |
parent | 049e3fba04e82f840cc43080edade0ed415fee72 (diff) | |
download | src-24d6f256f825e5d7f8ca6b5d16499f13614f9cdd.tar.gz src-24d6f256f825e5d7f8ca6b5d16499f13614f9cdd.zip |
vt(4): Skip vt_window_switch() for nested panics
[Why]
The same protection was added to vt_flush() in the previous commit. We
want the same one in vt_window_switch(): if e.g. the DRM driver panics
while handling a call to vt_window_switch(), we don't want to
recursively call vt_window_switch() again and trigger another panic.
Reviewed by: imp, manu
Approved by: imp, manu
Differential Revision: https://reviews.freebsd.org/D42750
-rw-r--r-- | sys/dev/vt/vt_core.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index 406472a8fbf6..6d44c81181a3 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -275,6 +275,7 @@ SYSINIT(vt_early_cons, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, vt_upgrade, &vt_consdev); static bool inside_vt_flush = false; +static bool inside_vt_window_switch = false; /* Initialize locks/mem depended members. */ static void @@ -564,6 +565,11 @@ vt_window_switch(struct vt_window *vw) struct vt_window *curvw = vd->vd_curwindow; keyboard_t *kbd; + if (inside_vt_window_switch && KERNEL_PANICKED()) + return (0); + + inside_vt_window_switch = true; + if (kdb_active) { /* * When grabbing the console for the debugger, avoid @@ -575,13 +581,16 @@ vt_window_switch(struct vt_window *vw) */ if (curvw == vw) return (0); - if (!(vw->vw_flags & (VWF_OPENED|VWF_CONSOLE))) + if (!(vw->vw_flags & (VWF_OPENED|VWF_CONSOLE))) { + inside_vt_window_switch = false; return (EINVAL); + } vd->vd_curwindow = vw; vd->vd_flags |= VDF_INVALID; if (vd->vd_driver->vd_postswitch) vd->vd_driver->vd_postswitch(vd); + inside_vt_window_switch = false; return (0); } @@ -595,10 +604,12 @@ vt_window_switch(struct vt_window *vw) if ((kdb_active || KERNEL_PANICKED()) && vd->vd_driver->vd_postswitch) vd->vd_driver->vd_postswitch(vd); + inside_vt_window_switch = false; VT_UNLOCK(vd); return (0); } if (!(vw->vw_flags & (VWF_OPENED|VWF_CONSOLE))) { + inside_vt_window_switch = false; VT_UNLOCK(vd); return (EINVAL); } @@ -627,6 +638,7 @@ vt_window_switch(struct vt_window *vw) mtx_unlock(&Giant); DPRINTF(10, "%s(ttyv%d) done\n", __func__, vw->vw_number); + inside_vt_window_switch = false; return (0); } |