[PATCH 4/6] ARM: reset: add reset functionality for jumping to a physical address
Frank Hofmann
frank.hofmann at tomtom.com
Tue Jun 7 07:37:23 EDT 2011
On Tue, 7 Jun 2011, Frank Hofmann wrote:
>
>
> On Mon, 6 Jun 2011, Will Deacon wrote:
>
>> Tools such as kexec and CPU hotplug require a way to reset the processor
>> and branch to some code in physical space. This requires various bits of
>> jiggery pokery with the caches and MMU which, when it goes wrong, tends
>> to lock up the system.
>>
>> This patch implements a new function, arm_machine_reset, for
>> consolidating this code in one place where it can be used by multiple
>> subsystems.
>>
> [ ... ]
>> +void arm_machine_reset(unsigned long reset_code_phys)
>> +{
>> + unsigned long cpu_reset_end = PAGE_ALIGN((unsigned long)cpu_reset);
>> + /* This is stricter than necessary but better to be safe than sorry.
>> */
>> + BUG_ON(virt_to_phys((void *)cpu_reset_end) >= TASK_SIZE);
>> +
>> + /* Disable interrupts first */
>> + local_irq_disable();
>> + local_fiq_disable();
>> +
>> + /*
>> + * Clean and invalidate L2.
>> + * This is racy, so we must be the last guy left.
>> + */
>> + WARN_ON(num_online_cpus() > 1);
>> + /* Flush while we still have locking available to us. */
>> + outer_flush_all();
>> + outer_disable();
>> + /* Data destroyed here will only be speculative. */
>> + outer_inv_all();
>> +
>> + prepare_for_reboot(0);
>> +
>> + /* Switch to the identity mapping. */
>> + ((typeof(cpu_reset) *)virt_to_phys((void *)cpu_reset))(reset_code_phys);
>
> void (*reset_func)(unsigned long) = virt_to_phys(cpu_reset)
Sorry, pressed wrong key ... posted too early.
I meant to say this line is magic, why not decouple the declaration bit
from the invocation so that at least the function call looks "normal" ?
Regarding the use of local_irq/fiq_disable - is it safe to call these
multiple times, i.e. is it safe to invoke the reset function from a
context where IRQ/FIQ are already off ?
Another question regarding the MMU tables.
prepare_for_reboot / setup_mm_for_reboot assume that current->mm is
available _and_ lowmem / user area there can be blotted over.
Wrt. to hibernation, that's a stretch unless some way is found to fully
"fake a context". With that I mean to create a threadinfo and pagedir
that's guaranteed to sit outside the target kernel heap.
Currently, the hibernation code switches to swapper_pg_dir and puts the
1:1 mappings in there; I'm starting to think that is safe if for no other
reason than swapper_pg_dir having _nothing_ in the user area ?
Is it convention, design or accident that swapper_pg_dir doesn't map
anything in the low range ?
FrankH.
>
>> +}
>> +
>> /*
>> * Function pointers to optional machine specific functions
>> */
>> --
>> 1.7.0.4
>>
>>
>
More information about the linux-arm-kernel
mailing list