[RFC] kdb: Switch kdb_printf to use safer console poll APIs

From: Sumit Garg
Date: Fri May 22 2020 - 10:34:59 EST


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@xxxxxxxxxx>
Signed-off-by: Sumit Garg <sumit.garg@xxxxxxxxxx>
---
kernel/debug/kdb/kdb_io.c | 39 +++++++++++++++++++++++++++++++++------
1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index 3a5a068..8e0d581 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,24 @@ 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;
- ++oops_in_progress;
- c->write(c, cp, retlen - (cp - kdb_buffer));
- --oops_in_progress;
+ p = c->device ? c->device(c, &line) : NULL;
+ if (p && p->ops && p->ops->poll_put_char) {
+ len = retlen - (cp - kdb_buffer);
+ cp2 = cp;
+ while (len--) {
+ p->ops->poll_put_char(p, line, *cp2);
+ cp2++;
+ }
+ } else {
+ ++oops_in_progress;
+ c->write(c, cp, retlen - (cp - kdb_buffer));
+ --oops_in_progress;
+ }
touch_nmi_watchdog();
}
}
@@ -765,11 +779,24 @@ 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;
- ++oops_in_progress;
- c->write(c, moreprompt, strlen(moreprompt));
- --oops_in_progress;
+ p = c->device ? c->device(c, &line) : NULL;
+ if (p && p->ops && p->ops->poll_put_char) {
+ len = strlen(moreprompt);
+ cp = moreprompt;
+ while (len--) {
+ p->ops->poll_put_char(p, line, *cp);
+ cp++;
+ }
+ } else {
+ ++oops_in_progress;
+ c->write(c, moreprompt, strlen(moreprompt));
+ --oops_in_progress;
+ }
touch_nmi_watchdog();
}

--
2.7.4