diff mbox

PB1176 broken in -rc1

Message ID CACRpkdbSG=Mnu7QrACn3y3GP-2H4_qT0kR_4C8umCmWc2YCqXQ@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Linus Walleij Aug. 16, 2011, 9:35 a.m. UTC
On Tue, Aug 16, 2011 at 11:26 AM, Will Deacon <will.deacon@arm.com> wrote:

>> Will, Jamie, any hints?
>
> Can you make your .config available somewhere please?

http://www.df.lth.se/~triad/realview_config

Basically that's the realview_defconfig with these
changes done on top:

scripts/config --file $(realview_dir)/.config \
        --enable BLK_DEV_INITRD \
        --set-str INITRAMFS_SOURCE rootfs-u338.cpio \
        --enable INITRAMFS_COMPRESSION_NONE \
        --enable MISC_DEVICES \
        --enable ARM_CHARLCD \
        --enable DEBUG_LL \
        --enable EARLY_PRINTK \
        --enable ARM_TEST \
        --enable ARM_TCM_TEST \
        --set-str CMDLINE "root=/dev/ram0 console=ttyAMA0 earlyprintk mem=128M"
        yes "" | make $(make_options) oldconfig


> It sounds like an unrelated issue, so let's try to track it down.

Thanx!

> How do you use the interface
> with the TCMs once they've been mapped at the high address?

Here is my test code patch I'm cooking RFC:

------------8<-----------------------------8<-----------------------------
From ece57aeca9a03107432c6090733f89f483872163 Mon Sep 17 00:00:00 2001
From: Linus Walleij <linus.walleij@linaro.org>
Date: Thu, 30 Jun 2011 14:33:48 +0200
Subject: [PATCH] ARM TCM sample code

This is a simple sample snippet of ARM TCM code use, we create
arm/test to host the code.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 Documentation/arm/tcm.txt   |   60 +--------------------------
 arch/arm/Kconfig.debug      |    2 +
 arch/arm/Makefile           |    2 +
 arch/arm/test/Kconfig       |   20 +++++++++
 arch/arm/test/Makefile      |    2 +
 arch/arm/test/tcm-example.c |   94 +++++++++++++++++++++++++++++++++++++++++++
 samples/Kconfig             |    9 ++++
 samples/Makefile            |    2 +-
 8 files changed, 132 insertions(+), 59 deletions(-)
 create mode 100644 arch/arm/test/Kconfig
 create mode 100644 arch/arm/test/Makefile
 create mode 100644 arch/arm/test/tcm-example.c

Comments

Will Deacon Aug. 16, 2011, 9:59 a.m. UTC | #1
On Tue, Aug 16, 2011 at 10:35:08AM +0100, Linus Walleij wrote:
> Basically that's the realview_defconfig with these
> changes done on top:
> 
> scripts/config --file $(realview_dir)/.config \
>         --enable BLK_DEV_INITRD \
>         --set-str INITRAMFS_SOURCE rootfs-u338.cpio \
>         --enable INITRAMFS_COMPRESSION_NONE \
>         --enable MISC_DEVICES \
>         --enable ARM_CHARLCD \
>         --enable DEBUG_LL \
>         --enable EARLY_PRINTK \
>         --enable ARM_TEST \
>         --enable ARM_TCM_TEST \
>         --set-str CMDLINE "root=/dev/ram0 console=ttyAMA0 earlyprintk mem=128M"
>         yes "" | make $(make_options) oldconfig

The problem is with earlyprintk because your picking up multiple definitions
of DEBUG_LL_UART_OFFSET as a result of basing your config on the defconfig.

Take a look at arch/arm/mach-realview/include/mach/debug-macro.S. I don't
think there's an easy way to fix this because it's used so early, even DT
can't save us.

> > How do you use the interface
> > with the TCMs once they've been mapped at the high address?
> 
> Here is my test code patch I'm cooking RFC:
> 
> ------------8<-----------------------------8<-----------------------------
> From ece57aeca9a03107432c6090733f89f483872163 Mon Sep 17 00:00:00 2001
> From: Linus Walleij <linus.walleij@linaro.org>
> Date: Thu, 30 Jun 2011 14:33:48 +0200
> Subject: [PATCH] ARM TCM sample code
> 
> This is a simple sample snippet of ARM TCM code use, we create
> arm/test to host the code.
> 
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

[...]

> -static void __init test_tcm(void)
> -{
> -	u32 *tcmem;
> -	int i;
> -
> -	hello_tcm();
> -	printk("Hello TCM executed from ITCM RAM\n");
> -
> -	printk("TCM variable from testrun: %u @ %p\n", tcmvar, &tcmvar);
> -	tcmvar = 0xDEADBEEFU;
> -	printk("TCM variable: 0x%x @ %p\n", tcmvar, &tcmvar);
> -
> -	printk("TCM assigned variable: 0x%x @ %p\n", tcmassigned, &tcmassigned);
> -
> -	printk("TCM constant: 0x%x @ %p\n", tcmconst, &tcmconst);
> -
> -	/* Allocate some TCM memory from the pool */
> -	tcmem = tcm_alloc(20);
> -	if (tcmem) {
> -		printk("TCM Allocated 20 bytes of TCM @ %p\n", tcmem);
> -		tcmem[0] = 0xDEADBEEFU;
> -		tcmem[1] = 0x2BADBABEU;
> -		tcmem[2] = 0xCAFEBABEU;
> -		tcmem[3] = 0xDEADBEEFU;
> -		tcmem[4] = 0x2BADBABEU;

Hmm, do you need a barrier here to (a) stop the compiler constant folding
the tcm array and (b) force a read back from the TCM? Also, where does the
TCM sit in relation to the L1 cache (yes, I should RTFM...).

> -		for (i = 0; i < 5; i++)
> -			printk("TCM tcmem[%d] = %08x\n", i, tcmem[i]);
> -		tcm_free(tcmem, 20);
> -	}
> -}

[...]

> +	if (tcmem) {
> +		pr_info("CPU: TCM Allocated 20 bytes of TCM @ %p\n", tcmem);
> +		tcmem[0] = CANARY1;
> +		tcmem[1] = CANARY2;
> +		tcmem[2] = CANARY3;
> +		tcmem[3] = CANARY1;
> +		tcmem[4] = CANARY2;

And again here?

> +		for (i = 0; i < 5; i++)
> +			pr_info("CPU: TCM tcmem[%d] = %08x\n", i, tcmem[i]);
> +		BUG_ON(tcmem[0] != CANARY1);
> +		BUG_ON(tcmem[1] != CANARY2);
> +		BUG_ON(tcmem[2] != CANARY3);
> +		BUG_ON(tcmem[3] != CANARY1);
> +		BUG_ON(tcmem[4] != CANARY2);
> +		tcm_free(tcmem, 20);
> +	}
> +	return 0;
> +}

Will
Russell King - ARM Linux Aug. 16, 2011, 10:09 a.m. UTC | #2
On Tue, Aug 16, 2011 at 10:59:36AM +0100, Will Deacon wrote:
> The problem is with earlyprintk because your picking up multiple definitions
> of DEBUG_LL_UART_OFFSET as a result of basing your config on the defconfig.
> 
> Take a look at arch/arm/mach-realview/include/mach/debug-macro.S. I don't
> think there's an easy way to fix this because it's used so early, even DT
> can't save us.

As I keep saying to people, only use the LL debug during _early_ platform
bring-up.  That's what it's there for.

Tying earlyprintk into the LL debug stuff has made the LL debug easier to
use, and therefore easier for people to fall into this trap.  That's not
the problem of the LL debug stuff, but the problem of its greater exposure.

So, as the LL debug stuff has this rule, so does earlyprintk.  Only use it
for early platform bring up and *once* you have a kernel booting through
to the proper console, disable it *immediately*.

Anything else will lead you into these pitfalls.
Will Deacon Aug. 16, 2011, 10:17 a.m. UTC | #3
Hi Russell,

On Tue, Aug 16, 2011 at 11:09:06AM +0100, Russell King - ARM Linux wrote:
> On Tue, Aug 16, 2011 at 10:59:36AM +0100, Will Deacon wrote:
> > The problem is with earlyprintk because your picking up multiple definitions
> > of DEBUG_LL_UART_OFFSET as a result of basing your config on the defconfig.
> > 
> > Take a look at arch/arm/mach-realview/include/mach/debug-macro.S. I don't
> > think there's an easy way to fix this because it's used so early, even DT
> > can't save us.
> 
> As I keep saying to people, only use the LL debug during _early_ platform
> bring-up.  That's what it's there for.
> 
> Tying earlyprintk into the LL debug stuff has made the LL debug easier to
> use, and therefore easier for people to fall into this trap.  That's not
> the problem of the LL debug stuff, but the problem of its greater exposure.
> 
> So, as the LL debug stuff has this rule, so does earlyprintk.  Only use it
> for early platform bring up and *once* you have a kernel booting through
> to the proper console, disable it *immediately*.
> 
> Anything else will lead you into these pitfalls.

Yup, I agree about the usage of earlyprintk. It would be good if the user
could select the platform on which LL debug will work at config time and
then not have to worry about multiple conflicting definitions of
DEBUG_LL_UART_OFFSET. That way, you know on which platform earlyprintk
will work and don't try to use it on any others.

Will
Linus Walleij Aug. 16, 2011, 12:44 p.m. UTC | #4
On Tue, Aug 16, 2011 at 11:59 AM, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, Aug 16, 2011 at 10:35:08AM +0100, Linus Walleij wrote:
>>
>> scripts/config --file $(realview_dir)/.config \
>>         --enable BLK_DEV_INITRD \
>>         --set-str INITRAMFS_SOURCE rootfs-u338.cpio \
>>         --enable INITRAMFS_COMPRESSION_NONE \
>>         --enable MISC_DEVICES \
>>         --enable ARM_CHARLCD \
>>         --enable DEBUG_LL \
>>         --enable EARLY_PRINTK \
>>         --enable ARM_TEST \
>>         --enable ARM_TCM_TEST \
>>         --set-str CMDLINE "root=/dev/ram0 console=ttyAMA0 earlyprintk mem=128M"
>>         yes "" | make $(make_options) oldconfig
>
> The problem is with earlyprintk because your picking up multiple definitions
> of DEBUG_LL_UART_OFFSET as a result of basing your config on the defconfig.

Well doesn't cure it for me I'm afraid, I've added DEBUG_LL and
EARLY_PRINTK here just because it wasn't booting, in the hopes
of catching some early debug messages.

But I do realize I should config out the other platforms and build a
kernel only for the PB1176 when I wanna use that...

Some twiddling reveals that it's that initramfs that breaks it
and only if you use TCM at the same time (!)

The most probably cause being that the size of the combined
kernel+initramfs passed the magic limit where it simply breaks,
I wish we could handle that in some good way :-/

Oh well, no disastrous problem anyway, I'll have to start using
an NFS rootfs like everyone else.

>> -     /* Allocate some TCM memory from the pool */
>> -     tcmem = tcm_alloc(20);
>> -     if (tcmem) {
>> -             printk("TCM Allocated 20 bytes of TCM @ %p\n", tcmem);
>> -             tcmem[0] = 0xDEADBEEFU;
>> -             tcmem[1] = 0x2BADBABEU;
>> -             tcmem[2] = 0xCAFEBABEU;
>> -             tcmem[3] = 0xDEADBEEFU;
>> -             tcmem[4] = 0x2BADBABEU;
>
> Hmm, do you need a barrier here to (a) stop the compiler constant folding
> the tcm array and (b) force a read back from the TCM? Also, where does the
> TCM sit in relation to the L1 cache (yes, I should RTFM...).

Nope, the TCM is uncached, no problems. The Address and data
bus just go directly to the in-CPU memory.

>> +     if (tcmem) {
>> +             pr_info("CPU: TCM Allocated 20 bytes of TCM @ %p\n", tcmem);
>> +             tcmem[0] = CANARY1;
>> +             tcmem[1] = CANARY2;
>> +             tcmem[2] = CANARY3;
>> +             tcmem[3] = CANARY1;
>> +             tcmem[4] = CANARY2;
>
> And again here?

The above deletion from Documentation/. appears as an insertion here...

Thanks,
Linus Walleij
Russell King - ARM Linux Aug. 16, 2011, 12:52 p.m. UTC | #5
On Tue, Aug 16, 2011 at 02:44:21PM +0200, Linus Walleij wrote:
> The most probably cause being that the size of the combined
> kernel+initramfs passed the magic limit where it simply breaks,
> I wish we could handle that in some good way :-/

That should be fixed, because we now place the initramfs image
between the code sections and the data sections.
diff mbox

Patch

diff --git a/Documentation/arm/tcm.txt b/Documentation/arm/tcm.txt
index 7c15871..f6ead49 100644
--- a/Documentation/arm/tcm.txt
+++ b/Documentation/arm/tcm.txt
@@ -95,61 +95,5 @@  To put assembler into TCM just use
 .section ".tcm.text" or .section ".tcm.data"
 respectively.

-Example code:
-
-#include <asm/tcm.h>
-
-/* Uninitialized data */
-static u32 __tcmdata tcmvar;
-/* Initialized data */
-static u32 __tcmdata tcmassigned = 0x2BADBABEU;
-/* Constant */
-static const u32 __tcmconst tcmconst = 0xCAFEBABEU;
-
-static void __tcmlocalfunc tcm_to_tcm(void)
-{
-	int i;
-	for (i = 0; i < 100; i++)
-		tcmvar ++;
-}
-
-static void __tcmfunc hello_tcm(void)
-{
-	/* Some abstract code that runs in ITCM */
-	int i;
-	for (i = 0; i < 100; i++) {
-		tcmvar ++;
-	}
-	tcm_to_tcm();
-}
-
-static void __init test_tcm(void)
-{
-	u32 *tcmem;
-	int i;
-
-	hello_tcm();
-	printk("Hello TCM executed from ITCM RAM\n");
-
-	printk("TCM variable from testrun: %u @ %p\n", tcmvar, &tcmvar);
-	tcmvar = 0xDEADBEEFU;
-	printk("TCM variable: 0x%x @ %p\n", tcmvar, &tcmvar);
-
-	printk("TCM assigned variable: 0x%x @ %p\n", tcmassigned, &tcmassigned);
-
-	printk("TCM constant: 0x%x @ %p\n", tcmconst, &tcmconst);
-
-	/* Allocate some TCM memory from the pool */
-	tcmem = tcm_alloc(20);
-	if (tcmem) {
-		printk("TCM Allocated 20 bytes of TCM @ %p\n", tcmem);
-		tcmem[0] = 0xDEADBEEFU;
-		tcmem[1] = 0x2BADBABEU;
-		tcmem[2] = 0xCAFEBABEU;
-		tcmem[3] = 0xDEADBEEFU;
-		tcmem[4] = 0x2BADBABEU;
-		for (i = 0; i < 5; i++)
-			printk("TCM tcmem[%d] = %08x\n", i, tcmem[i]);
-		tcm_free(tcmem, 20);
-	}
-}
+Example code can be found in the samples/arm_tcm directory of the kernel
+tree, and can be compiled in using menuconfig.
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 81cbe40..82bf536 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -129,4 +129,6 @@  config DEBUG_S3C_UART
 	  The uncompressor code port configuration is now handled
 	  by CONFIG_S3C_LOWLEVEL_UART_PORT.

+source "arch/arm/test/Kconfig"
+
 endmenu
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 70c424e..f2f370b 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -255,6 +255,8 @@  core-$(CONFIG_VFP)		+= arch/arm/vfp/
 core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
 core-y				+= $(machdirs) $(platdirs)

+core-$(CONFIG_ARM_TEST)		+= arch/arm/test/
+
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/

 libs-y				:= arch/arm/lib/ $(libs-y)
diff --git a/arch/arm/test/Kconfig b/arch/arm/test/Kconfig
new file mode 100644
index 0000000..13c38e1
--- /dev/null
+++ b/arch/arm/test/Kconfig
@@ -0,0 +1,20 @@ 
+config ARM_TEST
+       bool "Enable ARM kernel tests"
+
+if ARM_TEST
+
+menu "ARM Kernel tests"
+
+comment "test code to exercise the ARM kernel"
+
+config ARM_TCM_TEST
+	bool "ARM TCM test"
+	depends on HAVE_TCM
+	help
+		Enables some test code snippets to exercise the TCM memory
+		on platforms that have it. The code will not be executed
+		if no TCM memory is found.
+
+endmenu
+
+endif
diff --git a/arch/arm/test/Makefile b/arch/arm/test/Makefile
new file mode 100644
index 0000000..9161440
--- /dev/null
+++ b/arch/arm/test/Makefile
@@ -0,0 +1,2 @@ 
+obj-y :=
+obj-$(CONFIG_ARM_TCM_TEST) += tcm-example.o
diff --git a/arch/arm/test/tcm-example.c b/arch/arm/test/tcm-example.c
new file mode 100644
index 0000000..156d97e
--- /dev/null
+++ b/arch/arm/test/tcm-example.c
@@ -0,0 +1,94 @@ 
+/*
+ * Copyright (C) 2010 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * TCM memory test
+ *
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/tcm.h>
+
+#define CANARY1 0xDEADBEEFU
+#define CANARY2 0x2BADBABEU
+#define CANARY3 0xCAFEBABEU
+
+/* Uninitialized data */
+static u32 __tcmdata tcmvar;
+/* Initialized data */
+static u32 __tcmdata tcmassigned = CANARY2;
+/* Constant */
+static const u32 __tcmconst tcmconst = CANARY3;
+
+static void __tcmlocalfunc tcm_to_tcm(void)
+{
+	int i;
+	for (i = 0; i < 100; i++)
+		tcmvar ++;
+}
+
+static void __tcmfunc hello_tcm(void)
+{
+	/* Some abstract code that runs in ITCM */
+	int i;
+	for (i = 0; i < 100; i++) {
+		tcmvar ++;
+	}
+	tcm_to_tcm();
+}
+
+static int __init test_tcm(void)
+{
+	u32 *tcmem;
+	int i;
+
+	if (!tcm_dtcm_present() && !tcm_itcm_present()) {
+		pr_info("CPU: no TCMs present, skipping tests\n");
+		return 0;
+	}
+
+	if (!tcm_itcm_present())
+		goto skip_itcm_tests;
+
+	hello_tcm();
+	pr_info("CPU: hello TCM executed from ITCM RAM\n");
+
+	pr_info("CPU: TCM variable from testrun: %u @ %p\n",
+		tcmvar, &tcmvar);
+	BUG_ON(tcmvar != 200);
+
+skip_itcm_tests:
+	tcmvar = CANARY1;
+	pr_info("CPU: TCM variable: 0x%x @ %p\n", tcmvar, &tcmvar);
+	BUG_ON(tcmvar != CANARY1);
+
+	pr_info("CPU: TCM assigned variable: 0x%x @ %p\n",
+		tcmassigned, &tcmassigned);
+	BUG_ON(tcmassigned != CANARY2);
+
+	pr_info("CPU: TCM constant: 0x%x @ %p\n", tcmconst, &tcmconst);
+	BUG_ON(tcmconst != CANARY3);
+
+	/* Allocate some TCM memory from the pool */
+	tcmem = tcm_alloc(20);
+	if (tcmem) {
+		pr_info("CPU: TCM Allocated 20 bytes of TCM @ %p\n", tcmem);
+		tcmem[0] = CANARY1;
+		tcmem[1] = CANARY2;
+		tcmem[2] = CANARY3;
+		tcmem[3] = CANARY1;
+		tcmem[4] = CANARY2;
+		for (i = 0; i < 5; i++)
+			pr_info("CPU: TCM tcmem[%d] = %08x\n", i, tcmem[i]);
+		BUG_ON(tcmem[0] != CANARY1);
+		BUG_ON(tcmem[1] != CANARY2);
+		BUG_ON(tcmem[2] != CANARY3);
+		BUG_ON(tcmem[3] != CANARY1);
+		BUG_ON(tcmem[4] != CANARY2);
+		tcm_free(tcmem, 20);
+	}
+	return 0;
+}
+
+late_initcall(test_tcm);
diff --git a/samples/Kconfig b/samples/Kconfig
index 96a7572..91260c6 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -67,4 +67,13 @@  config SAMPLE_HIDRAW
 	help
 	  Build an example of how to use hidraw from userspace.

+config SAMPLE_ARM_TCM
+	bool "TCM sample testing module"
+	depends on HAVE_TCM
+	help
+	  This enables a small testing module that execise the ARM TCM
+	  memory on the platform at startup to make sure it's working.
+	  If you're really using the TCM it is a scarce resource so
+	  this should only be selected for testing and education.
+
 endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
index 6280817..11a1d27 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -1,4 +1,4 @@ 
 # Makefile for Linux samples code

 obj-$(CONFIG_SAMPLES)	+= kobject/ kprobes/ tracepoints/ trace_events/ \
-			   hw_breakpoint/ kfifo/ kdb/ hidraw/
+			   hw_breakpoint/ kfifo/ kdb/ hidraw/ arm_tcm/