summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-07-19 14:34:11 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-07-19 14:34:11 +0000
commit5bfa92540d5e3d2a68895b4f754be2625844d96c (patch)
tree69b5ccea2823af33ded2581c5d74aef91202d3b7 /sys
parenta3b66c601bf82fd0a8ad2bf8322510aff0e9e972 (diff)
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@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/amd64/db_interface.c4
-rw-r--r--sys/arch/i386/i386/db_interface.c4
-rw-r--r--sys/dev/pci/drm/i915/i915_drv.c16
-rw-r--r--sys/dev/wscons/wsdisplay.c26
-rw-r--r--sys/dev/wscons/wsdisplayvar.h4
5 files changed, 48 insertions, 6 deletions
diff --git a/sys/arch/amd64/amd64/db_interface.c b/sys/arch/amd64/amd64/db_interface.c
index c68c74026d9..a8931294d51 100644
--- a/sys/arch/amd64/amd64/db_interface.c
+++ b/sys/arch/amd64/amd64/db_interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_interface.c,v 1.28 2017/04/30 16:45:45 mpi Exp $ */
+/* $OpenBSD: db_interface.c,v 1.29 2017/07/19 14:34:10 kettenis Exp $ */
/* $NetBSD: db_interface.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */
/*
@@ -112,7 +112,7 @@ db_ktrap(int type, int code, db_regs_t *regs)
int s;
#if NWSDISPLAY > 0
- wsdisplay_switchtoconsole();
+ wsdisplay_enter_ddb();
#endif
switch (type) {
diff --git a/sys/arch/i386/i386/db_interface.c b/sys/arch/i386/i386/db_interface.c
index 07d123ba1c2..db211b13175 100644
--- a/sys/arch/i386/i386/db_interface.c
+++ b/sys/arch/i386/i386/db_interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_interface.c,v 1.35 2017/04/30 16:45:45 mpi Exp $ */
+/* $OpenBSD: db_interface.c,v 1.36 2017/07/19 14:34:10 kettenis Exp $ */
/* $NetBSD: db_interface.c,v 1.22 1996/05/03 19:42:00 christos Exp $ */
/*
@@ -106,7 +106,7 @@ db_ktrap(int type, int code, db_regs_t *regs)
int s;
#if NWSDISPLAY > 0
- wsdisplay_switchtoconsole();
+ wsdisplay_enter_ddb();
#endif
switch (type) {
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 $ */
/*
@@ -2137,6 +2137,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 *