On Fri, Sep 12, 2008 at 12:20 PM, Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net wrote:
In theory, gcc is free to reload esp from a cached register after disable_car. That would cause pretty explosions due to the stack pointer being in a now invalid location.
how can this be? I don't see how it can be. Can you provide an example?
My worry is simpler. The compiler is used to assuming that a pointer in a register is valid across function calls. After disable_car the stack will have moved on some CPUs. There is no choice. So all registers are junk after the call to disable_car().
Although I really don't like it, I think a safe and still readable way would be to rename stage1() to stage1_early(), rename stage1_after_car() to stage1_late() and rename disable_car() to disable_car_and_continue_at_stage1_late(). disable_car_and_continue_at_stage1_late() would be pure asm (probably even in a .S file and not just inline asm) and could take care of setting up the stack correctly and using the right calling convention. That would work regardless of gcc optimizations.
The names are too long.
Let's do this: stage0. disable_car. stage1.
stage1 called from disable car .The renaming is pretty easy. Stage0 finally has more work to do :-) The stage0 symbol in the .S file becomes stage0entry
There is another related problem (but independent of CAR switching): How do we find out where our global variables live?
You mean your global variable infrastructure? It should be designed so that given a valid ESP, the global area can be found. The global area should be aligned to CARSIZE. CARSIZE should be a power of two. . To find the globals I think it suffices to do something like this.
void *find_globals() { int i; u32 l;
l = (u32)&i; l &= ~ CARSIZE; return (void )l; }
no assembly.
Sorry to reopen this wound. We had it pretty resolved and then core2 came along ...
ron