Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Sep 2008 14:11:30 GMT
From:      Rafal Jaworowski <raj@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 150350 for review
Message-ID:  <200809231411.m8NEBUQA086574@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=150350

Change 150350 by raj@raj_mimi on 2008/09/23 14:10:58

	Handle loader-provided metadata on ARM.
	
	The bootinfo, kernel flags and loader env variables are now fully
	processed by initarm().
	
	Note we preserve backwards compatibility for cases when metadata is
	not handed over (kernel started directly without loader(8) and
	similar). To manage this some critical board info (mem size in
	particular) needs to be hard coded to fall back to.
	
	Obtained from:	Semihalf

Affected files ...

.. //depot/projects/arm/src/sys/arm/arm/locore.S#28 edit
.. //depot/projects/arm/src/sys/arm/mv/discovery/db78xxx.c#2 edit
.. //depot/projects/arm/src/sys/arm/mv/discovery/std.db78xxx#2 edit
.. //depot/projects/arm/src/sys/arm/mv/kirkwood/db88f6xxx.c#3 edit
.. //depot/projects/arm/src/sys/arm/mv/kirkwood/std.db88f6xxx#3 edit
.. //depot/projects/arm/src/sys/arm/mv/mv_machdep.c#4 edit
.. //depot/projects/arm/src/sys/arm/mv/orion/db88f5xxx.c#6 edit
.. //depot/projects/arm/src/sys/arm/mv/orion/std.db88f5xxx#4 edit
.. //depot/projects/arm/src/sys/conf/options.arm#31 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/arm/locore.S#28 (text+ko) ====

@@ -66,6 +66,13 @@
 ENTRY_NP(btext)
 
 ASENTRY_NP(_start)
+
+/*
+ * Move metadata ptr to r12 (ip)
+ */
+
+	mov	ip, r0
+
 #if defined (FLASHADDR) && defined(LOADERRAMADDR)
 	/* Check if we're running from flash. */
 	ldr	r7, =FLASHADDR
@@ -170,6 +177,8 @@
 	ldr	pc, .Lvirt_done
 
 virt_done:
+	mov	r0, ip			/* Load argument: metadata ptr */
+
 	mov	fp, #0			/* trace back starts here */
 	bl	_C_LABEL(initarm)	/* Off we go */
 

==== //depot/projects/arm/src/sys/arm/mv/discovery/db78xxx.c#2 (text+ko) ====

@@ -92,17 +92,6 @@
 	return (0);
 }
 
-long
-platform_ramsize(void)
-{
-
-	/*
-	 * XXX hard coded for now -- will be retrieved from bootloader
-	 * dynamically, eventually.
-	 */
-	return (512 << 20);
-}
-
 static void
 platform_identify(void *dummy)
 {

==== //depot/projects/arm/src/sys/arm/mv/discovery/std.db78xxx#2 (text+ko) ====

@@ -9,4 +9,5 @@
 options		KERNPHYSADDR=0x00200000
 options		KERNVIRTADDR=0xc0200000
 options		PHYSADDR=0x00000000
+options		PHYSMEM_SIZE=0x20000000
 options		STARTUP_PAGETABLE_ADDR=0x00100000

==== //depot/projects/arm/src/sys/arm/mv/kirkwood/db88f6xxx.c#3 (text+ko) ====

@@ -106,17 +106,6 @@
 	return (0);
 }
 
-long
-platform_ramsize(void)
-{
-
-	/*
-	 * XXX hard coded for now -- will be retrieved from bootloader
-	 * dynamically, eventually.
-	 */
-	return (512 << 20);
-}
-
 static void
 platform_identify(void *dummy)
 {

==== //depot/projects/arm/src/sys/arm/mv/kirkwood/std.db88f6xxx#3 (text+ko) ====

@@ -9,4 +9,5 @@
 options		KERNPHYSADDR=0x00900000
 options		KERNVIRTADDR=0xc0900000
 options		PHYSADDR=0x00000000
+options		PHYSMEM_SIZE=0x20000000
 options		STARTUP_PAGETABLE_ADDR=0x00100000

==== //depot/projects/arm/src/sys/arm/mv/mv_machdep.c#4 (text+ko) ====

@@ -83,9 +83,16 @@
 #include <machine/armreg.h>
 #include <machine/bus.h>
 #include <sys/reboot.h>
+#include <machine/bootinfo.h>
 
 #include <arm/mv/mvvar.h>	/* XXX eventually this should be eliminated */
 
+#ifdef  DEBUG
+#define debugf(fmt, args...) printf(fmt, ##args)
+#else
+#define debugf(fmt, args...)
+#endif
+
 #define KERNEL_PT_SYS	0	/* Page table for mapping proc0 zero page */
 #define KERNEL_PT_KERN	1
 
@@ -101,16 +108,24 @@
 #define ABT_STACK_SIZE	1
 #define UND_STACK_SIZE	1
 
+/* Maximum number of memory regions */
+#define MEM_REGIONS	8
+
+extern unsigned char kernbase[];
+extern unsigned char _etext[];
+extern unsigned char _edata[];
+extern unsigned char __bss_start[];
+extern unsigned char _end[];
+
 extern u_int data_abort_handler_address;
 extern u_int prefetch_abort_handler_address;
 extern u_int undefined_handler_address;
 
-extern const struct pmap_devmap	*pmap_devmap_bootstrap_table;
-extern vm_offset_t		pmap_bootstrap_lastaddr;
+extern const struct pmap_devmap *pmap_devmap_bootstrap_table;
+extern vm_offset_t pmap_bootstrap_lastaddr;
 
 struct pv_addr kernel_pt_table[KERNEL_PT_MAX];
 
-extern void *_end;
 extern int *end;
 
 struct pcpu __pcpu;
@@ -131,21 +146,283 @@
 
 static struct trapframe proc0_tf;
 
+struct mem_region {
+	vm_offset_t	mr_start;
+	vm_size_t	mr_size;
+};
+
+static struct mem_region availmem_regions[MEM_REGIONS];
+static int availmem_regions_sz;
+
+struct bootinfo *bootinfo;
+
+static void print_kenv(void);
+static void print_kernel_section_addr(void);
+static void print_bootinfo(void);
+
+static void physmap_init(int);
+
+static char *
+kenv_next(char *cp)
+{
+
+	if (cp != NULL) {
+		while (*cp != 0)
+			cp++;
+		cp++;
+		if (*cp == 0)
+			cp = NULL;
+	}
+	return (cp);
+}
+
+static void
+print_kenv(void)
+{
+	int len;
+	char *cp;
+
+	debugf("loader passed (static) kenv:\n");
+	if (kern_envp == NULL) {
+		debugf(" no env, null ptr\n");
+		return;
+	}
+	debugf(" kern_envp = 0x%08x\n", (uint32_t)kern_envp);
+
+	len = 0;
+	for (cp = kern_envp; cp != NULL; cp = kenv_next(cp))
+		debugf(" %x %s\n", (uint32_t)cp, cp);
+}
+
+static void
+print_bootinfo(void)
+{
+	struct bi_mem_region *mr;
+	struct bi_eth_addr *eth;
+	int i, j;
+
+	debugf("bootinfo:\n");
+	if (bootinfo == NULL) {
+		debugf(" no bootinfo, null ptr\n");
+		return;
+	}
+
+	debugf(" version = 0x%08x\n", bootinfo->bi_version);
+	debugf(" ccsrbar = 0x%08x\n", bootinfo->bi_bar_base);
+	debugf(" cpu_clk = 0x%08x\n", bootinfo->bi_cpu_clk);
+	debugf(" bus_clk = 0x%08x\n", bootinfo->bi_bus_clk);
+
+	debugf(" mem regions:\n");
+	mr = (struct bi_mem_region *)bootinfo->bi_data;
+	for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++)
+		debugf("    #%d, base = 0x%08x, size = 0x%08x\n", i,
+		    mr->mem_base, mr->mem_size);
+
+	debugf(" eth addresses:\n");
+	eth = (struct bi_eth_addr *)mr;
+	for (i = 0; i < bootinfo->bi_eth_addr_no; i++, eth++) {
+		debugf("    #%d, addr = ", i);
+		for (j = 0; j < 6; j++)
+			debugf("%02x ", eth->mac_addr[j]);
+		debugf("\n");
+	}
+}
+
+static void
+print_kernel_section_addr(void)
+{
+
+	debugf("kernel image addresses:\n");
+	debugf(" kernbase       = 0x%08x\n", (uint32_t)kernbase);
+	debugf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext);
+	debugf(" _edata         = 0x%08x\n", (uint32_t)_edata);
+	debugf(" __bss_start    = 0x%08x\n", (uint32_t)__bss_start);
+	debugf(" _end           = 0x%08x\n", (uint32_t)_end);
+}
+
+struct bi_mem_region *
+bootinfo_mr(void)
+{
+
+	return ((struct bi_mem_region *)bootinfo->bi_data);
+}
+
+static void
+physmap_init(int hardcoded)
+{
+	int i, j, cnt;
+	vm_offset_t phys_kernelend, kernload;
+	uint32_t s, e, sz;
+	struct mem_region *mp, *mp1;
+
+	phys_kernelend = KERNPHYSADDR + (virtual_avail - KERNVIRTADDR);
+	kernload = KERNPHYSADDR;
+
+	/*
+	 * Use hardcoded physical addresses if we don't use memory regions
+	 * from metadata.
+	 */
+	if (hardcoded) {
+		phys_avail[0] = 0;
+		phys_avail[1] = kernload;
+
+		phys_avail[2] = phys_kernelend;
+		phys_avail[3] = PHYSMEM_SIZE;
+
+		phys_avail[4] = 0;
+		phys_avail[5] = 0;
+		return;
+	}
+
+	/*
+	 * Remove kernel physical address range from avail
+	 * regions list. Page align all regions.
+	 * Non-page aligned memory isn't very interesting to us.
+	 * Also, sort the entries for ascending addresses.
+	 */
+	sz = 0;
+	cnt = availmem_regions_sz;
+	debugf("processing avail regions:\n");
+	for (mp = availmem_regions; mp->mr_size; mp++) {
+		s = mp->mr_start;
+		e = mp->mr_start + mp->mr_size;
+		debugf(" %08x-%08x -> ", s, e);
+		/* Check whether this region holds all of the kernel. */
+		if (s < kernload && e > phys_kernelend) {
+			availmem_regions[cnt].mr_start = phys_kernelend;
+			availmem_regions[cnt++].mr_size = e - phys_kernelend;
+			e = kernload;
+		}
+		/* Look whether this regions starts within the kernel. */
+		if (s >= kernload && s < phys_kernelend) {
+			if (e <= phys_kernelend)
+				goto empty;
+			s = phys_kernelend;
+		}
+		/* Now look whether this region ends within the kernel. */
+		if (e > kernload && e <= phys_kernelend) {
+			if (s >= kernload) {
+				goto empty;
+			}
+			e = kernload;
+		}
+		/* Now page align the start and size of the region. */
+		s = round_page(s);
+		e = trunc_page(e);
+		if (e < s)
+			e = s;
+		sz = e - s;
+		debugf("%08x-%08x = %x\n", s, e, sz);
+
+		/* Check whether some memory is left here. */
+		if (sz == 0) {
+		empty:
+			printf("skipping\n");
+			bcopy(mp + 1, mp,
+			    (cnt - (mp - availmem_regions)) * sizeof(*mp));
+			cnt--;
+			mp--;
+			continue;
+		}
+
+		/* Do an insertion sort. */
+		for (mp1 = availmem_regions; mp1 < mp; mp1++)
+			if (s < mp1->mr_start)
+				break;
+		if (mp1 < mp) {
+			bcopy(mp1, mp1 + 1, (char *)mp - (char *)mp1);
+			mp1->mr_start = s;
+			mp1->mr_size = sz;
+		} else {
+			mp->mr_start = s;
+			mp->mr_size = sz;
+		}
+	}
+	availmem_regions_sz = cnt;
+
+	/* Fill in phys_avail table, based on availmem_regions */
+	debugf("fill in phys_avail:\n");
+	for (i = 0, j = 0; i < availmem_regions_sz; i++, j += 2) {
+
+		debugf(" region: 0x%08x - 0x%08x (0x%08x)\n",
+		    availmem_regions[i].mr_start,
+		    availmem_regions[i].mr_start + availmem_regions[i].mr_size,
+		    availmem_regions[i].mr_size);
+
+		phys_avail[j] = availmem_regions[i].mr_start;
+		phys_avail[j + 1] = availmem_regions[i].mr_start +
+		    availmem_regions[i].mr_size;
+	}
+	phys_avail[j] = 0;
+	phys_avail[j + 1] = 0;
+}
+
 void *
-initarm(void *arg, void *arg2)
+initarm(void *mdp, void *unused __unused)
 {
-	struct pv_addr  kernel_l1pt;
+	struct pv_addr kernel_l1pt;
+	vm_offset_t freemempos, l2_start, lastaddr;
+	uint32_t memsize, l2size;
+	struct bi_mem_region *mr;
+	void *kmdp;
+	u_int l1pagetable;
 	int i = 0;
-	u_int l1pagetable;
-	vm_offset_t freemempos;
-	vm_offset_t l2_start;
-	vm_offset_t lastaddr;
-	uint32_t memsize, l2size;
 
-	boothowto = RB_VERBOSE | RB_SINGLE;
+	kmdp = NULL;
+	lastaddr = 0;
+	memsize = 0;
 
 	set_cpufuncs();
-	lastaddr = fake_preload_metadata();
+
+	/*
+	 * Mask metadata pointer: it is supposed to be on page boundary. If
+	 * the first agrument (mdp) doesn't point to a valid address the
+	 * bootloader must have passed us something else than the metadata
+	 * ptr... In this case we want to fall back to some built-in settings.
+	 */
+	mdp = (void *)((uint32_t)mdp & ~PAGE_MASK);
+
+	/* Parse metadata and fetch parameters */
+	if (mdp != NULL) {
+		preload_metadata = mdp;
+		kmdp = preload_search_by_type("elf kernel");
+		if (kmdp != NULL) {
+			bootinfo = (struct bootinfo *)preload_search_info(kmdp,
+			    MODINFO_METADATA|MODINFOMD_BOOTINFO);
+
+			boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
+			kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
+			lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
+		}
+
+		/* Initialize memory regions table */
+		mr = bootinfo_mr();
+		for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++) {
+			if (i == MEM_REGIONS)
+				break;
+			availmem_regions[i].mr_start = mr->mem_base;
+			availmem_regions[i].mr_size = mr->mem_size;
+			memsize += mr->mem_size;
+		}
+		availmem_regions_sz = i;
+	} else {
+		/* Fall back to hardcoded boothowto flags and metadata. */
+		boothowto = RB_VERBOSE | RB_SINGLE;
+		lastaddr = fake_preload_metadata();
+
+		/*
+		 * Assume a single memory region of size specified in board
+		 * configuration file.
+		 */
+		memsize = PHYSMEM_SIZE;
+	}
+
+	/*
+	 * If memsize is invalid, we can neither proceed nor panic (too
+	 * early for console output).
+	 */
+	if (memsize == 0)
+		while (1);
 
 	/* Platform-specific initialisation */
 	if (platform_pmap_init() != 0)
@@ -154,13 +431,11 @@
 	pcpu_init(pcpup, 0, sizeof(struct pcpu));
 	PCPU_SET(curthread, &thread0);
 
-	memsize = platform_ramsize();
-	
 	/* Calculate number of L2 tables needed for mapping vm_page_array */
 	l2size = (memsize / PAGE_SIZE) * sizeof(struct vm_page);
 	l2size = (l2size >> L1_S_SHIFT) + 1;
 
-	/* 
+	/*
 	 * Add one table for end of kernel map, one for stacks, msgbuf and
 	 * L1 and L2 tables map and one for vectors map.
 	 */
@@ -270,6 +545,13 @@
 	cninit();
 	physmem = memsize / PAGE_SIZE;
 
+	debugf("initarm: console initialized\n");
+	debugf(" arg1 mdp = 0x%08x\n", (uint32_t)mdp);
+	debugf(" boothowto = 0x%08x\n", boothowto);
+	print_bootinfo();
+	print_kernel_section_addr();
+	print_kenv();
+
 	/*
 	 * Re-initialise decode windows
 	 */
@@ -304,10 +586,7 @@
 	 */
 	cpu_idcache_wbinv_all();
 
-	bootverbose = 1;
-
 	/* Set stack for exception handlers */
-
 	data_abort_handler_address = (u_int)data_abort_handler;
 	prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
 	undefined_handler_address = (u_int)undefinedinstruction_bounce;
@@ -334,14 +613,12 @@
 	msgbufinit(msgbufp, MSGBUF_SIZE);
 	mutex_init();
 
-	phys_avail[0] = 0;
-	phys_avail[1] = KERNPHYSADDR;
-
-	phys_avail[2] = KERNPHYSADDR + (virtual_avail - KERNVIRTADDR);
-	phys_avail[3] = memsize;
-	
-	phys_avail[4] = 0;
-	phys_avail[5] = 0;
+	/*
+	 * Prepare map of physical memory regions available to vm subsystem.
+	 * If metadata pointer doesn't point to a valid address, use hardcoded
+	 * values.
+	 */
+	physmap_init((mdp != NULL) ? 0 : 1);
 
 	/* Do basic tuning, hz etc */
 	init_param1();

==== //depot/projects/arm/src/sys/arm/mv/orion/db88f5xxx.c#6 (text+ko) ====

@@ -159,18 +159,6 @@
 	return (0);
 }
 
-long
-platform_ramsize(void)
-{
-
-	/*
-	 * XXX hard coded for now -- will be retrieved from bootloader
-	 * dynamically, eventually. Fall back should read from mem controller
-	 * if other methods fail.
-	 */
-	return (128 << 20);
-}
-
 static void
 platform_identify(void *dummy)
 {

==== //depot/projects/arm/src/sys/arm/mv/orion/std.db88f5xxx#4 (text+ko) ====

@@ -9,4 +9,5 @@
 options		KERNPHYSADDR=0x00400000
 options		KERNVIRTADDR=0xc0400000
 options		PHYSADDR=0x00000000
+options		PHYSMEM_SIZE=0x08000000
 options		STARTUP_PAGETABLE_ADDR=0x00100000

==== //depot/projects/arm/src/sys/conf/options.arm#31 (text+ko) ====

@@ -22,6 +22,7 @@
 KERNVIRTADDR		opt_global.h
 LOADERRAMADDR		opt_global.h
 PHYSADDR		opt_global.h
+PHYSMEM_SIZE		opt_global.h
 SKYEYE_WORKAROUNDS	opt_global.h
 SOC_MV_DISCOVERY	opt_global.h
 SOC_MV_KIRKWOOD		opt_global.h



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