PHYSADDR

Tim Kientzle kientzle at freebsd.org
Thu Feb 28 16:57:03 UTC 2013


On Feb 27, 2013, at 10:41 PM, Warner Losh wrote:

> 
> On Feb 27, 2013, at 11:27 PM, Tim Kientzle wrote:
> 
>> Starting to look at what is needed for a Generic ARM kernel.
>> There's a lot here; I sincerely hope I'm not the only one… ;-)
>> 
>> First up:  Can we get rid of PHYSADDR?
> 
> There's lots of places in the tree that use it, but not so many that a whack-a-mole approach wouldn't work.

It's mostly only used in locore.S and machdep.c (and, of course,
the many copies of machdep.c).

>> I think we can always compute it at runtime from PC.
>> 
>> For example, I think this works in several places:
>>  and r0, pc, #0xF0000000
> 
> This only works early in boot before we've turned on the MMU, right?

I'm still pretty new to this section of the code, so might have
missed something, but I don't think we need PHYSADDR
after the kernel has relocated itself.

Do we?

> 
>> And I've found at least one reference that I think can be simply
>> eliminated:
>> 
>> Index: arm/elf_trampoline.c
>> ===================================================================
>> --- arm/elf_trampoline.c	(revision 247250)
>> +++ arm/elf_trampoline.c	(working copy)
>> @@ -169,7 +169,7 @@
>> void
>> _startC(void)
>> {
>> -	int physaddr = KERNPHYSADDR;
>> +	unsigned int physaddr = (unsigned int)&_start & 0xfffff000;
> 
> How'd you come up with this? Perhaps we should just define KERNPHYSADDR as this gross expression :)
> 
> But isn't _start a virtual address, not a physical address?

Honestly, I'm still trying to figure that part out.  ;-)

Disassembling the compiler output, taking the
address of the current function always uses a
PC-relative address.  So &_startC here would
give the current address of the function as it's
executing.

> 
>> 	int tmp1;
>> 	unsigned int sp = ((unsigned int)&_end & ~3) + 4;
>> #if defined(FLASHADDR) && defined(LOADERRAMADDR)
>> @@ -189,10 +189,9 @@
>> 		 */
>> 		unsigned int target_addr;
>> 		unsigned int tmp_sp;
>> -		uint32_t src_addr = (uint32_t)&_start - PHYSADDR + FLASHADDR
>> -		    + (pc - FLASHADDR - ((uint32_t)&_startC - PHYSADDR)) & 0xfffff000;
>> +		uint32_t src_addr = (uint32_t)&_start;
> 
> I'm not sure how this works…

Here's my reasoning:
FLASHADDR and PHYSADDR are always multiples of 4k,
so you can pull those out of the parentheses to get:

   _start  - PHYSADDR + FLASHADDR - FLASHADD + PHYSADDR + (pc - _startC) & 0xffffff000

And since pc was sampled early in _startC, the last expression
should always be zero.

I was a little surprised by this myself, so I might have missed
something.

>> -		target_addr = (unsigned int)&_start - PHYSADDR + LOADERRAMADDR;
>> +		target_addr = (unsigned int)&_start - (pc & 0xf0000000) + LOADERRAMADDR;
> 
> This might work, but I'd suggest a PC_TO_PHYSADDR(pc) macro or something similar…

I'll try that later on.  I suspect some of these PHYSADDRs
will simply go away, since I think what we really want in
the early bootstrap stage is just "what address is the
kernel currently executing at".  I still need to piece together
some more things before I understand that.

As with the above, at least some of the expressions
using PHYSADDR seem more complex than necessary.


>> 		tmp_sp = target_addr + 0x100000 +
>> 		    (unsigned int)&_end - (unsigned int)&_start;
>> 		memcpy((char *)target_addr, (char *)src_addr,
>> 
>> 
>> Tim
>> 
> 



More information about the freebsd-arm mailing list