Message ID | CACRpkdbSG=Mnu7QrACn3y3GP-2H4_qT0kR_4C8umCmWc2YCqXQ@mail.gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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
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.
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
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
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 --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/