Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 May 2011 04:10:44 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222400 - head/sys/powerpc/booke
Message-ID:  <201105280410.p4S4AiSk067132@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105280410.p4S4AiSk067132>