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