diff options
author | Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> | 2008-01-29 00:27:30 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2008-02-20 15:55:37 -0500 |
commit | b64f34cdfe5bef9dfed1304c513220b0f2862eca (patch) | |
tree | 04cb9216a9de18afcb27f9bac3fda1f3c7bacbbd /arch/ia64/kernel/ivt.S | |
parent | 5d9c4a7de64d398604a978d267a6987f1f4025b7 (diff) |
[IA64] VIRT_CPU_ACCOUNTING (accurate cpu time accounting)
This patch implements VIRT_CPU_ACCOUNTING for ia64,
which enable us to use more accurate cpu time accounting.
The VIRT_CPU_ACCOUNTING is an item of kernel config, which s390
and powerpc arch have. By turning this config on, these archs
change the mechanism of cpu time accounting from tick-sampling
based one to state-transition based one.
The state-transition based accounting is done by checking time
(cycle counter in processor) at every state-transition point,
such as entrance/exit of kernel, interrupt, softirq etc.
The difference between point to point is the actual time consumed
during in the state. There is no doubt about that this value is
more accurate than that of tick-sampling based accounting.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel/ivt.S')
-rw-r--r-- | arch/ia64/kernel/ivt.S | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index 34f44d8be00d..6678c49daba3 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S | |||
@@ -805,8 +805,13 @@ ENTRY(break_fault) | |||
805 | 805 | ||
806 | (p8) adds r28=16,r28 // A switch cr.iip to next bundle | 806 | (p8) adds r28=16,r28 // A switch cr.iip to next bundle |
807 | (p9) adds r8=1,r8 // A increment ei to next slot | 807 | (p9) adds r8=1,r8 // A increment ei to next slot |
808 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
809 | ;; | ||
810 | mov b6=r30 // I0 setup syscall handler branch reg early | ||
811 | #else | ||
808 | nop.i 0 | 812 | nop.i 0 |
809 | ;; | 813 | ;; |
814 | #endif | ||
810 | 815 | ||
811 | mov.m r25=ar.unat // M2 (5 cyc) | 816 | mov.m r25=ar.unat // M2 (5 cyc) |
812 | dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr | 817 | dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr |
@@ -817,7 +822,11 @@ ENTRY(break_fault) | |||
817 | // | 822 | // |
818 | /////////////////////////////////////////////////////////////////////// | 823 | /////////////////////////////////////////////////////////////////////// |
819 | st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag | 824 | st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag |
825 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
826 | mov.m r30=ar.itc // M get cycle for accounting | ||
827 | #else | ||
820 | mov b6=r30 // I0 setup syscall handler branch reg early | 828 | mov b6=r30 // I0 setup syscall handler branch reg early |
829 | #endif | ||
821 | cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already? | 830 | cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already? |
822 | 831 | ||
823 | and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit | 832 | and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit |
@@ -829,6 +838,30 @@ ENTRY(break_fault) | |||
829 | cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited? | 838 | cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited? |
830 | br.call.sptk.many b7=ia64_syscall_setup // B | 839 | br.call.sptk.many b7=ia64_syscall_setup // B |
831 | 1: | 840 | 1: |
841 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
842 | // mov.m r30=ar.itc is called in advance, and r13 is current | ||
843 | add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13 // A | ||
844 | add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13 // A | ||
845 | (pKStk) br.cond.spnt .skip_accounting // B unlikely skip | ||
846 | ;; | ||
847 | ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // M get last stamp | ||
848 | ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // M time at leave | ||
849 | ;; | ||
850 | ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // M cumulated stime | ||
851 | ld8 r21=[r17] // M cumulated utime | ||
852 | sub r22=r19,r18 // A stime before leave | ||
853 | ;; | ||
854 | st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // M update stamp | ||
855 | sub r18=r30,r19 // A elapsed time in user | ||
856 | ;; | ||
857 | add r20=r20,r22 // A sum stime | ||
858 | add r21=r21,r18 // A sum utime | ||
859 | ;; | ||
860 | st8 [r16]=r20 // M update stime | ||
861 | st8 [r17]=r21 // M update utime | ||
862 | ;; | ||
863 | .skip_accounting: | ||
864 | #endif | ||
832 | mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 | 865 | mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 |
833 | nop 0 | 866 | nop 0 |
834 | bsw.1 // B (6 cyc) regs are saved, switch to bank 1 | 867 | bsw.1 // B (6 cyc) regs are saved, switch to bank 1 |
@@ -928,6 +961,7 @@ END(interrupt) | |||
928 | * - r27: saved ar.rsc | 961 | * - r27: saved ar.rsc |
929 | * - r28: saved cr.iip | 962 | * - r28: saved cr.iip |
930 | * - r29: saved cr.ipsr | 963 | * - r29: saved cr.ipsr |
964 | * - r30: ar.itc for accounting (don't touch) | ||
931 | * - r31: saved pr | 965 | * - r31: saved pr |
932 | * - b0: original contents (to be saved) | 966 | * - b0: original contents (to be saved) |
933 | * On exit: | 967 | * On exit: |
@@ -1090,6 +1124,41 @@ END(dispatch_illegal_op_fault) | |||
1090 | DBG_FAULT(16) | 1124 | DBG_FAULT(16) |
1091 | FAULT(16) | 1125 | FAULT(16) |
1092 | 1126 | ||
1127 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
1128 | /* | ||
1129 | * There is no particular reason for this code to be here, other than | ||
1130 | * that there happens to be space here that would go unused otherwise. | ||
1131 | * If this fault ever gets "unreserved", simply moved the following | ||
1132 | * code to a more suitable spot... | ||
1133 | * | ||
1134 | * account_sys_enter is called from SAVE_MIN* macros if accounting is | ||
1135 | * enabled and if the macro is entered from user mode. | ||
1136 | */ | ||
1137 | ENTRY(account_sys_enter) | ||
1138 | // mov.m r20=ar.itc is called in advance, and r13 is current | ||
1139 | add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13 | ||
1140 | add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13 | ||
1141 | ;; | ||
1142 | ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel | ||
1143 | ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at left from kernel | ||
1144 | ;; | ||
1145 | ld8 r23=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime | ||
1146 | ld8 r21=[r17] // cumulated utime | ||
1147 | sub r22=r19,r18 // stime before leave kernel | ||
1148 | ;; | ||
1149 | st8 [r16]=r20,TI_AC_STIME-TI_AC_STAMP // update stamp | ||
1150 | sub r18=r20,r19 // elapsed time in user mode | ||
1151 | ;; | ||
1152 | add r23=r23,r22 // sum stime | ||
1153 | add r21=r21,r18 // sum utime | ||
1154 | ;; | ||
1155 | st8 [r16]=r23 // update stime | ||
1156 | st8 [r17]=r21 // update utime | ||
1157 | ;; | ||
1158 | br.ret.sptk.many rp | ||
1159 | END(account_sys_enter) | ||
1160 | #endif | ||
1161 | |||
1093 | .org ia64_ivt+0x4400 | 1162 | .org ia64_ivt+0x4400 |
1094 | ///////////////////////////////////////////////////////////////////////////////////////// | 1163 | ///////////////////////////////////////////////////////////////////////////////////////// |
1095 | // 0x4400 Entry 17 (size 64 bundles) Reserved | 1164 | // 0x4400 Entry 17 (size 64 bundles) Reserved |