Rebuilding the Tegra TX1 kernel from source

Hi, I am trying to re-build, from source, the Linux 3.10 kernel that is
shipped with the Jetson TX1 Development Kit. The kernel source I am using
comes from /usr/src/kernel_src.tbz2 and the .config file comes from
/proc/config.gz. I copy both of these files over to an x86_64 CentOS7
host system.

I am using the Linaro aarch64 little endian x86 cross compiler from Linaro,
as downloaded from http://www.linaro.org/downloads/.

I compile bits of the kernel with statements like:

LANG=C make ARCH=arm64 CROSS_COMPILE=/usr/local/linaro/bin/aarch64-linux-gnu- drivers/drivers/platform/tegra/ >/dev/null

for the above, I get this fatal error:

drivers/platform/tegra/tegra21_clocks.c: In function ‘tegra21_cpu_clk_init’:
drivers/platform/tegra/tegra21_clocks.c:1065:31: error: logical not is only applied to the left hand side of comparison [-Werror=logical-not-parentheses]
c->state = (!is_lp_cluster() == (c->u.cpu.mode == MODE_G)) ? ON : OFF;
^
cc1: all warnings being treated as errors
make[3]: *** [drivers/platform/tegra/tegra21_clocks.o] Error 1
make[2]: *** [drivers/platform/tegra] Error 2
make[1]: *** [drivers/platform] Error 2
make: *** [drivers/] Error 2

I can do a dirty trick (modify the kernel source code), to get around the above,
but then other fatal kernel compile problems show up when compiling other bits
of the kernel. So clearly I am doing something wrong. Either the source code
provided is not the source code used to build the shipped kernel binary, or the
gcc toolchain I am using is not the one being used to build the official kernel
binary, or something else. Please advise.

Thanks,
Joe

The current release has a 64-bit kernel, but user space is 32-bit. As a result, you need both the 32-bit (arm-linux-gnueabihf) and 64-bit cross-compilers (aarch64-linux-gnu). Adjust your paths, but mine are installed on Fedora in “/usr/local” directories, and as an example, I use this before cross-compile:

export CROSS_COMPILE=/usr/local/gcc-linaro-5.2-2015.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
export CROSS32CC=/usr/local/gcc-linaro-5.2-2015.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
export TEGRA_KERNEL_OUT=/home/me/Documents/embedded/L4T/R23.1/src/build
export ARCH=arm64

Note that CROSS32CC is the full path to just gcc, while CROSS_COMPILE is the prefix to the entire 64-bit tool chain. Don’t forget to use the “-O=OUTPUT_DIR” option on each stage. The HTML documentation lists more details.

I got exactly the same error since 23.1 release. This should fix it:

From b3097f2240bd45ebde4799241cb50bee2e1f8db8 Mon Sep 17 00:00:00 2001
From: Aleskander Mitev <a.mitev@____.com>
Date: Wed, 17 Feb 2016 17:18:12 +0200
Subject: [PATCH] Fixed compiler complaints

---
 drivers/platform/tegra/tegra21_clocks.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/platform/tegra/tegra21_clocks.c b/drivers/platform/tegra/tegra21_clocks.c
index 0a0584f..cf0e277 100644
--- a/drivers/platform/tegra/tegra21_clocks.c
+++ b/drivers/platform/tegra/tegra21_clocks.c
@@ -1062,7 +1062,7 @@ static struct clk_ops tegra_super_ops = {
  */
 static void tegra21_cpu_clk_init(struct clk *c)
 {
-	c->state = (!is_lp_cluster() == (c->u.cpu.mode == MODE_G)) ? ON : OFF;
+	c->state = ((!is_lp_cluster()) == (c->u.cpu.mode == MODE_G)) ? ON : OFF;
 }
 
 static int tegra21_cpu_clk_enable(struct clk *c)
-- 
2.1.4

There are no other errors as far as I use:

export CROSS_COMPILE=$TEGRA_DIR/toolchain/gcc-linaro-5.1-2015.08-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
export CROSS32CC=$TEGRA_DIR/toolchain/arm-2014.05/bin/arm-none-eabi-gcc
export TEGRA_KERNEL_OUT=OUTPUT
export ARCH=arm64

You can check compiler version used

Thanks, guys. I do get a lot of other fatal error, which I am beginning to think
has something to do with my host being CentOS7 rather than Ubuntu. In any case, if
anyone has seen the below style of warning and knows of the fix, let me know. Thanks.

In file included from include/asm-generic/unistd.h:1:0,
from /cuba/jak/tegra/458d45c/arch/arm64/include/uapi/asm/unistd.h:16,
from /cuba/jak/tegra/458d45c/arch/arm64/include/asm/unistd.h:50,
from arch/arm64/kernel/kuser32.S:32:
include/uapi/asm-generic/unistd.h:32:0: warning: “__NR_io_setup” redefined
#define __NR_io_setup 0
^
In file included from arch/arm64/kernel/kuser32.S:31:0:
/cuba/jak/tegra/458d45c/arch/arm64/include/asm/unistd32.h:510:0: note: this is the location of the previous definition
#define __NR_io_setup 243

I was able to get around that problem with the following advice from nekoxp
(https://devtalk.nvidia.com/default/topic/914941/custom-kernel-compilations/#4804526)

[b]Hi guys,

The fix for vgettimeofday.c is REALLY simple…

Edit arch/arm64/kernel/vdso32/Makefile and change the ccflags-y line from:

ccflags-y := -shared -fPIC -fno-common -fno-builtin -march=armv7-a

to:

ccflags-y := -shared -fPIC -fomit-frame-pointer -fno-common -fno-builtin -march=armv7-a

or:

ccflags-y := -shared -fPIC -fno-common -fno-builtin -marm -march=armv7-a

… or add -O2 or something else.

The reason? The Ubuntu toolchain compiles to the Thumb instruction set by default (i.e. -mthumb), and r7 is the Thumb frame pointer (at least from GCC’s perspective. ARM has no standard frame pointer in AAPCS for Thumb code).

Building for the ARM instruction set or without frame pointers (-O2 is where -fomit-frame-pointer becomes enabled automatically) is a reasonable solution.

Ta,
Matt S. [/b]

Thanks, dsillman, that worked! The real question is, how is nvidia able to build
kernels with these sources? I would have expected that the kernels would be able
to build without modification. I am now up to two modifications. That does not
leave me with much confidence that the kernel I build will be equivalent to the
binary kernel shipped out by NVidia.

One thing to know about many of the warnings or errors is that they depend upon compiler options and compiler version. The options themselves change default behavior quite often depending on version of compiler. Linaro is making a LOT of changes quite fast to port mainline compilers into the ARM world…simply using a single version change of which compiler you use can completely change whether that code is reported as an error or whether it succeeds. The number of significant improvements in the compiler code output means that this is one of those few places where it pays to keep up with the most recent version, but previously working compiles may fail. To know if the code is “broken” or not requires also using the same compiler version.