diff mbox

[3/3] ARM: early_printk: use printascii() rather than printch()

Message ID 20171002020618.23924-4-nicolas.pitre@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Nicolas Pitre Oct. 2, 2017, 2:06 a.m. UTC
With printch() the console messages are sent out one character at a time
which is agonizingly slow especially with semihosting as the whole trap
intercept, remote byte access, and system resume danse is performed for
every single character across a relatively slow remote debug connection.
Let's use printascii() to send a whole string at once. This is also going
to be more efficient, albeit to a quite lesser extent, with serial ports
as well.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/kernel/early_printk.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

Comments

Uwe Kleine-König Oct. 2, 2017, 5:20 a.m. UTC | #1
Hello Nicolas,

On Sun, Oct 01, 2017 at 10:06:18PM -0400, Nicolas Pitre wrote:
> With printch() the console messages are sent out one character at a time
> which is agonizingly slow especially with semihosting as the whole trap
> intercept, remote byte access, and system resume danse is performed for

s/danse/dance/ ?

> every single character across a relatively slow remote debug connection.
> Let's use printascii() to send a whole string at once. This is also going
> to be more efficient, albeit to a quite lesser extent, with serial ports
> as well.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
> ---
>  arch/arm/kernel/early_printk.c | 16 ++++++++++------
>  1 file changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm/kernel/early_printk.c b/arch/arm/kernel/early_printk.c
> index 4307653696..9257736ec9 100644
> --- a/arch/arm/kernel/early_printk.c
> +++ b/arch/arm/kernel/early_printk.c
> @@ -11,16 +11,20 @@
>  #include <linux/kernel.h>
>  #include <linux/console.h>
>  #include <linux/init.h>
> +#include <linux/string.h>
>  
> -extern void printch(int);
> +extern void printascii(const char *);
>  
>  static void early_write(const char *s, unsigned n)
>  {
> -	while (n-- > 0) {
> -		if (*s == '\n')
> -			printch('\r');
> -		printch(*s);
> -		s++;
> +	char buf[128];
> +	while (n) {
> +		unsigned l = min(n, sizeof(buf)-1);
> +		memcpy(buf, s, l);
> +		buf[l] = 0;
> +		s += l;
> +		n -= l;
> +		printascii(buf);

I wonder if it is a usual case that n < 128 and s[n] == '\0'. If so this
could be tested for and then the memcpy could be dropped.
(The downside of course is that s[n] might also be something completely
different?)

Best regards
Uwe
Nicolas Pitre Oct. 2, 2017, 2:09 p.m. UTC | #2
On Mon, 2 Oct 2017, Uwe Kleine-König wrote:

> Hello Nicolas,
> 
> On Sun, Oct 01, 2017 at 10:06:18PM -0400, Nicolas Pitre wrote:
> > With printch() the console messages are sent out one character at a time
> > which is agonizingly slow especially with semihosting as the whole trap
> > intercept, remote byte access, and system resume danse is performed for
> 
> s/danse/dance/ ?
> 
> > every single character across a relatively slow remote debug connection.
> > Let's use printascii() to send a whole string at once. This is also going
> > to be more efficient, albeit to a quite lesser extent, with serial ports
> > as well.
> > 
> > Signed-off-by: Nicolas Pitre <nico@linaro.org>
> > ---
> >  arch/arm/kernel/early_printk.c | 16 ++++++++++------
> >  1 file changed, 10 insertions(+), 6 deletions(-)
> > 
> > diff --git a/arch/arm/kernel/early_printk.c b/arch/arm/kernel/early_printk.c
> > index 4307653696..9257736ec9 100644
> > --- a/arch/arm/kernel/early_printk.c
> > +++ b/arch/arm/kernel/early_printk.c
> > @@ -11,16 +11,20 @@
> >  #include <linux/kernel.h>
> >  #include <linux/console.h>
> >  #include <linux/init.h>
> > +#include <linux/string.h>
> >  
> > -extern void printch(int);
> > +extern void printascii(const char *);
> >  
> >  static void early_write(const char *s, unsigned n)
> >  {
> > -	while (n-- > 0) {
> > -		if (*s == '\n')
> > -			printch('\r');
> > -		printch(*s);
> > -		s++;
> > +	char buf[128];
> > +	while (n) {
> > +		unsigned l = min(n, sizeof(buf)-1);
> > +		memcpy(buf, s, l);
> > +		buf[l] = 0;
> > +		s += l;
> > +		n -= l;
> > +		printascii(buf);
> 
> I wonder if it is a usual case that n < 128 and s[n] == '\0'. If so this
> could be tested for and then the memcpy could be dropped.

I did try it. Unfortunately the passed string is not null terminated.


Nicolas
Chris Brandt Oct. 31, 2017, 11:28 a.m. UTC | #3
On Sunday, October 01, 2017 1, Nicolas Pitre wrote:
> With printch() the console messages are sent out one character at a time
> which is agonizingly slow especially with semihosting as the whole trap
> intercept, remote byte access, and system resume danse is performed for
> every single character across a relatively slow remote debug connection.
> Let's use printascii() to send a whole string at once. This is also going
> to be more efficient, albeit to a quite lesser extent, with serial ports
> as well.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
> ---
>  arch/arm/kernel/early_printk.c | 16 ++++++++++------
>  1 file changed, 10 insertions(+), 6 deletions(-)

Now that this patch has hit -next, I'm noticing an issue with it.

There are no carriage returns, just line feeds, which makes for a very 
ugly display.


For example:

Booting Linux...
[    0.000000] Booting Linux on physical CPU 0x0
                                                [    0.000000] Linux version 4.14.0-rc5-00014-g5689707d65e6 (chris@ubuntu) (gcc version 5.4.1 20161213 (Linaro GCC 5.4-2017.01)) #735 Mon Oct 30 12:59:37 EST 2017
                                                                                          [    0.000000] CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=58c53c7d
                                                [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
               [    0.000000] OF: fdt: Machine model: RSKRZA1
                                                             [    0.000000] debug: ignoring loglevel setting.
                                                                                                             [    0.000000] bootconsole [earlycon0] enabled
                                   [    0.000000] Memory policy: Data cache writeback
                                                                                     [    0.000000] On node 0 totalpages: 8192
      [    0.000000] free_area_init_node: node 0, pgdat c003dfb4, node_mem_map c1fb8000
                                                                                       [    0.000000]   Normal zone: 64 pages used for memmap
                     [    0.000000]   Normal zone: 0 pages reserved
                                                                   [    0.000000]   Normal zone: 8192 pages, LIFO batch:0
 [    0.000000] CPU: All CPU(s) started in SVC mode.




Of course as soon as the normal console driver is loaded later it boot, 
everything looks fine again. But I use early_printk a lot, so I wonder 
if I could get my carriage returns back.

Chris
Nicolas Pitre Oct. 31, 2017, 4:22 p.m. UTC | #4
On Tue, 31 Oct 2017, Chris Brandt wrote:

> On Sunday, October 01, 2017 1, Nicolas Pitre wrote:
> > With printch() the console messages are sent out one character at a time
> > which is agonizingly slow especially with semihosting as the whole trap
> > intercept, remote byte access, and system resume danse is performed for
> > every single character across a relatively slow remote debug connection.
> > Let's use printascii() to send a whole string at once. This is also going
> > to be more efficient, albeit to a quite lesser extent, with serial ports
> > as well.
> > 
> > Signed-off-by: Nicolas Pitre <nico@linaro.org>
> > ---
> >  arch/arm/kernel/early_printk.c | 16 ++++++++++------
> >  1 file changed, 10 insertions(+), 6 deletions(-)
> 
> Now that this patch has hit -next, I'm noticing an issue with it.
> 
> There are no carriage returns, just line feeds, which makes for a very 
> ugly display.

Hmmm....

If you look at printascii in arch/arm/kernel/debug.S you'll find the 
following code:

1:              waituart r2, r3
                senduart r1, r3
                busyuart r2, r3
                teq     r1, #'\n'
                moveq   r1, #'\r'
                beq     1b

Why is that not working for you?

Are you using semihosting?

Do you have another printascii implementation?


Nicolas
Robin Murphy Oct. 31, 2017, 4:38 p.m. UTC | #5
On 31/10/17 16:22, Nicolas Pitre wrote:
> On Tue, 31 Oct 2017, Chris Brandt wrote:
> 
>> On Sunday, October 01, 2017 1, Nicolas Pitre wrote:
>>> With printch() the console messages are sent out one character at a time
>>> which is agonizingly slow especially with semihosting as the whole trap
>>> intercept, remote byte access, and system resume danse is performed for
>>> every single character across a relatively slow remote debug connection.
>>> Let's use printascii() to send a whole string at once. This is also going
>>> to be more efficient, albeit to a quite lesser extent, with serial ports
>>> as well.
>>>
>>> Signed-off-by: Nicolas Pitre <nico@linaro.org>
>>> ---
>>>  arch/arm/kernel/early_printk.c | 16 ++++++++++------
>>>  1 file changed, 10 insertions(+), 6 deletions(-)
>>
>> Now that this patch has hit -next, I'm noticing an issue with it.
>>
>> There are no carriage returns, just line feeds, which makes for a very 
>> ugly display.
> 
> Hmmm....
> 
> If you look at printascii in arch/arm/kernel/debug.S you'll find the 
> following code:
> 
> 1:              waituart r2, r3
>                 senduart r1, r3
>                 busyuart r2, r3
>                 teq     r1, #'\n'
>                 moveq   r1, #'\r'
>                 beq     1b
> 
> Why is that not working for you?

By inspection, the removed early_write() code inserted the '\r' before
the '\n' in the usual fashion; the printascii() code above ends up doing
the reverse, and I can imagine the atypical "\n\r" sequence probably
confuses some terminals trying to be clever with line ending detection.

Robin.

> 
> Are you using semihosting?
> 
> Do you have another printascii implementation?
> 
> 
> Nicolas
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
diff mbox

Patch

diff --git a/arch/arm/kernel/early_printk.c b/arch/arm/kernel/early_printk.c
index 4307653696..9257736ec9 100644
--- a/arch/arm/kernel/early_printk.c
+++ b/arch/arm/kernel/early_printk.c
@@ -11,16 +11,20 @@ 
 #include <linux/kernel.h>
 #include <linux/console.h>
 #include <linux/init.h>
+#include <linux/string.h>
 
-extern void printch(int);
+extern void printascii(const char *);
 
 static void early_write(const char *s, unsigned n)
 {
-	while (n-- > 0) {
-		if (*s == '\n')
-			printch('\r');
-		printch(*s);
-		s++;
+	char buf[128];
+	while (n) {
+		unsigned l = min(n, sizeof(buf)-1);
+		memcpy(buf, s, l);
+		buf[l] = 0;
+		s += l;
+		n -= l;
+		printascii(buf);
 	}
 }