aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Sébastien Pédron <dumbbell@FreeBSD.org>2023-11-24 17:30:33 +0000
committerJean-Sébastien Pédron <dumbbell@FreeBSD.org>2023-11-24 17:31:33 +0000
commit24d6f256f825e5d7f8ca6b5d16499f13614f9cdd (patch)
treee9671a37c88cbb9fa33071b74ced22dfcc405762
parent049e3fba04e82f840cc43080edade0ed415fee72 (diff)
downloadsrc-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.c14
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);
}