Because of the locking changes in the inteldrm(4) update, the code
that swicthes to the console framebuffer is pretty much broken.  The
diff below fixes the issue inteldrm(4) by introducing a new
enter_ddb() "accessop" for wsdisplay(4).  The implementation of this
function should bypass as much of the locking as is feasable. The KMS
drivers can implement this by calling drm_fb_helper_debug_enter().  If
the function isn't implemented it falls back on using show_screen()
which should be sufficient for simple framebuffer drivers like
efifb(4).

I'd like to commit this diff ASAP to make sure we get better bug
reports for panics that happen wile running X.  I'll fix radeondrm(4)
in a followup diff.

Note that you'll end up in a slightly funny state if you enter the ddb
with this diff.  The console framebuffer will be visible but we didn't
do a complete VT switch.  So if you type "continue" X will still e
active, but on a framebuffer you don't see.  You can easily get out of
that sitaution by doing a VT switch to the console and back to X.  But
I can also look at adding a leave_ddb() "accessop" that switches
things back as they were upon leaving ddb.

ok?


Index: dev/wscons/wsdisplay.c
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsdisplay.c,v
retrieving revision 1.126
diff -u -p -r1.126 wsdisplay.c
--- dev/wscons/wsdisplay.c      11 Jan 2017 08:21:33 -0000      1.126
+++ dev/wscons/wsdisplay.c      18 Jul 2017 18:34:15 -0000
@@ -2133,6 +2133,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.
  *
Index: dev/wscons/wsdisplayvar.h
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsdisplayvar.h,v
retrieving revision 1.30
diff -u -p -r1.30 wsdisplayvar.h
--- dev/wscons/wsdisplayvar.h   4 Sep 2016 18:20:34 -0000       1.30
+++ dev/wscons/wsdisplayvar.h   18 Jul 2017 18:34:15 -0000
@@ -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
  */
 #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 *
Index: dev/pci/drm/i915/i915_drv.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915/i915_drv.c,v
retrieving revision 1.105
diff -u -p -r1.105 i915_drv.c
--- dev/pci/drm/i915/i915_drv.c 12 Jul 2017 20:12:19 -0000      1.105
+++ dev/pci/drm/i915/i915_drv.c 18 Jul 2017 18:34:15 -0000
@@ -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_acce
        .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,
@@ -2031,6 +2033,20 @@ inteldrm_doswitch(void *v)
 
        if (dev_priv->switchcb)
                (*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
Index: arch/amd64/amd64/db_interface.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/db_interface.c,v
retrieving revision 1.28
diff -u -p -r1.28 db_interface.c
--- arch/amd64/amd64/db_interface.c     30 Apr 2017 16:45:45 -0000      1.28
+++ arch/amd64/amd64/db_interface.c     18 Jul 2017 18:34:16 -0000
@@ -112,7 +112,7 @@ db_ktrap(int type, int code, db_regs_t *
        int s;
 
 #if NWSDISPLAY > 0
-       wsdisplay_switchtoconsole();
+       wsdisplay_enter_ddb();
 #endif
 
        switch (type) {
Index: arch/i386/i386/db_interface.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/db_interface.c,v
retrieving revision 1.35
diff -u -p -r1.35 db_interface.c
--- arch/i386/i386/db_interface.c       30 Apr 2017 16:45:45 -0000      1.35
+++ arch/i386/i386/db_interface.c       18 Jul 2017 18:34:16 -0000
@@ -106,7 +106,7 @@ db_ktrap(int type, int code, db_regs_t *
        int s;
 
 #if NWSDISPLAY > 0
-       wsdisplay_switchtoconsole();
+       wsdisplay_enter_ddb();
 #endif
 
        switch (type) {

Reply via email to