On Mon, May 18, 2009 at 02:04:19PM -0500, Woodruff, Richard wrote: > cpu_init() is not yet accessible at the point this code is running.
Not at that _exact_ point, but there's no need what so ever for it to be at that exact point. There's nothing stopping a call to cpu_init() happening later. Much later. > You could reduce the context perhaps trying to optimize to what the > Linux-ARM implementation is today or do a more generic save like is > there now. > > This code is copied into place from the .S code into SRAM. Its > position independent and is not linked for this address. If you want > to call functions outside of it you need to manually setup linkage. I wouldn't want to. > Calling functions on the way _UP_ from wake is NOT easy (like the one > you propose) as the MMU is not yet enabled. The MMU is enabled only > below this. Calling cpu_init() is not do able here. Even if you > dress up the calling pointer to the physical address, it won't work > as cpu_init() makes a global variable dereferences (smp_processor_id > & stacks[]). As long as IRQs and FIQs are disabled, you are in a 100% predictable environment. 1. No IRQ or FIQ will be entered; if they are the CPU is buggy. 2. No data or prefetch abort will be entered _unless_ you purposely access some non-present memory (and you're not exactly going to start paging memory in with IRQs disabled.) So restoring the abort and IRQ mode register state is just plain not necessary in your SRAM code. Let's look at the code. Here are the pertinent bits from Kevin's patch: static void omap3_pm_idle(void) { local_irq_disable(); local_fiq_disable(); omap_sram_idle(); local_fiq_enable(); local_irq_enable(); } static void omap_sram_idle(void) { _omap_sram_idle(NULL, save_state); } _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend, omap34xx_cpu_suspend_sz); pm_idle = omap3_pm_idle; _omap_sram_idle() is the assembly code we're discussing, and here we're referring to its version in SRAM. From the above code, we can clearly see that this is entered with FIQs and IRQs disabled. So everything inside omap_sram_idle() is running in a well defined environment provided prefetch and data aborts don't happen. There is nothing stopping this from becoming: static void omap3_pm_idle(void) { local_irq_disable(); local_fiq_disable(); omap_sram_idle(); + cpu_init(); local_fiq_enable(); local_irq_enable(); } and having the saving of IRQ, FIQ and abort mode registers removed from the SRAM code. Other SoCs do precisely this - let's look at PXA: pxa_cpu_pm_fns->enter(state); cpu_init(); The call to the enter method essentially calls the core specific suspend function (eg, pxa25x_cpu_suspend()), which is an assembly function which ultimately ends up powering down the core resulting in full loss of state in the CPU. We seem to be able to avoid having to save the exception mode registers there. The same thing is done with sa11x0 and Samsung SoCs. I don't see any reason for OMAP to be "special" in this regard. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html