NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

port-evbarm/40136: Gumstix startup code uses wrong registers



>Number:         40136
>Category:       port-evbarm
>Synopsis:       Gumstix startup code uses wrong registers
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    port-evbarm-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Dec 08 23:55:00 +0000 2008
>Originator:     Brett Slager
>Release:        NetBSD current Dec 7, 2008
>Organization:
>Environment:
Same
>Description:
        The code to handle argc and argvs passed from u-boot is getting them
from the wrong registers.  The AAPCS states the first 4 arguments to a
procedure call go in the first 4 registers r0-r4.  Instead of getting argc
from r0 and argvs from r1, r6 and r5 are used which are local variables left
over from the do_go() function in u-boot.  If the way this function is
compiled in u-boot changes, and an updated u-boot is installed, netbsd gumstix
could fail to get the proper arguments.
>How-To-Repeat:
        Inspect the code:
        src/sys/arch/evbarm/gumstix/gumstix_start.S
        src/sys/arch/evbarm/gumstix/gumstix_machdep.c
        and the following from u-boot:
...code snip from u-boot...
int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
        addr = simple_strtoul(argv[1], NULL, 16);

        printf ("## Starting application at 0x%08lX ...\n", addr);
        .
        .
        .
        rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]);
...end code snip from u-boot...

        Instrument the startup to save and print the initial register values.
        Note the following:
...test boot output...
GUM> fatload ide 0 0xa0200000 testimg
reading testimg

3920780 bytes read
GUM> go 0xa0200000 garbage args extrastuff busheader=netcf
## Starting application at 0xA0200000 ...

NetBSD/evbarm (gumstix) booting ...
system serial: 0x06668d0053456883
Regs: r0=5, r1=a3ee0334, r2=1, r3=40100000 r4=a0200000, r5=a3ee0334, r6=6
...end test boot output...
Note that r0 (argc) has the right number of arguments...

>Fix:
        We really only need the first two arguments, but I left the code
saving all four - they may be useful later on if we get different booting
support.

(Tested and works on Gumstix connex board using slightly older source - today's
wouldn't get very far past the argument processing due to:
  vmem_check_sanity: overlapping VMEM 'kmem' span 0xc1c8d000 - 0xc1c8e000 free
  vmem_check_sanity: overlapping VMEM 'kmem' span 0xc1c8d000 - 0xc1c8e000 free
  panic: kernel diagnostic assertion "vmem_check_sanity(vm)" failed: file
  "/home/bds/src/netbsd/builds/0007/src/sys/kern/subr_vmem.c", line 1060)

Index: gumstix_start.S
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/gumstix/gumstix_start.S,v
retrieving revision 1.5
diff -u -p -r1.5 gumstix_start.S
--- gumstix_start.S     17 Oct 2007 19:54:12 -0000      1.5
+++ gumstix_start.S     7 Dec 2008 23:57:33 -0000
@@ -97,11 +97,11 @@ _C_LABEL(gumstix_start):
         *  in VA 0xc0200000..
         */
        /* save u-boot's args */
-       adr     r0, u_boot_args
+       adr     r4, u_boot_args
        nop
        nop
        nop
-       stmia   r0!, {r3, r4, r5, r6}
+       stmia   r4!, {r0, r1, r2, r3}
        nop
        nop
        nop
@@ -151,7 +151,7 @@ Lstartup_pagetable:
 
        .globl  _C_LABEL(u_boot_args)
 u_boot_args:
-       .space  16                      /* r3, r4, r5, r6 */
+       .space  16                      /* r0, r1, r2, r3 */
 
 
 #define MMU_INIT(va,pa,n_sec,attr) \
Index: gumstix_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/evbarm/gumstix/gumstix_machdep.c,v
retrieving revision 1.12
diff -u -p -r1.12 gumstix_machdep.c
--- gumstix_machdep.c   18 Nov 2008 18:20:10 -0000      1.12
+++ gumstix_machdep.c   7 Dec 2008 23:57:52 -0000
@@ -447,7 +447,7 @@ initarm(void *arg)
 {
        extern vaddr_t xscale_cache_clean_addr;
        extern uint32_t *u_boot_args[];
-       enum { r3 = 0, r4 = 1, r5 = 2, r6 = 3 };        /* args from u-boot */
+       enum { r0 = 0, r1 = 1, r2 = 2, r3 = 3 };        /* args from u-boot */
        int loop;
        int loop1;
        u_int l1pagetable;
@@ -505,7 +505,7 @@ initarm(void *arg)
         * Examine the boot args string for options we need to know about
         * now.
         */
-       process_kernel_args((int)u_boot_args[r6], (char **)u_boot_args[r5]);
+       process_kernel_args((int)u_boot_args[r0], (char **)u_boot_args[r1]);
 
        memstart = 0xa0000000UL;
        memsize = 0x04000000UL;         /* 64MB */
@@ -927,13 +927,6 @@ process_kernel_args(int argc, char *argv
 
        boothowto = 0;
 
-       /*
-        * XXXXX: The value of argc is wrong.  The number of arguments is
-        * corrected in the do_go() of u-boot.  However, it is not actually
-        * corrected. 
-        */
-       argc --;
-
        for (i = 1, j = 0; i < argc; i++) {
                if (!strncmp(argv[i], busheader_name, strlen(busheader_name))) {
                        /* configure for GPIOs of busheader side */



Home | Main Index | Thread Index | Old Index