linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles
@ 2016-12-04 10:53 Manuel Schölling
  2016-12-04 10:53 ` [PATCH v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
                   ` (5 more replies)
  0 siblings, 6 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-04 10:53 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
    scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
    by Adam Borowski (kilobyte@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
    vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
    VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
    escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c            |   9 +++
 drivers/video/console/Kconfig  |  25 ++++++-
 drivers/video/console/vgacon.c | 165 ++++++++++++++++++++++++++++-------------
 include/linux/console.h        |   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v7 1/3] console: Move scrollback data into its own struct
  2016-12-04 10:53 [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2016-12-04 10:53 ` Manuel Schölling
  2016-12-04 10:53 ` [PATCH v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-04 10:53 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/video/console/vgacon.c | 91 ++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+	void *data;
+	int tail;
+	int size;
+	int rows;
+	int cnt;
+	int cur;
+	int save;
+	int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-	if (vgacon_scrollback) {
-		vgacon_scrollback_cnt  = 0;
-		vgacon_scrollback_tail = 0;
-		vgacon_scrollback_cur  = 0;
-		vgacon_scrollback_rows = rows - 1;
-		vgacon_scrollback_size = rows * pitch;
+	if (vgacon_scrollback.data) {
+		vgacon_scrollback.cnt  = 0;
+		vgacon_scrollback.tail = 0;
+		vgacon_scrollback.cur  = 0;
+		vgacon_scrollback.rows = rows - 1;
+		vgacon_scrollback.size = rows * pitch;
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
+	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+		1024, GFP_NOWAIT);
 	vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback_size || c->vc_num != fg_console)
+	if (!vgacon_scrollback.size || c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback_cnt++;
+		vgacon_scrollback.cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback_tail += c->vc_size_row;
+		vgacon_scrollback.tail += c->vc_size_row;
 
-		if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-			vgacon_scrollback_tail = 0;
+		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+			vgacon_scrollback.tail = 0;
 
-		if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-			vgacon_scrollback_cnt = vgacon_scrollback_rows;
+		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+			vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback_save = 0;
+	vgacon_scrollback.save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback_restore) {
+	if (!vga_is_gfx && !vgacon_scrollback.restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback_restore = 1;
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.restore = 1;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback)
+	if (!vgacon_scrollback.data)
 		return;
 
-	if (!vgacon_scrollback_save) {
+	if (!vgacon_scrollback.save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback_save = 1;
+		vgacon_scrollback.save = 1;
 	}
 
-	vgacon_scrollback_restore = 0;
-	start = vgacon_scrollback_cur + lines;
+	vgacon_scrollback.restore = 0;
+	start = vgacon_scrollback.cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback_cnt)
-		start = vgacon_scrollback_cnt;
+	if (start > vgacon_scrollback.cnt)
+		start = vgacon_scrollback.cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback_cnt)
-		end = vgacon_scrollback_cnt;
+	if (end > vgacon_scrollback.cnt)
+		end = vgacon_scrollback.cnt;
 
-	vgacon_scrollback_cur = start;
+	vgacon_scrollback.cur = start;
 	count = end - start;
-	soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
 					 c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback_size;
+		soff += vgacon_scrollback.size;
 
-	count = vgacon_scrollback_cnt - start;
+	count = vgacon_scrollback.cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -287,13 +290,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback_size - soff);
-		scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+		copysize = min(count, vgacon_scrollback.size - soff);
+		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback, count);
+			scr_memcpyw(d, vgacon_scrollback.data, count);
 			d += count;
 		}
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v7 2/3] console: Add callback to flush scrollback buffer to consw struct
  2016-12-04 10:53 [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2016-12-04 10:53 ` [PATCH v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
@ 2016-12-04 10:53 ` Manuel Schölling
  2016-12-04 10:53 ` [PATCH v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-04 10:53 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/tty/vt/vt.c            |  9 +++++++++
 drivers/video/console/vgacon.c | 24 +++++++++++++++++++++++-
 include/linux/console.h        |  4 ++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
 		vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+	WARN_CONSOLE_UNLOCKED();
+
+	if (vc->vc_sw->con_flush_scrollback)
+		vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  *	Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
 		case 3: /* erase scroll-back buffer (and whole display) */
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
 				    vc->vc_screenbuf_size);
+			flush_scrollback(vc);
 			set_origin(vc);
 			if (con_is_visible(vc))
 				update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
 	int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+	if (vgacon_scrollback.data && reset_size > 0)
+		memset(vgacon_scrollback.data, 0, reset_size);
+
+	vgacon_scrollback.cnt  = 0;
+	vgacon_scrollback.tail = 0;
+	vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 	} else
 		vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+	if (c->vc_num == fg_console)
+		vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 			vga_vram_size);
 	vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
 	return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
 	.con_save_screen = vgacon_save_screen,
 	.con_build_attr = vgacon_build_attr,
 	.con_invert_region = vgacon_invert_region,
+	.con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
 	u16    *(*con_screen_pos)(struct vc_data *, int);
 	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
 	/*
+	 * Flush the video console driver's scrollback buffer
+	 */
+	void	(*con_flush_scrollback)(struct vc_data *);
+	/*
 	 * Prepare the console for the debugger.  This includes, but is not
 	 * limited to, unblanking the console, loading an appropriate
 	 * palette, and allowing debugger generated output.
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v7 3/3] console: Add persistent scrollback buffers for all VGA consoles
  2016-12-04 10:53 [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2016-12-04 10:53 ` [PATCH v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
  2016-12-04 10:53 ` [PATCH v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
@ 2016-12-04 10:53 ` Manuel Schölling
  2016-12-06 10:02 ` [PATCH v7 0/3] " Greg KH
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-04 10:53 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/video/console/Kconfig  |  25 +++++++-
 drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
        range 1 1024
        default "64"
        help
-         Enter the amount of System RAM to allocate for the scrollback
-	 buffer.  Each 64KB will give you approximately 16 80x25
-	 screenfuls of scrollback buffer
+	  Enter the amount of System RAM to allocate for scrollback
+	  buffers of VGA consoles. Each 64KB will give you approximately
+	  16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+	bool "Persistent Scrollback History for each console"
+	depends on VGACON_SOFT_SCROLLBACK
+	default n
+	help
+	  Say Y here if the scrollback history should persist when switching
+	  between consoles. Otherwise, the scrollback history will be flushed
+	  each time the console is switched.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
 	depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
 	void *data;
 	int tail;
 	int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
 	int cur;
 	int save;
 	int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-	if (vgacon_scrollback.data && reset_size > 0)
-		memset(vgacon_scrollback.data, 0, reset_size);
+	struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
+
+	if (scrollback->data && reset_size > 0)
+		memset(scrollback->data, 0, reset_size);
 
-	vgacon_scrollback.cnt  = 0;
-	vgacon_scrollback.tail = 0;
-	vgacon_scrollback.cur  = 0;
+	scrollback->cnt  = 0;
+	scrollback->tail = 0;
+	scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-	if (vgacon_scrollback.data) {
-		vgacon_scrollback.cnt  = 0;
-		vgacon_scrollback.tail = 0;
-		vgacon_scrollback.cur  = 0;
-		vgacon_scrollback.rows = rows - 1;
-		vgacon_scrollback.size = rows * pitch;
+	int pitch = vga_video_num_columns * 2;
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+	int rows = size / pitch;
+	void *data;
+
+	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+			     GFP_NOWAIT);
+
+	vgacon_scrollbacks[vc_num].data = data;
+	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+
+	vgacon_scrollback_cur->rows = rows - 1;
+	vgacon_scrollback_cur->size = rows * pitch;
+
+	vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+	vc_num = 0;
+#endif
+
+	if (!vgacon_scrollbacks[vc_num].data) {
+		vgacon_scrollback_init(vc_num);
+	} else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+#else
+		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+		vgacon_scrollback_reset(vc_num, size);
+#endif
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
-		1024, GFP_NOWAIT);
-	vgacon_scrollback_init(vga_video_num_columns * 2);
+	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
+	vgacon_scrollback_init(0);
 }
 
 static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback.size || c->vc_num != fg_console)
+	if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
+	    c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
+		scr_memcpyw(vgacon_scrollback_cur->data +
+			    vgacon_scrollback_cur->tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback.cnt++;
+
+		vgacon_scrollback_cur->cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback.tail += c->vc_size_row;
+		vgacon_scrollback_cur->tail += c->vc_size_row;
 
-		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
-			vgacon_scrollback.tail = 0;
+		if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
+			vgacon_scrollback_cur->tail = 0;
 
-		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
-			vgacon_scrollback.cnt = vgacon_scrollback.rows;
+		if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
+			vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
 
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback.save = 0;
+	vgacon_scrollback_cur->save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback.restore) {
+	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback.restore = 1;
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->restore = 1;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
@@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback.data)
+	if (!vgacon_scrollback_cur->data)
 		return;
 
-	if (!vgacon_scrollback.save) {
+	if (!vgacon_scrollback_cur->save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback.save = 1;
+		vgacon_scrollback_cur->save = 1;
 	}
 
-	vgacon_scrollback.restore = 0;
-	start = vgacon_scrollback.cur + lines;
+	vgacon_scrollback_cur->restore = 0;
+	start = vgacon_scrollback_cur->cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback.cnt)
-		start = vgacon_scrollback.cnt;
+	if (start > vgacon_scrollback_cur->cnt)
+		start = vgacon_scrollback_cur->cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback.cnt)
-		end = vgacon_scrollback.cnt;
+	if (end > vgacon_scrollback_cur->cnt)
+		end = vgacon_scrollback_cur->cnt;
 
-	vgacon_scrollback.cur = start;
+	vgacon_scrollback_cur->cur = start;
 	count = end - start;
-	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
-					 c->vc_size_row);
+	soff = vgacon_scrollback_cur->tail -
+		((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback.size;
+		soff += vgacon_scrollback_cur->size;
 
-	count = vgacon_scrollback.cnt - start;
+	count = vgacon_scrollback_cur->cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback.size - soff);
-		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
+		copysize = min(count, vgacon_scrollback_cur->size - soff);
+		scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback.data, count);
+			scr_memcpyw(d, vgacon_scrollback_cur->data, count);
 			d += count;
 		}
 
@@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct vc_data *c)
 {
 	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-	if (c->vc_num == fg_console)
-		vgacon_scrollback_reset(size);
+	vgacon_scrollback_reset(c->vc_num, size);
 }
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
 #define vgacon_scrollback_update(...)  do { } while (0)
+#define vgacon_scrollback_switch(...)  do { } while (0)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
@@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
 	}
 
-	vgacon_scrollback_init(c->vc_size_row);
+	vgacon_scrollback_switch(c->vc_num);
 	return 0;		/* Redrawing not needed */
 }
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles
  2016-12-04 10:53 [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
                   ` (2 preceding siblings ...)
  2016-12-04 10:53 ` [PATCH v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2016-12-06 10:02 ` Greg KH
  2016-12-06 16:32   ` Manuel Schölling
  2016-12-21 16:37 ` [PATCH RESEND " Manuel Schölling
  2017-01-02 14:27 ` [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  5 siblings, 1 reply; 49+ messages in thread
From: Greg KH @ 2016-12-06 10:02 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: plagnioj, tomi.valkeinen, jslaby, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

On Sun, Dec 04, 2016 at 11:53:53AM +0100, Manuel Schölling wrote:
> Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
> Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
> Tested-by: Adam Borowski <kilobyte@angband.pl>
> 
> --
> Changes in v7:
>   - Add new callback to consw struct for flushing video console driver's
>     scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
>     by Adam Borowski (kilobyte@angband.pl).
>   - Fix style issues

But this is now v8, right?  I see two v7 patch series in my inbox :(

confused,

greg k-h

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles
  2016-12-06 10:02 ` [PATCH v7 0/3] " Greg KH
@ 2016-12-06 16:32   ` Manuel Schölling
  0 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-06 16:32 UTC (permalink / raw)
  To: Greg KH
  Cc: plagnioj, tomi.valkeinen, jslaby, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

Hi Greg,

On Di, 2016-12-06 at 11:02 +0100, Greg KH wrote:
> On Sun, Dec 04, 2016 at 11:53:53AM +0100, Manuel Schölling wrote:
> > Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > Tested-by: Adam Borowski <kilobyte@angband.pl>
> > 
> > --
> > Changes in v7:
> >   - Add new callback to consw struct for flushing video console driver's
> >     scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
> >     by Adam Borowski (kilobyte@angband.pl).
> >   - Fix style issues
> 
> But this is now v8, right?  I see two v7 patch series in my inbox :(
> 
> confused,
Sorry for causing confusion. I wasn't sure about the workflow so asked
on #kernelnewbies a few days ago but apparently I misunderstood the
advice I got there:

This is just the same patch (v7) as I sent before, but I added the
Tested-By/Reviewed-By tags.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles
  2016-12-04 10:53 [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
                   ` (3 preceding siblings ...)
  2016-12-06 10:02 ` [PATCH v7 0/3] " Greg KH
@ 2016-12-21 16:37 ` Manuel Schölling
  2016-12-21 16:37   ` [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
                     ` (3 more replies)
  2017-01-02 14:27 ` [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  5 siblings, 4 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-21 16:37 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
    scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
    by Adam Borowski (kilobyte@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
    vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
    VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
    escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c            |   9 +++
 drivers/video/console/Kconfig  |  25 ++++++-
 drivers/video/console/vgacon.c | 165 ++++++++++++++++++++++++++++-------------
 include/linux/console.h        |   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct
  2016-12-21 16:37 ` [PATCH RESEND " Manuel Schölling
@ 2016-12-21 16:37   ` Manuel Schölling
  2016-12-21 16:37   ` [PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-21 16:37 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/video/console/vgacon.c | 91 ++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+	void *data;
+	int tail;
+	int size;
+	int rows;
+	int cnt;
+	int cur;
+	int save;
+	int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-	if (vgacon_scrollback) {
-		vgacon_scrollback_cnt  = 0;
-		vgacon_scrollback_tail = 0;
-		vgacon_scrollback_cur  = 0;
-		vgacon_scrollback_rows = rows - 1;
-		vgacon_scrollback_size = rows * pitch;
+	if (vgacon_scrollback.data) {
+		vgacon_scrollback.cnt  = 0;
+		vgacon_scrollback.tail = 0;
+		vgacon_scrollback.cur  = 0;
+		vgacon_scrollback.rows = rows - 1;
+		vgacon_scrollback.size = rows * pitch;
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
+	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+		1024, GFP_NOWAIT);
 	vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback_size || c->vc_num != fg_console)
+	if (!vgacon_scrollback.size || c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback_cnt++;
+		vgacon_scrollback.cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback_tail += c->vc_size_row;
+		vgacon_scrollback.tail += c->vc_size_row;
 
-		if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-			vgacon_scrollback_tail = 0;
+		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+			vgacon_scrollback.tail = 0;
 
-		if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-			vgacon_scrollback_cnt = vgacon_scrollback_rows;
+		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+			vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback_save = 0;
+	vgacon_scrollback.save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback_restore) {
+	if (!vga_is_gfx && !vgacon_scrollback.restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback_restore = 1;
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.restore = 1;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback)
+	if (!vgacon_scrollback.data)
 		return;
 
-	if (!vgacon_scrollback_save) {
+	if (!vgacon_scrollback.save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback_save = 1;
+		vgacon_scrollback.save = 1;
 	}
 
-	vgacon_scrollback_restore = 0;
-	start = vgacon_scrollback_cur + lines;
+	vgacon_scrollback.restore = 0;
+	start = vgacon_scrollback.cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback_cnt)
-		start = vgacon_scrollback_cnt;
+	if (start > vgacon_scrollback.cnt)
+		start = vgacon_scrollback.cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback_cnt)
-		end = vgacon_scrollback_cnt;
+	if (end > vgacon_scrollback.cnt)
+		end = vgacon_scrollback.cnt;
 
-	vgacon_scrollback_cur = start;
+	vgacon_scrollback.cur = start;
 	count = end - start;
-	soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
 					 c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback_size;
+		soff += vgacon_scrollback.size;
 
-	count = vgacon_scrollback_cnt - start;
+	count = vgacon_scrollback.cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -287,13 +290,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback_size - soff);
-		scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+		copysize = min(count, vgacon_scrollback.size - soff);
+		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback, count);
+			scr_memcpyw(d, vgacon_scrollback.data, count);
 			d += count;
 		}
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct
  2016-12-21 16:37 ` [PATCH RESEND " Manuel Schölling
  2016-12-21 16:37   ` [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
@ 2016-12-21 16:37   ` Manuel Schölling
  2016-12-21 16:37   ` [PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2017-01-04 13:54   ` [PATCH RESEND v7 0/3] " Andrey Utkin
  3 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-21 16:37 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/tty/vt/vt.c            |  9 +++++++++
 drivers/video/console/vgacon.c | 24 +++++++++++++++++++++++-
 include/linux/console.h        |  4 ++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
 		vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+	WARN_CONSOLE_UNLOCKED();
+
+	if (vc->vc_sw->con_flush_scrollback)
+		vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  *	Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
 		case 3: /* erase scroll-back buffer (and whole display) */
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
 				    vc->vc_screenbuf_size);
+			flush_scrollback(vc);
 			set_origin(vc);
 			if (con_is_visible(vc))
 				update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
 	int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+	if (vgacon_scrollback.data && reset_size > 0)
+		memset(vgacon_scrollback.data, 0, reset_size);
+
+	vgacon_scrollback.cnt  = 0;
+	vgacon_scrollback.tail = 0;
+	vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 	} else
 		vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+	if (c->vc_num == fg_console)
+		vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 			vga_vram_size);
 	vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
 	return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
 	.con_save_screen = vgacon_save_screen,
 	.con_build_attr = vgacon_build_attr,
 	.con_invert_region = vgacon_invert_region,
+	.con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
 	u16    *(*con_screen_pos)(struct vc_data *, int);
 	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
 	/*
+	 * Flush the video console driver's scrollback buffer
+	 */
+	void	(*con_flush_scrollback)(struct vc_data *);
+	/*
 	 * Prepare the console for the debugger.  This includes, but is not
 	 * limited to, unblanking the console, loading an appropriate
 	 * palette, and allowing debugger generated output.
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles
  2016-12-21 16:37 ` [PATCH RESEND " Manuel Schölling
  2016-12-21 16:37   ` [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
  2016-12-21 16:37   ` [PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
@ 2016-12-21 16:37   ` Manuel Schölling
  2017-01-04 13:54   ` [PATCH RESEND v7 0/3] " Andrey Utkin
  3 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2016-12-21 16:37 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/video/console/Kconfig  |  25 +++++++-
 drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
        range 1 1024
        default "64"
        help
-         Enter the amount of System RAM to allocate for the scrollback
-	 buffer.  Each 64KB will give you approximately 16 80x25
-	 screenfuls of scrollback buffer
+	  Enter the amount of System RAM to allocate for scrollback
+	  buffers of VGA consoles. Each 64KB will give you approximately
+	  16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+	bool "Persistent Scrollback History for each console"
+	depends on VGACON_SOFT_SCROLLBACK
+	default n
+	help
+	  Say Y here if the scrollback history should persist when switching
+	  between consoles. Otherwise, the scrollback history will be flushed
+	  each time the console is switched.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
 	depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
 	void *data;
 	int tail;
 	int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
 	int cur;
 	int save;
 	int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-	if (vgacon_scrollback.data && reset_size > 0)
-		memset(vgacon_scrollback.data, 0, reset_size);
+	struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
+
+	if (scrollback->data && reset_size > 0)
+		memset(scrollback->data, 0, reset_size);
 
-	vgacon_scrollback.cnt  = 0;
-	vgacon_scrollback.tail = 0;
-	vgacon_scrollback.cur  = 0;
+	scrollback->cnt  = 0;
+	scrollback->tail = 0;
+	scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-	if (vgacon_scrollback.data) {
-		vgacon_scrollback.cnt  = 0;
-		vgacon_scrollback.tail = 0;
-		vgacon_scrollback.cur  = 0;
-		vgacon_scrollback.rows = rows - 1;
-		vgacon_scrollback.size = rows * pitch;
+	int pitch = vga_video_num_columns * 2;
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+	int rows = size / pitch;
+	void *data;
+
+	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+			     GFP_NOWAIT);
+
+	vgacon_scrollbacks[vc_num].data = data;
+	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+
+	vgacon_scrollback_cur->rows = rows - 1;
+	vgacon_scrollback_cur->size = rows * pitch;
+
+	vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+	vc_num = 0;
+#endif
+
+	if (!vgacon_scrollbacks[vc_num].data) {
+		vgacon_scrollback_init(vc_num);
+	} else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+#else
+		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+		vgacon_scrollback_reset(vc_num, size);
+#endif
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
-		1024, GFP_NOWAIT);
-	vgacon_scrollback_init(vga_video_num_columns * 2);
+	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
+	vgacon_scrollback_init(0);
 }
 
 static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback.size || c->vc_num != fg_console)
+	if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
+	    c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
+		scr_memcpyw(vgacon_scrollback_cur->data +
+			    vgacon_scrollback_cur->tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback.cnt++;
+
+		vgacon_scrollback_cur->cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback.tail += c->vc_size_row;
+		vgacon_scrollback_cur->tail += c->vc_size_row;
 
-		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
-			vgacon_scrollback.tail = 0;
+		if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
+			vgacon_scrollback_cur->tail = 0;
 
-		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
-			vgacon_scrollback.cnt = vgacon_scrollback.rows;
+		if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
+			vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
 
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback.save = 0;
+	vgacon_scrollback_cur->save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback.restore) {
+	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback.restore = 1;
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->restore = 1;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
@@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback.data)
+	if (!vgacon_scrollback_cur->data)
 		return;
 
-	if (!vgacon_scrollback.save) {
+	if (!vgacon_scrollback_cur->save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback.save = 1;
+		vgacon_scrollback_cur->save = 1;
 	}
 
-	vgacon_scrollback.restore = 0;
-	start = vgacon_scrollback.cur + lines;
+	vgacon_scrollback_cur->restore = 0;
+	start = vgacon_scrollback_cur->cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback.cnt)
-		start = vgacon_scrollback.cnt;
+	if (start > vgacon_scrollback_cur->cnt)
+		start = vgacon_scrollback_cur->cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback.cnt)
-		end = vgacon_scrollback.cnt;
+	if (end > vgacon_scrollback_cur->cnt)
+		end = vgacon_scrollback_cur->cnt;
 
-	vgacon_scrollback.cur = start;
+	vgacon_scrollback_cur->cur = start;
 	count = end - start;
-	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
-					 c->vc_size_row);
+	soff = vgacon_scrollback_cur->tail -
+		((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback.size;
+		soff += vgacon_scrollback_cur->size;
 
-	count = vgacon_scrollback.cnt - start;
+	count = vgacon_scrollback_cur->cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback.size - soff);
-		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
+		copysize = min(count, vgacon_scrollback_cur->size - soff);
+		scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback.data, count);
+			scr_memcpyw(d, vgacon_scrollback_cur->data, count);
 			d += count;
 		}
 
@@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct vc_data *c)
 {
 	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-	if (c->vc_num == fg_console)
-		vgacon_scrollback_reset(size);
+	vgacon_scrollback_reset(c->vc_num, size);
 }
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
 #define vgacon_scrollback_update(...)  do { } while (0)
+#define vgacon_scrollback_switch(...)  do { } while (0)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
@@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
 	}
 
-	vgacon_scrollback_init(c->vc_size_row);
+	vgacon_scrollback_switch(c->vc_num);
 	return 0;		/* Redrawing not needed */
 }
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles
  2016-12-04 10:53 [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
                   ` (4 preceding siblings ...)
  2016-12-21 16:37 ` [PATCH RESEND " Manuel Schölling
@ 2017-01-02 14:27 ` Manuel Schölling
  2017-01-02 14:27   ` [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
                     ` (2 more replies)
  5 siblings, 3 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-02 14:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
    scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
    by Adam Borowski (kilobyte@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
    vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
    VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
    escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c            |   9 +++
 drivers/video/console/Kconfig  |  25 ++++++-
 drivers/video/console/vgacon.c | 165 ++++++++++++++++++++++++++++-------------
 include/linux/console.h        |   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct
  2017-01-02 14:27 ` [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2017-01-02 14:27   ` Manuel Schölling
  2017-01-02 14:27   ` [PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
  2017-01-02 14:27   ` [PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-02 14:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/video/console/vgacon.c | 91 ++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+	void *data;
+	int tail;
+	int size;
+	int rows;
+	int cnt;
+	int cur;
+	int save;
+	int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-	if (vgacon_scrollback) {
-		vgacon_scrollback_cnt  = 0;
-		vgacon_scrollback_tail = 0;
-		vgacon_scrollback_cur  = 0;
-		vgacon_scrollback_rows = rows - 1;
-		vgacon_scrollback_size = rows * pitch;
+	if (vgacon_scrollback.data) {
+		vgacon_scrollback.cnt  = 0;
+		vgacon_scrollback.tail = 0;
+		vgacon_scrollback.cur  = 0;
+		vgacon_scrollback.rows = rows - 1;
+		vgacon_scrollback.size = rows * pitch;
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
+	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+		1024, GFP_NOWAIT);
 	vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback_size || c->vc_num != fg_console)
+	if (!vgacon_scrollback.size || c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback_cnt++;
+		vgacon_scrollback.cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback_tail += c->vc_size_row;
+		vgacon_scrollback.tail += c->vc_size_row;
 
-		if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-			vgacon_scrollback_tail = 0;
+		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+			vgacon_scrollback.tail = 0;
 
-		if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-			vgacon_scrollback_cnt = vgacon_scrollback_rows;
+		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+			vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback_save = 0;
+	vgacon_scrollback.save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback_restore) {
+	if (!vga_is_gfx && !vgacon_scrollback.restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback_restore = 1;
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.restore = 1;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback)
+	if (!vgacon_scrollback.data)
 		return;
 
-	if (!vgacon_scrollback_save) {
+	if (!vgacon_scrollback.save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback_save = 1;
+		vgacon_scrollback.save = 1;
 	}
 
-	vgacon_scrollback_restore = 0;
-	start = vgacon_scrollback_cur + lines;
+	vgacon_scrollback.restore = 0;
+	start = vgacon_scrollback.cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback_cnt)
-		start = vgacon_scrollback_cnt;
+	if (start > vgacon_scrollback.cnt)
+		start = vgacon_scrollback.cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback_cnt)
-		end = vgacon_scrollback_cnt;
+	if (end > vgacon_scrollback.cnt)
+		end = vgacon_scrollback.cnt;
 
-	vgacon_scrollback_cur = start;
+	vgacon_scrollback.cur = start;
 	count = end - start;
-	soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
 					 c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback_size;
+		soff += vgacon_scrollback.size;
 
-	count = vgacon_scrollback_cnt - start;
+	count = vgacon_scrollback.cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -287,13 +290,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback_size - soff);
-		scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+		copysize = min(count, vgacon_scrollback.size - soff);
+		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback, count);
+			scr_memcpyw(d, vgacon_scrollback.data, count);
 			d += count;
 		}
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct
  2017-01-02 14:27 ` [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2017-01-02 14:27   ` [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
@ 2017-01-02 14:27   ` Manuel Schölling
  2017-01-02 14:27   ` [PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-02 14:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/tty/vt/vt.c            |  9 +++++++++
 drivers/video/console/vgacon.c | 24 +++++++++++++++++++++++-
 include/linux/console.h        |  4 ++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
 		vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+	WARN_CONSOLE_UNLOCKED();
+
+	if (vc->vc_sw->con_flush_scrollback)
+		vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  *	Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
 		case 3: /* erase scroll-back buffer (and whole display) */
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
 				    vc->vc_screenbuf_size);
+			flush_scrollback(vc);
 			set_origin(vc);
 			if (con_is_visible(vc))
 				update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
 	int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+	if (vgacon_scrollback.data && reset_size > 0)
+		memset(vgacon_scrollback.data, 0, reset_size);
+
+	vgacon_scrollback.cnt  = 0;
+	vgacon_scrollback.tail = 0;
+	vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 	} else
 		vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+	if (c->vc_num == fg_console)
+		vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 			vga_vram_size);
 	vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
 	return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
 	.con_save_screen = vgacon_save_screen,
 	.con_build_attr = vgacon_build_attr,
 	.con_invert_region = vgacon_invert_region,
+	.con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
 	u16    *(*con_screen_pos)(struct vc_data *, int);
 	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
 	/*
+	 * Flush the video console driver's scrollback buffer
+	 */
+	void	(*con_flush_scrollback)(struct vc_data *);
+	/*
 	 * Prepare the console for the debugger.  This includes, but is not
 	 * limited to, unblanking the console, loading an appropriate
 	 * palette, and allowing debugger generated output.
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-02 14:27 ` [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2017-01-02 14:27   ` [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
  2017-01-02 14:27   ` [PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
@ 2017-01-02 14:27   ` Manuel Schölling
  2 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-02 14:27 UTC (permalink / raw)
  To: plagnioj, tomi.valkeinen
  Cc: manuel.schoelling, jslaby, gregkh, andrey_utkin, kilobyte,
	linux-fbdev, linux-kernel

Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

---
 drivers/video/console/Kconfig  |  25 +++++++-
 drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
        range 1 1024
        default "64"
        help
-         Enter the amount of System RAM to allocate for the scrollback
-	 buffer.  Each 64KB will give you approximately 16 80x25
-	 screenfuls of scrollback buffer
+	  Enter the amount of System RAM to allocate for scrollback
+	  buffers of VGA consoles. Each 64KB will give you approximately
+	  16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+	bool "Persistent Scrollback History for each console"
+	depends on VGACON_SOFT_SCROLLBACK
+	default n
+	help
+	  Say Y here if the scrollback history should persist when switching
+	  between consoles. Otherwise, the scrollback history will be flushed
+	  each time the console is switched.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
 	depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
 	void *data;
 	int tail;
 	int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
 	int cur;
 	int save;
 	int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-	if (vgacon_scrollback.data && reset_size > 0)
-		memset(vgacon_scrollback.data, 0, reset_size);
+	struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
+
+	if (scrollback->data && reset_size > 0)
+		memset(scrollback->data, 0, reset_size);
 
-	vgacon_scrollback.cnt  = 0;
-	vgacon_scrollback.tail = 0;
-	vgacon_scrollback.cur  = 0;
+	scrollback->cnt  = 0;
+	scrollback->tail = 0;
+	scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-	if (vgacon_scrollback.data) {
-		vgacon_scrollback.cnt  = 0;
-		vgacon_scrollback.tail = 0;
-		vgacon_scrollback.cur  = 0;
-		vgacon_scrollback.rows = rows - 1;
-		vgacon_scrollback.size = rows * pitch;
+	int pitch = vga_video_num_columns * 2;
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+	int rows = size / pitch;
+	void *data;
+
+	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+			     GFP_NOWAIT);
+
+	vgacon_scrollbacks[vc_num].data = data;
+	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+
+	vgacon_scrollback_cur->rows = rows - 1;
+	vgacon_scrollback_cur->size = rows * pitch;
+
+	vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+	vc_num = 0;
+#endif
+
+	if (!vgacon_scrollbacks[vc_num].data) {
+		vgacon_scrollback_init(vc_num);
+	} else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+#else
+		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+		vgacon_scrollback_reset(vc_num, size);
+#endif
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
-		1024, GFP_NOWAIT);
-	vgacon_scrollback_init(vga_video_num_columns * 2);
+	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
+	vgacon_scrollback_init(0);
 }
 
 static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback.size || c->vc_num != fg_console)
+	if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
+	    c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
+		scr_memcpyw(vgacon_scrollback_cur->data +
+			    vgacon_scrollback_cur->tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback.cnt++;
+
+		vgacon_scrollback_cur->cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback.tail += c->vc_size_row;
+		vgacon_scrollback_cur->tail += c->vc_size_row;
 
-		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
-			vgacon_scrollback.tail = 0;
+		if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
+			vgacon_scrollback_cur->tail = 0;
 
-		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
-			vgacon_scrollback.cnt = vgacon_scrollback.rows;
+		if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
+			vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
 
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback.save = 0;
+	vgacon_scrollback_cur->save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback.restore) {
+	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback.restore = 1;
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->restore = 1;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
@@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback.data)
+	if (!vgacon_scrollback_cur->data)
 		return;
 
-	if (!vgacon_scrollback.save) {
+	if (!vgacon_scrollback_cur->save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback.save = 1;
+		vgacon_scrollback_cur->save = 1;
 	}
 
-	vgacon_scrollback.restore = 0;
-	start = vgacon_scrollback.cur + lines;
+	vgacon_scrollback_cur->restore = 0;
+	start = vgacon_scrollback_cur->cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback.cnt)
-		start = vgacon_scrollback.cnt;
+	if (start > vgacon_scrollback_cur->cnt)
+		start = vgacon_scrollback_cur->cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback.cnt)
-		end = vgacon_scrollback.cnt;
+	if (end > vgacon_scrollback_cur->cnt)
+		end = vgacon_scrollback_cur->cnt;
 
-	vgacon_scrollback.cur = start;
+	vgacon_scrollback_cur->cur = start;
 	count = end - start;
-	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
-					 c->vc_size_row);
+	soff = vgacon_scrollback_cur->tail -
+		((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback.size;
+		soff += vgacon_scrollback_cur->size;
 
-	count = vgacon_scrollback.cnt - start;
+	count = vgacon_scrollback_cur->cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback.size - soff);
-		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
+		copysize = min(count, vgacon_scrollback_cur->size - soff);
+		scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback.data, count);
+			scr_memcpyw(d, vgacon_scrollback_cur->data, count);
 			d += count;
 		}
 
@@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct vc_data *c)
 {
 	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-	if (c->vc_num == fg_console)
-		vgacon_scrollback_reset(size);
+	vgacon_scrollback_reset(c->vc_num, size);
 }
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
 #define vgacon_scrollback_update(...)  do { } while (0)
+#define vgacon_scrollback_switch(...)  do { } while (0)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
@@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
 	}
 
-	vgacon_scrollback_init(c->vc_size_row);
+	vgacon_scrollback_switch(c->vc_num);
 	return 0;		/* Redrawing not needed */
 }
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles
  2016-12-21 16:37 ` [PATCH RESEND " Manuel Schölling
                     ` (2 preceding siblings ...)
  2016-12-21 16:37   ` [PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2017-01-04 13:54   ` Andrey Utkin
  2017-01-05 11:33     ` [PATCH v8 " Manuel Schölling
                       ` (3 more replies)
  3 siblings, 4 replies; 49+ messages in thread
From: Andrey Utkin @ 2017-01-04 13:54 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: plagnioj, tomi.valkeinen, jslaby, gregkh, kilobyte, linux-fbdev,
	linux-kernel

Manuel,

Previous Greg KH reply implied that you should send it marked as v8 for
it to gain visibility and avoid confusion. Just prepend your changes
history with something like

Changes in v8:
 - Added Reviewed-by, Tested-by statements

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v8 0/3] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-04 13:54   ` [PATCH RESEND v7 0/3] " Andrey Utkin
@ 2017-01-05 11:33     ` Manuel Schölling
  2017-01-05 11:33     ` [PATCH v8 1/3] console: Move scrollback data into its own struct Manuel Schölling
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-05 11:33 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>

--
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
    scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
    by Adam Borowski (kilobyte@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
    vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
    VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
    escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c            |   9 +++
 drivers/video/console/Kconfig  |  25 ++++++-
 drivers/video/console/vgacon.c | 165 ++++++++++++++++++++++++++++-------------
 include/linux/console.h        |   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v8 1/3] console: Move scrollback data into its own struct
  2017-01-04 13:54   ` [PATCH RESEND v7 0/3] " Andrey Utkin
  2017-01-05 11:33     ` [PATCH v8 " Manuel Schölling
@ 2017-01-05 11:33     ` Manuel Schölling
  2017-01-05 11:33     ` [PATCH v8 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
  2017-01-05 11:33     ` [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  3 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-05 11:33 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/video/console/vgacon.c | 91 ++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+	void *data;
+	int tail;
+	int size;
+	int rows;
+	int cnt;
+	int cur;
+	int save;
+	int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-	if (vgacon_scrollback) {
-		vgacon_scrollback_cnt  = 0;
-		vgacon_scrollback_tail = 0;
-		vgacon_scrollback_cur  = 0;
-		vgacon_scrollback_rows = rows - 1;
-		vgacon_scrollback_size = rows * pitch;
+	if (vgacon_scrollback.data) {
+		vgacon_scrollback.cnt  = 0;
+		vgacon_scrollback.tail = 0;
+		vgacon_scrollback.cur  = 0;
+		vgacon_scrollback.rows = rows - 1;
+		vgacon_scrollback.size = rows * pitch;
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
+	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+		1024, GFP_NOWAIT);
 	vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback_size || c->vc_num != fg_console)
+	if (!vgacon_scrollback.size || c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback_cnt++;
+		vgacon_scrollback.cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback_tail += c->vc_size_row;
+		vgacon_scrollback.tail += c->vc_size_row;
 
-		if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-			vgacon_scrollback_tail = 0;
+		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+			vgacon_scrollback.tail = 0;
 
-		if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-			vgacon_scrollback_cnt = vgacon_scrollback_rows;
+		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+			vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback_save = 0;
+	vgacon_scrollback.save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback_restore) {
+	if (!vga_is_gfx && !vgacon_scrollback.restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback_restore = 1;
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.restore = 1;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback)
+	if (!vgacon_scrollback.data)
 		return;
 
-	if (!vgacon_scrollback_save) {
+	if (!vgacon_scrollback.save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback_save = 1;
+		vgacon_scrollback.save = 1;
 	}
 
-	vgacon_scrollback_restore = 0;
-	start = vgacon_scrollback_cur + lines;
+	vgacon_scrollback.restore = 0;
+	start = vgacon_scrollback.cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback_cnt)
-		start = vgacon_scrollback_cnt;
+	if (start > vgacon_scrollback.cnt)
+		start = vgacon_scrollback.cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback_cnt)
-		end = vgacon_scrollback_cnt;
+	if (end > vgacon_scrollback.cnt)
+		end = vgacon_scrollback.cnt;
 
-	vgacon_scrollback_cur = start;
+	vgacon_scrollback.cur = start;
 	count = end - start;
-	soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
 					 c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback_size;
+		soff += vgacon_scrollback.size;
 
-	count = vgacon_scrollback_cnt - start;
+	count = vgacon_scrollback.cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -287,13 +290,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback_size - soff);
-		scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+		copysize = min(count, vgacon_scrollback.size - soff);
+		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback, count);
+			scr_memcpyw(d, vgacon_scrollback.data, count);
 			d += count;
 		}
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v8 2/3] console: Add callback to flush scrollback buffer to consw struct
  2017-01-04 13:54   ` [PATCH RESEND v7 0/3] " Andrey Utkin
  2017-01-05 11:33     ` [PATCH v8 " Manuel Schölling
  2017-01-05 11:33     ` [PATCH v8 1/3] console: Move scrollback data into its own struct Manuel Schölling
@ 2017-01-05 11:33     ` Manuel Schölling
  2017-01-05 11:33     ` [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  3 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-05 11:33 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/tty/vt/vt.c            |  9 +++++++++
 drivers/video/console/vgacon.c | 24 +++++++++++++++++++++++-
 include/linux/console.h        |  4 ++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
 		vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+	WARN_CONSOLE_UNLOCKED();
+
+	if (vc->vc_sw->con_flush_scrollback)
+		vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  *	Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
 		case 3: /* erase scroll-back buffer (and whole display) */
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
 				    vc->vc_screenbuf_size);
+			flush_scrollback(vc);
 			set_origin(vc);
 			if (con_is_visible(vc))
 				update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
 	int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+	if (vgacon_scrollback.data && reset_size > 0)
+		memset(vgacon_scrollback.data, 0, reset_size);
+
+	vgacon_scrollback.cnt  = 0;
+	vgacon_scrollback.tail = 0;
+	vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 	} else
 		vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+	if (c->vc_num == fg_console)
+		vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 			vga_vram_size);
 	vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
 	return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
 	.con_save_screen = vgacon_save_screen,
 	.con_build_attr = vgacon_build_attr,
 	.con_invert_region = vgacon_invert_region,
+	.con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
 	u16    *(*con_screen_pos)(struct vc_data *, int);
 	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
 	/*
+	 * Flush the video console driver's scrollback buffer
+	 */
+	void	(*con_flush_scrollback)(struct vc_data *);
+	/*
 	 * Prepare the console for the debugger.  This includes, but is not
 	 * limited to, unblanking the console, loading an appropriate
 	 * palette, and allowing debugger generated output.
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-04 13:54   ` [PATCH RESEND v7 0/3] " Andrey Utkin
                       ` (2 preceding siblings ...)
  2017-01-05 11:33     ` [PATCH v8 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
@ 2017-01-05 11:33     ` Manuel Schölling
       [not found]       ` <CGME20170110162224epcas1p2095912fa6b73a1457fa86396149e78e9@epcas1p2.samsung.com>
  3 siblings, 1 reply; 49+ messages in thread
From: Manuel Schölling @ 2017-01-05 11:33 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/video/console/Kconfig  |  25 +++++++-
 drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
        range 1 1024
        default "64"
        help
-         Enter the amount of System RAM to allocate for the scrollback
-	 buffer.  Each 64KB will give you approximately 16 80x25
-	 screenfuls of scrollback buffer
+	  Enter the amount of System RAM to allocate for scrollback
+	  buffers of VGA consoles. Each 64KB will give you approximately
+	  16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+	bool "Persistent Scrollback History for each console"
+	depends on VGACON_SOFT_SCROLLBACK
+	default n
+	help
+	  Say Y here if the scrollback history should persist when switching
+	  between consoles. Otherwise, the scrollback history will be flushed
+	  each time the console is switched.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
 	depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
 	void *data;
 	int tail;
 	int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
 	int cur;
 	int save;
 	int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-	if (vgacon_scrollback.data && reset_size > 0)
-		memset(vgacon_scrollback.data, 0, reset_size);
+	struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
+
+	if (scrollback->data && reset_size > 0)
+		memset(scrollback->data, 0, reset_size);
 
-	vgacon_scrollback.cnt  = 0;
-	vgacon_scrollback.tail = 0;
-	vgacon_scrollback.cur  = 0;
+	scrollback->cnt  = 0;
+	scrollback->tail = 0;
+	scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-	if (vgacon_scrollback.data) {
-		vgacon_scrollback.cnt  = 0;
-		vgacon_scrollback.tail = 0;
-		vgacon_scrollback.cur  = 0;
-		vgacon_scrollback.rows = rows - 1;
-		vgacon_scrollback.size = rows * pitch;
+	int pitch = vga_video_num_columns * 2;
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+	int rows = size / pitch;
+	void *data;
+
+	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+			     GFP_NOWAIT);
+
+	vgacon_scrollbacks[vc_num].data = data;
+	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+
+	vgacon_scrollback_cur->rows = rows - 1;
+	vgacon_scrollback_cur->size = rows * pitch;
+
+	vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+	vc_num = 0;
+#endif
+
+	if (!vgacon_scrollbacks[vc_num].data) {
+		vgacon_scrollback_init(vc_num);
+	} else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+#else
+		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+		vgacon_scrollback_reset(vc_num, size);
+#endif
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
-		1024, GFP_NOWAIT);
-	vgacon_scrollback_init(vga_video_num_columns * 2);
+	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
+	vgacon_scrollback_init(0);
 }
 
 static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback.size || c->vc_num != fg_console)
+	if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
+	    c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
+		scr_memcpyw(vgacon_scrollback_cur->data +
+			    vgacon_scrollback_cur->tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback.cnt++;
+
+		vgacon_scrollback_cur->cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback.tail += c->vc_size_row;
+		vgacon_scrollback_cur->tail += c->vc_size_row;
 
-		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
-			vgacon_scrollback.tail = 0;
+		if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
+			vgacon_scrollback_cur->tail = 0;
 
-		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
-			vgacon_scrollback.cnt = vgacon_scrollback.rows;
+		if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
+			vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
 
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback.save = 0;
+	vgacon_scrollback_cur->save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback.restore) {
+	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback.restore = 1;
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->restore = 1;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
@@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback.data)
+	if (!vgacon_scrollback_cur->data)
 		return;
 
-	if (!vgacon_scrollback.save) {
+	if (!vgacon_scrollback_cur->save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback.save = 1;
+		vgacon_scrollback_cur->save = 1;
 	}
 
-	vgacon_scrollback.restore = 0;
-	start = vgacon_scrollback.cur + lines;
+	vgacon_scrollback_cur->restore = 0;
+	start = vgacon_scrollback_cur->cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback.cnt)
-		start = vgacon_scrollback.cnt;
+	if (start > vgacon_scrollback_cur->cnt)
+		start = vgacon_scrollback_cur->cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback.cnt)
-		end = vgacon_scrollback.cnt;
+	if (end > vgacon_scrollback_cur->cnt)
+		end = vgacon_scrollback_cur->cnt;
 
-	vgacon_scrollback.cur = start;
+	vgacon_scrollback_cur->cur = start;
 	count = end - start;
-	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
-					 c->vc_size_row);
+	soff = vgacon_scrollback_cur->tail -
+		((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback.size;
+		soff += vgacon_scrollback_cur->size;
 
-	count = vgacon_scrollback.cnt - start;
+	count = vgacon_scrollback_cur->cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback.size - soff);
-		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
+		copysize = min(count, vgacon_scrollback_cur->size - soff);
+		scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback.data, count);
+			scr_memcpyw(d, vgacon_scrollback_cur->data, count);
 			d += count;
 		}
 
@@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct vc_data *c)
 {
 	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-	if (c->vc_num == fg_console)
-		vgacon_scrollback_reset(size);
+	vgacon_scrollback_reset(c->vc_num, size);
 }
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
 #define vgacon_scrollback_update(...)  do { } while (0)
+#define vgacon_scrollback_switch(...)  do { } while (0)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
@@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
 	}
 
-	vgacon_scrollback_init(c->vc_size_row);
+	vgacon_scrollback_switch(c->vc_num);
 	return 0;		/* Redrawing not needed */
 }
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles
       [not found]       ` <CGME20170110162224epcas1p2095912fa6b73a1457fa86396149e78e9@epcas1p2.samsung.com>
@ 2017-01-10 16:22         ` Bartlomiej Zolnierkiewicz
       [not found]           ` <CGME20170110164435epcas1p314efb9c6ea3ffb971fce06f3bfaec736@epcas1p3.samsung.com>
  0 siblings, 1 reply; 49+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2017-01-10 16:22 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: gregkh, jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin,
	akpm, paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev


Hi,

The patchset generally looks fine to me but I have a question
regarding new VGACON_SOFT_SCROLLBACK_PERSISTENT config option.

Since the code size impact to support the persistent scrollback
feature is minimal wouldn't it be better to always include it?

The feature would be disabled by default and could be enabled
by using the new kernel command line parameter (you may also add
a new config option for enabling it by default if desired).

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

On Thursday, January 05, 2017 12:33:20 PM Manuel Schölling wrote:
> Add a scrollback buffers for each VGA console. The benefit is that
> the scrollback history is not flushed when switching between consoles
> but is persistent.
> The buffers are allocated on demand when a new console is opened.
> 
> This breaks tools like clear_console that rely on flushing the
> scrollback history by switching back and forth between consoles
> which is why this feature is disabled by default.
> Use the escape sequence \e[3J instead for flushing the buffer.
> 
> Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
> Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
> Tested-by: Adam Borowski <kilobyte@angband.pl>
> ---
>  drivers/video/console/Kconfig  |  25 +++++++-
>  drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
>  2 files changed, 111 insertions(+), 56 deletions(-)
> 
> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
> index c3f1fb9ee820..f500e58f7636 100644
> --- a/drivers/video/console/Kconfig
> +++ b/drivers/video/console/Kconfig
> @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
>         range 1 1024
>         default "64"
>         help
> -         Enter the amount of System RAM to allocate for the scrollback
> -	 buffer.  Each 64KB will give you approximately 16 80x25
> -	 screenfuls of scrollback buffer
> +	  Enter the amount of System RAM to allocate for scrollback
> +	  buffers of VGA consoles. Each 64KB will give you approximately
> +	  16 80x25 screenfuls of scrollback buffer.
> +
> +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> +	bool "Persistent Scrollback History for each console"
> +	depends on VGACON_SOFT_SCROLLBACK
> +	default n
> +	help
> +	  Say Y here if the scrollback history should persist when switching
> +	  between consoles. Otherwise, the scrollback history will be flushed
> +	  each time the console is switched.
> +
> +	  This feature might break your tool of choice to flush the scrollback
> +	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
> +	  will be broken, which might cause security issues.
> +	  You can use the escape sequence \e[3J instead if this feature is
> +	  activated.
> +
> +	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
> +	  created tty device.
> +	  So if you use a RAM-constrained system, say N here.
>  
>  config MDA_CONSOLE
>  	depends on !M68K && !PARISC && ISA
> diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
> index 9a7c2bbc5326..ca23d222e029 100644
> --- a/drivers/video/console/vgacon.c
> +++ b/drivers/video/console/vgacon.c
> @@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
>  
>  #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
>  /* software scrollback */
> -static struct vgacon_scrollback_info {
> +struct vgacon_scrollback_info {
>  	void *data;
>  	int tail;
>  	int size;
> @@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
>  	int cur;
>  	int save;
>  	int restore;
> -} vgacon_scrollback;
> +};
> +
> +static struct vgacon_scrollback_info *vgacon_scrollback_cur;
> +#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> +static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
> +#else
> +static struct vgacon_scrollback_info vgacon_scrollbacks[1];
> +#endif
>  
> -static void vgacon_scrollback_reset(size_t reset_size)
> +static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
>  {
> -	if (vgacon_scrollback.data && reset_size > 0)
> -		memset(vgacon_scrollback.data, 0, reset_size);
> +	struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
> +
> +	if (scrollback->data && reset_size > 0)
> +		memset(scrollback->data, 0, reset_size);
>  
> -	vgacon_scrollback.cnt  = 0;
> -	vgacon_scrollback.tail = 0;
> -	vgacon_scrollback.cur  = 0;
> +	scrollback->cnt  = 0;
> +	scrollback->tail = 0;
> +	scrollback->cur  = 0;
>  }
>  
> -static void vgacon_scrollback_init(int pitch)
> +static void vgacon_scrollback_init(int vc_num)
>  {
> -	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
> -
> -	if (vgacon_scrollback.data) {
> -		vgacon_scrollback.cnt  = 0;
> -		vgacon_scrollback.tail = 0;
> -		vgacon_scrollback.cur  = 0;
> -		vgacon_scrollback.rows = rows - 1;
> -		vgacon_scrollback.size = rows * pitch;
> +	int pitch = vga_video_num_columns * 2;
> +	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
> +	int rows = size / pitch;
> +	void *data;
> +
> +	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
> +			     GFP_NOWAIT);
> +
> +	vgacon_scrollbacks[vc_num].data = data;
> +	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
> +
> +	vgacon_scrollback_cur->rows = rows - 1;
> +	vgacon_scrollback_cur->size = rows * pitch;
> +
> +	vgacon_scrollback_reset(vc_num, size);
> +}
> +
> +static void vgacon_scrollback_switch(int vc_num)
> +{
> +#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> +	vc_num = 0;
> +#endif
> +
> +	if (!vgacon_scrollbacks[vc_num].data) {
> +		vgacon_scrollback_init(vc_num);
> +	} else {
> +#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> +		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
> +#else
> +		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
> +
> +		vgacon_scrollback_reset(vc_num, size);
> +#endif
>  	}
>  }
>  
>  static void vgacon_scrollback_startup(void)
>  {
> -	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
> -		1024, GFP_NOWAIT);
> -	vgacon_scrollback_init(vga_video_num_columns * 2);
> +	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
> +	vgacon_scrollback_init(0);
>  }
>  
>  static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
>  {
>  	void *p;
>  
> -	if (!vgacon_scrollback.size || c->vc_num != fg_console)
> +	if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
> +	    c->vc_num != fg_console)
>  		return;
>  
>  	p = (void *) (c->vc_origin + t * c->vc_size_row);
>  
>  	while (count--) {
> -		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
> +		scr_memcpyw(vgacon_scrollback_cur->data +
> +			    vgacon_scrollback_cur->tail,
>  			    p, c->vc_size_row);
> -		vgacon_scrollback.cnt++;
> +
> +		vgacon_scrollback_cur->cnt++;
>  		p += c->vc_size_row;
> -		vgacon_scrollback.tail += c->vc_size_row;
> +		vgacon_scrollback_cur->tail += c->vc_size_row;
>  
> -		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
> -			vgacon_scrollback.tail = 0;
> +		if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
> +			vgacon_scrollback_cur->tail = 0;
>  
> -		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
> -			vgacon_scrollback.cnt = vgacon_scrollback.rows;
> +		if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
> +			vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
>  
> -		vgacon_scrollback.cur = vgacon_scrollback.cnt;
> +		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
>  	}
>  }
>  
>  static void vgacon_restore_screen(struct vc_data *c)
>  {
> -	vgacon_scrollback.save = 0;
> +	vgacon_scrollback_cur->save = 0;
>  
> -	if (!vga_is_gfx && !vgacon_scrollback.restore) {
> +	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
>  		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
>  			    c->vc_screenbuf_size > vga_vram_size ?
>  			    vga_vram_size : c->vc_screenbuf_size);
> -		vgacon_scrollback.restore = 1;
> -		vgacon_scrollback.cur = vgacon_scrollback.cnt;
> +		vgacon_scrollback_cur->restore = 1;
> +		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
>  	}
>  }
>  
> @@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
>  		return;
>  	}
>  
> -	if (!vgacon_scrollback.data)
> +	if (!vgacon_scrollback_cur->data)
>  		return;
>  
> -	if (!vgacon_scrollback.save) {
> +	if (!vgacon_scrollback_cur->save) {
>  		vgacon_cursor(c, CM_ERASE);
>  		vgacon_save_screen(c);
> -		vgacon_scrollback.save = 1;
> +		vgacon_scrollback_cur->save = 1;
>  	}
>  
> -	vgacon_scrollback.restore = 0;
> -	start = vgacon_scrollback.cur + lines;
> +	vgacon_scrollback_cur->restore = 0;
> +	start = vgacon_scrollback_cur->cur + lines;
>  	end = start + abs(lines);
>  
>  	if (start < 0)
>  		start = 0;
>  
> -	if (start > vgacon_scrollback.cnt)
> -		start = vgacon_scrollback.cnt;
> +	if (start > vgacon_scrollback_cur->cnt)
> +		start = vgacon_scrollback_cur->cnt;
>  
>  	if (end < 0)
>  		end = 0;
>  
> -	if (end > vgacon_scrollback.cnt)
> -		end = vgacon_scrollback.cnt;
> +	if (end > vgacon_scrollback_cur->cnt)
> +		end = vgacon_scrollback_cur->cnt;
>  
> -	vgacon_scrollback.cur = start;
> +	vgacon_scrollback_cur->cur = start;
>  	count = end - start;
> -	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
> -					 c->vc_size_row);
> +	soff = vgacon_scrollback_cur->tail -
> +		((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
>  	soff -= count * c->vc_size_row;
>  
>  	if (soff < 0)
> -		soff += vgacon_scrollback.size;
> +		soff += vgacon_scrollback_cur->size;
>  
> -	count = vgacon_scrollback.cnt - start;
> +	count = vgacon_scrollback_cur->cnt - start;
>  
>  	if (count > c->vc_rows)
>  		count = c->vc_rows;
> @@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
>  
>  		count *= c->vc_size_row;
>  		/* how much memory to end of buffer left? */
> -		copysize = min(count, vgacon_scrollback.size - soff);
> -		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
> +		copysize = min(count, vgacon_scrollback_cur->size - soff);
> +		scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
>  		d += copysize;
>  		count -= copysize;
>  
>  		if (count) {
> -			scr_memcpyw(d, vgacon_scrollback.data, count);
> +			scr_memcpyw(d, vgacon_scrollback_cur->data, count);
>  			d += count;
>  		}
>  
> @@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct vc_data *c)
>  {
>  	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
>  
> -	if (c->vc_num == fg_console)
> -		vgacon_scrollback_reset(size);
> +	vgacon_scrollback_reset(c->vc_num, size);
>  }
>  #else
>  #define vgacon_scrollback_startup(...) do { } while (0)
>  #define vgacon_scrollback_init(...)    do { } while (0)
>  #define vgacon_scrollback_update(...)  do { } while (0)
> +#define vgacon_scrollback_switch(...)  do { } while (0)
>  
>  static void vgacon_restore_screen(struct vc_data *c)
>  {
> @@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
>  			vgacon_doresize(c, c->vc_cols, c->vc_rows);
>  	}
>  
> -	vgacon_scrollback_init(c->vc_size_row);
> +	vgacon_scrollback_switch(c->vc_num);
>  	return 0;		/* Redrawing not needed */
>  }

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles
       [not found]           ` <CGME20170110164435epcas1p314efb9c6ea3ffb971fce06f3bfaec736@epcas1p3.samsung.com>
@ 2017-01-10 16:44             ` Bartlomiej Zolnierkiewicz
  2017-01-10 17:31               ` Manuel Schölling
                                 ` (5 more replies)
  0 siblings, 6 replies; 49+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2017-01-10 16:44 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: gregkh, jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin,
	akpm, paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Tuesday, January 10, 2017 05:22:22 PM Bartlomiej Zolnierkiewicz wrote:
> 
> Hi,
> 
> The patchset generally looks fine to me but I have a question
> regarding new VGACON_SOFT_SCROLLBACK_PERSISTENT config option.
> 
> Since the code size impact to support the persistent scrollback
> feature is minimal wouldn't it be better to always include it?
> 
> The feature would be disabled by default and could be enabled
> by using the new kernel command line parameter (you may also add
> a new config option for enabling it by default if desired).

Something like:

#ifdef VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
static bool scrollback_persistent = 1;
#else
static bool scrollback_persistent;
#endif

module_param_named(scrollback_persistent, scrollback_persistent, bool, 0);
MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback feature");

and then use scrollback_persistent variable in vgacon_scrollback_switch()
to control the actual behavior instead of ifdefs.

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R&D Institute Poland
> Samsung Electronics
> 
> On Thursday, January 05, 2017 12:33:20 PM Manuel Schölling wrote:
> > Add a scrollback buffers for each VGA console. The benefit is that
> > the scrollback history is not flushed when switching between consoles
> > but is persistent.
> > The buffers are allocated on demand when a new console is opened.
> > 
> > This breaks tools like clear_console that rely on flushing the
> > scrollback history by switching back and forth between consoles
> > which is why this feature is disabled by default.
> > Use the escape sequence \e[3J instead for flushing the buffer.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> > Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > Tested-by: Adam Borowski <kilobyte@angband.pl>
> > ---
> >  drivers/video/console/Kconfig  |  25 +++++++-
> >  drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
> >  2 files changed, 111 insertions(+), 56 deletions(-)
> > 
> > diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
> > index c3f1fb9ee820..f500e58f7636 100644
> > --- a/drivers/video/console/Kconfig
> > +++ b/drivers/video/console/Kconfig
> > @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
> >         range 1 1024
> >         default "64"
> >         help
> > -         Enter the amount of System RAM to allocate for the scrollback
> > -	 buffer.  Each 64KB will give you approximately 16 80x25
> > -	 screenfuls of scrollback buffer
> > +	  Enter the amount of System RAM to allocate for scrollback
> > +	  buffers of VGA consoles. Each 64KB will give you approximately
> > +	  16 80x25 screenfuls of scrollback buffer.
> > +
> > +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> > +	bool "Persistent Scrollback History for each console"
> > +	depends on VGACON_SOFT_SCROLLBACK
> > +	default n
> > +	help
> > +	  Say Y here if the scrollback history should persist when switching
> > +	  between consoles. Otherwise, the scrollback history will be flushed
> > +	  each time the console is switched.
> > +
> > +	  This feature might break your tool of choice to flush the scrollback
> > +	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
> > +	  will be broken, which might cause security issues.
> > +	  You can use the escape sequence \e[3J instead if this feature is
> > +	  activated.
> > +
> > +	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
> > +	  created tty device.
> > +	  So if you use a RAM-constrained system, say N here.
> >  
> >  config MDA_CONSOLE
> >  	depends on !M68K && !PARISC && ISA
> > diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
> > index 9a7c2bbc5326..ca23d222e029 100644
> > --- a/drivers/video/console/vgacon.c
> > +++ b/drivers/video/console/vgacon.c
> > @@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
> >  
> >  #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
> >  /* software scrollback */
> > -static struct vgacon_scrollback_info {
> > +struct vgacon_scrollback_info {
> >  	void *data;
> >  	int tail;
> >  	int size;
> > @@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
> >  	int cur;
> >  	int save;
> >  	int restore;
> > -} vgacon_scrollback;
> > +};
> > +
> > +static struct vgacon_scrollback_info *vgacon_scrollback_cur;
> > +#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> > +static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
> > +#else
> > +static struct vgacon_scrollback_info vgacon_scrollbacks[1];
> > +#endif
> >  
> > -static void vgacon_scrollback_reset(size_t reset_size)
> > +static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
> >  {
> > -	if (vgacon_scrollback.data && reset_size > 0)
> > -		memset(vgacon_scrollback.data, 0, reset_size);
> > +	struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
> > +
> > +	if (scrollback->data && reset_size > 0)
> > +		memset(scrollback->data, 0, reset_size);
> >  
> > -	vgacon_scrollback.cnt  = 0;
> > -	vgacon_scrollback.tail = 0;
> > -	vgacon_scrollback.cur  = 0;
> > +	scrollback->cnt  = 0;
> > +	scrollback->tail = 0;
> > +	scrollback->cur  = 0;
> >  }
> >  
> > -static void vgacon_scrollback_init(int pitch)
> > +static void vgacon_scrollback_init(int vc_num)
> >  {
> > -	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
> > -
> > -	if (vgacon_scrollback.data) {
> > -		vgacon_scrollback.cnt  = 0;
> > -		vgacon_scrollback.tail = 0;
> > -		vgacon_scrollback.cur  = 0;
> > -		vgacon_scrollback.rows = rows - 1;
> > -		vgacon_scrollback.size = rows * pitch;
> > +	int pitch = vga_video_num_columns * 2;
> > +	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
> > +	int rows = size / pitch;
> > +	void *data;
> > +
> > +	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
> > +			     GFP_NOWAIT);
> > +
> > +	vgacon_scrollbacks[vc_num].data = data;
> > +	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
> > +
> > +	vgacon_scrollback_cur->rows = rows - 1;
> > +	vgacon_scrollback_cur->size = rows * pitch;
> > +
> > +	vgacon_scrollback_reset(vc_num, size);
> > +}
> > +
> > +static void vgacon_scrollback_switch(int vc_num)
> > +{
> > +#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> > +	vc_num = 0;
> > +#endif
> > +
> > +	if (!vgacon_scrollbacks[vc_num].data) {
> > +		vgacon_scrollback_init(vc_num);
> > +	} else {
> > +#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> > +		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
> > +#else
> > +		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
> > +
> > +		vgacon_scrollback_reset(vc_num, size);
> > +#endif
> >  	}
> >  }
> >  
> >  static void vgacon_scrollback_startup(void)
> >  {
> > -	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
> > -		1024, GFP_NOWAIT);
> > -	vgacon_scrollback_init(vga_video_num_columns * 2);
> > +	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
> > +	vgacon_scrollback_init(0);
> >  }
> >  
> >  static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
> >  {
> >  	void *p;
> >  
> > -	if (!vgacon_scrollback.size || c->vc_num != fg_console)
> > +	if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
> > +	    c->vc_num != fg_console)
> >  		return;
> >  
> >  	p = (void *) (c->vc_origin + t * c->vc_size_row);
> >  
> >  	while (count--) {
> > -		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
> > +		scr_memcpyw(vgacon_scrollback_cur->data +
> > +			    vgacon_scrollback_cur->tail,
> >  			    p, c->vc_size_row);
> > -		vgacon_scrollback.cnt++;
> > +
> > +		vgacon_scrollback_cur->cnt++;
> >  		p += c->vc_size_row;
> > -		vgacon_scrollback.tail += c->vc_size_row;
> > +		vgacon_scrollback_cur->tail += c->vc_size_row;
> >  
> > -		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
> > -			vgacon_scrollback.tail = 0;
> > +		if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
> > +			vgacon_scrollback_cur->tail = 0;
> >  
> > -		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
> > -			vgacon_scrollback.cnt = vgacon_scrollback.rows;
> > +		if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
> > +			vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
> >  
> > -		vgacon_scrollback.cur = vgacon_scrollback.cnt;
> > +		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
> >  	}
> >  }
> >  
> >  static void vgacon_restore_screen(struct vc_data *c)
> >  {
> > -	vgacon_scrollback.save = 0;
> > +	vgacon_scrollback_cur->save = 0;
> >  
> > -	if (!vga_is_gfx && !vgacon_scrollback.restore) {
> > +	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
> >  		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
> >  			    c->vc_screenbuf_size > vga_vram_size ?
> >  			    vga_vram_size : c->vc_screenbuf_size);
> > -		vgacon_scrollback.restore = 1;
> > -		vgacon_scrollback.cur = vgacon_scrollback.cnt;
> > +		vgacon_scrollback_cur->restore = 1;
> > +		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
> >  	}
> >  }
> >  
> > @@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
> >  		return;
> >  	}
> >  
> > -	if (!vgacon_scrollback.data)
> > +	if (!vgacon_scrollback_cur->data)
> >  		return;
> >  
> > -	if (!vgacon_scrollback.save) {
> > +	if (!vgacon_scrollback_cur->save) {
> >  		vgacon_cursor(c, CM_ERASE);
> >  		vgacon_save_screen(c);
> > -		vgacon_scrollback.save = 1;
> > +		vgacon_scrollback_cur->save = 1;
> >  	}
> >  
> > -	vgacon_scrollback.restore = 0;
> > -	start = vgacon_scrollback.cur + lines;
> > +	vgacon_scrollback_cur->restore = 0;
> > +	start = vgacon_scrollback_cur->cur + lines;
> >  	end = start + abs(lines);
> >  
> >  	if (start < 0)
> >  		start = 0;
> >  
> > -	if (start > vgacon_scrollback.cnt)
> > -		start = vgacon_scrollback.cnt;
> > +	if (start > vgacon_scrollback_cur->cnt)
> > +		start = vgacon_scrollback_cur->cnt;
> >  
> >  	if (end < 0)
> >  		end = 0;
> >  
> > -	if (end > vgacon_scrollback.cnt)
> > -		end = vgacon_scrollback.cnt;
> > +	if (end > vgacon_scrollback_cur->cnt)
> > +		end = vgacon_scrollback_cur->cnt;
> >  
> > -	vgacon_scrollback.cur = start;
> > +	vgacon_scrollback_cur->cur = start;
> >  	count = end - start;
> > -	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
> > -					 c->vc_size_row);
> > +	soff = vgacon_scrollback_cur->tail -
> > +		((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
> >  	soff -= count * c->vc_size_row;
> >  
> >  	if (soff < 0)
> > -		soff += vgacon_scrollback.size;
> > +		soff += vgacon_scrollback_cur->size;
> >  
> > -	count = vgacon_scrollback.cnt - start;
> > +	count = vgacon_scrollback_cur->cnt - start;
> >  
> >  	if (count > c->vc_rows)
> >  		count = c->vc_rows;
> > @@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
> >  
> >  		count *= c->vc_size_row;
> >  		/* how much memory to end of buffer left? */
> > -		copysize = min(count, vgacon_scrollback.size - soff);
> > -		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
> > +		copysize = min(count, vgacon_scrollback_cur->size - soff);
> > +		scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
> >  		d += copysize;
> >  		count -= copysize;
> >  
> >  		if (count) {
> > -			scr_memcpyw(d, vgacon_scrollback.data, count);
> > +			scr_memcpyw(d, vgacon_scrollback_cur->data, count);
> >  			d += count;
> >  		}
> >  
> > @@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct vc_data *c)
> >  {
> >  	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
> >  
> > -	if (c->vc_num == fg_console)
> > -		vgacon_scrollback_reset(size);
> > +	vgacon_scrollback_reset(c->vc_num, size);
> >  }
> >  #else
> >  #define vgacon_scrollback_startup(...) do { } while (0)
> >  #define vgacon_scrollback_init(...)    do { } while (0)
> >  #define vgacon_scrollback_update(...)  do { } while (0)
> > +#define vgacon_scrollback_switch(...)  do { } while (0)
> >  
> >  static void vgacon_restore_screen(struct vc_data *c)
> >  {
> > @@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
> >  			vgacon_doresize(c, c->vc_cols, c->vc_rows);
> >  	}
> >  
> > -	vgacon_scrollback_init(c->vc_size_row);
> > +	vgacon_scrollback_switch(c->vc_num);
> >  	return 0;		/* Redrawing not needed */
> >  }

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-10 16:44             ` Bartlomiej Zolnierkiewicz
@ 2017-01-10 17:31               ` Manuel Schölling
  2017-01-10 21:28               ` [PATCH v9 0/4] " Manuel Schölling
                                 ` (4 subsequent siblings)
  5 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-10 17:31 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: gregkh, jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin,
	akpm, paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

Hi Bartlomiej,

First of all thank you for you feedback!

On Tue, 2017-01-10 at 17:44 +0100, Bartlomiej Zolnierkiewicz wrote:
> On Tuesday, January 10, 2017 05:22:22 PM Bartlomiej Zolnierkiewicz
> wrote:
> > 
> > Hi,
> > 
> > The patchset generally looks fine to me but I have a question
> > regarding new VGACON_SOFT_SCROLLBACK_PERSISTENT config option.
> > 
> > Since the code size impact to support the persistent scrollback
> > feature is minimal wouldn't it be better to always include it?
> > 
> > The feature would be disabled by default and could be enabled
> > by using the new kernel command line parameter (you may also add
> > a new config option for enabling it by default if desired).
> 
> Something like:
> 
> #ifdef VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
> static bool scrollback_persistent = 1;
> #else
> static bool scrollback_persistent;
> #endif
> 
> module_param_named(scrollback_persistent, scrollback_persistent,
> bool, 0);
> MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback
> feature");
> 
> and then use scrollback_persistent variable in
> vgacon_scrollback_switch()
> to control the actual behavior instead of ifdefs.
Sounds pretty good to me. You are right: The code size impact is rather
small. I will apply your suggestions and send you another patch as soon
as I find the time to implement it (should be any time this week).

Thanks again!

Manuel



> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R&D Institute Poland
> Samsung Electronics
> 
> > Best regards,
> > --
> > Bartlomiej Zolnierkiewicz
> > Samsung R&D Institute Poland
> > Samsung Electronics
> > 
> > On Thursday, January 05, 2017 12:33:20 PM Manuel Schölling wrote:
> > > Add a scrollback buffers for each VGA console. The benefit is
> > > that
> > > the scrollback history is not flushed when switching between
> > > consoles
> > > but is persistent.
> > > The buffers are allocated on demand when a new console is opened.
> > > 
> > > This breaks tools like clear_console that rely on flushing the
> > > scrollback history by switching back and forth between consoles
> > > which is why this feature is disabled by default.
> > > Use the escape sequence \e[3J instead for flushing the buffer.
> > > 
> > > Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> > > Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > > Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > > Tested-by: Adam Borowski <kilobyte@angband.pl>
> > > ---
> > >  drivers/video/console/Kconfig  |  25 +++++++-
> > >  drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++-
> > > --------------
> > >  2 files changed, 111 insertions(+), 56 deletions(-)
> > > 
> > > diff --git a/drivers/video/console/Kconfig
> > > b/drivers/video/console/Kconfig
> > > index c3f1fb9ee820..f500e58f7636 100644
> > > --- a/drivers/video/console/Kconfig
> > > +++ b/drivers/video/console/Kconfig
> > > @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
> > >         range 1 1024
> > >         default "64"
> > >         help
> > > -         Enter the amount of System RAM to allocate for the
> > > scrollback
> > > -	 buffer.  Each 64KB will give you approximately 16 80x25
> > > -	 screenfuls of scrollback buffer
> > > +	  Enter the amount of System RAM to allocate for
> > > scrollback
> > > +	  buffers of VGA consoles. Each 64KB will give you
> > > approximately
> > > +	  16 80x25 screenfuls of scrollback buffer.
> > > +
> > > +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> > > +	bool "Persistent Scrollback History for each console"
> > > +	depends on VGACON_SOFT_SCROLLBACK
> > > +	default n
> > > +	help
> > > +	  Say Y here if the scrollback history should persist
> > > when switching
> > > +	  between consoles. Otherwise, the scrollback history
> > > will be flushed
> > > +	  each time the console is switched.
> > > +
> > > +	  This feature might break your tool of choice to flush
> > > the scrollback
> > > +	  buffer, e.g. clear(1) will work fine but Debian's
> > > clear_console(1)
> > > +	  will be broken, which might cause security issues.
> > > +	  You can use the escape sequence \e[3J instead if this
> > > feature is
> > > +	  activated.
> > > +
> > > +	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is
> > > taken for each
> > > +	  created tty device.
> > > +	  So if you use a RAM-constrained system, say N here.
> > >  
> > >  config MDA_CONSOLE
> > >  	depends on !M68K && !PARISC && ISA
> > > diff --git a/drivers/video/console/vgacon.c
> > > b/drivers/video/console/vgacon.c
> > > index 9a7c2bbc5326..ca23d222e029 100644
> > > --- a/drivers/video/console/vgacon.c
> > > +++ b/drivers/video/console/vgacon.c
> > > @@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct
> > > vc_data *c)
> > >  
> > >  #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
> > >  /* software scrollback */
> > > -static struct vgacon_scrollback_info {
> > > +struct vgacon_scrollback_info {
> > >  	void *data;
> > >  	int tail;
> > >  	int size;
> > > @@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
> > >  	int cur;
> > >  	int save;
> > >  	int restore;
> > > -} vgacon_scrollback;
> > > +};
> > > +
> > > +static struct vgacon_scrollback_info *vgacon_scrollback_cur;
> > > +#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> > > +static struct vgacon_scrollback_info
> > > vgacon_scrollbacks[MAX_NR_CONSOLES];
> > > +#else
> > > +static struct vgacon_scrollback_info vgacon_scrollbacks[1];
> > > +#endif
> > >  
> > > -static void vgacon_scrollback_reset(size_t reset_size)
> > > +static void vgacon_scrollback_reset(int vc_num, size_t
> > > reset_size)
> > >  {
> > > -	if (vgacon_scrollback.data && reset_size > 0)
> > > -		memset(vgacon_scrollback.data, 0, reset_size);
> > > +	struct vgacon_scrollback_info *scrollback =
> > > &vgacon_scrollbacks[vc_num];
> > > +
> > > +	if (scrollback->data && reset_size > 0)
> > > +		memset(scrollback->data, 0, reset_size);
> > >  
> > > -	vgacon_scrollback.cnt  = 0;
> > > -	vgacon_scrollback.tail = 0;
> > > -	vgacon_scrollback.cur  = 0;
> > > +	scrollback->cnt  = 0;
> > > +	scrollback->tail = 0;
> > > +	scrollback->cur  = 0;
> > >  }
> > >  
> > > -static void vgacon_scrollback_init(int pitch)
> > > +static void vgacon_scrollback_init(int vc_num)
> > >  {
> > > -	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE *
> > > 1024/pitch;
> > > -
> > > -	if (vgacon_scrollback.data) {
> > > -		vgacon_scrollback.cnt  = 0;
> > > -		vgacon_scrollback.tail = 0;
> > > -		vgacon_scrollback.cur  = 0;
> > > -		vgacon_scrollback.rows = rows - 1;
> > > -		vgacon_scrollback.size = rows * pitch;
> > > +	int pitch = vga_video_num_columns * 2;
> > > +	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
> > > +	int rows = size / pitch;
> > > +	void *data;
> > > +
> > > +	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
> > > 1024,
> > > +			     GFP_NOWAIT);
> > > +
> > > +	vgacon_scrollbacks[vc_num].data = data;
> > > +	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
> > > +
> > > +	vgacon_scrollback_cur->rows = rows - 1;
> > > +	vgacon_scrollback_cur->size = rows * pitch;
> > > +
> > > +	vgacon_scrollback_reset(vc_num, size);
> > > +}
> > > +
> > > +static void vgacon_scrollback_switch(int vc_num)
> > > +{
> > > +#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> > > +	vc_num = 0;
> > > +#endif
> > > +
> > > +	if (!vgacon_scrollbacks[vc_num].data) {
> > > +		vgacon_scrollback_init(vc_num);
> > > +	} else {
> > > +#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
> > > +		vgacon_scrollback_cur =
> > > &vgacon_scrollbacks[vc_num];
> > > +#else
> > > +		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE
> > > * 1024;
> > > +
> > > +		vgacon_scrollback_reset(vc_num, size);
> > > +#endif
> > >  	}
> > >  }
> > >  
> > >  static void vgacon_scrollback_startup(void)
> > >  {
> > > -	vgacon_scrollback.data =
> > > kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
> > > -		1024, GFP_NOWAIT);
> > > -	vgacon_scrollback_init(vga_video_num_columns * 2);
> > > +	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
> > > +	vgacon_scrollback_init(0);
> > >  }
> > >  
> > >  static void vgacon_scrollback_update(struct vc_data *c, int t,
> > > int count)
> > >  {
> > >  	void *p;
> > >  
> > > -	if (!vgacon_scrollback.size || c->vc_num != fg_console)
> > > +	if (!vgacon_scrollback_cur->data ||
> > > !vgacon_scrollback_cur->size ||
> > > +	    c->vc_num != fg_console)
> > >  		return;
> > >  
> > >  	p = (void *) (c->vc_origin + t * c->vc_size_row);
> > >  
> > >  	while (count--) {
> > > -		scr_memcpyw(vgacon_scrollback.data +
> > > vgacon_scrollback.tail,
> > > +		scr_memcpyw(vgacon_scrollback_cur->data +
> > > +			    vgacon_scrollback_cur->tail,
> > >  			    p, c->vc_size_row);
> > > -		vgacon_scrollback.cnt++;
> > > +
> > > +		vgacon_scrollback_cur->cnt++;
> > >  		p += c->vc_size_row;
> > > -		vgacon_scrollback.tail += c->vc_size_row;
> > > +		vgacon_scrollback_cur->tail += c->vc_size_row;
> > >  
> > > -		if (vgacon_scrollback.tail >=
> > > vgacon_scrollback.size)
> > > -			vgacon_scrollback.tail = 0;
> > > +		if (vgacon_scrollback_cur->tail >=
> > > vgacon_scrollback_cur->size)
> > > +			vgacon_scrollback_cur->tail = 0;
> > >  
> > > -		if (vgacon_scrollback.cnt >
> > > vgacon_scrollback.rows)
> > > -			vgacon_scrollback.cnt =
> > > vgacon_scrollback.rows;
> > > +		if (vgacon_scrollback_cur->cnt >
> > > vgacon_scrollback_cur->rows)
> > > +			vgacon_scrollback_cur->cnt =
> > > vgacon_scrollback_cur->rows;
> > >  
> > > -		vgacon_scrollback.cur = vgacon_scrollback.cnt;
> > > +		vgacon_scrollback_cur->cur =
> > > vgacon_scrollback_cur->cnt;
> > >  	}
> > >  }
> > >  
> > >  static void vgacon_restore_screen(struct vc_data *c)
> > >  {
> > > -	vgacon_scrollback.save = 0;
> > > +	vgacon_scrollback_cur->save = 0;
> > >  
> > > -	if (!vga_is_gfx && !vgacon_scrollback.restore) {
> > > +	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
> > >  		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c-
> > > >vc_screenbuf,
> > >  			    c->vc_screenbuf_size > vga_vram_size
> > > ?
> > >  			    vga_vram_size : c-
> > > >vc_screenbuf_size);
> > > -		vgacon_scrollback.restore = 1;
> > > -		vgacon_scrollback.cur = vgacon_scrollback.cnt;
> > > +		vgacon_scrollback_cur->restore = 1;
> > > +		vgacon_scrollback_cur->cur =
> > > vgacon_scrollback_cur->cnt;
> > >  	}
> > >  }
> > >  
> > > @@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct
> > > vc_data *c, int lines)
> > >  		return;
> > >  	}
> > >  
> > > -	if (!vgacon_scrollback.data)
> > > +	if (!vgacon_scrollback_cur->data)
> > >  		return;
> > >  
> > > -	if (!vgacon_scrollback.save) {
> > > +	if (!vgacon_scrollback_cur->save) {
> > >  		vgacon_cursor(c, CM_ERASE);
> > >  		vgacon_save_screen(c);
> > > -		vgacon_scrollback.save = 1;
> > > +		vgacon_scrollback_cur->save = 1;
> > >  	}
> > >  
> > > -	vgacon_scrollback.restore = 0;
> > > -	start = vgacon_scrollback.cur + lines;
> > > +	vgacon_scrollback_cur->restore = 0;
> > > +	start = vgacon_scrollback_cur->cur + lines;
> > >  	end = start + abs(lines);
> > >  
> > >  	if (start < 0)
> > >  		start = 0;
> > >  
> > > -	if (start > vgacon_scrollback.cnt)
> > > -		start = vgacon_scrollback.cnt;
> > > +	if (start > vgacon_scrollback_cur->cnt)
> > > +		start = vgacon_scrollback_cur->cnt;
> > >  
> > >  	if (end < 0)
> > >  		end = 0;
> > >  
> > > -	if (end > vgacon_scrollback.cnt)
> > > -		end = vgacon_scrollback.cnt;
> > > +	if (end > vgacon_scrollback_cur->cnt)
> > > +		end = vgacon_scrollback_cur->cnt;
> > >  
> > > -	vgacon_scrollback.cur = start;
> > > +	vgacon_scrollback_cur->cur = start;
> > >  	count = end - start;
> > > -	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt
> > > - end) *
> > > -					 c->vc_size_row);
> > > +	soff = vgacon_scrollback_cur->tail -
> > > +		((vgacon_scrollback_cur->cnt - end) * c-
> > > >vc_size_row);
> > >  	soff -= count * c->vc_size_row;
> > >  
> > >  	if (soff < 0)
> > > -		soff += vgacon_scrollback.size;
> > > +		soff += vgacon_scrollback_cur->size;
> > >  
> > > -	count = vgacon_scrollback.cnt - start;
> > > +	count = vgacon_scrollback_cur->cnt - start;
> > >  
> > >  	if (count > c->vc_rows)
> > >  		count = c->vc_rows;
> > > @@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct
> > > vc_data *c, int lines)
> > >  
> > >  		count *= c->vc_size_row;
> > >  		/* how much memory to end of buffer left? */
> > > -		copysize = min(count, vgacon_scrollback.size -
> > > soff);
> > > -		scr_memcpyw(d, vgacon_scrollback.data + soff,
> > > copysize);
> > > +		copysize = min(count, vgacon_scrollback_cur-
> > > >size - soff);
> > > +		scr_memcpyw(d, vgacon_scrollback_cur->data +
> > > soff, copysize);
> > >  		d += copysize;
> > >  		count -= copysize;
> > >  
> > >  		if (count) {
> > > -			scr_memcpyw(d, vgacon_scrollback.data,
> > > count);
> > > +			scr_memcpyw(d, vgacon_scrollback_cur-
> > > >data, count);
> > >  			d += count;
> > >  		}
> > >  
> > > @@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct
> > > vc_data *c)
> > >  {
> > >  	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
> > >  
> > > -	if (c->vc_num == fg_console)
> > > -		vgacon_scrollback_reset(size);
> > > +	vgacon_scrollback_reset(c->vc_num, size);
> > >  }
> > >  #else
> > >  #define vgacon_scrollback_startup(...) do { } while (0)
> > >  #define vgacon_scrollback_init(...)    do { } while (0)
> > >  #define vgacon_scrollback_update(...)  do { } while (0)
> > > +#define vgacon_scrollback_switch(...)  do { } while (0)
> > >  
> > >  static void vgacon_restore_screen(struct vc_data *c)
> > >  {
> > > @@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
> > >  			vgacon_doresize(c, c->vc_cols, c-
> > > >vc_rows);
> > >  	}
> > >  
> > > -	vgacon_scrollback_init(c->vc_size_row);
> > > +	vgacon_scrollback_switch(c->vc_num);
> > >  	return 0;		/* Redrawing not needed */
> > >  }
> 
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v9 0/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-10 16:44             ` Bartlomiej Zolnierkiewicz
  2017-01-10 17:31               ` Manuel Schölling
@ 2017-01-10 21:28               ` Manuel Schölling
  2017-01-10 21:28               ` [PATCH v9 1/4] console: Move scrollback data into its own struct Manuel Schölling
                                 ` (3 subsequent siblings)
  5 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-10 21:28 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

--
Changes in v9:
  - Make persistent scrollback feature a boot parameter
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
    scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
    by Adam Borowski (kilobyte@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
    vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
    VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
    escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c            |   9 +++
 drivers/video/console/Kconfig  |  25 ++++++-
 drivers/video/console/vgacon.c | 165 ++++++++++++++++++++++++++++-------------
 include/linux/console.h        |   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v9 1/4] console: Move scrollback data into its own struct
  2017-01-10 16:44             ` Bartlomiej Zolnierkiewicz
  2017-01-10 17:31               ` Manuel Schölling
  2017-01-10 21:28               ` [PATCH v9 0/4] " Manuel Schölling
@ 2017-01-10 21:28               ` Manuel Schölling
  2017-01-10 21:28               ` [PATCH v9 2/4] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
                                 ` (2 subsequent siblings)
  5 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-10 21:28 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/video/console/vgacon.c | 91 ++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+	void *data;
+	int tail;
+	int size;
+	int rows;
+	int cnt;
+	int cur;
+	int save;
+	int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-	if (vgacon_scrollback) {
-		vgacon_scrollback_cnt  = 0;
-		vgacon_scrollback_tail = 0;
-		vgacon_scrollback_cur  = 0;
-		vgacon_scrollback_rows = rows - 1;
-		vgacon_scrollback_size = rows * pitch;
+	if (vgacon_scrollback.data) {
+		vgacon_scrollback.cnt  = 0;
+		vgacon_scrollback.tail = 0;
+		vgacon_scrollback.cur  = 0;
+		vgacon_scrollback.rows = rows - 1;
+		vgacon_scrollback.size = rows * pitch;
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
+	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+		1024, GFP_NOWAIT);
 	vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback_size || c->vc_num != fg_console)
+	if (!vgacon_scrollback.size || c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback_cnt++;
+		vgacon_scrollback.cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback_tail += c->vc_size_row;
+		vgacon_scrollback.tail += c->vc_size_row;
 
-		if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-			vgacon_scrollback_tail = 0;
+		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+			vgacon_scrollback.tail = 0;
 
-		if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-			vgacon_scrollback_cnt = vgacon_scrollback_rows;
+		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+			vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback_save = 0;
+	vgacon_scrollback.save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback_restore) {
+	if (!vga_is_gfx && !vgacon_scrollback.restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback_restore = 1;
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.restore = 1;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback)
+	if (!vgacon_scrollback.data)
 		return;
 
-	if (!vgacon_scrollback_save) {
+	if (!vgacon_scrollback.save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback_save = 1;
+		vgacon_scrollback.save = 1;
 	}
 
-	vgacon_scrollback_restore = 0;
-	start = vgacon_scrollback_cur + lines;
+	vgacon_scrollback.restore = 0;
+	start = vgacon_scrollback.cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback_cnt)
-		start = vgacon_scrollback_cnt;
+	if (start > vgacon_scrollback.cnt)
+		start = vgacon_scrollback.cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback_cnt)
-		end = vgacon_scrollback_cnt;
+	if (end > vgacon_scrollback.cnt)
+		end = vgacon_scrollback.cnt;
 
-	vgacon_scrollback_cur = start;
+	vgacon_scrollback.cur = start;
 	count = end - start;
-	soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
 					 c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback_size;
+		soff += vgacon_scrollback.size;
 
-	count = vgacon_scrollback_cnt - start;
+	count = vgacon_scrollback.cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -287,13 +290,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback_size - soff);
-		scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+		copysize = min(count, vgacon_scrollback.size - soff);
+		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback, count);
+			scr_memcpyw(d, vgacon_scrollback.data, count);
 			d += count;
 		}
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v9 2/4] console: Add callback to flush scrollback buffer to consw struct
  2017-01-10 16:44             ` Bartlomiej Zolnierkiewicz
                                 ` (2 preceding siblings ...)
  2017-01-10 21:28               ` [PATCH v9 1/4] console: Move scrollback data into its own struct Manuel Schölling
@ 2017-01-10 21:28               ` Manuel Schölling
  2017-01-10 21:28               ` [PATCH v9 3/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2017-01-10 21:28               ` [PATCH v9 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
  5 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-10 21:28 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/tty/vt/vt.c            |  9 +++++++++
 drivers/video/console/vgacon.c | 24 +++++++++++++++++++++++-
 include/linux/console.h        |  4 ++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
 		vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+	WARN_CONSOLE_UNLOCKED();
+
+	if (vc->vc_sw->con_flush_scrollback)
+		vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  *	Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
 		case 3: /* erase scroll-back buffer (and whole display) */
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
 				    vc->vc_screenbuf_size);
+			flush_scrollback(vc);
 			set_origin(vc);
 			if (con_is_visible(vc))
 				update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
 	int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+	if (vgacon_scrollback.data && reset_size > 0)
+		memset(vgacon_scrollback.data, 0, reset_size);
+
+	vgacon_scrollback.cnt  = 0;
+	vgacon_scrollback.tail = 0;
+	vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 	} else
 		vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+	if (c->vc_num == fg_console)
+		vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 			vga_vram_size);
 	vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
 	return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
 	.con_save_screen = vgacon_save_screen,
 	.con_build_attr = vgacon_build_attr,
 	.con_invert_region = vgacon_invert_region,
+	.con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
 	u16    *(*con_screen_pos)(struct vc_data *, int);
 	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
 	/*
+	 * Flush the video console driver's scrollback buffer
+	 */
+	void	(*con_flush_scrollback)(struct vc_data *);
+	/*
 	 * Prepare the console for the debugger.  This includes, but is not
 	 * limited to, unblanking the console, loading an appropriate
 	 * palette, and allowing debugger generated output.
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v9 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-10 16:44             ` Bartlomiej Zolnierkiewicz
                                 ` (3 preceding siblings ...)
  2017-01-10 21:28               ` [PATCH v9 2/4] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
@ 2017-01-10 21:28               ` Manuel Schölling
  2017-01-10 21:28               ` [PATCH v9 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
  5 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-10 21:28 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/video/console/Kconfig  |  25 +++++++-
 drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
        range 1 1024
        default "64"
        help
-         Enter the amount of System RAM to allocate for the scrollback
-	 buffer.  Each 64KB will give you approximately 16 80x25
-	 screenfuls of scrollback buffer
+	  Enter the amount of System RAM to allocate for scrollback
+	  buffers of VGA consoles. Each 64KB will give you approximately
+	  16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+	bool "Persistent Scrollback History for each console"
+	depends on VGACON_SOFT_SCROLLBACK
+	default n
+	help
+	  Say Y here if the scrollback history should persist when switching
+	  between consoles. Otherwise, the scrollback history will be flushed
+	  each time the console is switched.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
 	depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
 	void *data;
 	int tail;
 	int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
 	int cur;
 	int save;
 	int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-	if (vgacon_scrollback.data && reset_size > 0)
-		memset(vgacon_scrollback.data, 0, reset_size);
+	struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
+
+	if (scrollback->data && reset_size > 0)
+		memset(scrollback->data, 0, reset_size);
 
-	vgacon_scrollback.cnt  = 0;
-	vgacon_scrollback.tail = 0;
-	vgacon_scrollback.cur  = 0;
+	scrollback->cnt  = 0;
+	scrollback->tail = 0;
+	scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-	if (vgacon_scrollback.data) {
-		vgacon_scrollback.cnt  = 0;
-		vgacon_scrollback.tail = 0;
-		vgacon_scrollback.cur  = 0;
-		vgacon_scrollback.rows = rows - 1;
-		vgacon_scrollback.size = rows * pitch;
+	int pitch = vga_video_num_columns * 2;
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+	int rows = size / pitch;
+	void *data;
+
+	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+			     GFP_NOWAIT);
+
+	vgacon_scrollbacks[vc_num].data = data;
+	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+
+	vgacon_scrollback_cur->rows = rows - 1;
+	vgacon_scrollback_cur->size = rows * pitch;
+
+	vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+	vc_num = 0;
+#endif
+
+	if (!vgacon_scrollbacks[vc_num].data) {
+		vgacon_scrollback_init(vc_num);
+	} else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+#else
+		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+		vgacon_scrollback_reset(vc_num, size);
+#endif
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
-		1024, GFP_NOWAIT);
-	vgacon_scrollback_init(vga_video_num_columns * 2);
+	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
+	vgacon_scrollback_init(0);
 }
 
 static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback.size || c->vc_num != fg_console)
+	if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
+	    c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
+		scr_memcpyw(vgacon_scrollback_cur->data +
+			    vgacon_scrollback_cur->tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback.cnt++;
+
+		vgacon_scrollback_cur->cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback.tail += c->vc_size_row;
+		vgacon_scrollback_cur->tail += c->vc_size_row;
 
-		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
-			vgacon_scrollback.tail = 0;
+		if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
+			vgacon_scrollback_cur->tail = 0;
 
-		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
-			vgacon_scrollback.cnt = vgacon_scrollback.rows;
+		if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
+			vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
 
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback.save = 0;
+	vgacon_scrollback_cur->save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback.restore) {
+	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback.restore = 1;
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->restore = 1;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
@@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback.data)
+	if (!vgacon_scrollback_cur->data)
 		return;
 
-	if (!vgacon_scrollback.save) {
+	if (!vgacon_scrollback_cur->save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback.save = 1;
+		vgacon_scrollback_cur->save = 1;
 	}
 
-	vgacon_scrollback.restore = 0;
-	start = vgacon_scrollback.cur + lines;
+	vgacon_scrollback_cur->restore = 0;
+	start = vgacon_scrollback_cur->cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback.cnt)
-		start = vgacon_scrollback.cnt;
+	if (start > vgacon_scrollback_cur->cnt)
+		start = vgacon_scrollback_cur->cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback.cnt)
-		end = vgacon_scrollback.cnt;
+	if (end > vgacon_scrollback_cur->cnt)
+		end = vgacon_scrollback_cur->cnt;
 
-	vgacon_scrollback.cur = start;
+	vgacon_scrollback_cur->cur = start;
 	count = end - start;
-	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
-					 c->vc_size_row);
+	soff = vgacon_scrollback_cur->tail -
+		((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback.size;
+		soff += vgacon_scrollback_cur->size;
 
-	count = vgacon_scrollback.cnt - start;
+	count = vgacon_scrollback_cur->cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback.size - soff);
-		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
+		copysize = min(count, vgacon_scrollback_cur->size - soff);
+		scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback.data, count);
+			scr_memcpyw(d, vgacon_scrollback_cur->data, count);
 			d += count;
 		}
 
@@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct vc_data *c)
 {
 	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-	if (c->vc_num == fg_console)
-		vgacon_scrollback_reset(size);
+	vgacon_scrollback_reset(c->vc_num, size);
 }
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
 #define vgacon_scrollback_update(...)  do { } while (0)
+#define vgacon_scrollback_switch(...)  do { } while (0)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
@@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
 	}
 
-	vgacon_scrollback_init(c->vc_size_row);
+	vgacon_scrollback_switch(c->vc_num);
 	return 0;		/* Redrawing not needed */
 }
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-01-10 16:44             ` Bartlomiej Zolnierkiewicz
                                 ` (4 preceding siblings ...)
  2017-01-10 21:28               ` [PATCH v9 3/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2017-01-10 21:28               ` Manuel Schölling
  2017-01-10 22:58                 ` Adam Borowski
                                   ` (2 more replies)
  5 siblings, 3 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-10 21:28 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

The impact of the persistent scrollback feature on the code size is
rather small, so the config option is removed. The feature stays
disabled by default and can be enabled by using the boot command line
parameter 'vgacon.scrollback_persistent=1' or by setting
VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/video/console/Kconfig  | 12 +++++++-----
 drivers/video/console/vgacon.c | 25 ++++++++++++-------------
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index f500e58f7636..5b71bd905a60 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -47,14 +47,16 @@ config VGACON_SOFT_SCROLLBACK_SIZE
 	  buffers of VGA consoles. Each 64KB will give you approximately
 	  16 80x25 screenfuls of scrollback buffer.
 
-config VGACON_SOFT_SCROLLBACK_PERSISTENT
-	bool "Persistent Scrollback History for each console"
+config VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+	bool "Persistent Scrollback History for each console by default"
 	depends on VGACON_SOFT_SCROLLBACK
 	default n
 	help
-	  Say Y here if the scrollback history should persist when switching
-	  between consoles. Otherwise, the scrollback history will be flushed
-	  each time the console is switched.
+	  Say Y here if the scrollback history should persist by default when
+	  switching between consoles. Otherwise, the scrollback history will be
+	  flushed each time the console is switched. This feature can also be
+	  enabled using the boot command line parameter
+	  'vgacon.scrollback_persistent=1'.
 
 	  This feature might break your tool of choice to flush the scrollback
 	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index ca23d222e029..45a76972495b 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -174,11 +174,9 @@ struct vgacon_scrollback_info {
 };
 
 static struct vgacon_scrollback_info *vgacon_scrollback_cur;
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
 static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
-#else
-static struct vgacon_scrollback_info vgacon_scrollbacks[1];
-#endif
+static bool scrollback_persistent = \
+	IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
 
 static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
@@ -213,20 +211,19 @@ static void vgacon_scrollback_init(int vc_num)
 
 static void vgacon_scrollback_switch(int vc_num)
 {
-#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-	vc_num = 0;
-#endif
+	if (!scrollback_persistent)
+		vc_num = 0;
 
 	if (!vgacon_scrollbacks[vc_num].data) {
 		vgacon_scrollback_init(vc_num);
 	} else {
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
-#else
-		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+		if (scrollback_persistent) {
+			vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+		} else {
+			size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-		vgacon_scrollback_reset(vc_num, size);
-#endif
+			vgacon_scrollback_reset(vc_num, size);
+		}
 	}
 }
 
@@ -1423,4 +1420,6 @@ const struct consw vga_con = {
 };
 EXPORT_SYMBOL(vga_con);
 
+module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
+MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");
 MODULE_LICENSE("GPL");
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-01-10 21:28               ` [PATCH v9 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
@ 2017-01-10 22:58                 ` Adam Borowski
  2017-01-11 21:41                   ` Manuel Schölling
  2017-01-13 20:00                   ` Manuel Schölling
  2017-01-11 13:32                 ` kbuild test robot
  2017-02-02 20:07                 ` [PATCH v9 " Paul Gortmaker
  2 siblings, 2 replies; 49+ messages in thread
From: Adam Borowski @ 2017-01-10 22:58 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: gregkh, jslaby, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Tue, Jan 10, 2017 at 10:28:38PM +0100, Manuel Schölling wrote:
> The impact of the persistent scrollback feature on the code size is
> rather small, so the config option is removed. The feature stays
> disabled by default and can be enabled by using the boot command line
> parameter 'vgacon.scrollback_persistent=1' or by setting
> VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> 
> Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>

> +module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
> +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");

A command-line knob settable by the end-user is something more persistent
than a config option.  As you're going to extend this code beyond vgacon in
the near future, perhaps it'd be better to have a shared setting for all
console drivers?


Meow!
-- 
Autotools hint: to do a zx-spectrum build on a pdp11 host, type:
  ./configure --host=zx-spectrum --build=pdp11

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-01-10 21:28               ` [PATCH v9 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
  2017-01-10 22:58                 ` Adam Borowski
@ 2017-01-11 13:32                 ` kbuild test robot
  2017-01-13 20:07                   ` [PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
                                     ` (4 more replies)
  2017-02-02 20:07                 ` [PATCH v9 " Paul Gortmaker
  2 siblings, 5 replies; 49+ messages in thread
From: kbuild test robot @ 2017-01-11 13:32 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: kbuild-all, gregkh, jslaby, kilobyte, lkml14, rdunlap, shorne,
	andrey_utkin, akpm, paul.burton, daniel.vetter, tj, hdegoede,
	linux-kernel, linux-fbdev, Manuel Schölling

[-- Attachment #1: Type: text/plain, Size: 3974 bytes --]

Hi Manuel,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.10-rc3 next-20170111]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Manuel-Sch-lling/console-Add-persistent-scrollback-buffers-for-all-VGA-consoles/20170111-203640
config: i386-randconfig-x018-201702 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/module.h:18:0,
                    from drivers/video/console/vgacon.c:36:
   drivers/video/console/vgacon.c: In function '__check_scrollback_persistent':
>> drivers/video/console/vgacon.c:1423:43: error: 'scrollback_persistent' undeclared (first use in this function)
    module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
                                              ^
   include/linux/moduleparam.h:344:68: note: in definition of macro '__param_check'
     static inline type __always_unused *__check_##name(void) { return(p); }
                                                                       ^
   include/linux/moduleparam.h:146:2: note: in expansion of macro 'param_check_bool'
     param_check_##type(name, &(value));       \
     ^~~~~~~~~~~~
>> drivers/video/console/vgacon.c:1423:1: note: in expansion of macro 'module_param_named'
    module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
    ^~~~~~~~~~~~~~~~~~
   drivers/video/console/vgacon.c:1423:43: note: each undeclared identifier is reported only once for each function it appears in
    module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
                                              ^
   include/linux/moduleparam.h:344:68: note: in definition of macro '__param_check'
     static inline type __always_unused *__check_##name(void) { return(p); }
                                                                       ^
   include/linux/moduleparam.h:146:2: note: in expansion of macro 'param_check_bool'
     param_check_##type(name, &(value));       \
     ^~~~~~~~~~~~
>> drivers/video/console/vgacon.c:1423:1: note: in expansion of macro 'module_param_named'
    module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
    ^~~~~~~~~~~~~~~~~~
   drivers/video/console/vgacon.c: At top level:
>> drivers/video/console/vgacon.c:1423:43: error: 'scrollback_persistent' undeclared here (not in a function)
    module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
                                              ^
   include/linux/moduleparam.h:225:54: note: in definition of macro '__module_param_call'
         VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } }
                                                         ^~~
   include/linux/moduleparam.h:147:2: note: in expansion of macro 'module_param_cb'
     module_param_cb(name, &param_ops_##type, &value, perm);     \
     ^~~~~~~~~~~~~~~
>> drivers/video/console/vgacon.c:1423:1: note: in expansion of macro 'module_param_named'
    module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
    ^~~~~~~~~~~~~~~~~~

vim +/scrollback_persistent +1423 drivers/video/console/vgacon.c

  1417		.con_build_attr = vgacon_build_attr,
  1418		.con_invert_region = vgacon_invert_region,
  1419		.con_flush_scrollback = vgacon_flush_scrollback,
  1420	};
  1421	EXPORT_SYMBOL(vga_con);
  1422	
> 1423	module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
  1424	MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");
  1425	MODULE_LICENSE("GPL");

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27586 bytes --]

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-01-10 22:58                 ` Adam Borowski
@ 2017-01-11 21:41                   ` Manuel Schölling
  2017-01-13 20:00                   ` Manuel Schölling
  1 sibling, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-11 21:41 UTC (permalink / raw)
  To: Adam Borowski
  Cc: gregkh, jslaby, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Tue, 2017-01-10 at 23:58 +0100, Adam Borowski wrote:
> On Tue, Jan 10, 2017 at 10:28:38PM +0100, Manuel Schölling wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> > Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, 0000);
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> A command-line knob settable by the end-user is something more
> persistent
> than a config option.  As you're going to extend this code beyond
> vgacon in
> the near future, perhaps it'd be better to have a shared setting for
> all
> console drivers?
Probably a good idea, but I'm struggling with the implementation a bit:

I tried to run 

  if (strstr(boot_command_line, "nopersistentscrollback")) {...}

in vgacon_scrollback_startup() but I am getting 

  WARNING: modpost: Found 2 section mismatch(es).

when compiling. Probably because vgacon_scrollback_startup() is
executed after init.

I tried to find another way to implement a boot cmd line parameter but
had no luck.
If you/somebody could point me in the right direction, it would be very
much appreciated.

Thanks!

Manuel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-01-10 22:58                 ` Adam Borowski
  2017-01-11 21:41                   ` Manuel Schölling
@ 2017-01-13 20:00                   ` Manuel Schölling
  2017-01-14  7:26                     ` Greg KH
  1 sibling, 1 reply; 49+ messages in thread
From: Manuel Schölling @ 2017-01-13 20:00 UTC (permalink / raw)
  To: Adam Borowski
  Cc: gregkh, jslaby, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Tue, 2017-01-10 at 23:58 +0100, Adam Borowski wrote:
> On Tue, Jan 10, 2017 at 10:28:38PM +0100, Manuel Schölling wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> > Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, 0000);
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> A command-line knob settable by the end-user is something more
> persistent
> than a config option.  As you're going to extend this code beyond
> vgacon in
> the near future, perhaps it'd be better to have a shared setting for
> all
> console drivers?
According to the guys at #kernelnewbies on IRC everybody hates new
command line options.
I'd rather stick to the module parameter for now and maybe introduce a 
new cmd line option later, once this feature has been implemented in
several console drivers.

Bye,

Manuel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-11 13:32                 ` kbuild test robot
@ 2017-01-13 20:07                   ` Manuel Schölling
  2017-01-25 10:55                     ` Greg KH
  2017-01-13 20:07                   ` [PATCH v10 1/4] console: Move scrollback data into its own struct Manuel Schölling
                                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 49+ messages in thread
From: Manuel Schölling @ 2017-01-13 20:07 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

Changes in v10:
  - Fix compilation error if CONFIG_VGACON_SOFT_SCROLLBACK=n
Changes in v9:
  - Make persistent scrollback feature a boot parameter
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
    scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
    by Adam Borowski (kilobyte@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
    vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
    VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
    escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (4):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles
  console: Make persistent scrollback a boot parameter

 drivers/tty/vt/vt.c            |   9 +++
 drivers/video/console/Kconfig  |  27 ++++++-
 drivers/video/console/vgacon.c | 164 ++++++++++++++++++++++++++++-------------
 include/linux/console.h        |   4 +
 4 files changed, 149 insertions(+), 55 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v10 1/4] console: Move scrollback data into its own struct
  2017-01-11 13:32                 ` kbuild test robot
  2017-01-13 20:07                   ` [PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2017-01-13 20:07                   ` Manuel Schölling
  2017-01-13 20:07                   ` [PATCH v10 2/4] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
                                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-13 20:07 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/video/console/vgacon.c | 91 ++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+	void *data;
+	int tail;
+	int size;
+	int rows;
+	int cnt;
+	int cur;
+	int save;
+	int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-	if (vgacon_scrollback) {
-		vgacon_scrollback_cnt  = 0;
-		vgacon_scrollback_tail = 0;
-		vgacon_scrollback_cur  = 0;
-		vgacon_scrollback_rows = rows - 1;
-		vgacon_scrollback_size = rows * pitch;
+	if (vgacon_scrollback.data) {
+		vgacon_scrollback.cnt  = 0;
+		vgacon_scrollback.tail = 0;
+		vgacon_scrollback.cur  = 0;
+		vgacon_scrollback.rows = rows - 1;
+		vgacon_scrollback.size = rows * pitch;
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
+	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+		1024, GFP_NOWAIT);
 	vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback_size || c->vc_num != fg_console)
+	if (!vgacon_scrollback.size || c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback_cnt++;
+		vgacon_scrollback.cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback_tail += c->vc_size_row;
+		vgacon_scrollback.tail += c->vc_size_row;
 
-		if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-			vgacon_scrollback_tail = 0;
+		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+			vgacon_scrollback.tail = 0;
 
-		if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-			vgacon_scrollback_cnt = vgacon_scrollback_rows;
+		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+			vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback_save = 0;
+	vgacon_scrollback.save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback_restore) {
+	if (!vga_is_gfx && !vgacon_scrollback.restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback_restore = 1;
-		vgacon_scrollback_cur = vgacon_scrollback_cnt;
+		vgacon_scrollback.restore = 1;
+		vgacon_scrollback.cur = vgacon_scrollback.cnt;
 	}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback)
+	if (!vgacon_scrollback.data)
 		return;
 
-	if (!vgacon_scrollback_save) {
+	if (!vgacon_scrollback.save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback_save = 1;
+		vgacon_scrollback.save = 1;
 	}
 
-	vgacon_scrollback_restore = 0;
-	start = vgacon_scrollback_cur + lines;
+	vgacon_scrollback.restore = 0;
+	start = vgacon_scrollback.cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback_cnt)
-		start = vgacon_scrollback_cnt;
+	if (start > vgacon_scrollback.cnt)
+		start = vgacon_scrollback.cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback_cnt)
-		end = vgacon_scrollback_cnt;
+	if (end > vgacon_scrollback.cnt)
+		end = vgacon_scrollback.cnt;
 
-	vgacon_scrollback_cur = start;
+	vgacon_scrollback.cur = start;
 	count = end - start;
-	soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
+	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
 					 c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback_size;
+		soff += vgacon_scrollback.size;
 
-	count = vgacon_scrollback_cnt - start;
+	count = vgacon_scrollback.cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -287,13 +290,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback_size - soff);
-		scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+		copysize = min(count, vgacon_scrollback.size - soff);
+		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback, count);
+			scr_memcpyw(d, vgacon_scrollback.data, count);
 			d += count;
 		}
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v10 2/4] console: Add callback to flush scrollback buffer to consw struct
  2017-01-11 13:32                 ` kbuild test robot
  2017-01-13 20:07                   ` [PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2017-01-13 20:07                   ` [PATCH v10 1/4] console: Move scrollback data into its own struct Manuel Schölling
@ 2017-01-13 20:07                   ` Manuel Schölling
  2017-01-13 20:07                   ` [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
  2017-01-13 20:07                   ` [PATCH v10 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
  4 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-13 20:07 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/tty/vt/vt.c            |  9 +++++++++
 drivers/video/console/vgacon.c | 24 +++++++++++++++++++++++-
 include/linux/console.h        |  4 ++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
 		vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+	WARN_CONSOLE_UNLOCKED();
+
+	if (vc->vc_sw->con_flush_scrollback)
+		vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  *	Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
 		case 3: /* erase scroll-back buffer (and whole display) */
 			scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
 				    vc->vc_screenbuf_size);
+			flush_scrollback(vc);
 			set_origin(vc);
 			if (con_is_visible(vc))
 				update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
 	int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+	if (vgacon_scrollback.data && reset_size > 0)
+		memset(vgacon_scrollback.data, 0, reset_size);
+
+	vgacon_scrollback.cnt  = 0;
+	vgacon_scrollback.tail = 0;
+	vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
 	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 	} else
 		vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+	if (c->vc_num == fg_console)
+		vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 			vga_vram_size);
 	vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b,
 	return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
 	.con_save_screen = vgacon_save_screen,
 	.con_build_attr = vgacon_build_attr,
 	.con_invert_region = vgacon_invert_region,
+	.con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
 	u16    *(*con_screen_pos)(struct vc_data *, int);
 	unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);
 	/*
+	 * Flush the video console driver's scrollback buffer
+	 */
+	void	(*con_flush_scrollback)(struct vc_data *);
+	/*
 	 * Prepare the console for the debugger.  This includes, but is not
 	 * limited to, unblanking the console, loading an appropriate
 	 * palette, and allowing debugger generated output.
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-11 13:32                 ` kbuild test robot
                                     ` (2 preceding siblings ...)
  2017-01-13 20:07                   ` [PATCH v10 2/4] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
@ 2017-01-13 20:07                   ` Manuel Schölling
  2017-01-19 13:23                     ` Greg KH
  2017-01-13 20:07                   ` [PATCH v10 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
  4 siblings, 1 reply; 49+ messages in thread
From: Manuel Schölling @ 2017-01-13 20:07 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
Tested-by: Adam Borowski <kilobyte@angband.pl>
---
 drivers/video/console/Kconfig  |  25 +++++++-
 drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
        range 1 1024
        default "64"
        help
-         Enter the amount of System RAM to allocate for the scrollback
-	 buffer.  Each 64KB will give you approximately 16 80x25
-	 screenfuls of scrollback buffer
+	  Enter the amount of System RAM to allocate for scrollback
+	  buffers of VGA consoles. Each 64KB will give you approximately
+	  16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+	bool "Persistent Scrollback History for each console"
+	depends on VGACON_SOFT_SCROLLBACK
+	default n
+	help
+	  Say Y here if the scrollback history should persist when switching
+	  between consoles. Otherwise, the scrollback history will be flushed
+	  each time the console is switched.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
 	depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
 	void *data;
 	int tail;
 	int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
 	int cur;
 	int save;
 	int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-	if (vgacon_scrollback.data && reset_size > 0)
-		memset(vgacon_scrollback.data, 0, reset_size);
+	struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
+
+	if (scrollback->data && reset_size > 0)
+		memset(scrollback->data, 0, reset_size);
 
-	vgacon_scrollback.cnt  = 0;
-	vgacon_scrollback.tail = 0;
-	vgacon_scrollback.cur  = 0;
+	scrollback->cnt  = 0;
+	scrollback->tail = 0;
+	scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-	int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-	if (vgacon_scrollback.data) {
-		vgacon_scrollback.cnt  = 0;
-		vgacon_scrollback.tail = 0;
-		vgacon_scrollback.cur  = 0;
-		vgacon_scrollback.rows = rows - 1;
-		vgacon_scrollback.size = rows * pitch;
+	int pitch = vga_video_num_columns * 2;
+	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+	int rows = size / pitch;
+	void *data;
+
+	data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+			     GFP_NOWAIT);
+
+	vgacon_scrollbacks[vc_num].data = data;
+	vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+
+	vgacon_scrollback_cur->rows = rows - 1;
+	vgacon_scrollback_cur->size = rows * pitch;
+
+	vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+	vc_num = 0;
+#endif
+
+	if (!vgacon_scrollbacks[vc_num].data) {
+		vgacon_scrollback_init(vc_num);
+	} else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+#else
+		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+		vgacon_scrollback_reset(vc_num, size);
+#endif
 	}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-	vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
-		1024, GFP_NOWAIT);
-	vgacon_scrollback_init(vga_video_num_columns * 2);
+	vgacon_scrollback_cur = &vgacon_scrollbacks[0];
+	vgacon_scrollback_init(0);
 }
 
 static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 {
 	void *p;
 
-	if (!vgacon_scrollback.size || c->vc_num != fg_console)
+	if (!vgacon_scrollback_cur->data || !vgacon_scrollback_cur->size ||
+	    c->vc_num != fg_console)
 		return;
 
 	p = (void *) (c->vc_origin + t * c->vc_size_row);
 
 	while (count--) {
-		scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
+		scr_memcpyw(vgacon_scrollback_cur->data +
+			    vgacon_scrollback_cur->tail,
 			    p, c->vc_size_row);
-		vgacon_scrollback.cnt++;
+
+		vgacon_scrollback_cur->cnt++;
 		p += c->vc_size_row;
-		vgacon_scrollback.tail += c->vc_size_row;
+		vgacon_scrollback_cur->tail += c->vc_size_row;
 
-		if (vgacon_scrollback.tail >= vgacon_scrollback.size)
-			vgacon_scrollback.tail = 0;
+		if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
+			vgacon_scrollback_cur->tail = 0;
 
-		if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
-			vgacon_scrollback.cnt = vgacon_scrollback.rows;
+		if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
+			vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
 
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-	vgacon_scrollback.save = 0;
+	vgacon_scrollback_cur->save = 0;
 
-	if (!vga_is_gfx && !vgacon_scrollback.restore) {
+	if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
 			    c->vc_screenbuf_size > vga_vram_size ?
 			    vga_vram_size : c->vc_screenbuf_size);
-		vgacon_scrollback.restore = 1;
-		vgacon_scrollback.cur = vgacon_scrollback.cnt;
+		vgacon_scrollback_cur->restore = 1;
+		vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
 	}
 }
 
@@ -252,41 +288,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 		return;
 	}
 
-	if (!vgacon_scrollback.data)
+	if (!vgacon_scrollback_cur->data)
 		return;
 
-	if (!vgacon_scrollback.save) {
+	if (!vgacon_scrollback_cur->save) {
 		vgacon_cursor(c, CM_ERASE);
 		vgacon_save_screen(c);
-		vgacon_scrollback.save = 1;
+		vgacon_scrollback_cur->save = 1;
 	}
 
-	vgacon_scrollback.restore = 0;
-	start = vgacon_scrollback.cur + lines;
+	vgacon_scrollback_cur->restore = 0;
+	start = vgacon_scrollback_cur->cur + lines;
 	end = start + abs(lines);
 
 	if (start < 0)
 		start = 0;
 
-	if (start > vgacon_scrollback.cnt)
-		start = vgacon_scrollback.cnt;
+	if (start > vgacon_scrollback_cur->cnt)
+		start = vgacon_scrollback_cur->cnt;
 
 	if (end < 0)
 		end = 0;
 
-	if (end > vgacon_scrollback.cnt)
-		end = vgacon_scrollback.cnt;
+	if (end > vgacon_scrollback_cur->cnt)
+		end = vgacon_scrollback_cur->cnt;
 
-	vgacon_scrollback.cur = start;
+	vgacon_scrollback_cur->cur = start;
 	count = end - start;
-	soff = vgacon_scrollback.tail - ((vgacon_scrollback.cnt - end) *
-					 c->vc_size_row);
+	soff = vgacon_scrollback_cur->tail -
+		((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
 	soff -= count * c->vc_size_row;
 
 	if (soff < 0)
-		soff += vgacon_scrollback.size;
+		soff += vgacon_scrollback_cur->size;
 
-	count = vgacon_scrollback.cnt - start;
+	count = vgacon_scrollback_cur->cnt - start;
 
 	if (count > c->vc_rows)
 		count = c->vc_rows;
@@ -300,13 +336,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
 
 		count *= c->vc_size_row;
 		/* how much memory to end of buffer left? */
-		copysize = min(count, vgacon_scrollback.size - soff);
-		scr_memcpyw(d, vgacon_scrollback.data + soff, copysize);
+		copysize = min(count, vgacon_scrollback_cur->size - soff);
+		scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
 		d += copysize;
 		count -= copysize;
 
 		if (count) {
-			scr_memcpyw(d, vgacon_scrollback.data, count);
+			scr_memcpyw(d, vgacon_scrollback_cur->data, count);
 			d += count;
 		}
 
@@ -320,13 +356,13 @@ static void vgacon_flush_scrollback(struct vc_data *c)
 {
 	size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-	if (c->vc_num == fg_console)
-		vgacon_scrollback_reset(size);
+	vgacon_scrollback_reset(c->vc_num, size);
 }
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)    do { } while (0)
 #define vgacon_scrollback_update(...)  do { } while (0)
+#define vgacon_scrollback_switch(...)  do { } while (0)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
@@ -805,7 +841,7 @@ static int vgacon_switch(struct vc_data *c)
 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
 	}
 
-	vgacon_scrollback_init(c->vc_size_row);
+	vgacon_scrollback_switch(c->vc_num);
 	return 0;		/* Redrawing not needed */
 }
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [PATCH v10 4/4] console: Make persistent scrollback a boot parameter
  2017-01-11 13:32                 ` kbuild test robot
                                     ` (3 preceding siblings ...)
  2017-01-13 20:07                   ` [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2017-01-13 20:07                   ` Manuel Schölling
  4 siblings, 0 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-13 20:07 UTC (permalink / raw)
  To: gregkh
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev, Manuel Schölling

The impact of the persistent scrollback feature on the code size is
rather small, so the config option is removed. The feature stays
disabled by default and can be enabled by using the boot command line
parameter 'vgacon.scrollback_persistent=1' or by setting
VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.

Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
 drivers/video/console/Kconfig  | 12 +++++++-----
 drivers/video/console/vgacon.c | 25 ++++++++++++-------------
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index f500e58f7636..5b71bd905a60 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -47,14 +47,16 @@ config VGACON_SOFT_SCROLLBACK_SIZE
 	  buffers of VGA consoles. Each 64KB will give you approximately
 	  16 80x25 screenfuls of scrollback buffer.
 
-config VGACON_SOFT_SCROLLBACK_PERSISTENT
-	bool "Persistent Scrollback History for each console"
+config VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+	bool "Persistent Scrollback History for each console by default"
 	depends on VGACON_SOFT_SCROLLBACK
 	default n
 	help
-	  Say Y here if the scrollback history should persist when switching
-	  between consoles. Otherwise, the scrollback history will be flushed
-	  each time the console is switched.
+	  Say Y here if the scrollback history should persist by default when
+	  switching between consoles. Otherwise, the scrollback history will be
+	  flushed each time the console is switched. This feature can also be
+	  enabled using the boot command line parameter
+	  'vgacon.scrollback_persistent=1'.
 
 	  This feature might break your tool of choice to flush the scrollback
 	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index ca23d222e029..dc06cb6a15dc 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -174,11 +174,11 @@ struct vgacon_scrollback_info {
 };
 
 static struct vgacon_scrollback_info *vgacon_scrollback_cur;
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
 static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
-#else
-static struct vgacon_scrollback_info vgacon_scrollbacks[1];
-#endif
+static bool scrollback_persistent = \
+	IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
+module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
+MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");
 
 static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
@@ -213,20 +213,19 @@ static void vgacon_scrollback_init(int vc_num)
 
 static void vgacon_scrollback_switch(int vc_num)
 {
-#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-	vc_num = 0;
-#endif
+	if (!scrollback_persistent)
+		vc_num = 0;
 
 	if (!vgacon_scrollbacks[vc_num].data) {
 		vgacon_scrollback_init(vc_num);
 	} else {
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-		vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
-#else
-		size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+		if (scrollback_persistent) {
+			vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+		} else {
+			size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-		vgacon_scrollback_reset(vc_num, size);
-#endif
+			vgacon_scrollback_reset(vc_num, size);
+		}
 	}
 }
 
-- 
2.11.0

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-01-13 20:00                   ` Manuel Schölling
@ 2017-01-14  7:26                     ` Greg KH
  0 siblings, 0 replies; 49+ messages in thread
From: Greg KH @ 2017-01-14  7:26 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: Adam Borowski, jslaby, lkml14, rdunlap, shorne, andrey_utkin,
	akpm, paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Fri, Jan 13, 2017 at 09:00:34PM +0100, Manuel Schölling wrote:
> On Tue, 2017-01-10 at 23:58 +0100, Adam Borowski wrote:
> > On Tue, Jan 10, 2017 at 10:28:38PM +0100, Manuel Schölling wrote:
> > > The impact of the persistent scrollback feature on the code size is
> > > rather small, so the config option is removed. The feature stays
> > > disabled by default and can be enabled by using the boot command
> > > line
> > > parameter 'vgacon.scrollback_persistent=1' or by setting
> > > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > > 
> > > Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> > > Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > > +module_param_named(scrollback_persistent, scrollback_persistent,
> > > bool, 0000);
> > > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > > scrollback for all vga consoles");
> > 
> > A command-line knob settable by the end-user is something more
> > persistent
> > than a config option.  As you're going to extend this code beyond
> > vgacon in
> > the near future, perhaps it'd be better to have a shared setting for
> > all
> > console drivers?
> According to the guys at #kernelnewbies on IRC everybody hates new
> command line options.

That was me, you can use my name here :)

> I'd rather stick to the module parameter for now and maybe introduce a 
> new cmd line option later, once this feature has been implemented in
> several console drivers.

Yes, that should be fine.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-13 20:07                   ` [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2017-01-19 13:23                     ` Greg KH
  2017-01-19 16:12                       ` Manuel Schölling
  0 siblings, 1 reply; 49+ messages in thread
From: Greg KH @ 2017-01-19 13:23 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> Add a scrollback buffers for each VGA console. The benefit is that
> the scrollback history is not flushed when switching between consoles
> but is persistent.
> The buffers are allocated on demand when a new console is opened.
> 
> This breaks tools like clear_console that rely on flushing the
> scrollback history by switching back and forth between consoles
> which is why this feature is disabled by default.
> Use the escape sequence \e[3J instead for flushing the buffer.
> 
> Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
> Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
> Tested-by: Adam Borowski <kilobyte@angband.pl>
> ---
>  drivers/video/console/Kconfig  |  25 +++++++-
>  drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---------------
>  2 files changed, 111 insertions(+), 56 deletions(-)
> 
> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
> index c3f1fb9ee820..f500e58f7636 100644
> --- a/drivers/video/console/Kconfig
> +++ b/drivers/video/console/Kconfig
> @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
>         range 1 1024
>         default "64"
>         help
> -         Enter the amount of System RAM to allocate for the scrollback
> -	 buffer.  Each 64KB will give you approximately 16 80x25
> -	 screenfuls of scrollback buffer
> +	  Enter the amount of System RAM to allocate for scrollback
> +	  buffers of VGA consoles. Each 64KB will give you approximately
> +	  16 80x25 screenfuls of scrollback buffer.
> +
> +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> +	bool "Persistent Scrollback History for each console"
> +	depends on VGACON_SOFT_SCROLLBACK
> +	default n
> +	help
> +	  Say Y here if the scrollback history should persist when switching
> +	  between consoles. Otherwise, the scrollback history will be flushed
> +	  each time the console is switched.
> +
> +	  This feature might break your tool of choice to flush the scrollback
> +	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
> +	  will be broken, which might cause security issues.
> +	  You can use the escape sequence \e[3J instead if this feature is
> +	  activated.

This issue is the one that makes me the most worried.  Why doesn't
clear_console() work anymore?  Why doesn't it use \e[3J ?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-19 13:23                     ` Greg KH
@ 2017-01-19 16:12                       ` Manuel Schölling
  2017-01-19 16:33                         ` Greg KH
  2017-01-19 17:20                         ` Adam Borowski
  0 siblings, 2 replies; 49+ messages in thread
From: Manuel Schölling @ 2017-01-19 16:12 UTC (permalink / raw)
  To: Greg KH
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Thu, 2017-01-19 at 14:23 +0100, Greg KH wrote:
> On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> > Add a scrollback buffers for each VGA console. The benefit is that
> > the scrollback history is not flushed when switching between
> > consoles
> > but is persistent.
> > The buffers are allocated on demand when a new console is opened.
> > 
> > This breaks tools like clear_console that rely on flushing the
> > scrollback history by switching back and forth between consoles
> > which is why this feature is disabled by default.
> > Use the escape sequence \e[3J instead for flushing the buffer.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> > Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > Tested-by: Adam Borowski <kilobyte@angband.pl>
> > ---
> >  drivers/video/console/Kconfig  |  25 +++++++-
> >  drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---
> > ------------
> >  2 files changed, 111 insertions(+), 56 deletions(-)
> > 
> > diff --git a/drivers/video/console/Kconfig
> > b/drivers/video/console/Kconfig
> > index c3f1fb9ee820..f500e58f7636 100644
> > --- a/drivers/video/console/Kconfig
> > +++ b/drivers/video/console/Kconfig
> > @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
> >         range 1 1024
> >         default "64"
> >         help
> > -         Enter the amount of System RAM to allocate for the
> > scrollback
> > -	 buffer.  Each 64KB will give you approximately 16 80x25
> > -	 screenfuls of scrollback buffer
> > +	  Enter the amount of System RAM to allocate for
> > scrollback
> > +	  buffers of VGA consoles. Each 64KB will give you
> > approximately
> > +	  16 80x25 screenfuls of scrollback buffer.
> > +
> > +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> > +	bool "Persistent Scrollback History for each console"
> > +	depends on VGACON_SOFT_SCROLLBACK
> > +	default n
> > +	help
> > +	  Say Y here if the scrollback history should persist when
> > switching
> > +	  between consoles. Otherwise, the scrollback history will
> > be flushed
> > +	  each time the console is switched.
> > +
> > +	  This feature might break your tool of choice to flush
> > the scrollback
> > +	  buffer, e.g. clear(1) will work fine but Debian's
> > clear_console(1)
> > +	  will be broken, which might cause security issues.
> > +	  You can use the escape sequence \e[3J instead if this
> > feature is
> > +	  activated.
> 
> This issue is the one that makes me the most worried.  Why doesn't
> clear_console() work anymore?  Why doesn't it use \e[3J ?

Well, clear_console() just switches from one console to another and
back again. It just assumes that the scrollback buffer is flushed when
switching.
My plan is to make a patch for clear_console() as soon as these patches
are in the kernel - it's chicken-and-egg problem.

Bye,

Manuel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-19 16:12                       ` Manuel Schölling
@ 2017-01-19 16:33                         ` Greg KH
  2017-01-19 23:04                           ` Adam Borowski
  2017-01-19 17:20                         ` Adam Borowski
  1 sibling, 1 reply; 49+ messages in thread
From: Greg KH @ 2017-01-19 16:33 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Thu, Jan 19, 2017 at 05:12:15PM +0100, Manuel Schölling wrote:
> On Thu, 2017-01-19 at 14:23 +0100, Greg KH wrote:
> > On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> > > Add a scrollback buffers for each VGA console. The benefit is that
> > > the scrollback history is not flushed when switching between
> > > consoles
> > > but is persistent.
> > > The buffers are allocated on demand when a new console is opened.
> > > 
> > > This breaks tools like clear_console that rely on flushing the
> > > scrollback history by switching back and forth between consoles
> > > which is why this feature is disabled by default.
> > > Use the escape sequence \e[3J instead for flushing the buffer.
> > > 
> > > Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> > > Reviewed-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > > Tested-by: Andrey Utkin <andrey_utkin@fastmail.com>
> > > Tested-by: Adam Borowski <kilobyte@angband.pl>
> > > ---
> > >  drivers/video/console/Kconfig  |  25 +++++++-
> > >  drivers/video/console/vgacon.c | 142 ++++++++++++++++++++++++++---
> > > ------------
> > >  2 files changed, 111 insertions(+), 56 deletions(-)
> > > 
> > > diff --git a/drivers/video/console/Kconfig
> > > b/drivers/video/console/Kconfig
> > > index c3f1fb9ee820..f500e58f7636 100644
> > > --- a/drivers/video/console/Kconfig
> > > +++ b/drivers/video/console/Kconfig
> > > @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
> > >         range 1 1024
> > >         default "64"
> > >         help
> > > -         Enter the amount of System RAM to allocate for the
> > > scrollback
> > > -	 buffer.  Each 64KB will give you approximately 16 80x25
> > > -	 screenfuls of scrollback buffer
> > > +	  Enter the amount of System RAM to allocate for
> > > scrollback
> > > +	  buffers of VGA consoles. Each 64KB will give you
> > > approximately
> > > +	  16 80x25 screenfuls of scrollback buffer.
> > > +
> > > +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> > > +	bool "Persistent Scrollback History for each console"
> > > +	depends on VGACON_SOFT_SCROLLBACK
> > > +	default n
> > > +	help
> > > +	  Say Y here if the scrollback history should persist when
> > > switching
> > > +	  between consoles. Otherwise, the scrollback history will
> > > be flushed
> > > +	  each time the console is switched.
> > > +
> > > +	  This feature might break your tool of choice to flush
> > > the scrollback
> > > +	  buffer, e.g. clear(1) will work fine but Debian's
> > > clear_console(1)
> > > +	  will be broken, which might cause security issues.
> > > +	  You can use the escape sequence \e[3J instead if this
> > > feature is
> > > +	  activated.
> > 
> > This issue is the one that makes me the most worried.  Why doesn't
> > clear_console() work anymore?  Why doesn't it use \e[3J ?
> 
> Well, clear_console() just switches from one console to another and
> back again. It just assumes that the scrollback buffer is flushed when
> switching.
> My plan is to make a patch for clear_console() as soon as these patches
> are in the kernel - it's chicken-and-egg problem.

I'd recommend that patch get to clear_console() first, having it use the
new escape sequence, if it isn't supported, shouldn't cause any
problems, right?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-19 16:12                       ` Manuel Schölling
  2017-01-19 16:33                         ` Greg KH
@ 2017-01-19 17:20                         ` Adam Borowski
  1 sibling, 0 replies; 49+ messages in thread
From: Adam Borowski @ 2017-01-19 17:20 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: Greg KH, jslaby, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Thu, Jan 19, 2017 at 05:12:15PM +0100, Manuel Schölling wrote:
> On Thu, 2017-01-19 at 14:23 +0100, Greg KH wrote:
> > On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> > > Add a scrollback buffers for each VGA console.  The benefit is that
> > > the scrollback history is not flushed when switching between consoles
> > > but is persistent.  The buffers are allocated on demand when a new
> > > console is opened.
> > > 
> > > This breaks tools like clear_console that rely on flushing the
> > > scrollback history by switching back and forth between consoles
> > > which is why this feature is disabled by default.
> > > Use the escape sequence \e[3J instead for flushing the buffer.
> > 
> > This issue is the one that makes me the most worried.  Why doesn't
> > clear_console() work anymore?  Why doesn't it use \e[3J ?
> 
> Well, clear_console() just switches from one console to another and
> back again. It just assumes that the scrollback buffer is flushed when
> switching.
> My plan is to make a patch for clear_console() as soon as these patches
> are in the kernel - it's chicken-and-egg problem.

No need to wait, \e[3J is supported since Linux 2.6.39; the problem I
spotted was that a previous version of your patch would break that.

It is also safe to output that sequence to a terminal unconditionally: I've
tested a number of terminals, they all either support it (most X terminals,
our console) or silently ignore it.

We can't, though, rely on terminfo to do so: it knows about this capability
(which it calls "E3") for TERM=linux only since very recently.  The TERM
variable is also unreliable: it fails to carry over a serial link while
blindly printing \e[3J works.

As for patching clear_console, https://bugs.debian.org/845177 has a minimal
fix; although for all setups supported by Debian that program could be be
better replaced with just "printf '\e[3J\e[2J'" which would make it work on
strictly more terminals than current code does.  Same for distributions
which copied clear_console (it originates from Ubuntu, maintained in Debian
since then).


Meow!
-- 
Autotools hint: to do a zx-spectrum build on a pdp11 host, type:
  ./configure --host=zx-spectrum --build=pdp11

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-19 16:33                         ` Greg KH
@ 2017-01-19 23:04                           ` Adam Borowski
  2017-01-20 13:16                             ` Adam Borowski
  0 siblings, 1 reply; 49+ messages in thread
From: Adam Borowski @ 2017-01-19 23:04 UTC (permalink / raw)
  To: Greg KH, Matthias Klose, 845177
  Cc: Manuel Schölling, jslaby, lkml14, rdunlap, shorne,
	andrey_utkin, akpm, paul.burton, daniel.vetter, tj, hdegoede,
	linux-kernel, linux-fbdev

On Thu, Jan 19, 2017 at 05:33:14PM +0100, Greg KH wrote:
> On Thu, Jan 19, 2017 at 05:12:15PM +0100, Manuel Schölling wrote:
> > On Thu, 2017-01-19 at 14:23 +0100, Greg KH wrote:
> > > On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> > > > +	  This feature might break your tool of choice to flush
> > > > the scrollback
> > > > +	  buffer, e.g. clear(1) will work fine but Debian's
> > > > clear_console(1)
> > > > +	  will be broken, which might cause security issues.
> > > > +	  You can use the escape sequence \e[3J instead if this
> > > > feature is
> > > > +	  activated.
> > > 
> > > This issue is the one that makes me the most worried.  Why doesn't
> > > clear_console() work anymore?  Why doesn't it use \e[3J ?
> > 
> > Well, clear_console() just switches from one console to another and
> > back again. It just assumes that the scrollback buffer is flushed when
> > switching.
> > My plan is to make a patch for clear_console() as soon as these patches
> > are in the kernel - it's chicken-and-egg problem.
> 
> I'd recommend that patch get to clear_console() first, having it use the
> new escape sequence, if it isn't supported, shouldn't cause any
> problems, right?

In that case, we need to hurry -- the last day for any non-serious fixes in
Debian is Jan 26, after that it'll be frozen for months, and any subsequent
changes won't get to stable users for around two years.

doko: would you consider, pretty please with a cherry on top, applying the
patch I've sent to this bug?  The privacy/security issue is pretty minor and
applies only to a tiny fraction of users, but I understand why Greg is
reluctant.

Manuel's scrollback changes won't go to 4.9, and won't be enabled by default
for the time being, but using a newer kernel on old userspace is something
really widespread, be it via bpo, containers on an updated host, etc.


Meow!
-- 
Autotools hint: to do a zx-spectrum build on a pdp11 host, type:
  ./configure --host=zx-spectrum --build=pdp11

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-19 23:04                           ` Adam Borowski
@ 2017-01-20 13:16                             ` Adam Borowski
  2017-01-20 13:31                               ` Greg KH
  0 siblings, 1 reply; 49+ messages in thread
From: Adam Borowski @ 2017-01-20 13:16 UTC (permalink / raw)
  To: Greg KH
  Cc: Manuel Schölling, jslaby, lkml14, rdunlap, shorne,
	andrey_utkin, akpm, paul.burton, daniel.vetter, tj, hdegoede,
	linux-kernel, linux-fbdev

On Fri, Jan 20, 2017 at 12:04:12AM +0100, Adam Borowski wrote:
> On Thu, Jan 19, 2017 at 05:33:14PM +0100, Greg KH wrote:
> > On Thu, Jan 19, 2017 at 05:12:15PM +0100, Manuel Schölling wrote:
> > > On Thu, 2017-01-19 at 14:23 +0100, Greg KH wrote:
> > > > On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> > > > > +	  This feature might break your tool of choice to flush
> > > > > the scrollback
> > > > > +	  buffer, e.g. clear(1) will work fine but Debian's
> > > > > clear_console(1)
> > > > > +	  will be broken, which might cause security issues.
> > > > > +	  You can use the escape sequence \e[3J instead if this
> > > > > feature is
> > > > > +	  activated.
> > 
> > I'd recommend that patch get to clear_console() first, having it use the
> > new escape sequence, if it isn't supported, shouldn't cause any
> > problems, right?
> 
> doko: would you consider, pretty please with a cherry on top, applying the
> patch I've sent to this bug?  The privacy/security issue is pretty minor and
> applies only to a tiny fraction of users, but I understand why Greg is
> reluctant.

# Subject: Bug#845177 closed by Matthias Klose <doko@debian.org>
#
# This is an automatic notification regarding your Bug report
# which was filed against the bash package:
#
# #845177: clear_console: assumes VT switch clears scrollback
#
# It has been closed by Matthias Klose <doko@debian.org>.
[...]
# Changes:
#    * clear_console: Securely erase the current console. Closes: #845177.

-- 
Autotools hint: to do a zx-spectrum build on a pdp11 host, type:
  ./configure --host=zx-spectrum --build=pdp11

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-20 13:16                             ` Adam Borowski
@ 2017-01-20 13:31                               ` Greg KH
  2017-01-20 14:27                                 ` Adam Borowski
  0 siblings, 1 reply; 49+ messages in thread
From: Greg KH @ 2017-01-20 13:31 UTC (permalink / raw)
  To: Adam Borowski
  Cc: Manuel Schölling, jslaby, lkml14, rdunlap, shorne,
	andrey_utkin, akpm, paul.burton, daniel.vetter, tj, hdegoede,
	linux-kernel, linux-fbdev

On Fri, Jan 20, 2017 at 02:16:11PM +0100, Adam Borowski wrote:
> On Fri, Jan 20, 2017 at 12:04:12AM +0100, Adam Borowski wrote:
> > On Thu, Jan 19, 2017 at 05:33:14PM +0100, Greg KH wrote:
> > > On Thu, Jan 19, 2017 at 05:12:15PM +0100, Manuel Schölling wrote:
> > > > On Thu, 2017-01-19 at 14:23 +0100, Greg KH wrote:
> > > > > On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> > > > > > +	  This feature might break your tool of choice to flush
> > > > > > the scrollback
> > > > > > +	  buffer, e.g. clear(1) will work fine but Debian's
> > > > > > clear_console(1)
> > > > > > +	  will be broken, which might cause security issues.
> > > > > > +	  You can use the escape sequence \e[3J instead if this
> > > > > > feature is
> > > > > > +	  activated.
> > > 
> > > I'd recommend that patch get to clear_console() first, having it use the
> > > new escape sequence, if it isn't supported, shouldn't cause any
> > > problems, right?
> > 
> > doko: would you consider, pretty please with a cherry on top, applying the
> > patch I've sent to this bug?  The privacy/security issue is pretty minor and
> > applies only to a tiny fraction of users, but I understand why Greg is
> > reluctant.
> 
> # Subject: Bug#845177 closed by Matthias Klose <doko@debian.org>
> #
> # This is an automatic notification regarding your Bug report
> # which was filed against the bash package:
> #
> # #845177: clear_console: assumes VT switch clears scrollback
> #
> # It has been closed by Matthias Klose <doko@debian.org>.
> [...]
> # Changes:
> #    * clear_console: Securely erase the current console. Closes: #845177.

This means it was accepted?  Or rejected?

confused,

greg k-h

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-20 13:31                               ` Greg KH
@ 2017-01-20 14:27                                 ` Adam Borowski
  0 siblings, 0 replies; 49+ messages in thread
From: Adam Borowski @ 2017-01-20 14:27 UTC (permalink / raw)
  To: Greg KH
  Cc: Manuel Schölling, jslaby, lkml14, rdunlap, shorne,
	andrey_utkin, akpm, paul.burton, daniel.vetter, tj, hdegoede,
	linux-kernel, linux-fbdev

On Fri, Jan 20, 2017 at 02:31:56PM +0100, Greg KH wrote:
> On Fri, Jan 20, 2017 at 02:16:11PM +0100, Adam Borowski wrote:
> > On Fri, Jan 20, 2017 at 12:04:12AM +0100, Adam Borowski wrote:
> > > On Thu, Jan 19, 2017 at 05:33:14PM +0100, Greg KH wrote:
> > > > I'd recommend that patch get to clear_console() first, having it use the
> > > > new escape sequence, if it isn't supported, shouldn't cause any
> > > > problems, right?
> > 
> > # Subject: Bug#845177 closed by Matthias Klose <doko@debian.org>
> > #
> > # This is an automatic notification regarding your Bug report
> > # which was filed against the bash package:
> > #
> > # #845177: clear_console: assumes VT switch clears scrollback
> > #
> > # It has been closed by Matthias Klose <doko@debian.org>.
> > [...]
> > # Changes:
> > #    * clear_console: Securely erase the current console. Closes: #845177.
> 
> This means it was accepted?  Or rejected?

Accepted.

It's in unstable (or will be in the next mirror pulse), we're at the fastest
possible moment to get stuff to the next stable release -- it'll be in
Stretch (about to freeze).  Ubuntu migration is currently open so it'll get
there soon, in time for Zesty (17.04).  Other Debian derivatives likewise
pull at their own pace.

Most distributions unrelated to Debian don't seem to ship clear_console but
I have no real idea: just checked Fedora 25, it doesn't have it in the
default install at least.


Meow!
-- 
Autotools hint: to do a zx-spectrum build on a pdp11 host, type:
  ./configure --host=zx-spectrum --build=pdp11

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles
  2017-01-13 20:07                   ` [PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
@ 2017-01-25 10:55                     ` Greg KH
  0 siblings, 0 replies; 49+ messages in thread
From: Greg KH @ 2017-01-25 10:55 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin, akpm,
	paul.burton, daniel.vetter, tj, hdegoede, linux-kernel,
	linux-fbdev

On Fri, Jan 13, 2017 at 09:07:54PM +0100, Manuel Schölling wrote:
> Changes in v10:
>   - Fix compilation error if CONFIG_VGACON_SOFT_SCROLLBACK=n

All now applied to my tty-testing branch, let's see what the 0-day bot
has to say about this :)

thanks for the persistence.

greg k-h

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-01-10 21:28               ` [PATCH v9 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
  2017-01-10 22:58                 ` Adam Borowski
  2017-01-11 13:32                 ` kbuild test robot
@ 2017-02-02 20:07                 ` Paul Gortmaker
  2017-02-03 16:04                   ` Manuel Schölling
  2 siblings, 1 reply; 49+ messages in thread
From: Paul Gortmaker @ 2017-02-02 20:07 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: gregkh, jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin,
	Andrew Morton, paul.burton, daniel.vetter, tj, hdegoede, LKML,
	linux-fbdev

On Tue, Jan 10, 2017 at 4:28 PM, Manuel Schölling
<manuel.schoelling@gmx.de> wrote:
> The impact of the persistent scrollback feature on the code size is
> rather small, so the config option is removed. The feature stays
> disabled by default and can be enabled by using the boot command line
> parameter 'vgacon.scrollback_persistent=1' or by setting
> VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
>
> Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> ---

[...]

> +module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
> +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");

Since this hasn't got widespread deployment yet and  only exists
in Greg's tree, can we please fix the above to use setup_param or
similar, since there is nothing modular about this code at all.

Thanks.
Paul.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-02-02 20:07                 ` [PATCH v9 " Paul Gortmaker
@ 2017-02-03 16:04                   ` Manuel Schölling
  2017-02-03 16:45                     ` Adam Borowski
  0 siblings, 1 reply; 49+ messages in thread
From: Manuel Schölling @ 2017-02-03 16:04 UTC (permalink / raw)
  To: Paul Gortmaker
  Cc: gregkh, jslaby, kilobyte, lkml14, rdunlap, shorne, andrey_utkin,
	Andrew Morton, paul.burton, daniel.vetter, tj, hdegoede, LKML,
	linux-fbdev

Hi Paul,

On Thu, 2017-02-02 at 15:07 -0500, Paul Gortmaker wrote:
> On Tue, Jan 10, 2017 at 4:28 PM, Manuel Schölling
> <manuel.schoelling@gmx.de> wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoelling@gmx.de>
> > Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
> > ---
> 
> [...]
> 
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, 0000);
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> Since this hasn't got widespread deployment yet and  only exists
> in Greg's tree, can we please fix the above to use setup_param or
> similar, since there is nothing modular about this code at all.
Not sure what you mean here.
If this is not the right may to declare it I'd be more than happy to
change this. But I could not find any function/macro named setup_param
[1].
It would be great if you could give me a hint what function to use
here!

Have a great weekend!

Manuel

[1] http://lxr.free-electrons.com/ident?i=setup_param

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter
  2017-02-03 16:04                   ` Manuel Schölling
@ 2017-02-03 16:45                     ` Adam Borowski
  0 siblings, 0 replies; 49+ messages in thread
From: Adam Borowski @ 2017-02-03 16:45 UTC (permalink / raw)
  To: Manuel Schölling
  Cc: Paul Gortmaker, gregkh, jslaby, lkml14, rdunlap, shorne,
	andrey_utkin, Andrew Morton, paul.burton, daniel.vetter, tj,
	hdegoede, LKML, linux-fbdev

On Fri, Feb 03, 2017 at 05:04:15PM +0100, Manuel Schölling wrote:
> On Thu, 2017-02-02 at 15:07 -0500, Paul Gortmaker wrote:
> > On Tue, Jan 10, 2017 at 4:28 PM, Manuel Schölling
> > <manuel.schoelling@gmx.de> wrote:
> > > The impact of the persistent scrollback feature on the code size is
> > > rather small, so the config option is removed. The feature stays
> > > disabled by default and can be enabled by using the boot command
> > > line
> > > parameter 'vgacon.scrollback_persistent=1' or by setting
> > > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > [...]
> > 
> > > +module_param_named(scrollback_persistent, scrollback_persistent,
> > > bool, 0000);
> > > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > > scrollback for all vga consoles");
> > 
> > Since this hasn't got widespread deployment yet and  only exists
> > in Greg's tree, can we please fix the above to use setup_param or
> > similar, since there is nothing modular about this code at all.
> Not sure what you mean here.
> If this is not the right may to declare it I'd be more than happy to
> change this. But I could not find any function/macro named setup_param
> [1].
> It would be great if you could give me a hint what function to use
> here!
> 
> [1] http://lxr.free-electrons.com/ident?i=setup_param

That shows only exact matches.

You want "git grep setup_param", which shows __setup_param() plus some
unrelated stuff.  I see only four uses in the kernel, but that's enough
to see how to use it.


Meow!
-- 
Autotools hint: to do a zx-spectrum build on a pdp11 host, type:
  ./configure --host=zx-spectrum --build=pdp11

^ permalink raw reply	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2017-02-03 16:46 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-04 10:53 [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
2016-12-04 10:53 ` [PATCH v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
2016-12-04 10:53 ` [PATCH v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
2016-12-04 10:53 ` [PATCH v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
2016-12-06 10:02 ` [PATCH v7 0/3] " Greg KH
2016-12-06 16:32   ` Manuel Schölling
2016-12-21 16:37 ` [PATCH RESEND " Manuel Schölling
2016-12-21 16:37   ` [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
2016-12-21 16:37   ` [PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
2016-12-21 16:37   ` [PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
2017-01-04 13:54   ` [PATCH RESEND v7 0/3] " Andrey Utkin
2017-01-05 11:33     ` [PATCH v8 " Manuel Schölling
2017-01-05 11:33     ` [PATCH v8 1/3] console: Move scrollback data into its own struct Manuel Schölling
2017-01-05 11:33     ` [PATCH v8 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
2017-01-05 11:33     ` [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
     [not found]       ` <CGME20170110162224epcas1p2095912fa6b73a1457fa86396149e78e9@epcas1p2.samsung.com>
2017-01-10 16:22         ` Bartlomiej Zolnierkiewicz
     [not found]           ` <CGME20170110164435epcas1p314efb9c6ea3ffb971fce06f3bfaec736@epcas1p3.samsung.com>
2017-01-10 16:44             ` Bartlomiej Zolnierkiewicz
2017-01-10 17:31               ` Manuel Schölling
2017-01-10 21:28               ` [PATCH v9 0/4] " Manuel Schölling
2017-01-10 21:28               ` [PATCH v9 1/4] console: Move scrollback data into its own struct Manuel Schölling
2017-01-10 21:28               ` [PATCH v9 2/4] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
2017-01-10 21:28               ` [PATCH v9 3/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
2017-01-10 21:28               ` [PATCH v9 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
2017-01-10 22:58                 ` Adam Borowski
2017-01-11 21:41                   ` Manuel Schölling
2017-01-13 20:00                   ` Manuel Schölling
2017-01-14  7:26                     ` Greg KH
2017-01-11 13:32                 ` kbuild test robot
2017-01-13 20:07                   ` [PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
2017-01-25 10:55                     ` Greg KH
2017-01-13 20:07                   ` [PATCH v10 1/4] console: Move scrollback data into its own struct Manuel Schölling
2017-01-13 20:07                   ` [PATCH v10 2/4] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
2017-01-13 20:07                   ` [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
2017-01-19 13:23                     ` Greg KH
2017-01-19 16:12                       ` Manuel Schölling
2017-01-19 16:33                         ` Greg KH
2017-01-19 23:04                           ` Adam Borowski
2017-01-20 13:16                             ` Adam Borowski
2017-01-20 13:31                               ` Greg KH
2017-01-20 14:27                                 ` Adam Borowski
2017-01-19 17:20                         ` Adam Borowski
2017-01-13 20:07                   ` [PATCH v10 4/4] console: Make persistent scrollback a boot parameter Manuel Schölling
2017-02-02 20:07                 ` [PATCH v9 " Paul Gortmaker
2017-02-03 16:04                   ` Manuel Schölling
2017-02-03 16:45                     ` Adam Borowski
2017-01-02 14:27 ` [PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling
2017-01-02 14:27   ` [PATCH RESEND v7 1/3] console: Move scrollback data into its own struct Manuel Schölling
2017-01-02 14:27   ` [PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct Manuel Schölling
2017-01-02 14:27   ` [PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles Manuel Schölling

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).