Tuesday, July 27, 2010

Final Kernel MMU/PageTable configuration

We now jump to __create_page_tables (same /arch/arm/kernel/head.S file)

/*
 207 * Setup the initial page tables.  We only setup the barest
 208 * amount which are required to get the kernel running, which
 209 * generally means mapping in the kernel code.
 210 *
 211 * r8  = machinfo
 212 * r9  = cpuid
 213 * r10 = procinfo
 214 *
 215 * Returns:
 216 *  r0, r3, r6, r7 corrupted
 217 *  r4 = physical page table address
 218 */
R4 loaded with Page Table Addr R4=@0x80004000
Reset entire 16K Page Table to zero.
Load R7 with entry from Proc. info offset at #8. 
=> R7=0x0C0E
 
         /*
 238         * Create identity mapping for first MB of kernel to
 239         * cater for the MMU enable.  This identity mapping
 240         * will be removed by paging_init().  We use our current program
 241         * counter to determine corresponding section base address.
 242         */
 
Load R6=PC=@0x800080AC
 
Ignore lower 20 bytes of R6 and OR with R7, Save result in R3
R3= @0x80000C0E
Store R3 value @([R4+R6] <<2) = [80004000] + 0800 << 2
= 80004000 + 2000
= @0x80006000
Save R3 at 0x80007000 as well.
Increment R0=R0+4
ldr     r6, =(KERNEL_END - 1) translated to
R6= 0xC02E8A3B 
Again R6 adjusted to PA results in
R6=0x8000700B
 
1:      cmp     r0, r6
 258        add     r3, r3, #1 << 20
 259        strls   r3, [r0], #4
 260        bls     1b
When loop starts, R0=80007004, R3=80000C0E, R6=8000700B
R3=R3+0x100000=80100C0E
R3 is then stored to 0x80007004, while R0 increments 4 more
 
The loop stops after 3 pages are mapped.
Fig: Dump after identity mapping loop
 281        /*
 282         * Then map first 1MB of ram in case it contains our boot params.
 283         */
 284        add     r0, r4, #PAGE_OFFSET >> 18
 285        orr     r6, r7, #(PHYS_OFFSET & 0xff000000)
 286        .if     (PHYS_OFFSET & 0x00f00000)
 287        orr     r6, r6, #(PHYS_OFFSET & 0x00f00000)
 288        .endif
 289        str     r6, [r0]
line 285 translates to
orr     r6, r7, #-0x80000000
next 289 is executed with r6=0x80000C0E, r0=0x80007000
 
In our case, no change to location 80007000, same as in above fig.
 
Finally, Jump back 
 332        mov     pc, lr
Control back to the following lines:
  91        /*
  92         * The following calls CPU specific code in a position independent
  93         * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
  94         * xxx_proc_info structure selected by __lookup_machine_type
  95         * above.  On return, the CPU will be ready for the MMU to be
  96         * turned on, and r0 will hold the CPU control register value.
  97         */
  98        ldr     r13, __switch_data              @ address to jump to after
  99                                                @ mmu has been enabled
 100        adr     lr, BSYM(__enable_mmu)          @ return (PIC) address
 101 ARM(   add     pc, r10, #PROCINFO_INITFUNC     )
 102 THUMB( add     r12, r10, #PROCINFO_INITFUNC    )
 103 THUMB( mov     pc, r12                         )
 104ENDPROC(stext)
R13=@0xC0008118 after ldr instrn. (Obtained from system.map)
R14 =@0x80008034
add pc, r10, #10 results in PC=@0x80008034
results in control at line
b      0x8000BA28
 
We jump to architecture specific Mem Mgmt setup function. In our case, we end up at
linux/arch/arm/mm/proc-v7.S
adr     r12, __v7_setup_stack           @ the local stack
 200        stmia   r12, {r0-r5, r7, r9, r11, lr}
 201        bl      v7_flush_dcache_all
 
Code again jumps to 0x8002ACE0
linux/arch/arm/mm/cache-v7.S
 /*
  21 *      v7_flush_dcache_all()
  22 *
  23 *      Flush the whole D-cache.
  24 *
  25 *      Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode)
  26 *
  27 *      - mm    - mm_struct describing address space
  28 */
  29ENTRY(v7_flush_dcache_all)
  30        dmb                                     @ ensure ordering with previous memory accesses
  31        mrc     p15, 1, r0, c0, c0, 1           @ read clidr
  32        ands    r3, r0, #0x7000000              @ extract loc from clidr
  33        mov     r3, r3, lsr #23                 @ left align loc bit field
  34        beq     finished                        @ if loc is 0, then no need to clean
  35        mov     r10, #0                         @ start clean at cache level 0
Cache handling to be discussed in a seperate post later. For now, we just run till we return.
Code runs and returns back to __v7_setup
ldmia   r12, {r0-r5, r7, r9, r11, lr}
 203
 204        mrc     p15, 0, r0, c0, c0, 0           @ read main ID register
 205        and     r10, r0, #0xff000000            @ ARM?
 206        teq     r10, #0x41000000
Here, we find the PROC ID(0x411FC083), variant(0x00100000), revision(0x3) and store combined
variant and revision(0x13) in R0. Next, we goto
2:      mov     r10, #0
 234#ifdef HARVARD_CACHE
 235        mcr     p15, 0, r10, c7, c5, 0          @ I+BTB cache invalidate
 236#endif
 237        dsb
 238#ifdef CONFIG_MMU
 239        mcr     p15, 0, r10, c8, c7, 0          @ invalidate I + D TLBs
 240        mcr     p15, 0, r10, c2, c0, 2          @ TTB control register
 241        orr     r4, r4, #TTB_FLAGS
 242        mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
 243        mov     r10, #0x1f                      @ domains 0, 1 = manager
 244        mcr     p15, 0, r10, c3, c0, 0          @ load domain access register
We skip line #235
invalidate I + D TLBs, TTB1, Domain Access Reg,
ldr     r5, =0xff0a81a8                 @ PRRR
 274        ldr     r6, =0x40e040e0                 @ NMRR
 275        mcr     p15, 0, r5, c10, c2, 0          @ write PRRR
 276        mcr     p15, 0, r6, c10, c2, 1          @ write NMRR
We skip Line#281
 
mrc     p15, 0, r0, c1, c0, 0           @ read control register
 284        bic     r0, r0, r5                      @ clear bits them
 285        orr     r0, r0, r6                      @ set them
 286 THUMB( orr     r0, r0, #1 << 30        )       @ Thumb exceptions
 287        mov     pc, lr 
 
Finally, we return from mm config.
Note that, we return to address saved in R14, which happens to be 
__enable_mmu as seen from line# 100
 
 /*
 156 * Setup common bits before finally enabling the MMU.  Essentially
 157 * this is just loading the page table pointer and domain access
 158 * registers.
 159 */
 160__enable_mmu:
 161#ifdef CONFIG_ALIGNMENT_TRAP
 162        orr     r0, r0, #CR_A
 163#else
 164        bic     r0, r0, #CR_A
 165#endif
We execute only line #162 and jump to
 175        mov     r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
 176                      domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
 177                      domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
 178                      domain_val(DOMAIN_IO, DOMAIN_CLIENT))
 179        mcr     p15, 0, r5, c3, c0, 0           @ load domain access register
 180        mcr     p15, 0, r4, c2, c0, 0           @ load page table pointer
 181        b       __turn_mmu_on
Line #175 ends up as
mov     r5, #0x1F
Finally, branch to __turn_mmu_on
/*
 185 * Enable the MMU.  This completely changes the structure of the visible
 186 * memory space.  You will not be able to trace execution through this.
 187 * If you have an enquiry about this, *please* check the linux-arm-kernel
 188 * mailing list archives BEFORE sending another post to the list.
 189 *
 190 *  r0  = cp#15 control register
 191 *  r13 = *virtual* address to jump to upon completion
 192 *
 193 * other registers depend on the function called upon completion
 194 */
 195        .align  5
 196__turn_mmu_on:
 197        mov     r0, r0
 198        mcr     p15, 0, r0, c1, c0, 0           @ write control reg
 199        mrc     p15, 0, r3, c0, c0, 0           @ read id reg
 200        mov     r3, r3
 201        mov     r3, r13
 202        mov     pc, r3
 203ENDPROC(__turn_mmu_on)

**** Comment says it all! ****
 
Note that line#197 is translated as a nop 
Last 2 lines are also present only to flush content of ARM core pipeline 
So now, we are switching completely to !!** VM **!!
From this point onwards, we can use debugger with source code mapping, as we now have
system.map addresses being valid!
Immediately followinf line #202, we enter __mmap_switched: as this was the addr stored in
R13 in line #98.
Fig: First line in VM, after returning from above function
 
 
 
 
 
 
Now, we are running @__mmap_switched in /arch/arm/kernel/head-common.S

  32/*
  33 * The following fragment of code is executed with the MMU on in MMU mode,
  34 * and uses absolute addresses; this is not position independent.
  35 *
  36 *  r0  = cp#15 control register
  37 *  r1  = machine ID
  38 *  r2  = atags pointer
  39 *  r9  = processor ID
  40 */
  41__mmap_switched:
  42        adr     r3, __switch_data + 4
  43
  44        ldmia   r3!, {r4, r5, r6, r7}
  45        cmp     r4, r5                          @ Copy data segment if needed
  461:      cmpne   r5, r6
  47        ldrne   fp, [r4], #4
  48        strne   fp, [r5], #4
  49        bne     1b
  50
  51        mov     fp, #0                          @ Clear BSS (and zero fp)
  521:      cmp     r6, r7
  53        strcc   fp, [r6],#4
  54        bcc     1b
  55
  56 ARM(   ldmia   r3, {r4, r5, r6, r7, sp})
  57 THUMB( ldmia   r3, {r4, r5, r6, r7}    )
  58 THUMB( ldr     sp, [r3, #16]           )
  59        str     r9, [r4]                        @ Save processor ID
  60        str     r1, [r5]                        @ Save machine type
  61        str     r2, [r6]                        @ Save atags pointer
  62        bic     r4, r0, #CR_A                   @ Clear 'A' bit
  63        stmia   r7, {r0, r4}                    @ Save control register values
  64        b       start_kernel
Note that fp => R11
In our case, r4, r5 values read from __switch_data are equal, so we wont execute 
several initial lines. but jump directly to line #51.
However, we do loop to clear BSS
Finally, after saving several IDs and pointers, we finally jump to
start_kernel()



Entering the kernel

http://lxr.linux.no/#linux+v2.6.34.1/arch/arm/kernel/head.S

Ensure svc mode and IRQ disabled
Read Proc ID from c0,c0 to R9 (=0x411FC083)
Call
__lookup_processor_type:
Found in arch/arm/kernel/head-common.S
Get pointers to __proc_info structures. This structure is formed during compile time.
The addresses held in these structures are VA while we are executing from PA (MMU OFF). 
Hence, we find the offset between virt&phys, which results in = 0xC0000000
With physical addresses, we can dereference table correctly and check for proc matching.
 
Switch back to head.S
Similarly, check machine ID match using __lookup_machine_type table
Next, determine validity of ATAGS by jumping to __vet_atags, again found in head-common.S
/* Determine validity of the r2 atags pointer.  The heuristic requires
 239 * that the pointer be aligned, in the first 16k of physical RAM and
 240 * that the ATAG_CORE marker is first and present.  Future revisions
 241 * of this function may be more lenient with the physical address and
 242 * may also be able to move the ATAGS block if necessary.
 243 *
 244 * r8  = machinfo
 245 *
 246 * Returns:
 247 *  r2 either valid atags pointer, or zero
 248 *  r5, r6 corrupted
 249 */
R2=@0x80000100
Verify ATAG_CORE marker, and return
Next, we call __create_page_tables
Fig: Snapshot just before jumping to __create_page_tables

Linux kernel decompression

/*
 247 * Check to see if we will overwrite ourselves.
 248 *   r4 = final kernel address
 249 *   r5 = start of this image
 250 *   r2 = end of malloc space (and therefore this image)
 251 * We basically want:
 252 *   r4 >= r2 -> OK
 253 *   r4 + image length <= r5 -> OK
 254 */
We have R4=0x80008000, R5=0x80008000, R2=0x8016E668, R6=0x00555860(imagelen), R7=0x060A
We compare R4 with R2 to see if we ever overwrite. Since we do, we need to adjust it
R0= R4+R6=0x8055D860
cmp r0, r5 and see if we dont overwrite.
In our case, we still fail, so need more adjustment.
We will simply change the decompressing addr. to one above malloc space(R2=0x8016E668)
mov     r5, r2                  @ decompress after malloc space
 264                mov     r0, r5
 265                mov     r3, r7
 266                bl      decompress_kernel
decompress_kernel is a function() defined in linux/arch/arm/boot/compressed/misc.c
 
This function decompresses the kernel. Note that if we have putc and getc defined, we 
see a print of "Uncompressing Linux..." when we start to decompress kernel.
In our case, we have sucn a definition done in 
\linux-2.6\arch\arm\mach-puppybeagle\include\mach\uncompress.h file
 
 
NOT SURE OF BELOW EXPLANATION!
ALL WE KNOW IS WE SAVE ALL ARGS PASSED TO FUNCTION PRINT UNCOMPRESS....JUMP DO_DECOMPRESS
@  
Here, he starts reading certain offset entries found at address 0x80008A60, 0x80008A64, 0x80008A68, 
and 0x80008A68, adds them up to the base address 0x8015D618(GOT START) and save them in the BSS section.
These offset entries are found to be ATAGs passed by the Bootloader.
 
So ATAGS @0x80008A60
GOT START @ 0x8015D618
BSS Entry value = value @ [GOTSTART+ ATAG] 
 
Decompress function is a standard C function that compresses the zImage and returns back.

We have decompressed from 0x8016E668(mallocspace end) till 0x8043B4E8 (Image size of 0x002CCE80)

Now copy relocation code:

reloc_start code addr:  R2=@0x80008380
LC1 label:   R3=@0x80008814
End of Decompxd. kernel: R1@0x8043B4E8

Now copy data from R2(0x80008380) and store it @R1(0x8043B4E8), ie after decompressed image
We do this copying until R2 == R3 (1172 Bytes)

Also, relocate Stack. SP now points to R13=0x8043BA18

Do a cache_clean_flush
    -> Calls call_cache_fn
        -> Searches for appropriate proctype flush call (In our case, its __armv7_mmu_cache_flush)
            ->Jumps to Hierarchial
                loop along loop3 3-4 times
                loop along loop2 2-3 times
                loop along loop1 2 times

            finally pop up, invalidate caches and return to __armv7_mmu_cache_off
            here again, invalidate TLB, BTC, DSB, ISB

We at the end returned to reloc_start:





Now call relocation code:

ARM(           add     pc, r5, r0              ) @ call relocation code
 294 THUMB(         add     r12, r5, r0             )
 295 THUMB(         mov     pc, r12                 ) @ call relocation code
 296
 
 
/*
 537 * All code following this line is relocatable.  It is relocated by
 538 * the above code to the end of the decompressed kernel image and
 539 * executed there.  During this time, we have no stacks.
 540 *
 541 * r0     = decompressed kernel length
 542 * r1-r3  = unused
 543 * r4     = kernel execution address
 544 * r5     = decompressed kernel start
 545 * r7     = architecture ID
 546 * r8     = atags pointer
 547 * r9-r12,r14 = corrupted
 548 */

 Fig: State of the code with only first line of the  relocation code is executed:


From fig, we see that R9 holds the source_end addr. We decrement this addr. by 128 bytes to skip copying stack. So, R9=@0x8043B468. We see that R4 holds the expected kernel execution address.(0x80008000)
R1 = R4
R5=@0x8016E668 holds the start addr of the source.
We start copying this image code from R5 and store it at addr pointed to by R1

After relocating kernel image, relocate stack as ell. New stack is now R13=@0x802D4EE0

With everything relocated, do a cache flush and turn cache off.

    call_kernel:    bl      cache_clean_flush
 567                bl      cache_off


Finally call kernel placed at exact 0x80008000 location!


mov     r0, #0                  @ must be zero
 569                mov     r1, r7                  @ restore architecture number
 570                mov     r2, r8                  @ restore atags pointer
 571                mov     pc, r4                  @ call kernel

Note R4 value, at which control flow jumps to!



After this, we enter start label inside actual kernel code for the first time!
/arch/arm/kernel/head.S
ENTRY(stext)

Monday, July 26, 2010

Entry point Debugging contd....

After initializing PTE, we move to next stages:


/*
 431 * If ever we are running from Flash, then we surely want the cache
 432 * to be enabled also for our execution instance...  We map 2MB of it
 433 * so there is no map overlap problem for up to 1 MB compressed kernel.
 434 * If the execution is in RAM then we would only be duplicating the above.
 435 */
What we do here is to take a magic addr value 0xC1E, OR it with Higher 12 PC bits
to obtain 0x80000C1E in R1.
Also, with higher 12 PC bits, we do only #2 lsl and add it with PTE addr 0x80004000
to obtain address 0x80006000 in R0.
 
We now save the value of R1 in [R0].
(Actually, 0x80006000 already had same value!, redundant code if we are not running
from FLASH memory!).
 
Next add R1 = R1 + 0x100000 = 0x80100C1E
store this value in R0+4 = 0x80006004 (Again redundant for RAM code!).
Now, branch back to _armv7_mmu_cache_on
_armv7_mmu_cache_on:
Drain write buffer. Again test ID_MMFR0 stored in R11 with VMSA(0xF).
If not equal, flush I,D, TLBs.
Now load C1,C0 reg to R0, 
R0 = I-cache enable, RR cache replacement and write buffers are set.
R0 = MMU Enable bit set
[R0=0x00C5587F]  
Load R3 containing Page table Pointer to C2,C0
[R3= 0x800040000]
Load R1=0xFFFFFFFF = -1
Load this R1 value to domain access control reg. C3,C0
Fig: This is the view of MMU regs. Note that highlighted DACR value changed from DO
to Manager after R1 was set)
**** Finally load R0 value to C1,C0 to Caches, TLBs and MMU ****
Now, we suddenly switch to VM context, Lauterbach goes for a toss if not properly
configured to handle MMU page tables!!
 
Fig: This is the view of MMU regs. after MMU enabled. Compare with previous pic to
see what register values actually changed when MMU was enabled!) 
 
 
 
If properly configured, we continue debugging. Above pic shows what we see when we
had Lauterbach configured properly to handle MMU changes!
Read back MMU control reg value to R0
R0 = 0x00C5187F
This ensures everything was configured correctly!
Next, load R0 with #0 and push it to C7,C4 reg to configure ISB (?!!)
Finally retrieve back original return addr previously secured in R12 reg. 
 
We have now returned back to start function, after successfully executing cache_on
Next, allocate malloc space above stack, but 64K max. (Refer to mem. mapping fig.)
Malloc space ends @0x8016e668
/*
 247 * Check to see if we will overwrite ourselves.
 248 *   r4 = final kernel address
 249 *   r5 = start of this image
 250 *   r2 = end of malloc space (and therefore this image)
 251 * We basically want:
 252 *   r4 >= r2 -> OK
 253 *   r4 + image length <= r5 -> OK
 254 */
This is the  state before we proceed further. Check above reg. values to see the 
behavior.

Entry point Debugging

Save reg. R1 & R2 containing Machine ID & ATAG pointer respectively.
Also, note that R0 is 0 by default, as passed by u-boot due to legacy coding.

At first, we ensure that if we are running in SVC mode, if not we need to change to SVC. (In our case, we are in SVC mode as passed by u-boot).

Next, disable interrupts if not already done (We already have it disabled).

Next we check if we are running from the addr. from where we had compiled, using our compiled LC0 addr. with the current LC0 addr. (LC0 table is in the same file).
In our case, LC0 is @0x80008138 while compiled addr is @0x138. We have an offset of 0x80008000, so we append this offset to all entries in the LC0 table. The changes are as follows:

Label                 Reg                                Compiled val      New value(with added offset)
LC0                      r1                                    0x0138                0x0138
__bss_start           r2                                    0x0015564c         0x8015d64c
_end                     r3                                    0x00155668          0x8015d668

zreladdr                 r4 <-Already holds 0x80008000

_start                    r5                                  0x0                       0x80008000
_got_start              r6->r11(changed)           0x00155618           0x8015d618
_got_end               ip (r12)                          0x00155640           0x8015d640

user_stack+4096   sp (r13)                          0x00156668           0x8015e668


---------------------- malloc space (0x8016e668)

64K Max.

---------------------- user stack (0x8015e668)


---------------------- _end (0x8015d668)


---------------------- __bss_start (0x8015d64c)



---------------------- _got_end (0x8015d640)



---------------------- _got_start(0x8015d618)




---------------------- _start (0x80008000)


Relocate all entries in GOT(r11) as well.
Clear bss (r2) till bss_end(r3).


Now C environment should be setup,
Turn the cache on, set up some pointers, and start decompressing.
Jump to cache_on (@0x80008160)
cache_on:
Turn on the cache.  We need to setup some page tables so that we 
can have both the I and D caches on. 
We place the page tables 16k down from the kernel execution address,
and we hope that nothing else is using it.  If we're using it, we
will go pop!
* On entry,
 r4 = kernel execution address
 r6 = processor ID
 r7 = architecture number
 r8 = atags pointer
 r9 = run-time address of "start"  (???)
 On exit,
  r1, r2, r3, r9, r10, r12 corrupted
 This routine must preserve:
 346 *  r4, r5, r6, r7, r8
Sub branching to call_cache_fn()
/*
 575 * Here follow the relocatable cache support functions for the
 576 * various processors.  This is a generic hook for locating an
 577 * entry and jumping to an instruction at the specified offset
 578 * from the start of the block.  Please note this is all position
 579 * independent code.
 580 *
 581 *  r1  = corrupted
 582 *  r2  = corrupted
 583 *  r3  = block offset
 584 *  r6  = corrupted
 585 *  r12 = corrupted
 586 */
 
(proc_types @0x800083f8 for beagle)
In this function, we read processor id from c0,c0 co-processor reg and
start comparing with proc_types table entries. Each table value, along
with its mask is compared until match is found.
 
For Beagle, this is the matching table entry:
.word   0x000f0000              @ new CPU Id
 761                .word   0x000f0000
 762                W(b)    __armv7_mmu_cache_on
 763                W(b)    __armv7_mmu_cache_off
 764                W(b)    __armv7_mmu_cache_flush
 
 
Once a match is found, we jump to corresponding functions. In our case,
we jump to __armv7_mmu_cache_on
 
Here, first we preserve lr value in r12.
Read ID_MMFR0 (For beagle, its 0x31100003), test with VMSA(0xF) and see that 
they are not equal.Hence, jump to __setup_mmu.
 
__setup_mmu:
 R3 = R4 - 16384 (R4=0x80008000, Subtract 16K below entry point, where MMU Page table
will be set)
We will first see if R3 value is aligned for 0xff, if not align it.
In our  case, R3=0x80004000 is perfectly aligned, so do nothing!
Now, start initializing the page tables, turning on cacheable and bufferable bits for 
RAM area only.
From R3, lsr 18 times to get 0x2000
Again lsl 18 times, we get 0x80000000.Save in R9. This would be the start of RAM address!
(What we did here is to ignore lower 18 bit offset and consider only upper 16 bits)
Add another 0x10000000 to above value to get a reasonable RAM size that we can assume.
So, it would be 0x90000000. Save it in R10.
So R9=0x80000000 and R10=0x90000000 gives an estimated RAM start and end values.
Next we will take another magic value of 18 and OR with 3<<10, which ends up as 0x0C12 in 
R1. This will be our initial VA
 
Finally, set R2 = (R3+16k) = 0x80008000.
 
#VA-PA1
Compare R1 with R9 (VA with PA):
If VA > PA, we set R1 = R1 | 0x0C to make it cacheable, bufferable
Next, compare R1 with R10 (if now VA > PA end), if true
If VA > PA, we set R1 = R1 | 0x0C, to clear cacheable and bufferable.
So, what we do from above procedure is to set any VA address between PA start and PA end 
to be cacheable and bufferable!
Finally, after above checks, save VA at the page table.
#VA-PA2 
Now, update VA addr. Add another 0x100000 to existing VA value.
This is nothing but creating first level Page Table, with 1MB sections. 
Repeat the above steps from #VA-PA1 to #VA-PA2 for entire 16K PTE.
 
Below is the final dump of the 16K PTEs:
 
 















Code flow, Mem Configuration

We load image @0x80300000 in RAM using
mmcinit
fatload mmc 0 0x80300000 uImage.bin
bootm 0x80300000

We have our uImage.bin compiled and defined with a load addr and entry addr @0x80008000 using mkimage tool of u-boot.
So, when the image is loaded, the code starts its execution from addr @0x80008000.
Put a breakpoint @0x80008000, which defines  the first instrn. exec addr of uImage.bin.
This happens to be the code @
linux/arch/arm/boot/compressed/head.S, beginning at the label start:

Tuesday, July 13, 2010

Hanging at jiffies, missing timer clock function

With the addition of Machine Descriptor, I managed to progress a bit, but now I see that the linux kernel boot hangs waiting for jiffies value to be incremented by the timer function.

So, the next step is to implement OMAP timer functionality....

Machine Descriptor

Even though previous image was built successfully, the image crashed while looking for a board irq initialization function. So created a new file (called dummy.c for now) under mach-puppybeagle directory with the following content:

#include
#include
#include
#include
#include


#define    PUPPY_L4_BASE            0x48000000
#define PUPPY_SDRAM_BASE        0x80000000


void arch_reset(char mode, const char *cmd)
{

}

void arch_idle(void)
{

}

void puppy_timer_init(void)
{

}

struct sys_timer puppy_sys_timer = {
    .init = puppy_timer_init,
};


void puppy_irq_init(void)
{
    //printk ("puppy_irq_init++\n");
}

void puppy_board_init(void)
{

}

MACHINE_START(PUPPYBEAGLE, "PuppyBeagle")
    .phys_io    = PUPPY_L4_BASE,
    .boot_params    = PUPPY_SDRAM_BASE + 0x100,
    .timer        = &puppy_sys_timer,
    .init_irq    = puppy_irq_init,
    .init_machine    = puppy_board_init,
MACHINE_END