PHYSADDR
Warner Losh
imp at bsdimp.com
Sun Mar 3 04:18:37 UTC 2013
I didn't review this in great detail, but I agree: this isn't quite ready to commit.
Just had one comment inline...
On Mar 2, 2013, at 6:18 PM, Ian Lepore wrote:
> 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
>
> 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.
> + */
Linux requires that the kernel be booted without the MMU enabled to simplify this case. Is there any reason we can't do the same?
> 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)
> _______________________________________________
> freebsd-arm at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-arm
> To unsubscribe, send any mail to "freebsd-arm-unsubscribe at freebsd.org"
More information about the freebsd-arm
mailing list