dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/5] fbcon,vgacon,vt: Share helpers for text cursors
@ 2026-09-28  8:55 Thomas Zimmermann
  2026-09-28  8:55 ` [PATCH v3 1/5] vt: Add cursor-size helpers Thomas Zimmermann
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: Thomas Zimmermann @ 2026-09-28  8:55 UTC (permalink / raw)
  To: deller, gregkh, jirislaby, simona
  Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
	Thomas Zimmermann

VT consoles fbcon and vgacon implement various cursor sizes (i.e.,
underline, block, half-block, etc). Share related code and harmonize
the look and behaviour.

In patches 1 to 3, move VT cursor-size calculations to the VT subsystem
and use the new helpers from vgacon. Replace similar code in the console.
The new helpers also take VT's default cursor size into account.

Fbcon implements a custom helper that creates a cursor glyph for the
given cursor size. In patches 4 and 5, move the code into the font
library and update fbcon to use the new helper. The cursor-glyph shape
rendering is tied to the font in use. Hence move them next to each other.
Also update fbcon to use the shared cursor-size helpers.

Tested with fbcon under bochs (qemu) and with vgacon on an old SiS
6202 VGA card. Other consoles (newport_con, sticon) don't support cursor
sizes, so leave them as-is.

v3:
- mention user interfaces to control cursor size in commit message (GregKH)
- elaborate defaults (GregKH)
- move retry logic into helper
- handle CUR_DEF
v2:
- restore vc_cell_height in vgacon
- avoid interference from concurrent user space
- fix docs

Thomas Zimmermann (5):
  vt: Add cursor-size helpers
  vgacon: Remove trailing whitespaces
  vgacon: Use vt_cursor_{start,end}()
  lib/fonts: Add font_glyph_cursor() helper
  fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph()

 drivers/tty/vt/vt.c                  | 104 +++++++++++++++++++++++++++
 drivers/video/console/vgacon.c       |  43 +++--------
 drivers/video/fbdev/core/bitblit.c   |   3 +-
 drivers/video/fbdev/core/fbcon.c     |  45 +++---------
 drivers/video/fbdev/core/fbcon.h     |   2 +-
 drivers/video/fbdev/core/fbcon_ccw.c |   3 +-
 drivers/video/fbdev/core/fbcon_cw.c  |   3 +-
 drivers/video/fbdev/core/fbcon_ud.c  |   3 +-
 include/linux/console_struct.h       |   7 ++
 include/linux/font.h                 |   4 ++
 lib/fonts/Makefile                   |   3 +-
 lib/fonts/font_cursor.c              |  56 +++++++++++++++
 12 files changed, 199 insertions(+), 77 deletions(-)
 create mode 100644 lib/fonts/font_cursor.c


base-commit: ff831af91674990f9f1814340860e96943d5df1a
prerequisite-patch-id: c67e5d886a47b7d0266d81100837557fda34cb24
prerequisite-patch-id: a5a973e527c88a5b47053d7a72aefe0b550197cb
prerequisite-patch-id: b9adc9622920a3e70168e672c2c92795b3e3a106
prerequisite-patch-id: 5030de433a01c2e99056cadb676a8e2ba35f055a
-- 
2.55.0


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

* [PATCH v3 1/5] vt: Add cursor-size helpers
  2026-09-28  8:55 [PATCH v3 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
@ 2026-09-28  8:55 ` Thomas Zimmermann
  2026-09-28  9:07   ` Jani Nikula
                     ` (2 more replies)
  2026-09-28  8:55 ` [PATCH v3 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
                   ` (3 subsequent siblings)
  4 siblings, 3 replies; 16+ messages in thread
From: Thomas Zimmermann @ 2026-09-28  8:55 UTC (permalink / raw)
  To: deller, gregkh, jirislaby, simona
  Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
	Thomas Zimmermann

Cursors in the VT subsystem are blocks within a character cell that are
filled with the foreground color. The new helpers vc_cursor_start() and
vc_cursor_end() return the scanlines in which the cursor block starts rsp.
ends. This is compatible with VGA hardware.

In terms of cursor design, the new cursor-size helpers follow established
styles in fbcon. The only exception is in underline cursors for fonts with
a size larger than 10. The underlining dash is now one pixel closer to
the font-glyph data, so that the cursor looks less detached. This follows
the style used by vgacon.

Users control the cursor size with the vt module's parameter cur_default
or with the ESC sequence \e[?Nc, where N is the cursor-size constant. In
case of an invalid setting, the new helpers fall back to cur_default and
then underline cursors; in this order.

Similar code in vgacon and fbcon ignores the cursor's default size stored
in vt.cur_default. The consoles default to full-block cursors, while vt
defaults to underline cursors. VGA BIOSes also tend to use underline by.
default. Upon initialization vt applies its default to the console, but
each console might fall back to it own default. For example, running the
ESC code from above with the invalid constant of 8 magically flips the
cursor from underline to block size on vgacon. Another call with N set
to 0 (i.e., default) magically flips it back to underlyine. Making
underline the new default everywhere harmonizes vt, fbcon and most VGA
BIOSes.

v3:
- mention user interfaces to control cursor size in commit message (GregKH)
- elaborate defaults (GregKH)
- move retry logic into helper
- handle CUR_DEF
v2:
- export non-font interface for vgacon
- avoid interference from concurrent user space (Sashiko)
- fix function docs (Sashiko)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
 drivers/tty/vt/vt.c            | 104 +++++++++++++++++++++++++++++++++
 include/linux/console_struct.h |   7 +++
 2 files changed, 111 insertions(+)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 57edf37495a8..8141296ccad0 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -71,6 +71,7 @@
  * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
  */
 
+#include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/sched/signal.h>
@@ -264,6 +265,109 @@ unsigned int vc_font_size(const struct vc_font *font)
 }
 EXPORT_SYMBOL_GPL(vc_font_size);
 
+/*
+ * Cursors
+ */
+
+static unsigned int vc_cursor_size(unsigned int cursor_size)
+{
+	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
+
+retry:
+	switch (cursor_size) {
+	case CUR_NONE:
+	case CUR_UNDERLINE:
+	case CUR_LOWER_THIRD:
+	case CUR_LOWER_HALF:
+	case CUR_TWO_THIRDS:
+	case CUR_BLOCK:
+		return cursor_size;
+	default:
+		pr_warn_once("Unknown cursor %u\n", cursor_size);
+		fallthrough;
+	case CUR_DEF:
+		/*
+		 * Use user-given default size, or underline if
+		 * the given default is invalid.
+		 */
+		if (cursor_size != cursor_default_size)
+			cursor_size = cursor_default_size;
+		else
+			cursor_size = CUR_UNDERLINE;
+		goto retry;
+	}
+}
+
+/**
+ * vc_cursor_start - Calculates the cursor's first scanline within a character cell
+ * @cell_height: The overall height of the character cell
+ * @cursor_size: The size constant of cursor pattern
+ *
+ * The parameter @cell_height is the height of the character cell as
+ * displayed by the console. The argument given in @cursor_size is one
+ * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
+ * For unknown values, the helper draws the default cursor or an underline
+ * dash.
+ *
+ * Returns:
+ * The index of the cursor's first scanline within the character cell
+ */
+unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size)
+{
+	switch (vc_cursor_size(cursor_size)) {
+	case CUR_NONE:
+		return cell_height;
+	case CUR_UNDERLINE:
+	default:
+		if (cell_height < 10)
+			return cell_height - 1;
+		else
+			return cell_height - 3;
+	case CUR_LOWER_THIRD:
+		return cell_height - cell_height / 3;
+	case CUR_LOWER_HALF:
+		return cell_height - cell_height / 2;
+	case CUR_TWO_THIRDS:
+		return cell_height - (cell_height * 2) / 3;
+	case CUR_BLOCK:
+		return 0;
+	}
+}
+EXPORT_SYMBOL_GPL(vc_cursor_start);
+
+/**
+ * vc_cursor_end - Calculates the first scanline after the cursor within a character cell
+ * @cell_height: The overall height of the character cell
+ * @cursor_size: The size constant of cursor pattern
+ *
+ * The parameter @cell_height is the height of the character cell as
+ * displayed by the console. The argument given in @cursor_size is one
+ * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
+ * For unknown values, the helper draws the default cursor or an underline
+ * dash.
+ *
+ * Returns:
+ * The index of the first scanline after the cursor within the character cell
+ */
+unsigned int vc_cursor_end(unsigned int cell_height, unsigned int cursor_size)
+{
+	switch (vc_cursor_size(cursor_size)) {
+	case CUR_UNDERLINE:
+	default:
+		if (cell_height < 10)
+			return cell_height;
+		else
+			return cell_height - 1;
+	case CUR_NONE:
+	case CUR_LOWER_THIRD:
+	case CUR_LOWER_HALF:
+	case CUR_TWO_THIRDS:
+	case CUR_BLOCK:
+		return cell_height;
+	}
+}
+EXPORT_SYMBOL_GPL(vc_cursor_end);
+
 /*
  * /sys/class/tty/tty0/
  *
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index fe915afdece5..1d37c7898ea0 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -204,6 +204,10 @@ struct vc {
 extern struct vc vc_cons [MAX_NR_CONSOLES];
 extern void vc_SAK(struct work_struct *work);
 
+/*
+ * Cursors
+ */
+
 #define CUR_MAKE(size, change, set)	((size) | ((change) << 8) |	\
 		((set) << 16))
 #define CUR_SIZE(c)		 ((c) & 0x00000f)
@@ -222,6 +226,9 @@ extern void vc_SAK(struct work_struct *work);
 #define CUR_CHANGE(c)		 ((c) & 0x00ff00)
 #define CUR_SET(c)		(((c) & 0xff0000) >> 8)
 
+unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size);
+unsigned int vc_cursor_end(unsigned int cell_height, unsigned int cursor_size);
+
 bool con_is_visible(const struct vc_data *vc);
 
 #endif /* _LINUX_CONSOLE_STRUCT_H */
-- 
2.55.0


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

* [PATCH v3 2/5] vgacon: Remove trailing whitespaces
  2026-09-28  8:55 [PATCH v3 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
  2026-09-28  8:55 ` [PATCH v3 1/5] vt: Add cursor-size helpers Thomas Zimmermann
@ 2026-09-28  8:55 ` Thomas Zimmermann
  2026-09-28  8:59   ` sashiko-bot
  2026-09-28  8:55 ` [PATCH v3 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Thomas Zimmermann @ 2026-09-28  8:55 UTC (permalink / raw)
  To: deller, gregkh, jirislaby, simona
  Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
	Thomas Zimmermann

Fix coding style.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
 drivers/video/console/vgacon.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 37bd18730fe0..536e7fe4d142 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -881,14 +881,14 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
 	/* First, the Sequencer */
 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
 	/* CPU writes only to map 2 */
-	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);	
+	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
 	/* Sequential addressing */
-	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);	
+	vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
 	/* Clear synchronous reset */
 	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
 
 	/* Now, the graphics controller, select map 2 */
-	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);		
+	vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x02);
 	/* disable odd-even addressing */
 	vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00);
 	/* map start at A000:0000 */
@@ -930,7 +930,7 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
 
 	raw_spin_lock_irq(&vga_lock);
 	/* First, the sequencer, Synchronous reset */
-	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);	
+	vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
 	/* CPU writes to maps 0 and 1 */
 	vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
 	/* odd-even addressing */
@@ -959,7 +959,7 @@ static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
 		/* Wilton (1987) mentions the following; I don't know what
 		   it means, but it works, and it appears necessary */
 		inb_p(video_port_status);
-		vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);	
+		vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
 		clear_attribs = true;
 	}
 	raw_spin_unlock_irq(&vga_lock);
-- 
2.55.0


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

* [PATCH v3 3/5] vgacon: Use vt_cursor_{start,end}()
  2026-09-28  8:55 [PATCH v3 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
  2026-09-28  8:55 ` [PATCH v3 1/5] vt: Add cursor-size helpers Thomas Zimmermann
  2026-09-28  8:55 ` [PATCH v3 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
@ 2026-09-28  8:55 ` Thomas Zimmermann
  2026-09-28  9:09   ` sashiko-bot
  2026-09-28  8:55 ` [PATCH v3 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
  2026-09-28  8:55 ` [PATCH v3 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
  4 siblings, 1 reply; 16+ messages in thread
From: Thomas Zimmermann @ 2026-09-28  8:55 UTC (permalink / raw)
  To: deller, gregkh, jirislaby, simona
  Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
	Thomas Zimmermann

Replace vgacon's custom cursor metrics with the shared helpers
vc_cursor_start() and vc_font_cursor_end(). Note that the _end()
function returns the index of the scanline below the cursor, while
VGA hardware expects the cursor's final scanline. Hence vgacon
subtracts 1 from the end value.

The cursor shapes remain mostly unchanged, except that non-underline
cursors now also use the glyph's top-most and bottom-most scanline.
This follows the style used by fbcon.

v2:
- restore use of vc_cell_height (Sashiko)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
 drivers/video/console/vgacon.c | 33 +++++----------------------------
 1 file changed, 5 insertions(+), 28 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 536e7fe4d142..b1408bb5e265 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -506,6 +506,7 @@ static void vgacon_set_cursor_size(int from, int to)
 static void vgacon_cursor(struct vc_data *c, bool enable)
 {
 	unsigned int c_height;
+	unsigned int c_size;
 
 	if (c->vc_mode != KD_TEXT)
 		return;
@@ -513,10 +514,11 @@ static void vgacon_cursor(struct vc_data *c, bool enable)
 	vgacon_restore_screen(c);
 
 	c_height = c->vc_cell_height;
+	c_size = CUR_SIZE(c->vc_cursor_type);
 
 	write_vga(14, (c->vc_pos - vga_vram_base) / 2);
 
-	if (!enable) {
+	if (!enable || c_size == CUR_NONE) {
 	        if (vga_video_type >= VIDEO_TYPE_VGAC)
 			vgacon_set_cursor_size(31, 30);
 		else
@@ -524,33 +526,8 @@ static void vgacon_cursor(struct vc_data *c, bool enable)
 		return;
 	}
 
-	switch (CUR_SIZE(c->vc_cursor_type)) {
-	case CUR_UNDERLINE:
-		vgacon_set_cursor_size(c_height - (c_height < 10 ? 2 : 3),
-				       c_height - (c_height < 10 ? 1 : 2));
-		break;
-	case CUR_TWO_THIRDS:
-		vgacon_set_cursor_size(c_height / 3,
-				       c_height - (c_height < 10 ? 1 : 2));
-		break;
-	case CUR_LOWER_THIRD:
-		vgacon_set_cursor_size(c_height * 2 / 3,
-				       c_height - (c_height < 10 ? 1 : 2));
-		break;
-	case CUR_LOWER_HALF:
-		vgacon_set_cursor_size(c_height / 2,
-				       c_height - (c_height < 10 ? 1 : 2));
-		break;
-	case CUR_NONE:
-		if (vga_video_type >= VIDEO_TYPE_VGAC)
-			vgacon_set_cursor_size(31, 30);
-		else
-			vgacon_set_cursor_size(31, 31);
-		break;
-	default:
-		vgacon_set_cursor_size(1, c_height);
-		break;
-	}
+	vgacon_set_cursor_size(vc_cursor_start(c_height, c_size),
+			       vc_cursor_end(c_height, c_size) - 1);
 }
 
 static void vgacon_doresize(struct vc_data *c,
-- 
2.55.0


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

* [PATCH v3 4/5] lib/fonts: Add font_glyph_cursor() helper
  2026-09-28  8:55 [PATCH v3 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
                   ` (2 preceding siblings ...)
  2026-09-28  8:55 ` [PATCH v3 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
@ 2026-09-28  8:55 ` Thomas Zimmermann
  2026-09-28  9:16   ` sashiko-bot
  2026-09-28  8:55 ` [PATCH v3 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
  4 siblings, 1 reply; 16+ messages in thread
From: Thomas Zimmermann @ 2026-09-28  8:55 UTC (permalink / raw)
  To: deller, gregkh, jirislaby, simona
  Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
	Thomas Zimmermann

The new helper font_glyph_cursor() fills a glyph with a cursor pattern.
As with the font_glyph_rotate_*() helpers, the caller has to provide the
output memory.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
 include/linux/font.h    |  4 +++
 lib/fonts/Makefile      |  3 ++-
 lib/fonts/font_cursor.c | 56 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 lib/fonts/font_cursor.c

diff --git a/include/linux/font.h b/include/linux/font.h
index 5e1cf9830084..be1a26ff8ae9 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -109,6 +109,10 @@ const unsigned char *font_data_glyph_buf(font_data_t *fd,
 bool font_data_is_equal(font_data_t *lhs, font_data_t *rhs);
 int font_data_export(font_data_t *fd, struct console_font *font, unsigned int vpitch);
 
+/* font_cursor.c */
+void font_glyph_cursor(unsigned int width, unsigned int height,
+		       unsigned int from, unsigned int to, unsigned char *out);
+
 /* font_rotate.c */
 void font_glyph_rotate_90(const unsigned char *glyph, unsigned int width, unsigned int height,
 			  unsigned char *out);
diff --git a/lib/fonts/Makefile b/lib/fonts/Makefile
index 7202a70a56ef..bc08bf8ea3f8 100644
--- a/lib/fonts/Makefile
+++ b/lib/fonts/Makefile
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 # Font handling
 
-font-y := fonts.o
+font-y := fonts.o \
+	  font_cursor.o
 font-$(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION) += font_rotate.o
 
 # Built-in fonts; sorted by Family-Size in ascending order
diff --git a/lib/fonts/font_cursor.c b/lib/fonts/font_cursor.c
new file mode 100644
index 000000000000..7f4d587669aa
--- /dev/null
+++ b/lib/fonts/font_cursor.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <linux/string.h>
+
+#include "font.h"
+
+/**
+ * font_glyph_cursor - Create a cursor glyph
+ * @width: The glyph width in bits per scanline
+ * @height: The number of scanlines in the glyph
+ * @start: The first scanline of the cursor block
+ * @end: The first scanline after the cursor block
+ * @out: The cursor-glyph bitmap
+ *
+ * The parameters @width and @height refer to the glyph size. The caller
+ * has to provide the output buffer @out of sufficient size to hold the
+ * cursor glyph. The arguments in @start and @end describe the number of
+ * scanlines occupied by the cursor block; counting from the top of the
+ * glyph. The helper fills these scanlines with a pattern and clears the
+ * remaining scanlines.
+ */
+void font_glyph_cursor(unsigned int width, unsigned int height,
+		       unsigned int start, unsigned int end, unsigned char *out)
+{
+	unsigned int pitch = font_glyph_pitch(width);
+	const unsigned char *out_end = out + height * pitch;
+	unsigned int size;
+
+	if (WARN_ON_ONCE(start > height))
+		start = height;
+	if (WARN_ON_ONCE(end > height))
+		end = height;
+
+	if (end < start)
+		end = start;
+
+	/* clear scanlines before cursor block */
+	size = start * pitch;
+	memset(out, 0x00, size);
+	out += size;
+
+	/* set cursor block */
+	size = (end - start) * pitch;
+	memset(out, 0xff, size);
+	out += size;
+
+	/* clear scanlines below cursor block */
+	size = (height - end) * pitch;
+	memset(out, 0x00, size);
+	out += size;
+
+	WARN_ON_ONCE(out != out_end);
+}
+EXPORT_SYMBOL_GPL(font_glyph_cursor);
-- 
2.55.0


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

* [PATCH v3 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph()
  2026-09-28  8:55 [PATCH v3 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
                   ` (3 preceding siblings ...)
  2026-09-28  8:55 ` [PATCH v3 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
@ 2026-09-28  8:55 ` Thomas Zimmermann
  2026-09-28  9:21   ` sashiko-bot
  4 siblings, 1 reply; 16+ messages in thread
From: Thomas Zimmermann @ 2026-09-28  8:55 UTC (permalink / raw)
  To: deller, gregkh, jirislaby, simona
  Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
	Thomas Zimmermann

The kernel's font library provides font_glyph_cursor() to create cursor
glyphs. Replace fbcon's fbcon_fill_cursor_mask() with a new helper that
uses font_glyph_cursor().

The cursor shapes remain mostly unchanged. The only exception is in
underline cursors for fonts with a size larger than 10. The underlining
dash is now one pixel closer to the font-glyph data, so that the cursor
looks less detached. This follows the style used by vgacon.

v2:
- adapt to new VT interface

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>
---
 drivers/video/fbdev/core/bitblit.c   |  3 +-
 drivers/video/fbdev/core/fbcon.c     | 45 +++++++---------------------
 drivers/video/fbdev/core/fbcon.h     |  2 +-
 drivers/video/fbdev/core/fbcon_ccw.c |  3 +-
 drivers/video/fbdev/core/fbcon_cw.c  |  3 +-
 drivers/video/fbdev/core/fbcon_ud.c  |  3 +-
 6 files changed, 16 insertions(+), 43 deletions(-)

diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
index 39f44258d793..03b3b18e1fe9 100644
--- a/drivers/video/fbdev/core/bitblit.c
+++ b/drivers/video/fbdev/core/bitblit.c
@@ -334,11 +334,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
 	    vc->vc_cursor_type != par->p->cursor_shape ||
 	    par->cursor_state.mask == NULL ||
 	    par->cursor_reset) {
-		unsigned char *mask = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
+		unsigned char *mask = fbcon_cursor_glyph(&vc->vc_font, vc->vc_cursor_type);
 
 		if (!mask)
 			return;
-		fbcon_fill_cursor_mask(par, vc, mask);
 
 		kfree(par->cursor_state.mask);
 		par->cursor_state.mask = (const char *)mask;
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 615fa596b7cc..8581b7a9b3b7 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -444,44 +444,21 @@ static void fbcon_del_cursor_work(struct fb_info *info)
 	cancel_delayed_work_sync(&par->cursor_work);
 }
 
-void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask)
+unsigned char *fbcon_cursor_glyph(const struct vc_font *font, unsigned int cursor_type)
 {
-	static const unsigned int pattern = 0xffffffff;
-	unsigned int pitch = vc_font_pitch(&vc->vc_font);
-	unsigned int cur_height, size;
+	unsigned int height = font->height;
+	unsigned int cursor_size = CUR_SIZE(cursor_type);
+	unsigned char *glyph;
 
-	switch (CUR_SIZE(vc->vc_cursor_type)) {
-	case CUR_NONE:
-		cur_height = 0;
-		break;
-	case CUR_UNDERLINE:
-		if (vc->vc_font.height < 10)
-			cur_height = 1;
-		else
-			cur_height = 2;
-		break;
-	case CUR_LOWER_THIRD:
-		cur_height = vc->vc_font.height / 3;
-		break;
-	case CUR_LOWER_HALF:
-		cur_height = vc->vc_font.height / 2;
-		break;
-	case CUR_TWO_THIRDS:
-		cur_height = (vc->vc_font.height * 2) / 3;
-		break;
-	case CUR_BLOCK:
-	default:
-		cur_height = vc->vc_font.height;
-		break;
-	}
+	glyph = kmalloc_array(height, vc_font_pitch(font), GFP_ATOMIC);
+	if (!glyph)
+		return NULL;
 
-	size = (vc->vc_font.height - cur_height) * pitch;
-	while (size--)
-		*mask++ = (unsigned char)~pattern;
+	font_glyph_cursor(font->width, height,
+			  vc_cursor_start(height, cursor_size),
+			  vc_cursor_end(height, cursor_size), glyph);
 
-	size = cur_height * pitch;
-	while (size--)
-		*mask++ = (unsigned char)pattern;
+	return glyph;
 }
 
 #ifndef MODULE
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 407d207b14f1..054cf66b15fa 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -202,7 +202,7 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
 extern void fbcon_set_bitops_ur(struct fbcon_par *par);
 extern int  soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
 
-void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask);
+unsigned char *fbcon_cursor_glyph(const struct vc_font *font, unsigned int cursor_type);
 
 #define FBCON_ATTRIBUTE_UNDERLINE 1
 #define FBCON_ATTRIBUTE_REVERSE   2
diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c
index 33f02d579e02..9a9839631cc5 100644
--- a/drivers/video/fbdev/core/fbcon_ccw.c
+++ b/drivers/video/fbdev/core/fbcon_ccw.c
@@ -298,10 +298,9 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
 	    par->cursor_reset) {
 		unsigned char *tmp, *mask;
 
-		tmp = kmalloc_array(vc->vc_font.height, vc_font_pitch(&vc->vc_font), GFP_ATOMIC);
+		tmp = fbcon_cursor_glyph(&vc->vc_font, vc->vc_cursor_type);
 		if (!tmp)
 			return;
-		fbcon_fill_cursor_mask(par, vc, tmp);
 
 		mask = kmalloc_array(vc->vc_font.width, w, GFP_ATOMIC);
 		if (!mask) {
diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c
index bde820967eb9..4cb20337cf79 100644
--- a/drivers/video/fbdev/core/fbcon_cw.c
+++ b/drivers/video/fbdev/core/fbcon_cw.c
@@ -281,10 +281,9 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
 	    par->cursor_reset) {
 		unsigned char *tmp, *mask;
 
-		tmp = kmalloc_array(vc->vc_font.height, vc_font_pitch(&vc->vc_font), GFP_ATOMIC);
+		tmp = fbcon_cursor_glyph(&vc->vc_font, vc->vc_cursor_type);
 		if (!tmp)
 			return;
-		fbcon_fill_cursor_mask(par, vc, tmp);
 
 		mask = kmalloc_array(vc->vc_font.width, w, GFP_ATOMIC);
 		if (!mask) {
diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c
index eaf08999e249..ac22b9846b79 100644
--- a/drivers/video/fbdev/core/fbcon_ud.c
+++ b/drivers/video/fbdev/core/fbcon_ud.c
@@ -328,10 +328,9 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
 	    par->cursor_reset) {
 		unsigned char *tmp, *mask;
 
-		tmp = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
+		tmp = fbcon_cursor_glyph(&vc->vc_font, vc->vc_cursor_type);
 		if (!tmp)
 			return;
-		fbcon_fill_cursor_mask(par, vc, tmp);
 
 		mask = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
 		if (!mask) {
-- 
2.55.0


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

* Re: [PATCH v3 2/5] vgacon: Remove trailing whitespaces
  2026-09-28  8:55 ` [PATCH v3 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
@ 2026-09-28  8:59   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-28  8:59 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: dri-devel, linux-serial

> Fix coding style.
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260928085724.41660-1-tzimmermann@suse.de?part=2


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

* Re: [PATCH v3 1/5] vt: Add cursor-size helpers
  2026-09-28  8:55 ` [PATCH v3 1/5] vt: Add cursor-size helpers Thomas Zimmermann
@ 2026-09-28  9:07   ` Jani Nikula
  2026-09-28 11:45     ` Thomas Zimmermann
  2026-09-28  9:09   ` sashiko-bot
  2026-10-01  8:59   ` Greg KH
  2 siblings, 1 reply; 16+ messages in thread
From: Jani Nikula @ 2026-09-28  9:07 UTC (permalink / raw)
  To: Thomas Zimmermann, deller, gregkh, jirislaby, simona
  Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews,
	Thomas Zimmermann

On Mon, 28 Sep 2026, Thomas Zimmermann <tzimmermann@suse.de> wrote:
> Cursors in the VT subsystem are blocks within a character cell that are
> filled with the foreground color. The new helpers vc_cursor_start() and
> vc_cursor_end() return the scanlines in which the cursor block starts rsp.
> ends. This is compatible with VGA hardware.
>
> In terms of cursor design, the new cursor-size helpers follow established
> styles in fbcon. The only exception is in underline cursors for fonts with
> a size larger than 10. The underlining dash is now one pixel closer to
> the font-glyph data, so that the cursor looks less detached. This follows
> the style used by vgacon.
>
> Users control the cursor size with the vt module's parameter cur_default
> or with the ESC sequence \e[?Nc, where N is the cursor-size constant. In
> case of an invalid setting, the new helpers fall back to cur_default and
> then underline cursors; in this order.
>
> Similar code in vgacon and fbcon ignores the cursor's default size stored
> in vt.cur_default. The consoles default to full-block cursors, while vt
> defaults to underline cursors. VGA BIOSes also tend to use underline by.
> default. Upon initialization vt applies its default to the console, but
> each console might fall back to it own default. For example, running the
> ESC code from above with the invalid constant of 8 magically flips the
> cursor from underline to block size on vgacon. Another call with N set
> to 0 (i.e., default) magically flips it back to underlyine. Making
> underline the new default everywhere harmonizes vt, fbcon and most VGA
> BIOSes.
>
> v3:
> - mention user interfaces to control cursor size in commit message (GregKH)
> - elaborate defaults (GregKH)
> - move retry logic into helper
> - handle CUR_DEF
> v2:
> - export non-font interface for vgacon
> - avoid interference from concurrent user space (Sashiko)
> - fix function docs (Sashiko)
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> Reviewed-by: Helge Deller <deller@gmx.de>
> ---
>  drivers/tty/vt/vt.c            | 104 +++++++++++++++++++++++++++++++++
>  include/linux/console_struct.h |   7 +++
>  2 files changed, 111 insertions(+)
>
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 57edf37495a8..8141296ccad0 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c
> @@ -71,6 +71,7 @@
>   * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
>   */
>  
> +#include <linux/compiler.h>
>  #include <linux/module.h>
>  #include <linux/types.h>
>  #include <linux/sched/signal.h>
> @@ -264,6 +265,109 @@ unsigned int vc_font_size(const struct vc_font *font)
>  }
>  EXPORT_SYMBOL_GPL(vc_font_size);
>  
> +/*
> + * Cursors
> + */
> +
> +static unsigned int vc_cursor_size(unsigned int cursor_size)
> +{
> +	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
> +
> +retry:
> +	switch (cursor_size) {
> +	case CUR_NONE:
> +	case CUR_UNDERLINE:
> +	case CUR_LOWER_THIRD:
> +	case CUR_LOWER_HALF:
> +	case CUR_TWO_THIRDS:
> +	case CUR_BLOCK:
> +		return cursor_size;
> +	default:
> +		pr_warn_once("Unknown cursor %u\n", cursor_size);
> +		fallthrough;
> +	case CUR_DEF:
> +		/*
> +		 * Use user-given default size, or underline if
> +		 * the given default is invalid.
> +		 */
> +		if (cursor_size != cursor_default_size)
> +			cursor_size = cursor_default_size;
> +		else
> +			cursor_size = CUR_UNDERLINE;
> +		goto retry;

Complete bikeshed, but IMO goto for retries is ugly. It's fine for error
handling, but this could trivially be a loop.

BR,
Jani.

> +	}
> +}
> +
> +/**
> + * vc_cursor_start - Calculates the cursor's first scanline within a character cell
> + * @cell_height: The overall height of the character cell
> + * @cursor_size: The size constant of cursor pattern
> + *
> + * The parameter @cell_height is the height of the character cell as
> + * displayed by the console. The argument given in @cursor_size is one
> + * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
> + * For unknown values, the helper draws the default cursor or an underline
> + * dash.
> + *
> + * Returns:
> + * The index of the cursor's first scanline within the character cell
> + */
> +unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size)
> +{
> +	switch (vc_cursor_size(cursor_size)) {
> +	case CUR_NONE:
> +		return cell_height;
> +	case CUR_UNDERLINE:
> +	default:
> +		if (cell_height < 10)
> +			return cell_height - 1;
> +		else
> +			return cell_height - 3;
> +	case CUR_LOWER_THIRD:
> +		return cell_height - cell_height / 3;
> +	case CUR_LOWER_HALF:
> +		return cell_height - cell_height / 2;
> +	case CUR_TWO_THIRDS:
> +		return cell_height - (cell_height * 2) / 3;
> +	case CUR_BLOCK:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL_GPL(vc_cursor_start);
> +
> +/**
> + * vc_cursor_end - Calculates the first scanline after the cursor within a character cell
> + * @cell_height: The overall height of the character cell
> + * @cursor_size: The size constant of cursor pattern
> + *
> + * The parameter @cell_height is the height of the character cell as
> + * displayed by the console. The argument given in @cursor_size is one
> + * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
> + * For unknown values, the helper draws the default cursor or an underline
> + * dash.
> + *
> + * Returns:
> + * The index of the first scanline after the cursor within the character cell
> + */
> +unsigned int vc_cursor_end(unsigned int cell_height, unsigned int cursor_size)
> +{
> +	switch (vc_cursor_size(cursor_size)) {
> +	case CUR_UNDERLINE:
> +	default:
> +		if (cell_height < 10)
> +			return cell_height;
> +		else
> +			return cell_height - 1;
> +	case CUR_NONE:
> +	case CUR_LOWER_THIRD:
> +	case CUR_LOWER_HALF:
> +	case CUR_TWO_THIRDS:
> +	case CUR_BLOCK:
> +		return cell_height;
> +	}
> +}
> +EXPORT_SYMBOL_GPL(vc_cursor_end);
> +
>  /*
>   * /sys/class/tty/tty0/
>   *
> diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
> index fe915afdece5..1d37c7898ea0 100644
> --- a/include/linux/console_struct.h
> +++ b/include/linux/console_struct.h
> @@ -204,6 +204,10 @@ struct vc {
>  extern struct vc vc_cons [MAX_NR_CONSOLES];
>  extern void vc_SAK(struct work_struct *work);
>  
> +/*
> + * Cursors
> + */
> +
>  #define CUR_MAKE(size, change, set)	((size) | ((change) << 8) |	\
>  		((set) << 16))
>  #define CUR_SIZE(c)		 ((c) & 0x00000f)
> @@ -222,6 +226,9 @@ extern void vc_SAK(struct work_struct *work);
>  #define CUR_CHANGE(c)		 ((c) & 0x00ff00)
>  #define CUR_SET(c)		(((c) & 0xff0000) >> 8)
>  
> +unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size);
> +unsigned int vc_cursor_end(unsigned int cell_height, unsigned int cursor_size);
> +
>  bool con_is_visible(const struct vc_data *vc);
>  
>  #endif /* _LINUX_CONSOLE_STRUCT_H */

-- 
Jani Nikula, Intel

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

* Re: [PATCH v3 1/5] vt: Add cursor-size helpers
  2026-09-28  8:55 ` [PATCH v3 1/5] vt: Add cursor-size helpers Thomas Zimmermann
  2026-09-28  9:07   ` Jani Nikula
@ 2026-09-28  9:09   ` sashiko-bot
  2026-09-28 11:14     ` Thomas Zimmermann
  2026-10-01  8:59   ` Greg KH
  2 siblings, 1 reply; 16+ messages in thread
From: sashiko-bot @ 2026-09-28  9:09 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: linux-serial, dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] vt: unprivileged log injection via pr_warn_once in cursor sizing
--

commit 4874174842fbef217a6215957d5bf1bff1442b36
Author: Thomas Zimmermann <tzimmermann@suse.de>

vt: Add cursor-size helpers

The new helpers vc_cursor_start() and vc_cursor_end() return the scanlines
in which the cursor block starts respectively ends. Users can control the
cursor size with the vt module's parameter cur_default or with the ESC
sequence \e[?Nc. In case of an invalid setting, the new helpers fall back
to cur_default and then underline cursors.

> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 57edf37495a81..8141296ccad05 100644
> --- a/drivers/tty/vt/vt.c
> +++ b/drivers/tty/vt/vt.c

[ ... ]

> @@ -264,6 +265,109 @@ unsigned int vc_font_size(const struct vc_font *font)
>  }
>  EXPORT_SYMBOL_GPL(vc_font_size);
>  
> +/*
> + * Cursors
> + */
> +
> +static unsigned int vc_cursor_size(unsigned int cursor_size)
> +{
> +	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
> +
> +retry:
> +	switch (cursor_size) {
> +	case CUR_NONE:
> +	case CUR_UNDERLINE:
> +	case CUR_LOWER_THIRD:
> +	case CUR_LOWER_HALF:
> +	case CUR_TWO_THIRDS:
> +	case CUR_BLOCK:
> +		return cursor_size;
> +	default:
> +		pr_warn_once("Unknown cursor %u\n", cursor_size);
> +		fallthrough;

[Severity: Low]
Is it expected that an unprivileged user can trigger this warning message?

An unprivileged user can write a specific DEC escape sequence (e.g.,
\e[?103c) to the VT, which parses an unhandled size into
vc->vc_cursor_type via CSI_MAKE.

When the console driver later updates the cursor, vc_cursor_size() hits
the default case and emits this warning.

Since pr_warn_once() is rate-limited to once per boot, it cannot cause
a denial of service, but it still allows local unprivileged users with
write access to a VT to add a warning line to the kernel log.

> +	case CUR_DEF:
> +		/*
> +		 * Use user-given default size, or underline if
> +		 * the given default is invalid.
> +		 */
> +		if (cursor_size != cursor_default_size)
> +			cursor_size = cursor_default_size;
> +		else
> +			cursor_size = CUR_UNDERLINE;
> +		goto retry;
> +	}
> +}

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260928085724.41660-1-tzimmermann@suse.de?part=1

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

* Re: [PATCH v3 3/5] vgacon: Use vt_cursor_{start,end}()
  2026-09-28  8:55 ` [PATCH v3 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
@ 2026-09-28  9:09   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-28  9:09 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: linux-serial, dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] vgacon: CUR_DEF bypasses pre-VGA hardware cursor hiding workaround
--

commit d1a44aa19f5cbfffe54990d3cf6f73ab9b42b5ed
Author: Thomas Zimmermann <tzimmermann@suse.de>

vgacon: Use vt_cursor_{start,end}()
    
Replace vgacon's custom cursor metrics with the shared helpers
vc_cursor_start() and vc_font_cursor_end(). Note that the _end()
function returns the index of the scanline below the cursor, while
VGA hardware expects the cursor's final scanline. Hence vgacon
subtracts 1 from the end value.
    
The cursor shapes remain mostly unchanged, except that non-underline
cursors now also use the glyph's top-most and bottom-most scanline.
This follows the style used by fbcon.
    
v2:
- restore use of vc_cell_height (Sashiko)
    
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Helge Deller <deller@gmx.de>

> diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
> index 536e7fe4d1426..b1408bb5e2656 100644
> --- a/drivers/video/console/vgacon.c
> +++ b/drivers/video/console/vgacon.c
[ ... ]
> @@ -513,10 +514,11 @@ static void vgacon_cursor(struct vc_data *c, bool enable)
>  	vgacon_restore_screen(c);
>  
>  	c_height = c->vc_cell_height;
> +	c_size = CUR_SIZE(c->vc_cursor_type);
>  
>  	write_vga(14, (c->vc_pos - vga_vram_base) / 2);
>  
> -	if (!enable) {
> +	if (!enable || c_size == CUR_NONE) {

[Severity: Medium]
Does this check fail to intercept CUR_DEF if the default cursor is
configured as CUR_NONE?

If cur_default is set to CUR_NONE and an unprivileged user triggers a cursor
reset (\e[?0c), c_size will equal CUR_DEF. Since CUR_DEF does not equal
CUR_NONE, this bypasses the hardware-specific hide sequence below.

>  	        if (vga_video_type >= VIDEO_TYPE_VGAC)
>  			vgacon_set_cursor_size(31, 30);
>  		else
> @@ -524,33 +526,8 @@ static void vgacon_cursor(struct vc_data *c, bool enable)
>  		return;
>  	}
>  
[ ... ]
> -	default:
> -		vgacon_set_cursor_size(1, c_height);
> -		break;
> -	}
> +	vgacon_set_cursor_size(vc_cursor_start(c_height, c_size),
> +			       vc_cursor_end(c_height, c_size) - 1);

[Severity: Medium]
If c_size is CUR_DEF and the default cursor is CUR_NONE, could this
cause cursor wrapping on EGA/MDA hardware?

When vc_cursor_start() and vc_cursor_end() resolve the CUR_DEF to CUR_NONE
internally, they both return c_height. This results in
vgacon_set_cursor_size() being called with start = c_height and
end = c_height - 1.

Pre-VGA hardware (EGA/MDA/CGA 6845 CRTCs) do not support start > end for
hiding cursors, which leads to a massive wrapping block cursor instead of
hiding it.

>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260928085724.41660-1-tzimmermann@suse.de?part=3

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

* Re: [PATCH v3 4/5] lib/fonts: Add font_glyph_cursor() helper
  2026-09-28  8:55 ` [PATCH v3 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
@ 2026-09-28  9:16   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-28  9:16 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: linux-serial, dri-devel

> The new helper font_glyph_cursor() fills a glyph with a cursor pattern.
> As with the font_glyph_rotate_*() helpers, the caller has to provide the
> output memory.
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260928085724.41660-1-tzimmermann@suse.de?part=4


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

* Re: [PATCH v3 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph()
  2026-09-28  8:55 ` [PATCH v3 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
@ 2026-09-28  9:21   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-28  9:21 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: dri-devel, linux-serial

> The kernel's font library provides font_glyph_cursor() to create cursor
> glyphs. Replace fbcon's fbcon_fill_cursor_mask() with a new helper that
> uses font_glyph_cursor().
> 
> The cursor shapes remain mostly unchanged. The only exception is in
> underline cursors for fonts with a size larger than 10. The underlining
> dash is now one pixel closer to the font-glyph data, so that the cursor
> looks less detached. This follows the style used by vgacon.
> 
> v2:
> - adapt to new VT interface
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260928085724.41660-1-tzimmermann@suse.de?part=5


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

* Re: [PATCH v3 1/5] vt: Add cursor-size helpers
  2026-09-28  9:09   ` sashiko-bot
@ 2026-09-28 11:14     ` Thomas Zimmermann
  2026-09-28 11:41       ` Greg KH
  0 siblings, 1 reply; 16+ messages in thread
From: Thomas Zimmermann @ 2026-09-28 11:14 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: linux-serial, dri-devel



Am 28.09.26 um 11:09 schrieb sashiko-bot@kernel.org:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Low] vt: unprivileged log injection via pr_warn_once in cursor sizing

FYI this is by intention. In DRM land, we usually allow for warn_once to 
be triggered by user-space code.  If that's not an option for vt, let's 
use pr_debug() instead.

> --
>
> commit 4874174842fbef217a6215957d5bf1bff1442b36
> Author: Thomas Zimmermann <tzimmermann@suse.de>
>
> vt: Add cursor-size helpers
>
> The new helpers vc_cursor_start() and vc_cursor_end() return the scanlines
> in which the cursor block starts respectively ends. Users can control the
> cursor size with the vt module's parameter cur_default or with the ESC
> sequence \e[?Nc. In case of an invalid setting, the new helpers fall back
> to cur_default and then underline cursors.
>
>> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
>> index 57edf37495a81..8141296ccad05 100644
>> --- a/drivers/tty/vt/vt.c
>> +++ b/drivers/tty/vt/vt.c
> [ ... ]
>
>> @@ -264,6 +265,109 @@ unsigned int vc_font_size(const struct vc_font *font)
>>   }
>>   EXPORT_SYMBOL_GPL(vc_font_size);
>>   
>> +/*
>> + * Cursors
>> + */
>> +
>> +static unsigned int vc_cursor_size(unsigned int cursor_size)
>> +{
>> +	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
>> +
>> +retry:
>> +	switch (cursor_size) {
>> +	case CUR_NONE:
>> +	case CUR_UNDERLINE:
>> +	case CUR_LOWER_THIRD:
>> +	case CUR_LOWER_HALF:
>> +	case CUR_TWO_THIRDS:
>> +	case CUR_BLOCK:
>> +		return cursor_size;
>> +	default:
>> +		pr_warn_once("Unknown cursor %u\n", cursor_size);
>> +		fallthrough;
> [Severity: Low]
> Is it expected that an unprivileged user can trigger this warning message?
>
> An unprivileged user can write a specific DEC escape sequence (e.g.,
> \e[?103c) to the VT, which parses an unhandled size into
> vc->vc_cursor_type via CSI_MAKE.
>
> When the console driver later updates the cursor, vc_cursor_size() hits
> the default case and emits this warning.
>
> Since pr_warn_once() is rate-limited to once per boot, it cannot cause
> a denial of service, but it still allows local unprivileged users with
> write access to a VT to add a warning line to the kernel log.
>
>> +	case CUR_DEF:
>> +		/*
>> +		 * Use user-given default size, or underline if
>> +		 * the given default is invalid.
>> +		 */
>> +		if (cursor_size != cursor_default_size)
>> +			cursor_size = cursor_default_size;
>> +		else
>> +			cursor_size = CUR_UNDERLINE;
>> +		goto retry;
>> +	}
>> +}
> [ ... ]
>

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri, (HRB 36809, AG Nürnberg)



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

* Re: [PATCH v3 1/5] vt: Add cursor-size helpers
  2026-09-28 11:14     ` Thomas Zimmermann
@ 2026-09-28 11:41       ` Greg KH
  0 siblings, 0 replies; 16+ messages in thread
From: Greg KH @ 2026-09-28 11:41 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: sashiko-reviews, linux-serial, dri-devel

On Mon, Sep 28, 2026 at 01:14:20PM +0200, Thomas Zimmermann wrote:
> 
> 
> Am 28.09.26 um 11:09 schrieb sashiko-bot@kernel.org:
> > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> > - [Low] vt: unprivileged log injection via pr_warn_once in cursor sizing
> 
> FYI this is by intention. In DRM land, we usually allow for warn_once to be
> triggered by user-space code.  If that's not an option for vt, let's use
> pr_debug() instead.

_once() should be fine, no worries.

thanks,

greg k-h

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

* Re: [PATCH v3 1/5] vt: Add cursor-size helpers
  2026-09-28  9:07   ` Jani Nikula
@ 2026-09-28 11:45     ` Thomas Zimmermann
  0 siblings, 0 replies; 16+ messages in thread
From: Thomas Zimmermann @ 2026-09-28 11:45 UTC (permalink / raw)
  To: Jani Nikula, deller, gregkh, jirislaby, simona
  Cc: linux-fbdev, dri-devel, linux-serial, sashiko-reviews

Hi

Am 28.09.26 um 11:07 schrieb Jani Nikula:
> On Mon, 28 Sep 2026, Thomas Zimmermann <tzimmermann@suse.de> wrote:
>> Cursors in the VT subsystem are blocks within a character cell that are
>> filled with the foreground color. The new helpers vc_cursor_start() and
>> vc_cursor_end() return the scanlines in which the cursor block starts rsp.
>> ends. This is compatible with VGA hardware.
>>
>> In terms of cursor design, the new cursor-size helpers follow established
>> styles in fbcon. The only exception is in underline cursors for fonts with
>> a size larger than 10. The underlining dash is now one pixel closer to
>> the font-glyph data, so that the cursor looks less detached. This follows
>> the style used by vgacon.
>>
>> Users control the cursor size with the vt module's parameter cur_default
>> or with the ESC sequence \e[?Nc, where N is the cursor-size constant. In
>> case of an invalid setting, the new helpers fall back to cur_default and
>> then underline cursors; in this order.
>>
>> Similar code in vgacon and fbcon ignores the cursor's default size stored
>> in vt.cur_default. The consoles default to full-block cursors, while vt
>> defaults to underline cursors. VGA BIOSes also tend to use underline by.
>> default. Upon initialization vt applies its default to the console, but
>> each console might fall back to it own default. For example, running the
>> ESC code from above with the invalid constant of 8 magically flips the
>> cursor from underline to block size on vgacon. Another call with N set
>> to 0 (i.e., default) magically flips it back to underlyine. Making
>> underline the new default everywhere harmonizes vt, fbcon and most VGA
>> BIOSes.
>>
>> v3:
>> - mention user interfaces to control cursor size in commit message (GregKH)
>> - elaborate defaults (GregKH)
>> - move retry logic into helper
>> - handle CUR_DEF
>> v2:
>> - export non-font interface for vgacon
>> - avoid interference from concurrent user space (Sashiko)
>> - fix function docs (Sashiko)
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> Reviewed-by: Helge Deller <deller@gmx.de>
>> ---
>>   drivers/tty/vt/vt.c            | 104 +++++++++++++++++++++++++++++++++
>>   include/linux/console_struct.h |   7 +++
>>   2 files changed, 111 insertions(+)
>>
>> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
>> index 57edf37495a8..8141296ccad0 100644
>> --- a/drivers/tty/vt/vt.c
>> +++ b/drivers/tty/vt/vt.c
>> @@ -71,6 +71,7 @@
>>    * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
>>    */
>>   
>> +#include <linux/compiler.h>
>>   #include <linux/module.h>
>>   #include <linux/types.h>
>>   #include <linux/sched/signal.h>
>> @@ -264,6 +265,109 @@ unsigned int vc_font_size(const struct vc_font *font)
>>   }
>>   EXPORT_SYMBOL_GPL(vc_font_size);
>>   
>> +/*
>> + * Cursors
>> + */
>> +
>> +static unsigned int vc_cursor_size(unsigned int cursor_size)
>> +{
>> +	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
>> +
>> +retry:
>> +	switch (cursor_size) {
>> +	case CUR_NONE:
>> +	case CUR_UNDERLINE:
>> +	case CUR_LOWER_THIRD:
>> +	case CUR_LOWER_HALF:
>> +	case CUR_TWO_THIRDS:
>> +	case CUR_BLOCK:
>> +		return cursor_size;
>> +	default:
>> +		pr_warn_once("Unknown cursor %u\n", cursor_size);
>> +		fallthrough;
>> +	case CUR_DEF:
>> +		/*
>> +		 * Use user-given default size, or underline if
>> +		 * the given default is invalid.
>> +		 */
>> +		if (cursor_size != cursor_default_size)
>> +			cursor_size = cursor_default_size;
>> +		else
>> +			cursor_size = CUR_UNDERLINE;
>> +		goto retry;
> Complete bikeshed, but IMO goto for retries is ugly. It's fine for error
> handling, but this could trivially be a loop.

Ok. I have no strong opinion about it.

Best regards
Thomas

>
> BR,
> Jani.
>
>> +	}
>> +}
>> +
>> +/**
>> + * vc_cursor_start - Calculates the cursor's first scanline within a character cell
>> + * @cell_height: The overall height of the character cell
>> + * @cursor_size: The size constant of cursor pattern
>> + *
>> + * The parameter @cell_height is the height of the character cell as
>> + * displayed by the console. The argument given in @cursor_size is one
>> + * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
>> + * For unknown values, the helper draws the default cursor or an underline
>> + * dash.
>> + *
>> + * Returns:
>> + * The index of the cursor's first scanline within the character cell
>> + */
>> +unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size)
>> +{
>> +	switch (vc_cursor_size(cursor_size)) {
>> +	case CUR_NONE:
>> +		return cell_height;
>> +	case CUR_UNDERLINE:
>> +	default:
>> +		if (cell_height < 10)
>> +			return cell_height - 1;
>> +		else
>> +			return cell_height - 3;
>> +	case CUR_LOWER_THIRD:
>> +		return cell_height - cell_height / 3;
>> +	case CUR_LOWER_HALF:
>> +		return cell_height - cell_height / 2;
>> +	case CUR_TWO_THIRDS:
>> +		return cell_height - (cell_height * 2) / 3;
>> +	case CUR_BLOCK:
>> +		return 0;
>> +	}
>> +}
>> +EXPORT_SYMBOL_GPL(vc_cursor_start);
>> +
>> +/**
>> + * vc_cursor_end - Calculates the first scanline after the cursor within a character cell
>> + * @cell_height: The overall height of the character cell
>> + * @cursor_size: The size constant of cursor pattern
>> + *
>> + * The parameter @cell_height is the height of the character cell as
>> + * displayed by the console. The argument given in @cursor_size is one
>> + * of the CUR_ constants, as stored in struct @vc_data.vc_cursor_type.
>> + * For unknown values, the helper draws the default cursor or an underline
>> + * dash.
>> + *
>> + * Returns:
>> + * The index of the first scanline after the cursor within the character cell
>> + */
>> +unsigned int vc_cursor_end(unsigned int cell_height, unsigned int cursor_size)
>> +{
>> +	switch (vc_cursor_size(cursor_size)) {
>> +	case CUR_UNDERLINE:
>> +	default:
>> +		if (cell_height < 10)
>> +			return cell_height;
>> +		else
>> +			return cell_height - 1;
>> +	case CUR_NONE:
>> +	case CUR_LOWER_THIRD:
>> +	case CUR_LOWER_HALF:
>> +	case CUR_TWO_THIRDS:
>> +	case CUR_BLOCK:
>> +		return cell_height;
>> +	}
>> +}
>> +EXPORT_SYMBOL_GPL(vc_cursor_end);
>> +
>>   /*
>>    * /sys/class/tty/tty0/
>>    *
>> diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
>> index fe915afdece5..1d37c7898ea0 100644
>> --- a/include/linux/console_struct.h
>> +++ b/include/linux/console_struct.h
>> @@ -204,6 +204,10 @@ struct vc {
>>   extern struct vc vc_cons [MAX_NR_CONSOLES];
>>   extern void vc_SAK(struct work_struct *work);
>>   
>> +/*
>> + * Cursors
>> + */
>> +
>>   #define CUR_MAKE(size, change, set)	((size) | ((change) << 8) |	\
>>   		((set) << 16))
>>   #define CUR_SIZE(c)		 ((c) & 0x00000f)
>> @@ -222,6 +226,9 @@ extern void vc_SAK(struct work_struct *work);
>>   #define CUR_CHANGE(c)		 ((c) & 0x00ff00)
>>   #define CUR_SET(c)		(((c) & 0xff0000) >> 8)
>>   
>> +unsigned int vc_cursor_start(unsigned int cell_height, unsigned int cursor_size);
>> +unsigned int vc_cursor_end(unsigned int cell_height, unsigned int cursor_size);
>> +
>>   bool con_is_visible(const struct vc_data *vc);
>>   
>>   #endif /* _LINUX_CONSOLE_STRUCT_H */

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri, (HRB 36809, AG Nürnberg)



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

* Re: [PATCH v3 1/5] vt: Add cursor-size helpers
  2026-09-28  8:55 ` [PATCH v3 1/5] vt: Add cursor-size helpers Thomas Zimmermann
  2026-09-28  9:07   ` Jani Nikula
  2026-09-28  9:09   ` sashiko-bot
@ 2026-10-01  8:59   ` Greg KH
  2 siblings, 0 replies; 16+ messages in thread
From: Greg KH @ 2026-10-01  8:59 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: deller, jirislaby, simona, linux-fbdev, dri-devel, linux-serial,
	sashiko-reviews

On Mon, Sep 28, 2026 at 10:55:24AM +0200, Thomas Zimmermann wrote:
> Cursors in the VT subsystem are blocks within a character cell that are
> filled with the foreground color. The new helpers vc_cursor_start() and
> vc_cursor_end() return the scanlines in which the cursor block starts rsp.
> ends. This is compatible with VGA hardware.
> 
> In terms of cursor design, the new cursor-size helpers follow established
> styles in fbcon. The only exception is in underline cursors for fonts with
> a size larger than 10. The underlining dash is now one pixel closer to
> the font-glyph data, so that the cursor looks less detached. This follows
> the style used by vgacon.
> 
> Users control the cursor size with the vt module's parameter cur_default
> or with the ESC sequence \e[?Nc, where N is the cursor-size constant. In
> case of an invalid setting, the new helpers fall back to cur_default and
> then underline cursors; in this order.
> 
> Similar code in vgacon and fbcon ignores the cursor's default size stored
> in vt.cur_default. The consoles default to full-block cursors, while vt
> defaults to underline cursors. VGA BIOSes also tend to use underline by.
> default. Upon initialization vt applies its default to the console, but
> each console might fall back to it own default. For example, running the
> ESC code from above with the invalid constant of 8 magically flips the
> cursor from underline to block size on vgacon. Another call with N set
> to 0 (i.e., default) magically flips it back to underlyine. Making
> underline the new default everywhere harmonizes vt, fbcon and most VGA
> BIOSes.
> 
> v3:
> - mention user interfaces to control cursor size in commit message (GregKH)
> - elaborate defaults (GregKH)
> - move retry logic into helper
> - handle CUR_DEF
> v2:
> - export non-font interface for vgacon
> - avoid interference from concurrent user space (Sashiko)
> - fix function docs (Sashiko)
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> Reviewed-by: Helge Deller <deller@gmx.de>
> ---
>  drivers/tty/vt/vt.c            | 104 +++++++++++++++++++++++++++++++++
>  include/linux/console_struct.h |   7 +++
>  2 files changed, 111 insertions(+)

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

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

end of thread, other threads:[~2026-10-01  8:59 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-28  8:55 [PATCH v3 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
2026-09-28  8:55 ` [PATCH v3 1/5] vt: Add cursor-size helpers Thomas Zimmermann
2026-09-28  9:07   ` Jani Nikula
2026-09-28 11:45     ` Thomas Zimmermann
2026-09-28  9:09   ` sashiko-bot
2026-09-28 11:14     ` Thomas Zimmermann
2026-09-28 11:41       ` Greg KH
2026-10-01  8:59   ` Greg KH
2026-09-28  8:55 ` [PATCH v3 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
2026-09-28  8:59   ` sashiko-bot
2026-09-28  8:55 ` [PATCH v3 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
2026-09-28  9:09   ` sashiko-bot
2026-09-28  8:55 ` [PATCH v3 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
2026-09-28  9:16   ` sashiko-bot
2026-09-28  8:55 ` [PATCH v3 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
2026-09-28  9:21   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox