[RFC PATCH 3/3] ARM: mm: add l2x0 suspend/resume support
Lorenzo Pieralisi
lorenzo.pieralisi at arm.com
Mon Sep 26 13:14:52 EDT 2011
On Mon, Sep 26, 2011 at 04:06:45PM +0100, Russell King - ARM Linux wrote:
> On Mon, Sep 26, 2011 at 03:32:41PM +0100, Lorenzo Pieralisi wrote:
> > Context is saved once for all at boot time, along with the L2 physical address
> > and cache type.
>
> Why is this assembly code? As Barry's previous patch shows, it's
> entirely possible to save all the state required at init time from
> the existing C code without needing any additional functions.
>
It need not be, but variables that are needed when the MMU is off (L2
phys address and cache type) must be made visible to C code and
initialized there then.
> > The resume hook avoids using the stack since it might be called
> > before the C environment is up and running and fetches data using
> > program counter relative addressing so that it can be run both
> > with MMU on or off to simplify its adoption.
>
> What about parts where the security gets in the way of reinitializing
> the L2 cache?
>
That's a fair point. I think L2 must be initialized by secure code, and
we should not reprogramme it at all.
Having said that, this code only adds support for L2 resume when the
MMU is off to Barry's patch. The security "problem" exists anyway.
I check the control register to see if it is already enabled; all in all
it is just an assembly stub that can be called before or after cpu_resume,
that's it, to support suspend and idle also when L2 is retained and the
boot firmware just jumps back to Linux on power up.
Whether we need an L2 resume function in the kernel or not, I think it is still
a moot point. Let's keep the discussion going.
> > +resume_l210:
> > + ldr r2, [r0], #4 @ just use scratch regs
> > + str r2, [r1, #L2X0_AUX_CTRL]
> > + mov r3, #0
> > + mov r12, #L2X0_LOCKDOWN_WAY_D_BASE
> > + mov r2, r12
> > + str r3, [r1, r2]
> > + add r2, r2, #4
> > + str r3, [r1, r2]
> > + movne r0, #0x1 @ if l210 we are done
> > + strne r0, [r1, #L2X0_CTRL] @ enable L2
> > + movne pc, lr
>
> It's not very obvious where the compare is for this conditional (which is
> at the end of l2x0_resume in the .data section. Also, wouldn't a branch
> to the enable at the end of this function be better and a more obvious
> flow?
>
I added a comment to the function entry for the flags, but it is agreed,
it can be improved; and yes a branch is the way to go.
> > +resume_l310:
> > + add r12, r12, r1
> > + add r12, r12, #L2X0_LOCKDOWN_STRIDE @ start D lock
> > + mov r2, #0
> > + mov r3, #7
> > +unlock:
> > + str r2, [r12, #4] @ I lock
> > + str r2, [r12], #L2X0_LOCKDOWN_STRIDE @ D lock and increment
> > + subs r3, r3, #1
> > + bne unlock
>
> Why not reverse r2 and r3 here? r3 was already set to zero previously.
>
> And given what you're doing, this code could become:
>
> mov r3, #0
> add r12, r1, #L2X0_LOCKDOWN_WAY_D_BASE
> str r3, [r12, #4] @ I lock
> str r3, [r12], #L2X0_LOCKDOWN_STRIDE @ D lock and increment
> bne enable_l2
> resume_l310:
> mov r2, #7
> unlock:
> str r3, [r12, #4] @ I lock
> str r3, [r12], #L2X0_LOCKDOWN_STRIDE @ D lock and increment
> subs r2, r2, #1
> bne unlock
>
>
Definitely, I reshuffled the instructions to adapt the latest changes and I
missed out on this optimization you spotted straight away. Thanks for this.
> > + ldmia r0!, {r2, r3, r12}
> > + str r2, [r1, #L2X0_TAG_LATENCY_CTRL]
> > + str r3, [r1, #L2X0_DATA_LATENCY_CTRL]
> > + str r12, [r1, #L2X0_ADDR_FILTER_START]
> > + ldmia r0!, {r2, r3, r12}
> > + str r2, [r1, #L2X0_ADDR_FILTER_END]
> > + str r3, [r1, #L2X0_DEBUG_CTRL]
> > + str r12, [r1, #L2X0_PREFETCH_CTRL]
> > + ldr r2, [r0]
> > + str r2, [r1, #L2X0_POWER_CTRL]
>
> enable_l2:
>
> > + mov r0, #0x1
> > + str r0, [r1, #L2X0_CTRL] @ enable L2
> > + mov pc, lr
>
Consider it done.
Thanks,
Lorenzo
More information about the linux-arm-kernel
mailing list