2013年3月28日 星期四

CNS3420VB cannot boot with Linux versions 3.3 and after (to v3.9-rc1)

The build procedure is as following:

make ARCH=arm cns3420vb_defconfig
make ARCH=arm zImage

The upstream Linux doesn't boot with version 3.3 and after with following message:
## Starting application at 0x04000000 ...
Uncompressing Li done, booting t

The suspect is located after git bisect:
commit 0536bdf33faff4d940ac094c77998cfac368cfff
Author: Nicolas Pitre <nicolas.pitre@linaro.org>
Date:   Thu Aug 25 00:35:59 2011 -0400

    ARM: move iotable mappings within the vmalloc region
  
    In order to remove the build time variation between different SOCs with
    regards to VMALLOC_END, the iotable mappings are now allocated inside
    the vmalloc region.  This allows for VMALLOC_END to be identical across
    all machines.
  
    The value for VMALLOC_END is now set to 0xff000000 which is right where
    the consistent DMA area starts.
  
    To accommodate all static mappings on machines with possible highmem usage,
    the default vmalloc area size is changed to 240 MB so that VMALLOC_START
    is no higher than 0xf0000000 by default.
  
    Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
    Tested-by: Stephen Warren <swarren@nvidia.com>
    Tested-by: Kevin Hilman <khilman@ti.com>
    Tested-by: Jamie Iles <jamie@jamieiles.com>

Commit 34ae6c96a6a7db4ed8ec0524bf7fa1086b9ab2ba has similar issue.

issue 1: if two iotable mappings overlapped, Linux boot failed with "Uncompressing Li done, booting t"

issue2: if mapping is good, but somehow GIC is not configured, Linux boot failed with "Calibrating delay loop...", for GIC is not set up properly.


FIX1: github mkl0301/linux branch cns3420vb-fix-3.2-not-boot


However even with the patch on v3.9-rc1 still doesn't boot, with the same message. While bisect-ing (with the patch, of course), it is found that sometimes it "half works", which likes scu/gic not set causes jiffies not updated, stuck at "Calibrating delay loop...".


The first commit that has this issue:
commit 384a290283fde63ba8dc671fca5420111cdac19a
Author: Nicolas Pitre
Date:   Wed Apr 11 18:55:48 2012 -0400

    ARM: gic: use a private mapping for CPU target interfaces
   
    The GIC interface numbering does not necessarily follow the logical
    CPU numbering, especially for complex topologies such as multi-cluster
    systems.
   
    Fortunately we can easily probe the GIC to create a mapping as the
    Interrupt Processor Targets Registers for the first 32 interrupts are
    read-only, and each field returns a value that always corresponds to
    the processor reading the register.
   
    Initially all mappings target all CPUs in case an IPI is required to
    boot secondary CPUs.  It is refined as those CPUs discover what their
    actual mapping is.
   
    Signed-off-by: Nicolas Pitre
    Acked-by: Will Deacon
ARM® Generic Interrupt Controller Architecture Specificationhttp://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0048a/index.html

It seems that in function gic_dist_init(), the cpumask read from register GIC_DIST_TARGET is 0x0, which cause this issue.

It seems the arch/arm/common/gic.c has been modified many times, for the issue doesn't occur every time while bisecting. So this is only a temporary fix.

FIX2: github mkl0301/linux branch cns3420vb-fix-3.8-not-boot

Now we finally reach to the original issue
## Starting application at 0x04000000 ...
Uncompressing Li done, booting t

bisecting v3.9-rc1 and commit 384a2902. The first commit that doesn't boot is:

commit b8b499c86be58cb309964fcab5b62ac4a240a878
Author: Alexander Shiyan
Date:   Wed Dec 12 08:32:11 2012 +0100

    ARM: 7602/1: Pass real "__machine_arch_type" variable to setup_machine_tags() procedure
   
    This modification is needed to proper boot the custom machines with
    the IDs that are not described in the mach-types.h table.
   
    Signed-off-by: Alexander Shiyan
    Signed-off-by: Russell King
According to Documentation/arm/Booting, "5. Calling the kernel image", r1 should store the machine type number. This machine type number will be stored to variable __machine_arch_type before calling start_kernel() in arch/arm/kernel/head-common.S.

The variable __machine_arch_type is supposed to be used by setup_arch() to determine the machine type. But before commit  b8b499c8, it is machine_arch_type, which is a predefined machine number, instead of the __machine_arch_type, determines the machine type.

So there was no issues using u-boot command "go", which doesn't put machine type to r1 until commit  b8b499c8. But after commit  b8b499c8, Linux use the machine number given by the bootloader to determine the machine type. u-boot command "go" doesn't fulfil the requirement any more.

FIX3: The proper fix of this will be: using uImage+u-boot command "bootm".
(But I just hack the u-boot and have the command "go" store machine number in r1 with zImage....)

Finally, I could boot v3.9-rc1 with FIX1+FIX3.


沒有留言: