lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri,  8 May 2009 16:23:10 -0500
From:	Jason Wessel <jason.wessel@...driver.com>
To:	linux-kernel@...r.kernel.org
Cc:	kgdb-bugreport@...ts.sourceforge.net, kdb@....sgi.com,
	Jason Wessel <jason.wessel@...driver.com>
Subject: [PATCH 03/13] RFC ONLY - kgdb,8250,pl011: Return immediately from console poll

This is a RFC patch.  The work to possibly merge kdb and kgdb is being
evaluated and this patch is considered only a proof of concept or
prototype.

The design of kdb required that every device that can provide input to
kdb have a polling routine that exits immediately if there is no
character available.

This is required in order to get the page scrolling mechanism working,
it is also a reasonable requirement for future kgdb I/O drivers
because that allows for the possibility of multiple input channels.

NO_POLL_CHAR will be the return code to the polling routine when ever
there is no character available.  There are several other console
polling drivers which can be modified, but for the prototype only the
8250 and pl011 driver have been changed to make use of this.

Signed-off-by: Jason Wessel <jason.wessel@...driver.com>
---
 drivers/serial/8250.c       |    4 +-
 drivers/serial/amba-pl011.c |    6 ++--
 include/linux/kgdb.h        |    3 ++
 include/linux/serial_core.h |    1 +
 kernel/kgdb.c               |   47 +++++++++++++++++++++++++++++++++++++-----
 5 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index b4b3981..03f815b 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1884,8 +1884,8 @@ static int serial8250_get_poll_char(struct uart_port *port)
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
 	unsigned char lsr = serial_inp(up, UART_LSR);
 
-	while (!(lsr & UART_LSR_DR))
-		lsr = serial_inp(up, UART_LSR);
+	if (!(lsr & UART_LSR_DR))
+		return NO_POLL_CHAR;
 
 	return serial_inp(up, UART_RX);
 }
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 8b2b970..fb2ed6a 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -318,9 +318,9 @@ static int pl010_get_poll_char(struct uart_port *port)
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 	unsigned int status;
 
-	do {
-		status = readw(uap->port.membase + UART01x_FR);
-	} while (status & UART01x_FR_RXFE);
+	status = readw(uap->port.membase + UART01x_FR);
+	if (status & UART01x_FR_RXFE)
+		return NO_POLL_CHAR;
 
 	return readw(uap->port.membase + UART01x_DR);
 }
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 3e838d6..967803d 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -283,4 +283,7 @@ extern int kgdb_nmicallback(int cpu, void *regs);
 extern int			kgdb_single_step;
 extern atomic_t			kgdb_active;
 
+#ifdef CONFIG_KGDB_SERIAL_CONSOLE
+extern void __init early_kgdboc_init(void);
+#endif /* CONFIG_KGDB_SERIAL_CONSOLE */
 #endif /* _KGDB_H_ */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 57a97e5..6fda5b8 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -232,6 +232,7 @@ struct uart_ops {
 #endif
 };
 
+#define NO_POLL_CHAR		0x00ff0000
 #define UART_CONFIG_TYPE	(1 << 0)
 #define UART_CONFIG_IRQ		(1 << 1)
 
diff --git a/kernel/kgdb.c b/kernel/kgdb.c
index 067f2cf..2f093bc 100644
--- a/kernel/kgdb.c
+++ b/kernel/kgdb.c
@@ -50,6 +50,7 @@
 #include <linux/kdebug.h>
 #include <linux/kdb.h>
 #include <linux/kdbprivate.h>
+#include <linux/serial_core.h>
 
 #include <asm/cacheflush.h>
 #include <asm/byteorder.h>
@@ -254,6 +255,8 @@ void __weak kgdb_disable_hw_debug(struct pt_regs *regs)
  * KDB interface to KGDB internals
  */
 #ifdef CONFIG_KGDB_KDB
+int kdb_poll_idx = 1;
+EXPORT_SYMBOL_GPL(kdb_poll_idx);
 static void gdb_cmd_status(struct kgdb_state *ks);
 static void put_packet(char *buffer);
 static int kgdb_activate_sw_breakpoints(void);
@@ -261,6 +264,8 @@ static int kgdb_activate_sw_breakpoints(void);
 static int kgdbio_get_char(void)
 {
 	int ret = kgdb_io_ops->read_char();
+	if (ret == NO_POLL_CHAR)
+		return -1;
 	if (!kgdb_use_passthrough)
 		return ret;
 	if (ret == 127)
@@ -271,7 +276,27 @@ static int kgdbio_get_char(void)
 get_char_func kdb_poll_funcs[] = {
 	kgdbio_get_char,
 	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
 };
+EXPORT_SYMBOL_GPL(kdb_poll_funcs);
+
+static int kgdb_read_wait(void)
+{
+	int ret = -1;
+	int i;
+
+	/* poll any additional I/O interfaces that are defined */
+	while (ret < 0)
+		for (i = 0; kdb_poll_funcs[i] != NULL; i++) {
+			ret = kdb_poll_funcs[i]();
+			if (ret > 0)
+				break;
+		}
+	return ret;
+}
 
 static int comm_passthrough(struct kgdb_state *ks)
 {
@@ -333,6 +358,7 @@ static int comm_passthrough(struct kgdb_state *ks)
 	kdb_bp_remove_global();
 	KDB_STATE_CLEAR(DOING_SS);
 	KDB_STATE_CLEAR(DOING_SSB);
+	KDB_STATE_SET(PAGER);
 	for_each_online_cpu(i) {
 		kdb_save_running_cpu(kgdb_info[i].debuggerinfo,
 				     kgdb_info[i].task, i);
@@ -356,6 +382,7 @@ static int comm_passthrough(struct kgdb_state *ks)
 	kdb_initial_cpu = -1;
 	kdb_current_task = NULL;
 	kdb_current_regs = NULL;
+	KDB_STATE_CLEAR(PAGER);
 	kdbnearsym_cleanup();
 	if (error == KDB_CMD_KGDB) {
 		if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) {
@@ -397,6 +424,14 @@ static int comm_passthrough(struct kgdb_state *ks)
 {
 	return KGDB_PASS_EVENT;
 }
+
+static int kgdb_read_wait(void)
+{
+	int ret = kgdb_io_ops->read_char();
+	while (ret == NO_POLL_CHAR)
+		ret = kgdb_io_ops->read_char();
+	return ret;
+}
 #endif /* CONFIG_KGDB_KDB */
 
 /*
@@ -427,7 +462,7 @@ static void get_packet(char *buffer)
 		 * Spin and wait around for the start character, ignore all
 		 * other characters:
 		 */
-		while ((ch = (kgdb_io_ops->read_char())) != '$')
+		while ((ch = (kgdb_read_wait())) != '$')
 			/* nothing */;
 
 		kgdb_connected = 1;
@@ -440,7 +475,7 @@ static void get_packet(char *buffer)
 		 * now, read until a # or end of buffer is found:
 		 */
 		while (count < (BUFMAX - 1)) {
-			ch = kgdb_io_ops->read_char();
+			ch = kgdb_read_wait();
 			if (ch == '#')
 				break;
 			checksum = checksum + ch;
@@ -450,8 +485,8 @@ static void get_packet(char *buffer)
 		buffer[count] = 0;
 
 		if (ch == '#') {
-			xmitcsum = hex(kgdb_io_ops->read_char()) << 4;
-			xmitcsum += hex(kgdb_io_ops->read_char());
+			xmitcsum = hex(kgdb_read_wait()) << 4;
+			xmitcsum += hex(kgdb_read_wait());
 
 			if (checksum != xmitcsum)
 				/* failed checksum */
@@ -496,10 +531,10 @@ static void put_packet(char *buffer)
 			kgdb_io_ops->flush();
 
 		/* Now see what we get in reply. */
-		ch = kgdb_io_ops->read_char();
+		ch = kgdb_read_wait();
 
 		if (ch == 3)
-			ch = kgdb_io_ops->read_char();
+			ch = kgdb_read_wait();
 
 		/* If we get an ACK, we are done. */
 		if (ch == '+')
-- 
1.6.3.rc0.1.gf800

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ