Date: Sat, 02 Mar 2013 18:18:53 -0700 From: Ian Lepore <ian@FreeBSD.org> To: Tim Kientzle <tim@kientzle.com> Cc: freebsd-arm@FreeBSD.org Subject: Re: PHYSADDR Message-ID: <1362273533.1195.199.camel@revolution.hippie.lan> In-Reply-To: <AC642AAD-8D8C-429E-AE3B-A34241DA2517@kientzle.com> References: <E886046B-1612-425B-902B-72D4B0E93618@freebsd.org> <1362068453.1195.40.camel@revolution.hippie.lan> <674A08B3-6600-4B77-8511-9EF54E4B9B1F@FreeBSD.org> <8FEA3237-8ABF-4564-B672-4B4C0C6EF291@kientzle.com> <1362155632.1195.120.camel@revolution.hippie.lan> <5B622D1B-4EAE-4184-A194-DD14083A48B6@kientzle.com> <1362246634.1195.178.camel@revolution.hippie.lan> <AC642AAD-8D8C-429E-AE3B-A34241DA2517@kientzle.com>
next in thread | previous in thread | raw e-mail | index | archive | help
--=-YTotqcJXRcyvz05kVYP6 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit On Sat, 2013-03-02 at 10:10 -0800, Tim Kientzle wrote: > On Mar 2, 2013, at 9:50 AM, Ian Lepore wrote: > > >[...] > > > I'm not sure its safe to assume that (entry-pc & 0xfffff000) is the > > beginning of the kernel; it's true now but need not be so. But that's > > no big deal, we can tweak the linker script to give us the offset of the > > _start symbol so it'll work no matter what. > > Patches? ;-) This turned out to be a bit trickier than I first thought it would be, but it worked out. This gets rids of any reference to PHYSADDR and similar constants in the main path through the code. I didn't address the "running from flash" case or anything under #ifdef SMP, yet. The only constant left is KERNBASE which is 0xC0000000 for all arm systems. For now I've got #undef PHYSADDR at the top of the code; this is just for testing without having to remove it yet from anywhere else. There are two ldscript changes: define a new ENTRY_OFFSET symbol which is the offset between the start of the load image and the _start symbol, and also it puts the physical addresses in the headers, by calculating a physical value for ENTRY(), and using an AT(expr) for the text segment, which very conviently just flows to the following segments without needing to re-specify it on every new segment. This isn't ready to commit, but it's ready to play with, and to get comments from folks who know some of the history of this code (Olivier has been helping me on irc all day answering such questions). -- Ian --=-YTotqcJXRcyvz05kVYP6 Content-Description: Content-Disposition: inline; filename="locore_physaddr.diff" Content-Type: text/x-patch; name="locore_physaddr.diff"; charset="us-ascii" Content-Transfer-Encoding: 7bit Index: sys/arm/arm/locore.S =================================================================== --- sys/arm/arm/locore.S (revision 247421) +++ sys/arm/arm/locore.S (working copy) @@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$"); +#undef PHYSADDR + /* What size should this really be ? It is only used by initarm() */ #define INIT_ARM_STACK_SIZE (2048 * 4) @@ -52,16 +54,8 @@ __FBSDID("$FreeBSD$"); mov tmp, tmp /* wait for it to complete */ ;\ CPWAIT_BRANCH /* branch to next insn */ -/* - * This is for kvm_mkdb, and should be the address of the beginning - * of the kernel text segment (not necessarily the same as kernbase). - */ .text .align 0 -.globl kernbase -.set kernbase,KERNBASE -.globl physaddr -.set physaddr,PHYSADDR /* * On entry for FreeBSD boot ABI: @@ -87,7 +81,7 @@ ASENTRY_NP(_start) orr r7, r7, #(I32_bit|F32_bit) msr cpsr_c, r7 -#if defined (FLASHADDR) && defined(LOADERRAMADDR) +#if defined(PHYSADDR) && defined(FLASHADDR) && defined(LOADERRAMADDR) /* Check if we're running from flash. */ ldr r7, =FLASHADDR /* @@ -123,11 +117,23 @@ Lram_offset: .word from_ram-_C_LABEL(_start) from_ram: nop #endif + + /* + * The MMU could be disabled (we're on physical addressing), + * or it could be enabled with VA=PA, or it could be enabled + * with some mystery mapping. In the latter case, there's no + * easy way to recover the current physical address from the PC. + * We could maybe do a manual tlb walk, but for now we'll just + * require that the physical address be provided at compile time. + * This is all legacy stuff to support redboot long ago. + */ + adr r7, Lunmapped +#ifdef PHYSADDR bic r7, r7, #0xf0000000 orr r7, r7, #PHYSADDR +#endif - disable_mmu: /* Disable MMU for a while */ mrc p15, 0, r2, c1, c0, 0 @@ -142,12 +148,39 @@ disable_mmu: nop mov pc, r7 Lunmapped: + +#ifdef PHYSADDR + ldr r6, =PHYSADDR /* If PHYSADDR is provided, use it. */ +#else + adr r0, entry_offset /* Load the linker-provided offset */ + ldr r0, [r0] /* between _start and the start of */ + adr r6, _start /* the image. Subtract the offset */ + sub r6, r6, r0 /* to get the physical load addr. */ +#endif + adr r0, kern_physaddr /* Save it (for debugging mostly). */ + str r6, [r0] /* We'll use the addr to build L1 */ + mov r0, #0xff000000 /* section PDEs that map 1MB each; */ + orr r0, #0x00f00000 /* mask the load address to round */ + and r6, r6, r0 /* to previous 1MB boundary. */ + #ifdef STARTUP_PAGETABLE_ADDR + /* build page table from scratch */ - ldr r0, Lstartup_pagetable adr r4, mmu_init_table - b 3f +#define fix_mmu_init(offset) \ + ldr r0, [r4, offset] ; \ + orr r0, r0, r6 ; \ + str r0, [r4, offset] + + fix_mmu_init(#4) /* Adjust the va and pa values in */ + fix_mmu_init(#8) /* the first two mmu init table */ + fix_mmu_init(#16) /* entries to the actual physical */ + fix_mmu_init(#20) /* load address calculated above. */ + + ldr r0, Lstartup_pagetable + b 3f /* Go start building the table. */ + 2: str r3, [r0, r2] add r2, r2, #4 @@ -156,11 +189,9 @@ Lunmapped: bhi 2b 3: ldmia r4!, {r1,r2,r3} /* # of sections, VA, PA|attr */ + mov r2, r2, LSR #(L1_S_SHIFT-2) cmp r1, #0 - adrne r5, 2b - bicne r5, r5, #0xf0000000 - orrne r5, r5, #PHYSADDR - movne pc, r5 + bne 2b #if defined(SMP) orr r0, r0, #2 /* Set TTB shared memory flag */ @@ -222,15 +253,7 @@ virt_done: b _C_LABEL(panic) /* NOTREACHED */ #ifdef STARTUP_PAGETABLE_ADDR -#define MMU_INIT(va,pa,n_sec,attr) \ - .word n_sec ; \ - .word 4*((va)>>L1_S_SHIFT) ; \ - .word (pa)|(attr) ; -Lvirtaddr: - .word KERNVIRTADDR -Lphysaddr: - .word KERNPHYSADDR Lreal_start: .word _start Lend: @@ -241,21 +264,47 @@ Lstartup_pagetable: Lstartup_pagetable_secondary: .word temp_pagetable #endif -mmu_init_table: - /* fill all table VA==PA */ - /* map SDRAM VA==PA, WT cacheable */ + +/* + * mmu_init_table: data used to construct the initial page tables. + * + * Note that the first two table entries are magical. They establish va=pa and + * kernva=pa mappings for the first 64 mb starting at the kernel's physical load + * address. The virtual and physical addresses of just the first two entries + * are re-written by the code that builds the L1 table, to add in the offset at + * which the kernel is physically loaded/running. Any entries after the first + * two are mapped without modification. This is especially useful for things + * like temporarily adding mappings for serial console hardware for debugging. + */ #if !defined(SMP) - MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) - /* map VA 0xc0000000..0xc3ffffff to PA */ - MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) +#define VM_ATTR_DEV (L1_TYPE_S|L1_S_AP(AP_KRW)) +#define VM_ATTR_RAM (L1_TYPE_S|L1_S_AP(AP_KRW)|L1_S_C) #else - MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW)) - /* map VA 0xc0000000..0xc3ffffff to PA */ - MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW)) - MMU_INIT(0x48000000, 0x48000000, 1, L1_TYPE_S|L1_SHARED|L1_S_C|L1_S_AP(AP_KRW)) +#define VM_ATTR_DEV (L1_TYPE_S|L1_S_AP(AP_KRW)|L1_SHARED) +#define VM_ATTR_RAM (L1_TYPE_S|L1_S_AP(AP_KRW)|L1_SHARED|L1_S_C) #endif + +#define MMU_INIT(va,pa,n_sec,attr) \ + .word (n_sec) ; \ + .word (va) ; \ + .word (pa)|(attr) ; + +mmu_init_table: + MMU_INIT(0, 0, 256, VM_ATTR_RAM) + MMU_INIT(KERNBASE, 0, 256, VM_ATTR_RAM) +/* MMU_INIT(0xFFF00000, 0xFFF00000, 1, VM_ATTR_DEV) example hw entry */ .word 0 /* end of table */ -#endif + +#endif /* STARTUP_PAGETABLE_ADDR */ + + .extern ENTRY_OFFSET /* Import this symbol generated by */ +entry_offset: /* ldscript.arm. It is the offset */ + .word ENTRY_OFFSET /* of _start in the loaded image. */ + + .globl kern_physaddr /* Export calculated addr, mostly */ +kern_physaddr: /* for debugging. There may be */ + .word 0 /* no reason to keep this. */ + .Lstart: .word _edata .word _end Index: sys/conf/ldscript.arm =================================================================== --- sys/conf/ldscript.arm (revision 247421) +++ sys/conf/ldscript.arm (working copy) @@ -1,13 +1,17 @@ /* $FreeBSD$ */ OUTPUT_ARCH(arm) -ENTRY(_start) -SEARCH_DIR(/usr/lib); +PHYSOFFS = KERNVIRTADDR - KERNPHYSADDR; +PHYSENTRY = _start - PHYSOFFS; + +ENTRY(PHYSENTRY) + SECTIONS { /* Read-only sections, merged into text segment: */ . = KERNVIRTADDR + SIZEOF_HEADERS; - .text : + ENTRY_OFFSET = _start - KERNVIRTADDR; + .text : AT(ADDR(.text) - PHYSOFFS) { *(.text) *(.stub) --=-YTotqcJXRcyvz05kVYP6--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1362273533.1195.199.camel>