Author: marcel
Date: Sat May 28 04:10:44 2011
New Revision: 222400
URL: http://svn.freebsd.org/changeset/base/222400

Log:
  Better support different kernel hand-offs. When loaded directly
  from U-Boot, the kernel is passed a standard argc/argv pair.
  The Juniper loader passes the metadata pointer as the second
  argument and passes 0 in the first. The FreeBSD loader passes
  the metadata pointer in the first argument.
  
  As such, have locore preserve the first 2 arguments in registers
  r30 & r31. Change e500_init() to accept these arguments. Don't
  pass global offsets (i.e. kernel_text and _end) as arguments to
  e500_init(). We can reference those directly.
  
  Rename e500_init() to booke_init() now that we're changing the
  prototype.
  
  In booke_init(), "decode" arg1 and arg2 to obtain the metadata
  pointer correctly. For the U-Boot case, clear SBSS and BSS and
  bank on having a static FDT for now. This allows loading the
  ELF kernel and jumping to the entry point without trampoline.

Modified:
  head/sys/powerpc/booke/locore.S
  head/sys/powerpc/booke/machdep.c
  head/sys/powerpc/booke/pmap.c

Modified: head/sys/powerpc/booke/locore.S
==============================================================================
--- head/sys/powerpc/booke/locore.S     Sat May 28 00:58:19 2011        
(r222399)
+++ head/sys/powerpc/booke/locore.S     Sat May 28 04:10:44 2011        
(r222400)
@@ -83,17 +83,18 @@ __start:
  * locore registers use:
  *     r1      : stack pointer
  *     r2      : trace pointer (AP only, for early diagnostics)
- *     r3-r27  : scratch registers
- *     r28     : kernload
- *     r29     : temp TLB1 entry
- *     r30     : initial TLB1 entry we started in
- *     r31     : metadata pointer
+ *     r3-r26  : scratch registers
+ *     r27     : kernload
+ *     r28     : temp TLB1 entry
+ *     r29     : initial TLB1 entry we started in
+ *     r30-r31 : arguments (metadata pointer)
  */
 
 /*
- * Keep metadata ptr in r31 for later use.
+ * Keep arguments in r30 & r31 for later use.
  */
-       mr      %r31, %r3
+       mr      %r30, %r3
+       mr      %r31, %r4
 
 /*
  * Initial cleanup
@@ -120,7 +121,7 @@ __start:
  */
        bl      1f
 1:     mflr    %r3
-       bl      tlb1_find_current       /* the entry number found is returned 
in r30 */
+       bl      tlb1_find_current       /* the entry found is returned in r29 */
 
        bl      tlb1_inval_all_but_current
 /*
@@ -140,7 +141,7 @@ __start:
 /*
  * Invalidate initial entry
  */
-       mr      %r3, %r30
+       mr      %r3, %r29
        bl      tlb1_inval_entry
 
 /*
@@ -170,7 +171,7 @@ __start:
        bl      3f
 3:     mflr    %r4                     /* Use current address */
        rlwinm  %r4, %r4, 0, 0, 7       /* 16MB alignment mask */
-       mr      %r28, %r4               /* Keep kernel load address */
+       mr      %r27, %r4               /* Keep kernel load address */
        ori     %r4, %r4, (MAS3_SX | MAS3_SW | MAS3_SR)@l
        mtspr   SPR_MAS3, %r4           /* Set RPN and protection */
        isync
@@ -193,7 +194,7 @@ __start:
 /*
  * Invalidate temp mapping
  */
-       mr      %r3, %r29
+       mr      %r3, %r28
        bl      tlb1_inval_entry
 
 /*
@@ -201,7 +202,7 @@ __start:
  */
        lis     %r3, kernload@ha
        addi    %r3, %r3, kernload@l
-       stw     %r28, 0(%r3)
+       stw     %r27, 0(%r3)
 #ifdef SMP
        /*
         * APs need a separate copy of kernload info within the __boot_page
@@ -210,7 +211,7 @@ __start:
         */
        lis     %r3, kernload_ap@ha
        addi    %r3, %r3, kernload_ap@l
-       stw     %r28, 0(%r3)
+       stw     %r27, 0(%r3)
        msync
 #endif
 
@@ -229,14 +230,11 @@ __start:
 /*
  * Set up arguments and jump to system initialization code
  */
-       lis     %r3, kernel_text@ha
-       addi    %r3, %r3, kernel_text@l
-       lis     %r4, _end@ha
-       addi    %r4, %r4, _end@l
-       mr      %r5, %r31               /* metadata ptr */
+       mr      %r3, %r30
+       mr      %r4, %r31
 
        /* Prepare e500 core */
-       bl      e500_init
+       bl      booke_init
 
        /* Switch to thread0.td_kstack now */
        mr      %r1, %r3
@@ -290,7 +288,7 @@ kernload_ap:
  */
        bl      2f
 2:     mflr    %r3
-       bl      tlb1_find_current       /* the entry number found is in r30 */
+       bl      tlb1_find_current       /* the entry number found is in r29 */
 
        bl      tlb1_inval_all_but_current
 /*
@@ -310,7 +308,7 @@ kernload_ap:
 /*
  * Invalidate initial entry
  */
-       mr      %r3, %r30
+       mr      %r3, %r29
        bl      tlb1_inval_entry
 
 /*
@@ -373,7 +371,7 @@ kernload_ap:
 /*
  * Invalidate temp mapping
  */
-       mr      %r3, %r29
+       mr      %r3, %r28
        bl      tlb1_inval_entry
 
 /*
@@ -425,7 +423,7 @@ tlb_inval_all:
        blr
 
 /*
- * expects address to look up in r3, returns entry number in r30
+ * expects address to look up in r3, returns entry number in r29
  *
  * FIXME: the hidden assumption is we are now running in AS=0, but we should
  * retrieve actual AS from MSR[IS|DS] and put it in MAS6[SAS]
@@ -437,7 +435,7 @@ tlb1_find_current:
        isync
        tlbsx   0, %r3
        mfspr   %r17, SPR_MAS0
-       rlwinm  %r30, %r17, 16, 20, 31          /* MAS0[ESEL] -> r30 */
+       rlwinm  %r29, %r17, 16, 20, 31          /* MAS0[ESEL] -> r29 */
 
        /* Make sure we have IPROT set on the entry */
        mfspr   %r17, SPR_MAS1
@@ -470,14 +468,14 @@ tlb1_inval_entry:
        blr
 
 /*
- * r30         current entry number
- * r29         returned temp entry
+ * r29         current entry number
+ * r28         returned temp entry
  * r3-r5       scratched
  */
 tlb1_temp_mapping_as1:
        /* Read our current translation */
        lis     %r3, MAS0_TLBSEL1@h     /* Select TLB1 */
-       rlwimi  %r3, %r30, 16, 12, 15   /* Select our current entry */
+       rlwimi  %r3, %r29, 16, 12, 15   /* Select our current entry */
        mtspr   SPR_MAS0, %r3
        isync
        tlbre
@@ -489,8 +487,8 @@ tlb1_temp_mapping_as1:
         * entry is the last in TLB1
         */
        lis     %r3, MAS0_TLBSEL1@h     /* Select TLB1 */
-       addi    %r29, %r30, 1           /* Use next entry. */
-       rlwimi  %r3, %r29, 16, 12, 15   /* Select temp entry */
+       addi    %r28, %r29, 1           /* Use next entry. */
+       rlwimi  %r3, %r28, 16, 12, 15   /* Select temp entry */
        mtspr   SPR_MAS0, %r3
        isync
        mfspr   %r5, SPR_MAS1
@@ -510,7 +508,7 @@ tlb1_temp_mapping_as1:
  * Loops over TLB1, invalidates all entries skipping the one which currently
  * maps this code.
  *
- * r30         current entry
+ * r29         current entry
  * r3-r5       scratched
  */
 tlb1_inval_all_but_current:
@@ -524,7 +522,7 @@ tlb1_inval_all_but_current:
        isync
        tlbre
        mfspr   %r5, SPR_MAS1
-       cmpw    %r4, %r30               /* our current entry? */
+       cmpw    %r4, %r29               /* our current entry? */
        beq     2f
        rlwinm  %r5, %r5, 0, 2, 31      /* clear VALID and IPROT bits */
        mtspr   SPR_MAS1, %r5

Modified: head/sys/powerpc/booke/machdep.c
==============================================================================
--- head/sys/powerpc/booke/machdep.c    Sat May 28 00:58:19 2011        
(r222399)
+++ head/sys/powerpc/booke/machdep.c    Sat May 28 04:10:44 2011        
(r222400)
@@ -190,7 +190,7 @@ SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST,
 
 void print_kernel_section_addr(void);
 void print_kenv(void);
-u_int e500_init(u_int32_t, u_int32_t, void *);
+u_int booke_init(uint32_t, uint32_t);
 
 static void
 cpu_e500_startup(void *dummy)
@@ -276,19 +276,41 @@ print_kernel_section_addr(void)
 }
 
 u_int
-e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
+booke_init(uint32_t arg1, uint32_t arg2)
 {
        struct pcpu *pc;
-       void *kmdp;
+       void *kmdp, *mdp;
        vm_offset_t dtbp, end;
        uint32_t csr;
 
        kmdp = NULL;
 
-       end = endkernel;
+       end = (uintptr_t)_end;
        dtbp = (vm_offset_t)NULL;
 
        /*
+        * Handle the various ways we can get loaded and started:
+        *  -   FreeBSD's loader passes the pointer to the metadata
+        *      in arg1, with arg2 undefined. arg1 has a value that's
+        *      relative to the kernel's link address (i.e. larger
+        *      than 0xc0000000).
+        *  -   Juniper's loader passes the metadata pointer in arg2
+        *      and sets arg1 to zero. This is to signal that the
+        *      loader maps the kernel and starts it at its link
+        *      address (unlike the FreeBSD loader).
+        *  -   U-Boot passes the standard argc and argv parameters
+        *      in arg1 and arg2 (resp). arg1 is between 1 and some
+        *      relatively small number, such as 64K. arg2 is the
+        *      physical address of the argv vector.
+        */
+       if (arg1 > (uintptr_t)kernel_text)      /* FreeBSD loader */
+               mdp = (void *)arg1;
+       else if (arg1 == 0)                     /* Juniper loader */
+               mdp = (void *)arg2;
+       else                                    /* U-Boot */
+               mdp = NULL;
+
+       /*
         * Parse metadata and fetch parameters.
         */
        if (mdp != NULL) {
@@ -309,17 +331,8 @@ e500_init(u_int32_t startkernel, u_int32
 #endif
                }
        } else {
-               /*
-                * We should scream but how? Cannot even output anything...
-                */
-
-                /*
-                 * FIXME add return value and handle in the locore so we can
-                 * return to the loader maybe? (this seems not very easy to
-                 * restore everything as the TLB have all been reprogrammed
-                 * in the locore etc...)
-                 */
-               while (1);
+               bzero(__sbss_start, __sbss_end - __sbss_start);
+               bzero(__bss_start, _end - __bss_start);
        }
 
 #if defined(FDT_DTB_STATIC)
@@ -368,9 +381,7 @@ e500_init(u_int32_t startkernel, u_int32
        cninit();
 
        /* Print out some debug info... */
-       debugf("e500_init: console initialized\n");
-       debugf(" arg1 startkernel = 0x%08x\n", startkernel);
-       debugf(" arg2 endkernel = 0x%08x\n", endkernel);
+       debugf("%s: console initialized\n", __func__);
        debugf(" arg3 mdp = 0x%08x\n", (u_int32_t)mdp);
        debugf(" end = 0x%08x\n", (u_int32_t)end);
        debugf(" boothowto = 0x%08x\n", boothowto);
@@ -403,7 +414,7 @@ e500_init(u_int32_t startkernel, u_int32
 
        /* Initialise virtual memory. */
        pmap_mmu_install(MMU_TYPE_BOOKE, 0);
-       pmap_bootstrap(startkernel, end);
+       pmap_bootstrap((uintptr_t)kernel_text, end);
        debugf("MSR = 0x%08x\n", mfmsr());
        //tlb1_print_entries();
        //tlb1_print_tlbentries();
@@ -449,8 +460,8 @@ e500_init(u_int32_t startkernel, u_int32
                printf("L1 I-cache %sabled\n",
                    (csr & L1CSR1_ICE) ? "en" : "dis");
 
-       debugf("e500_init: SP = 0x%08x\n", ((uintptr_t)thread0.td_pcb - 16) & 
~15);
-       debugf("e500_init: e\n");
+       debugf("%s: SP = 0x%08x\n", __func__,
+           ((uintptr_t)thread0.td_pcb - 16) & ~15);
 
        return (((uintptr_t)thread0.td_pcb - 16) & ~15);
 }

Modified: head/sys/powerpc/booke/pmap.c
==============================================================================
--- head/sys/powerpc/booke/pmap.c       Sat May 28 00:58:19 2011        
(r222399)
+++ head/sys/powerpc/booke/pmap.c       Sat May 28 04:10:44 2011        
(r222400)
@@ -943,7 +943,7 @@ pte_find(mmu_t mmu, pmap_t pmap, vm_offs
 /**************************************************************************/
 
 /*
- * This is called during e500_init, before the system is really initialized.
+ * This is called during booke_init, before the system is really initialized.
  */
 static void
 mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to