diff mbox series

[INTERNAL,REVIEW] kdb: Switch kdb_printf to use safer console poll APIs

Message ID 1590145006-15823-1-git-send-email-sumit.garg@linaro.org
State New
Headers show
Series [INTERNAL,REVIEW] kdb: Switch kdb_printf to use safer console poll APIs | expand

Commit Message

Sumit Garg May 22, 2020, 10:56 a.m. UTC
In kgdb NMI context, polling driver APIs are more safer to use instead
of console APIs since the polling drivers know they will execute from
all sorts of crazy places. And for the most common use cases this would
also result in no console handler ever being called. So switch to use
polling driver APIs in case a particular console supports polling mode.

Suggested-by: Daniel Thompson <daniel.thompson@linaro.org>
Signed-off-by: Sumit Garg <sumit.garg@linaro.org>

---

Please confirm if this is as per your suggestion and all kgdb modes should
work fine. If yes, then I will post this patch in upstream.

 kernel/debug/kdb/kdb_io.c | 42 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 36 insertions(+), 6 deletions(-)

-- 
2.7.4
diff mbox series

Patch

diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index e32ece6..86cc416 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -24,6 +24,7 @@ 
 #include <linux/kgdb.h>
 #include <linux/kdb.h>
 #include <linux/kallsyms.h>
+#include <linux/tty_driver.h>
 #include "kdb_private.h"
 
 #define CMD_BUFLEN 256
@@ -699,11 +700,26 @@  int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap)
 			}
 		}
 		for_each_console(c) {
+			int line;
+			struct tty_driver *p;
+
 			if (!(c->flags & CON_ENABLED))
 				continue;
-			bust_spinlocks(1);
-			c->write(c, cp, retlen - (cp - kdb_buffer));
-			bust_spinlocks(0);
+
+			p = c->device ? c->device(c, &line) : NULL;
+			if (p && p->ops && p->ops->poll_init &&
+			    !p->ops->poll_init(p, line, NULL)) {
+				len = retlen - (cp - kdb_buffer);
+				cp2 = cp;
+				while (len--) {
+					p->ops->poll_put_char(p, line, *cp2);
+					cp2++;
+				}
+			} else {
+				bust_spinlocks(1);
+				c->write(c, cp, retlen - (cp - kdb_buffer));
+				bust_spinlocks(0);
+			}
 			touch_nmi_watchdog();
 		}
 	}
@@ -765,11 +781,25 @@  int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap)
 			}
 		}
 		for_each_console(c) {
+			int line;
+			struct tty_driver *p;
+
 			if (!(c->flags & CON_ENABLED))
 				continue;
-			bust_spinlocks(1);
-			c->write(c, moreprompt, strlen(moreprompt));
-			bust_spinlocks(0);
+			p = c->device ? c->device(c, &line) : NULL;
+			if (p && p->ops && p->ops->poll_init &&
+			    !p->ops->poll_init(p, line, NULL)) {
+				len = strlen(moreprompt);
+				cp = moreprompt;
+				while (len--) {
+					p->ops->poll_put_char(p, line, *cp);
+					cp++;
+				}
+			} else {
+				bust_spinlocks(1);
+				c->write(c, moreprompt, strlen(moreprompt));
+				bust_spinlocks(0);
+			}
 			touch_nmi_watchdog();
 		}