Linux Serial subsystem development
 help / color / mirror / Atom feed
* [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors
@ 2026-09-15 12:29 Thomas Zimmermann
  2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 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 implments 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.

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                  | 93 ++++++++++++++++++++++++++++
 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, 188 insertions(+), 77 deletions(-)
 create mode 100644 lib/fonts/font_cursor.c


base-commit: 2535e80aa0dd3d4269a43bf86a1686baddcf08d6
-- 
2.55.0


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

* [PATCH v2 1/5] vt: Add cursor-size helpers
  2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
  2026-09-15 12:40   ` sashiko-bot
  2026-09-23 12:57   ` Greg KH
  2026-09-15 12:29 ` [PATCH v2 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 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.

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. The new helper fall back to cur_default and
then underline cursors; in this order.

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            | 93 ++++++++++++++++++++++++++++++++++
 include/linux/console_struct.h |  7 +++
 2 files changed, 100 insertions(+)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 57edf37495a8..5d2583cd6e79 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,98 @@ unsigned int vc_font_size(const struct vc_font *font)
 }
 EXPORT_SYMBOL_GPL(vc_font_size);
 
+/*
+ * Cursors
+ */
+
+/**
+ * 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)
+{
+	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
+
+retry:
+	switch (cursor_size) {
+	case CUR_NONE:
+		return cell_height;
+	case CUR_UNDERLINE:
+		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;
+	default:
+		pr_warn_once("Unknown cursor %u\n", cursor_size);
+		if (cursor_size != cursor_default_size)
+			cursor_size = cursor_default_size;
+		else
+			cursor_size = CUR_UNDERLINE;
+		goto retry;
+	}
+}
+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)
+{
+	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
+
+retry:
+	switch (cursor_size) {
+	case CUR_UNDERLINE:
+		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;
+	default:
+		pr_warn_once("Unknown cursor %u\n", cursor_size);
+		if (cursor_size != cursor_default_size)
+			cursor_size = cursor_default_size;
+		else
+			cursor_size = CUR_UNDERLINE;
+		goto retry;
+	}
+}
+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] 13+ messages in thread

* [PATCH v2 2/5] vgacon: Remove trailing whitespaces
  2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
  2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
  2026-09-15 12:35   ` sashiko-bot
  2026-09-15 12:29 ` [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 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] 13+ messages in thread

* [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}()
  2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
  2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
  2026-09-15 12:29 ` [PATCH v2 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
  2026-09-15 12:39   ` sashiko-bot
  2026-09-15 12:29 ` [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
  2026-09-15 12:29 ` [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
  4 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 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] 13+ messages in thread

* [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper
  2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
                   ` (2 preceding siblings ...)
  2026-09-15 12:29 ` [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
  2026-09-15 12:40   ` sashiko-bot
  2026-09-15 12:29 ` [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
  4 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 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] 13+ messages in thread

* [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph()
  2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
                   ` (3 preceding siblings ...)
  2026-09-15 12:29 ` [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
@ 2026-09-15 12:29 ` Thomas Zimmermann
  2026-09-15 12:41   ` sashiko-bot
  4 siblings, 1 reply; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-15 12:29 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] 13+ messages in thread

* Re: [PATCH v2 2/5] vgacon: Remove trailing whitespaces
  2026-09-15 12:29 ` [PATCH v2 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
@ 2026-09-15 12:35   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-15 12:35 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/20260915123304.1027277-1-tzimmermann@suse.de?part=2


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

* Re: [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}()
  2026-09-15 12:29 ` [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
@ 2026-09-15 12:39   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-15 12:39 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: dri-devel, linux-serial

> 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>

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

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


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

* Re: [PATCH v2 1/5] vt: Add cursor-size helpers
  2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
@ 2026-09-15 12:40   ` sashiko-bot
  2026-09-23 12:57   ` Greg KH
  1 sibling, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-15 12:40 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: dri-devel, linux-serial

> 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.
> 
> 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. The new helper fall back to cur_default and
> then underline cursors; in this order.
> 
> 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>

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

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


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

* Re: [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper
  2026-09-15 12:29 ` [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
@ 2026-09-15 12:40   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-15 12:40 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: dri-devel, linux-serial

> 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/20260915123304.1027277-1-tzimmermann@suse.de?part=4


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

* Re: [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph()
  2026-09-15 12:29 ` [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
@ 2026-09-15 12:41   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-09-15 12:41 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: linux-serial, dri-devel

> 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/20260915123304.1027277-1-tzimmermann@suse.de?part=5


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

* Re: [PATCH v2 1/5] vt: Add cursor-size helpers
  2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
  2026-09-15 12:40   ` sashiko-bot
@ 2026-09-23 12:57   ` Greg KH
  2026-09-23 13:30     ` Thomas Zimmermann
  1 sibling, 1 reply; 13+ messages in thread
From: Greg KH @ 2026-09-23 12:57 UTC (permalink / raw)
  To: Thomas Zimmermann
  Cc: deller, jirislaby, simona, linux-fbdev, dri-devel, linux-serial,
	sashiko-reviews

On Tue, Sep 15, 2026 at 02:29:12PM +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.
> 
> 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. The new helper fall back to cur_default and
> then underline cursors; in this order.
> 
> 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            | 93 ++++++++++++++++++++++++++++++++++
>  include/linux/console_struct.h |  7 +++
>  2 files changed, 100 insertions(+)
> 
> diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
> index 57edf37495a8..5d2583cd6e79 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,98 @@ unsigned int vc_font_size(const struct vc_font *font)
>  }
>  EXPORT_SYMBOL_GPL(vc_font_size);
>  
> +/*
> + * Cursors
> + */
> +
> +/**
> + * 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)
> +{
> +	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
> +
> +retry:
> +	switch (cursor_size) {
> +	case CUR_NONE:
> +		return cell_height;
> +	case CUR_UNDERLINE:
> +		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;
> +	default:
> +		pr_warn_once("Unknown cursor %u\n", cursor_size);

Can userspace trigger this?  If not, who can?

> +		if (cursor_size != cursor_default_size)
> +			cursor_size = cursor_default_size;
> +		else
> +			cursor_size = CUR_UNDERLINE;

Why underline as a default?

thanks,

greg k-h

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

* Re: [PATCH v2 1/5] vt: Add cursor-size helpers
  2026-09-23 12:57   ` Greg KH
@ 2026-09-23 13:30     ` Thomas Zimmermann
  0 siblings, 0 replies; 13+ messages in thread
From: Thomas Zimmermann @ 2026-09-23 13:30 UTC (permalink / raw)
  To: Greg KH
  Cc: deller, jirislaby, simona, linux-fbdev, dri-devel, linux-serial,
	sashiko-reviews

Hi

Am 23.09.26 um 14:57 schrieb Greg KH:
[...]
>> + * 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)
>> +{
>> +	const unsigned int cursor_default_size = CUR_SIZE(READ_ONCE(cur_default));
>> +
>> +retry:
>> +	switch (cursor_size) {
>> +	case CUR_NONE:
>> +		return cell_height;
>> +	case CUR_UNDERLINE:
>> +		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;
>> +	default:
>> +		pr_warn_once("Unknown cursor %u\n", cursor_size);
> Can userspace trigger this?  If not, who can?

Yes. There's the "vt.cur_default" parameter on the kernel's command line 
[1], and apparently there's some escape sequence. [2]  The cursor size 
is the lowest 4 bits of that value, while

[1] https://elixir.bootlin.com/linux/v7.2.6/source/drivers/tty/vt/vt.c#L167
[2] https://elixir.bootlin.com/linux/v7.2.6/source/drivers/tty/vt/vt.c#L2523

Apart from that, I just noticed that this switch should certainly handle 
CUR_DEF without printing a warning.


>
>> +		if (cursor_size != cursor_default_size)
>> +			cursor_size = cursor_default_size;
>> +		else
>> +			cursor_size = CUR_UNDERLINE;
> Why underline as a default?

This has been the default all along. It is the default value of the 
cur_default parameter and picked up by vt when starting up a console. 
[3] VGA BIOSes tend to default to underline as well AFAICT. Only the old 
cursor code in fbcon falls back to full-size blocks if nothing else 
works. Using underline harmonizes behavior across components.

[3] https://elixir.bootlin.com/linux/v7.2.6/source/drivers/tty/vt/vt.c#L2297

Best regards
Thomas

>
> thanks,
>
> greg k-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] 13+ messages in thread

end of thread, other threads:[~2026-09-23 13:30 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-15 12:29 [PATCH v2 0/5] fbcon,vgacon,vt: Share helpers for text cursors Thomas Zimmermann
2026-09-15 12:29 ` [PATCH v2 1/5] vt: Add cursor-size helpers Thomas Zimmermann
2026-09-15 12:40   ` sashiko-bot
2026-09-23 12:57   ` Greg KH
2026-09-23 13:30     ` Thomas Zimmermann
2026-09-15 12:29 ` [PATCH v2 2/5] vgacon: Remove trailing whitespaces Thomas Zimmermann
2026-09-15 12:35   ` sashiko-bot
2026-09-15 12:29 ` [PATCH v2 3/5] vgacon: Use vt_cursor_{start,end}() Thomas Zimmermann
2026-09-15 12:39   ` sashiko-bot
2026-09-15 12:29 ` [PATCH v2 4/5] lib/fonts: Add font_glyph_cursor() helper Thomas Zimmermann
2026-09-15 12:40   ` sashiko-bot
2026-09-15 12:29 ` [PATCH v2 5/5] fbcon: Replace fbcon_fill_cursor_mask() with fbcon_cursor_glyph() Thomas Zimmermann
2026-09-15 12:41   ` sashiko-bot

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