forked from Minki/linux
38477ad751
While testing with CONFIG_VIRT_CPU_ACCOUNTING=y, I found that
I occasionally get very huge system time in some threads.
So I dug the issue and finally noticed that it was caused
because of an interrupt which interrupt in the following window:
> [arch/ia64/kernel/entry.S: (!CONFIG_PREEMPT && CONFIG_VIRT_CPU_ACCOUNTING)]
>
> ENTRY(ia64_leave_syscall)
> :
> (pUStk) rsm psr.i
> cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall
> (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
> .work_processed_syscall:
> adds r2=PT(LOADRS)+16,r12
> (pUStk) mov.m r22=ar.itc // fetch time at leave
> adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
> ;;
> <<< window: from here >>>
> (p6) ld4 r31=[r18] // load current_thread_info()->flags
> ld8 r19=[r2],PT(B6)-PT(LOADRS)
> adds r3=PT(AR_BSPSTORE)+16,r12
> ;;
> mov r16=ar.bsp
> ld8 r18=[r2],PT(R9)-PT(B6)
> (p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
> ;;
> ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE)
> (p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending?
> (p6) br.cond.spnt .work_pending_syscall
> ;;
> ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
> ld8 r11=[r3],PT(CR_IIP)-PT(R11)
> (pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE!
> ;;
> invala
> <<< window: to here >>>
> rsm psr.i | psr.ic // turn off interrupts and interruption collection
If pUStk is true, it means we are going to return user mode, hence we fetch
ar.itc to get time at leave from system.
It seems that it is not possible to interrupt the window if pUStk is true,
because interrupts are disabled early. And also disabling interrupt makes
sense because it is safe for referring current_thread_info()->flags.
However interrupting the window while pUStk is true was possible.
The route was:
ia64_trace_syscall
-> .work_pending_syscall_end
-> .work_processed_syscall
Only in case entering the window from this route, interrupts are enabled
during in the window even if pUStk is true. I suppose interrupts must be
disabled here anyway if pUStk is true.
I'm not sure but afraid that what kind of bad effect were there, other
than crazy system time which I found.
FYI, there was a commit
|
||
---|---|---|
.. | ||
cpufreq | ||
.gitignore | ||
acpi-ext.c | ||
acpi-processor.c | ||
acpi.c | ||
asm-offsets.c | ||
audit.c | ||
brl_emu.c | ||
crash_dump.c | ||
crash.c | ||
cyclone.c | ||
efi_stub.S | ||
efi.c | ||
entry.h | ||
entry.S | ||
err_inject.c | ||
esi_stub.S | ||
esi.c | ||
fsys.S | ||
fsyscall_gtod_data.h | ||
gate-data.S | ||
gate.lds.S | ||
gate.S | ||
head.S | ||
ia64_ksyms.c | ||
init_task.c | ||
iosapic.c | ||
irq_ia64.c | ||
irq_lsapic.c | ||
irq.c | ||
ivt.S | ||
jprobes.S | ||
kprobes.c | ||
machine_kexec.c | ||
machvec.c | ||
Makefile | ||
mca_asm.S | ||
mca_drv_asm.S | ||
mca_drv.c | ||
mca_drv.h | ||
mca.c | ||
minstate.h | ||
module.c | ||
msi_ia64.c | ||
numa.c | ||
pal.S | ||
palinfo.c | ||
patch.c | ||
perfmon_default_smpl.c | ||
perfmon_generic.h | ||
perfmon_itanium.h | ||
perfmon_mckinley.h | ||
perfmon_montecito.h | ||
perfmon.c | ||
process.c | ||
ptrace.c | ||
relocate_kernel.S | ||
sal.c | ||
salinfo.c | ||
setup.c | ||
sigframe.h | ||
signal.c | ||
smp.c | ||
smpboot.c | ||
sys_ia64.c | ||
time.c | ||
topology.c | ||
traps.c | ||
unaligned.c | ||
uncached.c | ||
unwind_decoder.c | ||
unwind_i.h | ||
unwind.c | ||
vmlinux.lds.S |