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>