Message ID | 20231010073855.26319-3-frankja@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | s390x: Improve console handling | expand |
Quoting Janosch Frank (2023-10-10 09:38:54) [...] > diff --git a/lib/s390x/sclp-console.c b/lib/s390x/sclp-console.c > index 19c74e46..313be1e4 100644 > --- a/lib/s390x/sclp-console.c > +++ b/lib/s390x/sclp-console.c [...] > +static bool lpar_ascii_compat; This only toggles adding \r. So why not name it accordingly? Something like: ascii_line_end_dos or ascii_add_cr_line_end > static char lm_buff[120]; > static unsigned char lm_buff_off; > static struct spinlock lm_buff_lock; > @@ -97,14 +100,27 @@ static void sclp_print_ascii(const char *str) > { > int len = strlen(str); > WriteEventData *sccb = (void *)_sccb; > + char *str_dest = (char *)&sccb->msg; > + int i = 0; > > sclp_mark_busy(); > memset(sccb, 0, sizeof(*sccb)); > + > + for (; i < len; i++) { > + *str_dest = str[i]; > + str_dest++; > + /* Add a \r to the \n for HMC ASCII console */ > + if (str[i] == '\n' && lpar_ascii_compat) { > + *str_dest = '\r'; > + str_dest++; > + } > + } Please don't hide the check inside the loop. Do: if (lpar_ascii_compat) // your loop else memcpy() Also, please add protection against overflowing sccb->msg (max 4088 bytes if I looked it up right). > + len = (uintptr_t)str_dest - (uintptr_t)&sccb->msg; And when you do the above, it should be easy to get rid of pointer subtraction. [...] > void sclp_console_setup(void) > { > + lpar_ascii_compat = detect_host_early() == HOST_IS_LPAR; > + > /* We send ASCII and line mode. */ > sclp_write_event_mask(0, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); > + /* Hard terminal reset to clear screen for HMC ASCII console */ > + if (lpar_ascii_compat) > + sclp_print_ascii("\ec"); I have in the past cursed programs which clear the screen, but I can see the advantage here. How do others feel about this?
On 10/10/23 10:35, Nico Boehr wrote: > Quoting Janosch Frank (2023-10-10 09:38:54) > [...] >> diff --git a/lib/s390x/sclp-console.c b/lib/s390x/sclp-console.c >> index 19c74e46..313be1e4 100644 >> --- a/lib/s390x/sclp-console.c >> +++ b/lib/s390x/sclp-console.c > [...] >> +static bool lpar_ascii_compat; > > This only toggles adding \r. So why not name it accordingly? Because it also toggles clearing the screen > Something like: > ascii_line_end_dos > or > ascii_add_cr_line_end > >> static char lm_buff[120]; >> static unsigned char lm_buff_off; >> static struct spinlock lm_buff_lock; >> @@ -97,14 +100,27 @@ static void sclp_print_ascii(const char *str) >> { >> int len = strlen(str); >> WriteEventData *sccb = (void *)_sccb; >> + char *str_dest = (char *)&sccb->msg; >> + int i = 0; >> >> sclp_mark_busy(); >> memset(sccb, 0, sizeof(*sccb)); >> + >> + for (; i < len; i++) { >> + *str_dest = str[i]; >> + str_dest++; >> + /* Add a \r to the \n for HMC ASCII console */ >> + if (str[i] == '\n' && lpar_ascii_compat) { >> + *str_dest = '\r'; >> + str_dest++; >> + } >> + } > > Please don't hide the check inside the loop. > Do: > if (lpar_ascii_compat) > // your loop > else > memcpy() I'd rather have a loop than to nest it inside an if. > > Also, please add protection against overflowing sccb->msg (max 4088 bytes > if I looked it up right). I considered this but we already have a 2k length check before that and I'd like to see someone print ~2k in a single call. The question is if we want the complexity for something that we'll very likely never hit. > >> + len = (uintptr_t)str_dest - (uintptr_t)&sccb->msg; > > And when you do the above, it should be easy to get rid of pointer > subtraction. > > [...] >> void sclp_console_setup(void) >> { >> + lpar_ascii_compat = detect_host_early() == HOST_IS_LPAR; >> + >> /* We send ASCII and line mode. */ >> sclp_write_event_mask(0, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); >> + /* Hard terminal reset to clear screen for HMC ASCII console */ >> + if (lpar_ascii_compat) >> + sclp_print_ascii("\ec"); > > I have in the past cursed programs which clear the screen, but I can see > the advantage here. How do others feel about this?
Quoting Janosch Frank (2023-10-10 10:57:24) > On 10/10/23 10:35, Nico Boehr wrote: > > Quoting Janosch Frank (2023-10-10 09:38:54) > > [...] > >> diff --git a/lib/s390x/sclp-console.c b/lib/s390x/sclp-console.c > >> index 19c74e46..313be1e4 100644 > >> --- a/lib/s390x/sclp-console.c > >> +++ b/lib/s390x/sclp-console.c > > [...] > >> +static bool lpar_ascii_compat; > > > > This only toggles adding \r. So why not name it accordingly? > > Because it also toggles clearing the screen OK [...] > >> @@ -97,14 +100,27 @@ static void sclp_print_ascii(const char *str) > >> { > >> int len = strlen(str); > >> WriteEventData *sccb = (void *)_sccb; > >> + char *str_dest = (char *)&sccb->msg; > >> + int i = 0; > >> > >> sclp_mark_busy(); > >> memset(sccb, 0, sizeof(*sccb)); > >> + > >> + for (; i < len; i++) { > >> + *str_dest = str[i]; > >> + str_dest++; > >> + /* Add a \r to the \n for HMC ASCII console */ > >> + if (str[i] == '\n' && lpar_ascii_compat) { > >> + *str_dest = '\r'; > >> + str_dest++; > >> + } > >> + } > > > > Please don't hide the check inside the loop. > > Do: > > if (lpar_ascii_compat) > > // your loop > > else > > memcpy() > > > I'd rather have a loop than to nest it inside an if. I disagree, but it's not worth discussing too much over this. > > Also, please add protection against overflowing sccb->msg (max 4088 bytes > > if I looked it up right). > > I considered this but we already have a 2k length check before that ...which is not sufficient... > and I'd like to see someone print ~2k in a single call. > > The question is if we want the complexity for something that we'll very > likely never hit. IMO we want it since it can lead to random memory corruption which can be very hard to debug. And I don't think it's complex since in the simplest case you could just go with a strnlen() here. Better just truncate the string than to corrupt random memory.
diff --git a/lib/s390x/sclp-console.c b/lib/s390x/sclp-console.c index 19c74e46..313be1e4 100644 --- a/lib/s390x/sclp-console.c +++ b/lib/s390x/sclp-console.c @@ -11,6 +11,7 @@ #include <asm/arch_def.h> #include <asm/io.h> #include <asm/spinlock.h> +#include "hardware.h" #include "sclp.h" /* @@ -85,6 +86,8 @@ static uint8_t _ascebc[256] = { 0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF }; +static bool lpar_ascii_compat; + static char lm_buff[120]; static unsigned char lm_buff_off; static struct spinlock lm_buff_lock; @@ -97,14 +100,27 @@ static void sclp_print_ascii(const char *str) { int len = strlen(str); WriteEventData *sccb = (void *)_sccb; + char *str_dest = (char *)&sccb->msg; + int i = 0; sclp_mark_busy(); memset(sccb, 0, sizeof(*sccb)); + + for (; i < len; i++) { + *str_dest = str[i]; + str_dest++; + /* Add a \r to the \n for HMC ASCII console */ + if (str[i] == '\n' && lpar_ascii_compat) { + *str_dest = '\r'; + str_dest++; + } + } + + len = (uintptr_t)str_dest - (uintptr_t)&sccb->msg; sccb->h.length = offsetof(WriteEventData, msg) + len; sccb->h.function_code = SCLP_FC_NORMAL_WRITE; sccb->ebh.length = sizeof(EventBufferHeader) + len; sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; - memcpy(&sccb->msg, str, len); sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); } @@ -218,8 +234,13 @@ static void sclp_console_disable_read(void) void sclp_console_setup(void) { + lpar_ascii_compat = detect_host_early() == HOST_IS_LPAR; + /* We send ASCII and line mode. */ sclp_write_event_mask(0, SCLP_EVENT_MASK_MSG_ASCII | SCLP_EVENT_MASK_MSG); + /* Hard terminal reset to clear screen for HMC ASCII console */ + if (lpar_ascii_compat) + sclp_print_ascii("\ec"); } void sclp_print(const char *str)
Without the \r the output of the HMC ASCII console takes a lot of additional effort to read in comparison to the line mode console. Additionally we add a console clear for the HMC ASCII console so that old messages from a previously running operating system are not polluting the console. Signed-off-by: Janosch Frank <frankja@linux.ibm.com> --- lib/s390x/sclp-console.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)