ARM: vfp: fix vfp_sync_state()
The more I look at vfp_sync_state(), the more I believe it's trying to do its job in a really obscure way. Essentially, last_VFP_context[] tracks who owns the state in the VFP hardware. If last_VFP_context[] is the context for the thread which we're interested in, then the VFP hardware has context which is not saved in the software state - so we need to bring the software state up to date. If last_VFP_context[] is for some other thread, we really don't care what state the VFP hardware is in; it doesn't contain any information pertinent to the thread we're trying to deal with - so don't touch the hardware. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
Родитель
462f39a8c7
Коммит
54cb3dbb4a
|
@ -444,32 +444,28 @@ void vfp_sync_state(struct thread_info *thread)
|
|||
void vfp_sync_state(struct thread_info *thread)
|
||||
{
|
||||
unsigned int cpu = get_cpu();
|
||||
u32 fpexc = fmrx(FPEXC);
|
||||
|
||||
/*
|
||||
* If VFP is enabled, the previous state was already saved and
|
||||
* last_VFP_context updated.
|
||||
* If the thread we're interested in is the current owner of the
|
||||
* hardware VFP state, then we need to save its state.
|
||||
*/
|
||||
if (fpexc & FPEXC_EN)
|
||||
goto out;
|
||||
if (last_VFP_context[cpu] == &thread->vfpstate) {
|
||||
u32 fpexc = fmrx(FPEXC);
|
||||
|
||||
if (!last_VFP_context[cpu])
|
||||
goto out;
|
||||
/*
|
||||
* Save the last VFP state on this CPU.
|
||||
*/
|
||||
fmxr(FPEXC, fpexc | FPEXC_EN);
|
||||
vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
|
||||
fmxr(FPEXC, fpexc & ~FPEXC_EN);
|
||||
|
||||
/*
|
||||
* Save the last VFP state on this CPU.
|
||||
*/
|
||||
fmxr(FPEXC, fpexc | FPEXC_EN);
|
||||
vfp_save_state(last_VFP_context[cpu], fpexc);
|
||||
fmxr(FPEXC, fpexc);
|
||||
/*
|
||||
* Set the context to NULL to force a reload the next time
|
||||
* the thread uses the VFP.
|
||||
*/
|
||||
last_VFP_context[cpu] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the context to NULL to force a reload the next time the thread
|
||||
* uses the VFP.
|
||||
*/
|
||||
last_VFP_context[cpu] = NULL;
|
||||
|
||||
out:
|
||||
put_cpu();
|
||||
}
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче