From 5bfa92540d5e3d2a68895b4f754be2625844d96c Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Wed, 19 Jul 2017 14:34:11 +0000 Subject: Add a enter_ddb() "accessop" to wsdisplay(4) to allow KMS drivers to bypass the modeset lock when entering ddb. This avoids triggering various asserts when the kernel panics while running X. ok deraadt@ --- sys/dev/pci/drm/i915/i915_drv.c | 16 ++++++++++++++++ sys/dev/wscons/wsdisplay.c | 26 +++++++++++++++++++++++++- sys/dev/wscons/wsdisplayvar.h | 4 +++- 3 files changed, 44 insertions(+), 2 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/pci/drm/i915/i915_drv.c b/sys/dev/pci/drm/i915/i915_drv.c index 327b17e7737..cb6a43c6b6e 100644 --- a/sys/dev/pci/drm/i915/i915_drv.c +++ b/sys/dev/pci/drm/i915/i915_drv.c @@ -1879,6 +1879,7 @@ void inteldrm_free_screen(void *, void *); int inteldrm_show_screen(void *, void *, int, void (*)(void *, int, int), void *); void inteldrm_doswitch(void *); +void inteldrm_enter_ddb(void *, void *); int inteldrm_load_font(void *, void *, struct wsdisplay_font *); int inteldrm_list_font(void *, struct wsdisplay_font *); int inteldrm_getchar(void *, int, int, struct wsdisplay_charcell *); @@ -1908,6 +1909,7 @@ struct wsdisplay_accessops inteldrm_accessops = { .alloc_screen = inteldrm_alloc_screen, .free_screen = inteldrm_free_screen, .show_screen = inteldrm_show_screen, + .enter_ddb = inteldrm_enter_ddb, .getchar = inteldrm_getchar, .load_font = inteldrm_load_font, .list_font = inteldrm_list_font, @@ -2033,6 +2035,20 @@ inteldrm_doswitch(void *v) (*dev_priv->switchcb)(dev_priv->switchcbarg, 0, 0); } +void +inteldrm_enter_ddb(void *v, void *cookie) +{ + struct inteldrm_softc *dev_priv = v; + struct rasops_info *ri = &dev_priv->ro; + struct drm_fb_helper *helper = &dev_priv->fbdev->helper; + + if (cookie == ri->ri_active) + return; + + rasops_show_screen(ri, cookie, 0, NULL, NULL); + drm_fb_helper_debug_enter(helper->fbdev); +} + int inteldrm_getchar(void *v, int row, int col, struct wsdisplay_charcell *cell) { diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c index 90c8f4680e1..74102fa0962 100644 --- a/sys/dev/wscons/wsdisplay.c +++ b/sys/dev/wscons/wsdisplay.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wsdisplay.c,v 1.127 2017/07/18 21:27:50 kettenis Exp $ */ +/* $OpenBSD: wsdisplay.c,v 1.128 2017/07/19 14:34:10 kettenis Exp $ */ /* $NetBSD: wsdisplay.c,v 1.82 2005/02/27 00:27:52 perry Exp $ */ /* @@ -2136,6 +2136,30 @@ wsdisplay_switchtoconsole(void) } } +/* + * Switch rhe console display to its ddb screen, avoiding locking + * where we can. + */ +void +wsdisplay_enter_ddb(void) +{ + struct wsdisplay_softc *sc; + struct wsscreen *scr; + + if (wsdisplay_console_device != NULL && cn_tab == &wsdisplay_cons) { + sc = wsdisplay_console_device; + if ((scr = sc->sc_scr[0]) == NULL) + return; + if (sc->sc_accessops) { + (*sc->sc_accessops->enter_ddb)(sc->sc_accesscookie, + scr->scr_dconf->emulcookie); + } else { + (*sc->sc_accessops->show_screen)(sc->sc_accesscookie, + scr->scr_dconf->emulcookie, 0, NULL, NULL); + } + } +} + /* * Deal with the xserver doing driver in userland and thus screwing up suspend * and resume by switching away from it at suspend/resume time. diff --git a/sys/dev/wscons/wsdisplayvar.h b/sys/dev/wscons/wsdisplayvar.h index 9e20834d751..995d09200ea 100644 --- a/sys/dev/wscons/wsdisplayvar.h +++ b/sys/dev/wscons/wsdisplayvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wsdisplayvar.h,v 1.30 2016/09/04 18:20:34 tedu Exp $ */ +/* $OpenBSD: wsdisplayvar.h,v 1.31 2017/07/19 14:34:10 kettenis Exp $ */ /* $NetBSD: wsdisplayvar.h,v 1.30 2005/02/04 02:10:49 perry Exp $ */ /* @@ -145,6 +145,7 @@ struct wsdisplay_accessops { int (*getchar)(void *, int, int, struct wsdisplay_charcell *); void (*burn_screen)(void *, u_int, u_int); void (*pollc)(void *, int); + void (*enter_ddb)(void *, void *); }; /* passed to wscons by the video driver to tell about its capabilities */ @@ -229,6 +230,7 @@ int wsdisplay_cfg_ioctl(struct wsdisplay_softc *sc, */ #define WSDISPLAY_NULLSCREEN -1 void wsdisplay_switchtoconsole(void); +void wsdisplay_enter_ddb(void); void wsdisplay_suspend(void); void wsdisplay_resume(void); const struct wsscreen_descr * -- cgit v1.2.3