Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Mar 2018 07:55:30 +0000 (UTC)
From:      Eitan Adler <eadler@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r330918 - stable/11/sys/dev/syscons
Message-ID:  <201803140755.w2E7tUKB077717@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: eadler
Date: Wed Mar 14 07:55:29 2018
New Revision: 330918
URL: https://svnweb.freebsd.org/changeset/base/330918

Log:
  MFC r315984:
  
  Restore switching to a separate kernel terminal "input" state and extend
  it to a separate state for each CPU.
  
  Terminal "input" is user or kernel output.  Its state includes the current
  parser state for escape sequences and multi-byte characters, and some
  results of previous parsing (mainly attributes), and in teken the cursor
  position, but not completed output.  This state must be switched for kernel
  output since the kernel can preempt anything, including itself, and this
  must not affect the preempted state more than necessary.  Since vty0 is
  shared, it is necessary to affect the frame buffer and cursor position and
  history, but escape sequences must not be affected and attributes for
  further output must not be affected.
  
  This used to work.  The syscons terminal state contained mainly the parser
  state for escape sequences and attributes, but not the cursor position,
  and was switched.  This was first broken by SMP and/or preemptive kernels.
  Then there should really be a separate state for each thread, and one more
  for ddb, or locking to prevent preemption.  Serialization of printf() helps.
  But it is arcane that full syscons escape sequences mostly work in kernel
  printf(), and I have never seen them used except by me to test this fix.
  They worked perfectly except for the races, since "input" from the kernel
  was not special in any way.
  
  This was broken to use teken.  The general switch was removed, and the
  kernel normal attribute was switched specially.  The kernel reverse
  attribute (config option SC_CONS_REVERSE_ATTR) became unused, and is
  still unusable because teken doesn't support default reverse attributes
  (it used to only be used via the ANSI escape sequence to set reverse
  video).
  
  The only new difficulty for using teken seems to be that the cursor
  position is in the "input" state, so it must be updated in the active
  input state for each half of the switch.  Do this to complete the
  restoration.
  
  The per-CPU state is mainly to make per-CPU coloring work cleanly, at
  a cost of some space.  Each CPU gets its own full set of attribute
  (not just the current attribute) maintained in the usual way.  This
  also reduces races from unserialized printf()s.  However, this gives
  races for serialized printf()s that otherwise have none.  Nothing
  prevents the CPU doing the a printf() changing in the middle of an
  escape sequence.

Modified:
  stable/11/sys/dev/syscons/scterm-teken.c
  stable/11/sys/dev/syscons/syscons.c
  stable/11/sys/dev/syscons/syscons.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/syscons/scterm-teken.c
==============================================================================
--- stable/11/sys/dev/syscons/scterm-teken.c	Wed Mar 14 07:51:33 2018	(r330917)
+++ stable/11/sys/dev/syscons/scterm-teken.c	Wed Mar 14 07:55:29 2018	(r330918)
@@ -164,23 +164,12 @@ scteken_term(scr_stat *scp, void **softc)
 }
 
 static void
-scteken_puts(scr_stat *scp, u_char *buf, int len, int kernel)
+scteken_puts(scr_stat *scp, u_char *buf, int len)
 {
 	teken_stat *ts = scp->ts;
-	teken_attr_t backup, kattr;
 
 	scp->sc->write_in_progress++;
-	if (kernel) {
-		/* Use special colors for kernel messages. */
-		backup = *teken_get_curattr(&ts->ts_teken);
-		scteken_sc_to_te_attr(sc_kattr(), &kattr);
-		teken_set_curattr(&ts->ts_teken, &kattr);
-		teken_input(&ts->ts_teken, buf, len);
-		teken_set_curattr(&ts->ts_teken, &backup);
-	} else {
-		/* Print user messages with regular colors. */
-		teken_input(&ts->ts_teken, buf, len);
-	}
+	teken_input(&ts->ts_teken, buf, len);
 	scp->sc->write_in_progress--;
 }
 

Modified: stable/11/sys/dev/syscons/syscons.c
==============================================================================
--- stable/11/sys/dev/syscons/syscons.c	Wed Mar 14 07:51:33 2018	(r330917)
+++ stable/11/sys/dev/syscons/syscons.c	Wed Mar 14 07:55:29 2018	(r330918)
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/reboot.h>
 #include <sys/serial.h>
 #include <sys/signalvar.h>
+#include <sys/smp.h>
 #include <sys/sysctl.h>
 #include <sys/tty.h>
 #include <sys/power.h>
@@ -99,6 +100,7 @@ static	int		sc_console_unit = -1;
 static	int		sc_saver_keyb_only = 1;
 static  scr_stat    	*sc_console;
 static  struct consdev	*sc_consptr;
+static	void		*kernel_console_ts[MAXCPU];
 static	scr_stat	main_console;
 static	struct tty 	*main_devs[MAXCONS];
 
@@ -183,7 +185,7 @@ static void scshutdown(void *, int);
 static void scsuspend(void *);
 static void scresume(void *);
 static u_int scgetc(sc_softc_t *sc, u_int flags, struct sc_cnstate *sp);
-static void sc_puts(scr_stat *scp, u_char *buf, int len, int kernel);
+static void sc_puts(scr_stat *scp, u_char *buf, int len);
 #define SCGETC_CN	1
 #define SCGETC_NONBLOCK	2
 static void sccnupdate(scr_stat *scp);
@@ -220,6 +222,7 @@ static void update_font(scr_stat *);
 static int save_kbd_state(scr_stat *scp);
 static int update_kbd_state(scr_stat *scp, int state, int mask);
 static int update_kbd_leds(scr_stat *scp, int which);
+static int sc_kattr(void);
 static timeout_t blink_screen;
 static struct tty *sc_alloc_tty(int, int);
 
@@ -397,7 +400,7 @@ sctty_outwakeup(struct tty *tp)
 	if (len == 0)
 	    break;
 	SC_VIDEO_LOCK(scp->sc);
-	sc_puts(scp, buf, len, 0);
+	sc_puts(scp, buf, len);
 	SC_VIDEO_UNLOCK(scp->sc);
     }
 }
@@ -544,7 +547,8 @@ sc_attach_unit(int unit, int flags)
     sc_softc_t *sc;
     scr_stat *scp;
     struct cdev *dev;
-    int vc;
+    void *oldts, *ts;
+    int i, vc;
 
     if (!vty_enabled(VTY_SC))
         return ENXIO;
@@ -559,8 +563,27 @@ sc_attach_unit(int unit, int flags)
 	/* assert(sc_console != NULL) */
 	flags |= SC_KERNEL_CONSOLE;
 	scmeminit(NULL);
+
+	scinit(unit, flags);
+
+	if (sc_console->tsw->te_size > 0) {
+	    /* assert(sc_console->ts != NULL); */
+	    oldts = sc_console->ts;
+	    for (i = 0; i <= mp_maxid; i++) {
+		ts = malloc(sc_console->tsw->te_size, M_DEVBUF, M_WAITOK);
+		bcopy(oldts, ts, sc_console->tsw->te_size);
+		sc_console->ts = ts;
+		(*sc_console->tsw->te_default_attr)(sc_console, sc_kattrtab[i],
+						    SC_KERNEL_CONS_REV_ATTR);
+		kernel_console_ts[i] = ts;
+	    }
+	    sc_console->ts = oldts;
+    	    (*sc_console->tsw->te_default_attr)(sc_console, SC_NORM_ATTR,
+						SC_NORM_REV_ATTR);
+	}
+    } else {
+	scinit(unit, flags);
     }
-    scinit(unit, flags);
 
     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
     sc->config = flags;
@@ -1888,6 +1911,7 @@ sc_cnputc(struct consdev *cd, int c)
     struct sc_cnstate st;
     u_char buf[1];
     scr_stat *scp = sc_console;
+    void *oldts, *ts;
 #ifndef SC_NO_HISTORY
 #if 0
     struct tty *tp;
@@ -1951,7 +1975,16 @@ sc_cnputc(struct consdev *cd, int c)
 	if (atomic_load_acq_int(&sc_cnputc_loghead) - sc_cnputc_logtail >=
 	    sizeof(sc_cnputc_log))
 	    continue;
-	sc_puts(scp, buf, 1, 1);
+	/* Console output has a per-CPU "input" state.  Switch for it. */
+	oldts = scp->ts;
+	ts = kernel_console_ts[PCPU_GET(cpuid)];
+	if (ts != NULL) {
+	    scp->ts = ts;
+	    (*scp->tsw->te_set_cursor)(scp, scp->xpos, scp->ypos);
+	}
+	sc_puts(scp, buf, 1);
+	scp->ts = oldts;
+	(*scp->tsw->te_set_cursor)(scp, scp->xpos, scp->ypos);
     }
 
     s = spltty();	/* block sckbdevent and scrn_timer */
@@ -2901,7 +2934,7 @@ exchange_scr(sc_softc_t *sc)
 }
 
 static void
-sc_puts(scr_stat *scp, u_char *buf, int len, int kernel)
+sc_puts(scr_stat *scp, u_char *buf, int len)
 {
 #ifdef DEV_SPLASH
     /* make screensaver happy */
@@ -2910,7 +2943,7 @@ sc_puts(scr_stat *scp, u_char *buf, int len, int kerne
 #endif
 
     if (scp->tsw)
-	(*scp->tsw->te_puts)(scp, buf, len, kernel);
+	(*scp->tsw->te_puts)(scp, buf, len);
     if (scp->sc->delayed_next_scr)
 	sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1);
 }
@@ -3150,7 +3183,8 @@ scinit(int unit, int flags)
 			(void *)sc_buffer, FALSE);
 	    if (sc_init_emulator(scp, SC_DFLT_TERM))
 		sc_init_emulator(scp, "*");
-	    (*scp->tsw->te_default_attr)(scp, SC_NORM_ATTR, SC_NORM_REV_ATTR);
+	    (*scp->tsw->te_default_attr)(scp, SC_KERNEL_CONS_ATTR,
+					 SC_KERNEL_CONS_REV_ATTR);
 	} else {
 	    /* assert(sc_malloc) */
 	    sc->dev = malloc(sizeof(struct tty *)*sc->vtys, M_DEVBUF,
@@ -4086,9 +4120,11 @@ sc_bell(scr_stat *scp, int pitch, int duration)
     }
 }
 
-int
+static int
 sc_kattr(void)
 {
+    if (sc_console == NULL)
+	return (SC_KERNEL_CONS_ATTR);
     return (sc_kattrtab[PCPU_GET(cpuid) % nitems(sc_kattrtab)]);
 }
 

Modified: stable/11/sys/dev/syscons/syscons.h
==============================================================================
--- stable/11/sys/dev/syscons/syscons.h	Wed Mar 14 07:51:33 2018	(r330917)
+++ stable/11/sys/dev/syscons/syscons.h	Wed Mar 14 07:55:29 2018	(r330918)
@@ -391,7 +391,7 @@ typedef int	sc_term_init_t(scr_stat *scp, void **tcp, 
 #define SC_TE_COLD_INIT	0
 #define SC_TE_WARM_INIT	1
 typedef int	sc_term_term_t(scr_stat *scp, void **tcp);
-typedef void	sc_term_puts_t(scr_stat *scp, u_char *buf, int len, int kernel);
+typedef void	sc_term_puts_t(scr_stat *scp, u_char *buf, int len);
 typedef int	sc_term_ioctl_t(scr_stat *scp, struct tty *tp, u_long cmd,
 				caddr_t data, struct thread *td);
 typedef int	sc_term_reset_t(scr_stat *scp, int code);
@@ -593,7 +593,6 @@ void		sc_paste(scr_stat *scp, const u_char *p, int cou
 void		sc_respond(scr_stat *scp, const u_char *p,
 			   int count, int wakeup);
 void		sc_bell(scr_stat *scp, int pitch, int duration);
-int		sc_kattr(void);
 
 /* schistory.c */
 #ifndef SC_NO_HISTORY



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803140755.w2E7tUKB077717>