diff options
-rw-r--r-- | arch/ia64/Kconfig | 11 | ||||
-rw-r--r-- | arch/ia64/ia32/elfcore32.h | 14 | ||||
-rw-r--r-- | arch/ia64/kernel/asm-offsets.c | 6 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 65 | ||||
-rw-r--r-- | arch/ia64/kernel/fsys.S | 26 | ||||
-rw-r--r-- | arch/ia64/kernel/head.S | 20 | ||||
-rw-r--r-- | arch/ia64/kernel/ivt.S | 69 | ||||
-rw-r--r-- | arch/ia64/kernel/minstate.h | 14 | ||||
-rw-r--r-- | arch/ia64/kernel/time.c | 78 | ||||
-rw-r--r-- | include/asm-ia64/cputime.h | 104 | ||||
-rw-r--r-- | include/asm-ia64/system.h | 12 | ||||
-rw-r--r-- | include/asm-ia64/thread_info.h | 14 |
12 files changed, 432 insertions, 1 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index dff9edfc7465..c3567727c13c 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -280,6 +280,17 @@ config FORCE_MAX_ZONEORDER | |||
280 | default "17" if HUGETLB_PAGE | 280 | default "17" if HUGETLB_PAGE |
281 | default "11" | 281 | default "11" |
282 | 282 | ||
283 | config VIRT_CPU_ACCOUNTING | ||
284 | bool "Deterministic task and CPU time accounting" | ||
285 | default n | ||
286 | help | ||
287 | Select this option to enable more accurate task and CPU time | ||
288 | accounting. This is done by reading a CPU counter on each | ||
289 | kernel entry and exit and on transitions within the kernel | ||
290 | between system, softirq and hardirq state, so there is a | ||
291 | small performance impact. | ||
292 | If in doubt, say N here. | ||
293 | |||
283 | config SMP | 294 | config SMP |
284 | bool "Symmetric multi-processing support" | 295 | bool "Symmetric multi-processing support" |
285 | help | 296 | help |
diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h index 446c9aac924d..9a3abf58cea3 100644 --- a/arch/ia64/ia32/elfcore32.h +++ b/arch/ia64/ia32/elfcore32.h | |||
@@ -30,7 +30,19 @@ struct elf_siginfo | |||
30 | int si_errno; /* errno */ | 30 | int si_errno; /* errno */ |
31 | }; | 31 | }; |
32 | 32 | ||
33 | #define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0) | 33 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
34 | /* | ||
35 | * Hacks are here since types between compat_timeval (= pair of s32) and | ||
36 | * ia64-native timeval (= pair of s64) are not compatible, at least a file | ||
37 | * arch/ia64/ia32/../../../fs/binfmt_elf.c will get warnings from compiler on | ||
38 | * use of cputime_to_timeval(), which usually an alias of jiffies_to_timeval(). | ||
39 | */ | ||
40 | #define cputime_to_timeval(a,b) \ | ||
41 | do { (b)->tv_usec = 0; (b)->tv_sec = (a)/NSEC_PER_SEC; } while(0) | ||
42 | #else | ||
43 | #define jiffies_to_timeval(a,b) \ | ||
44 | do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; } while(0) | ||
45 | #endif | ||
34 | 46 | ||
35 | struct elf_prstatus | 47 | struct elf_prstatus |
36 | { | 48 | { |
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 0aebc6f79e95..5865130b0a92 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c | |||
@@ -39,6 +39,12 @@ void foo(void) | |||
39 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | 39 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); |
40 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); | 40 | DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); |
41 | DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); | 41 | DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); |
42 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
43 | DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp)); | ||
44 | DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave)); | ||
45 | DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime)); | ||
46 | DEFINE(TI_AC_UTIME, offsetof(struct thread_info, ac_utime)); | ||
47 | #endif | ||
42 | 48 | ||
43 | BLANK(); | 49 | BLANK(); |
44 | 50 | ||
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 3c331c464b40..b0be4a280174 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -710,6 +710,16 @@ ENTRY(ia64_leave_syscall) | |||
710 | (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk | 710 | (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk |
711 | #endif | 711 | #endif |
712 | .work_processed_syscall: | 712 | .work_processed_syscall: |
713 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
714 | adds r2=PT(LOADRS)+16,r12 | ||
715 | (pUStk) mov.m r22=ar.itc // fetch time at leave | ||
716 | adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 | ||
717 | ;; | ||
718 | (p6) ld4 r31=[r18] // load current_thread_info()->flags | ||
719 | ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" | ||
720 | adds r3=PT(AR_BSPSTORE)+16,r12 // deferred | ||
721 | ;; | ||
722 | #else | ||
713 | adds r2=PT(LOADRS)+16,r12 | 723 | adds r2=PT(LOADRS)+16,r12 |
714 | adds r3=PT(AR_BSPSTORE)+16,r12 | 724 | adds r3=PT(AR_BSPSTORE)+16,r12 |
715 | adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 | 725 | adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 |
@@ -718,6 +728,7 @@ ENTRY(ia64_leave_syscall) | |||
718 | ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" | 728 | ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" |
719 | nop.i 0 | 729 | nop.i 0 |
720 | ;; | 730 | ;; |
731 | #endif | ||
721 | mov r16=ar.bsp // M2 get existing backing store pointer | 732 | mov r16=ar.bsp // M2 get existing backing store pointer |
722 | ld8 r18=[r2],PT(R9)-PT(B6) // load b6 | 733 | ld8 r18=[r2],PT(R9)-PT(B6) // load b6 |
723 | (p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? | 734 | (p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? |
@@ -737,12 +748,21 @@ ENTRY(ia64_leave_syscall) | |||
737 | 748 | ||
738 | ld8 r29=[r2],16 // M0|1 load cr.ipsr | 749 | ld8 r29=[r2],16 // M0|1 load cr.ipsr |
739 | ld8 r28=[r3],16 // M0|1 load cr.iip | 750 | ld8 r28=[r3],16 // M0|1 load cr.iip |
751 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
752 | (pUStk) add r14=TI_AC_LEAVE+IA64_TASK_SIZE,r13 | ||
753 | ;; | ||
754 | ld8 r30=[r2],16 // M0|1 load cr.ifs | ||
755 | ld8 r25=[r3],16 // M0|1 load ar.unat | ||
756 | (pUStk) add r15=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 | ||
757 | ;; | ||
758 | #else | ||
740 | mov r22=r0 // A clear r22 | 759 | mov r22=r0 // A clear r22 |
741 | ;; | 760 | ;; |
742 | ld8 r30=[r2],16 // M0|1 load cr.ifs | 761 | ld8 r30=[r2],16 // M0|1 load cr.ifs |
743 | ld8 r25=[r3],16 // M0|1 load ar.unat | 762 | ld8 r25=[r3],16 // M0|1 load ar.unat |
744 | (pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 | 763 | (pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 |
745 | ;; | 764 | ;; |
765 | #endif | ||
746 | ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs | 766 | ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs |
747 | (pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled | 767 | (pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled |
748 | nop 0 | 768 | nop 0 |
@@ -759,7 +779,11 @@ ENTRY(ia64_leave_syscall) | |||
759 | ld8.fill r1=[r3],16 // M0|1 load r1 | 779 | ld8.fill r1=[r3],16 // M0|1 load r1 |
760 | (pUStk) mov r17=1 // A | 780 | (pUStk) mov r17=1 // A |
761 | ;; | 781 | ;; |
782 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
783 | (pUStk) st1 [r15]=r17 // M2|3 | ||
784 | #else | ||
762 | (pUStk) st1 [r14]=r17 // M2|3 | 785 | (pUStk) st1 [r14]=r17 // M2|3 |
786 | #endif | ||
763 | ld8.fill r13=[r3],16 // M0|1 | 787 | ld8.fill r13=[r3],16 // M0|1 |
764 | mov f8=f0 // F clear f8 | 788 | mov f8=f0 // F clear f8 |
765 | ;; | 789 | ;; |
@@ -775,12 +799,22 @@ ENTRY(ia64_leave_syscall) | |||
775 | shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition | 799 | shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition |
776 | cover // B add current frame into dirty partition & set cr.ifs | 800 | cover // B add current frame into dirty partition & set cr.ifs |
777 | ;; | 801 | ;; |
802 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
803 | mov r19=ar.bsp // M2 get new backing store pointer | ||
804 | st8 [r14]=r22 // M save time at leave | ||
805 | mov f10=f0 // F clear f10 | ||
806 | |||
807 | mov r22=r0 // A clear r22 | ||
808 | movl r14=__kernel_syscall_via_epc // X | ||
809 | ;; | ||
810 | #else | ||
778 | mov r19=ar.bsp // M2 get new backing store pointer | 811 | mov r19=ar.bsp // M2 get new backing store pointer |
779 | mov f10=f0 // F clear f10 | 812 | mov f10=f0 // F clear f10 |
780 | 813 | ||
781 | nop.m 0 | 814 | nop.m 0 |
782 | movl r14=__kernel_syscall_via_epc // X | 815 | movl r14=__kernel_syscall_via_epc // X |
783 | ;; | 816 | ;; |
817 | #endif | ||
784 | mov.m ar.csd=r0 // M2 clear ar.csd | 818 | mov.m ar.csd=r0 // M2 clear ar.csd |
785 | mov.m ar.ccv=r0 // M2 clear ar.ccv | 819 | mov.m ar.ccv=r0 // M2 clear ar.ccv |
786 | mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc) | 820 | mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc) |
@@ -913,10 +947,18 @@ GLOBAL_ENTRY(ia64_leave_kernel) | |||
913 | adds r16=PT(CR_IPSR)+16,r12 | 947 | adds r16=PT(CR_IPSR)+16,r12 |
914 | adds r17=PT(CR_IIP)+16,r12 | 948 | adds r17=PT(CR_IIP)+16,r12 |
915 | 949 | ||
950 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
951 | .pred.rel.mutex pUStk,pKStk | ||
952 | (pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled | ||
953 | (pUStk) mov.m r22=ar.itc // M fetch time at leave | ||
954 | nop.i 0 | ||
955 | ;; | ||
956 | #else | ||
916 | (pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled | 957 | (pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled |
917 | nop.i 0 | 958 | nop.i 0 |
918 | nop.i 0 | 959 | nop.i 0 |
919 | ;; | 960 | ;; |
961 | #endif | ||
920 | ld8 r29=[r16],16 // load cr.ipsr | 962 | ld8 r29=[r16],16 // load cr.ipsr |
921 | ld8 r28=[r17],16 // load cr.iip | 963 | ld8 r28=[r17],16 // load cr.iip |
922 | ;; | 964 | ;; |
@@ -938,15 +980,37 @@ GLOBAL_ENTRY(ia64_leave_kernel) | |||
938 | ;; | 980 | ;; |
939 | ld8.fill r12=[r16],16 | 981 | ld8.fill r12=[r16],16 |
940 | ld8.fill r13=[r17],16 | 982 | ld8.fill r13=[r17],16 |
983 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
984 | (pUStk) adds r3=TI_AC_LEAVE+IA64_TASK_SIZE,r18 | ||
985 | #else | ||
941 | (pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 | 986 | (pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 |
987 | #endif | ||
942 | ;; | 988 | ;; |
943 | ld8 r20=[r16],16 // ar.fpsr | 989 | ld8 r20=[r16],16 // ar.fpsr |
944 | ld8.fill r15=[r17],16 | 990 | ld8.fill r15=[r17],16 |
991 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
992 | (pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 // deferred | ||
993 | #endif | ||
945 | ;; | 994 | ;; |
946 | ld8.fill r14=[r16],16 | 995 | ld8.fill r14=[r16],16 |
947 | ld8.fill r2=[r17] | 996 | ld8.fill r2=[r17] |
948 | (pUStk) mov r17=1 | 997 | (pUStk) mov r17=1 |
949 | ;; | 998 | ;; |
999 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
1000 | // mmi_ : ld8 st1 shr;; mmi_ : st8 st1 shr;; | ||
1001 | // mib : mov add br -> mib : ld8 add br | ||
1002 | // bbb_ : br nop cover;; mbb_ : mov br cover;; | ||
1003 | // | ||
1004 | // no one require bsp in r16 if (pKStk) branch is selected. | ||
1005 | (pUStk) st8 [r3]=r22 // save time at leave | ||
1006 | (pUStk) st1 [r18]=r17 // restore current->thread.on_ustack | ||
1007 | shr.u r18=r19,16 // get byte size of existing "dirty" partition | ||
1008 | ;; | ||
1009 | ld8.fill r3=[r16] // deferred | ||
1010 | LOAD_PHYS_STACK_REG_SIZE(r17) | ||
1011 | (pKStk) br.cond.dpnt skip_rbs_switch | ||
1012 | mov r16=ar.bsp // get existing backing store pointer | ||
1013 | #else | ||
950 | ld8.fill r3=[r16] | 1014 | ld8.fill r3=[r16] |
951 | (pUStk) st1 [r18]=r17 // restore current->thread.on_ustack | 1015 | (pUStk) st1 [r18]=r17 // restore current->thread.on_ustack |
952 | shr.u r18=r19,16 // get byte size of existing "dirty" partition | 1016 | shr.u r18=r19,16 // get byte size of existing "dirty" partition |
@@ -954,6 +1018,7 @@ GLOBAL_ENTRY(ia64_leave_kernel) | |||
954 | mov r16=ar.bsp // get existing backing store pointer | 1018 | mov r16=ar.bsp // get existing backing store pointer |
955 | LOAD_PHYS_STACK_REG_SIZE(r17) | 1019 | LOAD_PHYS_STACK_REG_SIZE(r17) |
956 | (pKStk) br.cond.dpnt skip_rbs_switch | 1020 | (pKStk) br.cond.dpnt skip_rbs_switch |
1021 | #endif | ||
957 | 1022 | ||
958 | /* | 1023 | /* |
959 | * Restore user backing store. | 1024 | * Restore user backing store. |
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index 44841971f077..c932d86e2d81 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
@@ -660,7 +660,11 @@ GLOBAL_ENTRY(fsys_bubble_down) | |||
660 | nop.i 0 | 660 | nop.i 0 |
661 | ;; | 661 | ;; |
662 | mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0 | 662 | mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0 |
663 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
664 | mov.m r30=ar.itc // M get cycle for accounting | ||
665 | #else | ||
663 | nop.m 0 | 666 | nop.m 0 |
667 | #endif | ||
664 | nop.i 0 | 668 | nop.i 0 |
665 | ;; | 669 | ;; |
666 | mov r23=ar.bspstore // M2 (12 cyc) save ar.bspstore | 670 | mov r23=ar.bspstore // M2 (12 cyc) save ar.bspstore |
@@ -682,6 +686,28 @@ GLOBAL_ENTRY(fsys_bubble_down) | |||
682 | cmp.ne pKStk,pUStk=r0,r0 // A set pKStk <- 0, pUStk <- 1 | 686 | cmp.ne pKStk,pUStk=r0,r0 // A set pKStk <- 0, pUStk <- 1 |
683 | br.call.sptk.many b7=ia64_syscall_setup // B | 687 | br.call.sptk.many b7=ia64_syscall_setup // B |
684 | ;; | 688 | ;; |
689 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
690 | // mov.m r30=ar.itc is called in advance | ||
691 | add r16=TI_AC_STAMP+IA64_TASK_SIZE,r2 | ||
692 | add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r2 | ||
693 | ;; | ||
694 | ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel | ||
695 | ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at leave kernel | ||
696 | ;; | ||
697 | ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime | ||
698 | ld8 r21=[r17] // cumulated utime | ||
699 | sub r22=r19,r18 // stime before leave kernel | ||
700 | ;; | ||
701 | st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // update stamp | ||
702 | sub r18=r30,r19 // elapsed time in user mode | ||
703 | ;; | ||
704 | add r20=r20,r22 // sum stime | ||
705 | add r21=r21,r18 // sum utime | ||
706 | ;; | ||
707 | st8 [r16]=r20 // update stime | ||
708 | st8 [r17]=r21 // update utime | ||
709 | ;; | ||
710 | #endif | ||
685 | mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 | 711 | mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 |
686 | mov rp=r14 // I0 set the real return addr | 712 | mov rp=r14 // I0 set the real return addr |
687 | and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A | 713 | and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A |
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index d3a41d5f8d12..ddeab4e36fd5 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S | |||
@@ -1002,6 +1002,26 @@ GLOBAL_ENTRY(sched_clock) | |||
1002 | br.ret.sptk.many rp | 1002 | br.ret.sptk.many rp |
1003 | END(sched_clock) | 1003 | END(sched_clock) |
1004 | 1004 | ||
1005 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
1006 | GLOBAL_ENTRY(cycle_to_cputime) | ||
1007 | alloc r16=ar.pfs,1,0,0,0 | ||
1008 | addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0 | ||
1009 | ;; | ||
1010 | ldf8 f8=[r8] | ||
1011 | ;; | ||
1012 | setf.sig f9=r32 | ||
1013 | ;; | ||
1014 | xmpy.lu f10=f9,f8 // calculate low 64 bits of 128-bit product (4 cyc) | ||
1015 | xmpy.hu f11=f9,f8 // calculate high 64 bits of 128-bit product | ||
1016 | ;; | ||
1017 | getf.sig r8=f10 // (5 cyc) | ||
1018 | getf.sig r9=f11 | ||
1019 | ;; | ||
1020 | shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT | ||
1021 | br.ret.sptk.many rp | ||
1022 | END(cycle_to_cputime) | ||
1023 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
1024 | |||
1005 | GLOBAL_ENTRY(start_kernel_thread) | 1025 | GLOBAL_ENTRY(start_kernel_thread) |
1006 | .prologue | 1026 | .prologue |
1007 | .save rp, r0 // this is the end of the call-chain | 1027 | .save rp, r0 // this is the end of the call-chain |
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 |
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h index c9ac8bada786..7c548ac52bbc 100644 --- a/arch/ia64/kernel/minstate.h +++ b/arch/ia64/kernel/minstate.h | |||
@@ -3,6 +3,18 @@ | |||
3 | 3 | ||
4 | #include "entry.h" | 4 | #include "entry.h" |
5 | 5 | ||
6 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
7 | /* read ar.itc in advance, and use it before leaving bank 0 */ | ||
8 | #define ACCOUNT_GET_STAMP \ | ||
9 | (pUStk) mov.m r20=ar.itc; | ||
10 | #define ACCOUNT_SYS_ENTER \ | ||
11 | (pUStk) br.call.spnt rp=account_sys_enter \ | ||
12 | ;; | ||
13 | #else | ||
14 | #define ACCOUNT_GET_STAMP | ||
15 | #define ACCOUNT_SYS_ENTER | ||
16 | #endif | ||
17 | |||
6 | /* | 18 | /* |
7 | * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves | 19 | * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves |
8 | * the minimum state necessary that allows us to turn psr.ic back | 20 | * the minimum state necessary that allows us to turn psr.ic back |
@@ -122,11 +134,13 @@ | |||
122 | ;; \ | 134 | ;; \ |
123 | .mem.offset 0,0; st8.spill [r16]=r2,16; \ | 135 | .mem.offset 0,0; st8.spill [r16]=r2,16; \ |
124 | .mem.offset 8,0; st8.spill [r17]=r3,16; \ | 136 | .mem.offset 8,0; st8.spill [r17]=r3,16; \ |
137 | ACCOUNT_GET_STAMP \ | ||
125 | adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ | 138 | adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ |
126 | ;; \ | 139 | ;; \ |
127 | EXTRA; \ | 140 | EXTRA; \ |
128 | movl r1=__gp; /* establish kernel global pointer */ \ | 141 | movl r1=__gp; /* establish kernel global pointer */ \ |
129 | ;; \ | 142 | ;; \ |
143 | ACCOUNT_SYS_ENTER \ | ||
130 | bsw.1; /* switch back to bank 1 (must be last in insn group) */ \ | 144 | bsw.1; /* switch back to bank 1 (must be last in insn group) */ \ |
131 | ;; | 145 | ;; |
132 | 146 | ||
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index 17fda5293c67..48e15a51782f 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
@@ -59,6 +59,84 @@ static struct clocksource clocksource_itc = { | |||
59 | }; | 59 | }; |
60 | static struct clocksource *itc_clocksource; | 60 | static struct clocksource *itc_clocksource; |
61 | 61 | ||
62 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
63 | |||
64 | #include <linux/kernel_stat.h> | ||
65 | |||
66 | extern cputime_t cycle_to_cputime(u64 cyc); | ||
67 | |||
68 | /* | ||
69 | * Called from the context switch with interrupts disabled, to charge all | ||
70 | * accumulated times to the current process, and to prepare accounting on | ||
71 | * the next process. | ||
72 | */ | ||
73 | void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next) | ||
74 | { | ||
75 | struct thread_info *pi = task_thread_info(prev); | ||
76 | struct thread_info *ni = task_thread_info(next); | ||
77 | cputime_t delta_stime, delta_utime; | ||
78 | __u64 now; | ||
79 | |||
80 | now = ia64_get_itc(); | ||
81 | |||
82 | delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp)); | ||
83 | account_system_time(prev, 0, delta_stime); | ||
84 | account_system_time_scaled(prev, delta_stime); | ||
85 | |||
86 | if (pi->ac_utime) { | ||
87 | delta_utime = cycle_to_cputime(pi->ac_utime); | ||
88 | account_user_time(prev, delta_utime); | ||
89 | account_user_time_scaled(prev, delta_utime); | ||
90 | } | ||
91 | |||
92 | pi->ac_stamp = ni->ac_stamp = now; | ||
93 | ni->ac_stime = ni->ac_utime = 0; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Account time for a transition between system, hard irq or soft irq state. | ||
98 | * Note that this function is called with interrupts enabled. | ||
99 | */ | ||
100 | void account_system_vtime(struct task_struct *tsk) | ||
101 | { | ||
102 | struct thread_info *ti = task_thread_info(tsk); | ||
103 | unsigned long flags; | ||
104 | cputime_t delta_stime; | ||
105 | __u64 now; | ||
106 | |||
107 | local_irq_save(flags); | ||
108 | |||
109 | now = ia64_get_itc(); | ||
110 | |||
111 | delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); | ||
112 | account_system_time(tsk, 0, delta_stime); | ||
113 | account_system_time_scaled(tsk, delta_stime); | ||
114 | ti->ac_stime = 0; | ||
115 | |||
116 | ti->ac_stamp = now; | ||
117 | |||
118 | local_irq_restore(flags); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Called from the timer interrupt handler to charge accumulated user time | ||
123 | * to the current process. Must be called with interrupts disabled. | ||
124 | */ | ||
125 | void account_process_tick(struct task_struct *p, int user_tick) | ||
126 | { | ||
127 | struct thread_info *ti = task_thread_info(p); | ||
128 | cputime_t delta_utime; | ||
129 | |||
130 | if (ti->ac_utime) { | ||
131 | delta_utime = cycle_to_cputime(ti->ac_utime); | ||
132 | account_user_time(p, delta_utime); | ||
133 | account_user_time_scaled(p, delta_utime); | ||
134 | ti->ac_utime = 0; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
139 | |||
62 | static irqreturn_t | 140 | static irqreturn_t |
63 | timer_interrupt (int irq, void *dev_id) | 141 | timer_interrupt (int irq, void *dev_id) |
64 | { | 142 | { |
diff --git a/include/asm-ia64/cputime.h b/include/asm-ia64/cputime.h index 72400a78002a..f9abdec6577a 100644 --- a/include/asm-ia64/cputime.h +++ b/include/asm-ia64/cputime.h | |||
@@ -1,6 +1,110 @@ | |||
1 | /* | ||
2 | * include/asm-ia64/cputime.h: | ||
3 | * Definitions for measuring cputime on ia64 machines. | ||
4 | * | ||
5 | * Based on <asm-powerpc/cputime.h>. | ||
6 | * | ||
7 | * Copyright (C) 2007 FUJITSU LIMITED | ||
8 | * Copyright (C) 2007 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | * | ||
15 | * If we have CONFIG_VIRT_CPU_ACCOUNTING, we measure cpu time in nsec. | ||
16 | * Otherwise we measure cpu time in jiffies using the generic definitions. | ||
17 | */ | ||
18 | |||
1 | #ifndef __IA64_CPUTIME_H | 19 | #ifndef __IA64_CPUTIME_H |
2 | #define __IA64_CPUTIME_H | 20 | #define __IA64_CPUTIME_H |
3 | 21 | ||
22 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | ||
4 | #include <asm-generic/cputime.h> | 23 | #include <asm-generic/cputime.h> |
24 | #else | ||
25 | |||
26 | #include <linux/time.h> | ||
27 | #include <linux/jiffies.h> | ||
28 | #include <asm/processor.h> | ||
29 | |||
30 | typedef u64 cputime_t; | ||
31 | typedef u64 cputime64_t; | ||
32 | |||
33 | #define cputime_zero ((cputime_t)0) | ||
34 | #define cputime_max ((~((cputime_t)0) >> 1) - 1) | ||
35 | #define cputime_add(__a, __b) ((__a) + (__b)) | ||
36 | #define cputime_sub(__a, __b) ((__a) - (__b)) | ||
37 | #define cputime_div(__a, __n) ((__a) / (__n)) | ||
38 | #define cputime_halve(__a) ((__a) >> 1) | ||
39 | #define cputime_eq(__a, __b) ((__a) == (__b)) | ||
40 | #define cputime_gt(__a, __b) ((__a) > (__b)) | ||
41 | #define cputime_ge(__a, __b) ((__a) >= (__b)) | ||
42 | #define cputime_lt(__a, __b) ((__a) < (__b)) | ||
43 | #define cputime_le(__a, __b) ((__a) <= (__b)) | ||
44 | |||
45 | #define cputime64_zero ((cputime64_t)0) | ||
46 | #define cputime64_add(__a, __b) ((__a) + (__b)) | ||
47 | #define cputime64_sub(__a, __b) ((__a) - (__b)) | ||
48 | #define cputime_to_cputime64(__ct) (__ct) | ||
49 | |||
50 | /* | ||
51 | * Convert cputime <-> jiffies (HZ) | ||
52 | */ | ||
53 | #define cputime_to_jiffies(__ct) ((__ct) / (NSEC_PER_SEC / HZ)) | ||
54 | #define jiffies_to_cputime(__jif) ((__jif) * (NSEC_PER_SEC / HZ)) | ||
55 | #define cputime64_to_jiffies64(__ct) ((__ct) / (NSEC_PER_SEC / HZ)) | ||
56 | #define jiffies64_to_cputime64(__jif) ((__jif) * (NSEC_PER_SEC / HZ)) | ||
57 | |||
58 | /* | ||
59 | * Convert cputime <-> milliseconds | ||
60 | */ | ||
61 | #define cputime_to_msecs(__ct) ((__ct) / NSEC_PER_MSEC) | ||
62 | #define msecs_to_cputime(__msecs) ((__msecs) * NSEC_PER_MSEC) | ||
63 | |||
64 | /* | ||
65 | * Convert cputime <-> seconds | ||
66 | */ | ||
67 | #define cputime_to_secs(__ct) ((__ct) / NSEC_PER_SEC) | ||
68 | #define secs_to_cputime(__secs) ((__secs) * NSEC_PER_SEC) | ||
69 | |||
70 | /* | ||
71 | * Convert cputime <-> timespec (nsec) | ||
72 | */ | ||
73 | static inline cputime_t timespec_to_cputime(const struct timespec *val) | ||
74 | { | ||
75 | cputime_t ret = val->tv_sec * NSEC_PER_SEC; | ||
76 | return (ret + val->tv_nsec); | ||
77 | } | ||
78 | static inline void cputime_to_timespec(const cputime_t ct, struct timespec *val) | ||
79 | { | ||
80 | val->tv_sec = ct / NSEC_PER_SEC; | ||
81 | val->tv_nsec = ct % NSEC_PER_SEC; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Convert cputime <-> timeval (msec) | ||
86 | */ | ||
87 | static inline cputime_t timeval_to_cputime(struct timeval *val) | ||
88 | { | ||
89 | cputime_t ret = val->tv_sec * NSEC_PER_SEC; | ||
90 | return (ret + val->tv_usec * NSEC_PER_USEC); | ||
91 | } | ||
92 | static inline void cputime_to_timeval(const cputime_t ct, struct timeval *val) | ||
93 | { | ||
94 | val->tv_sec = ct / NSEC_PER_SEC; | ||
95 | val->tv_usec = (ct % NSEC_PER_SEC) / NSEC_PER_USEC; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Convert cputime <-> clock (USER_HZ) | ||
100 | */ | ||
101 | #define cputime_to_clock_t(__ct) ((__ct) / (NSEC_PER_SEC / USER_HZ)) | ||
102 | #define clock_t_to_cputime(__x) ((__x) * (NSEC_PER_SEC / USER_HZ)) | ||
103 | |||
104 | /* | ||
105 | * Convert cputime64 to clock. | ||
106 | */ | ||
107 | #define cputime64_to_clock_t(__ct) cputime_to_clock_t((cputime_t)__ct) | ||
5 | 108 | ||
109 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
6 | #endif /* __IA64_CPUTIME_H */ | 110 | #endif /* __IA64_CPUTIME_H */ |
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index 595112bca3cc..dff8128fa58e 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h | |||
@@ -210,6 +210,13 @@ struct task_struct; | |||
210 | extern void ia64_save_extra (struct task_struct *task); | 210 | extern void ia64_save_extra (struct task_struct *task); |
211 | extern void ia64_load_extra (struct task_struct *task); | 211 | extern void ia64_load_extra (struct task_struct *task); |
212 | 212 | ||
213 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
214 | extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next); | ||
215 | # define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n) | ||
216 | #else | ||
217 | # define IA64_ACCOUNT_ON_SWITCH(p,n) | ||
218 | #endif | ||
219 | |||
213 | #ifdef CONFIG_PERFMON | 220 | #ifdef CONFIG_PERFMON |
214 | DECLARE_PER_CPU(unsigned long, pfm_syst_info); | 221 | DECLARE_PER_CPU(unsigned long, pfm_syst_info); |
215 | # define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1) | 222 | # define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1) |
@@ -222,6 +229,7 @@ extern void ia64_load_extra (struct task_struct *task); | |||
222 | || IS_IA32_PROCESS(task_pt_regs(t)) || PERFMON_IS_SYSWIDE()) | 229 | || IS_IA32_PROCESS(task_pt_regs(t)) || PERFMON_IS_SYSWIDE()) |
223 | 230 | ||
224 | #define __switch_to(prev,next,last) do { \ | 231 | #define __switch_to(prev,next,last) do { \ |
232 | IA64_ACCOUNT_ON_SWITCH(prev, next); \ | ||
225 | if (IA64_HAS_EXTRA_STATE(prev)) \ | 233 | if (IA64_HAS_EXTRA_STATE(prev)) \ |
226 | ia64_save_extra(prev); \ | 234 | ia64_save_extra(prev); \ |
227 | if (IA64_HAS_EXTRA_STATE(next)) \ | 235 | if (IA64_HAS_EXTRA_STATE(next)) \ |
@@ -266,6 +274,10 @@ void cpu_idle_wait(void); | |||
266 | 274 | ||
267 | void default_idle(void); | 275 | void default_idle(void); |
268 | 276 | ||
277 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
278 | extern void account_system_vtime(struct task_struct *); | ||
279 | #endif | ||
280 | |||
269 | #endif /* __KERNEL__ */ | 281 | #endif /* __KERNEL__ */ |
270 | 282 | ||
271 | #endif /* __ASSEMBLY__ */ | 283 | #endif /* __ASSEMBLY__ */ |
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index 93d83cbe0c8c..6da8069a0f77 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h | |||
@@ -31,6 +31,12 @@ struct thread_info { | |||
31 | mm_segment_t addr_limit; /* user-level address space limit */ | 31 | mm_segment_t addr_limit; /* user-level address space limit */ |
32 | int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ | 32 | int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ |
33 | struct restart_block restart_block; | 33 | struct restart_block restart_block; |
34 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
35 | __u64 ac_stamp; | ||
36 | __u64 ac_leave; | ||
37 | __u64 ac_stime; | ||
38 | __u64 ac_utime; | ||
39 | #endif | ||
34 | }; | 40 | }; |
35 | 41 | ||
36 | #define THREAD_SIZE KERNEL_STACK_SIZE | 42 | #define THREAD_SIZE KERNEL_STACK_SIZE |
@@ -62,9 +68,17 @@ struct thread_info { | |||
62 | #define task_stack_page(tsk) ((void *)(tsk)) | 68 | #define task_stack_page(tsk) ((void *)(tsk)) |
63 | 69 | ||
64 | #define __HAVE_THREAD_FUNCTIONS | 70 | #define __HAVE_THREAD_FUNCTIONS |
71 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
72 | #define setup_thread_stack(p, org) \ | ||
73 | *task_thread_info(p) = *task_thread_info(org); \ | ||
74 | task_thread_info(p)->ac_stime = 0; \ | ||
75 | task_thread_info(p)->ac_utime = 0; \ | ||
76 | task_thread_info(p)->task = (p); | ||
77 | #else | ||
65 | #define setup_thread_stack(p, org) \ | 78 | #define setup_thread_stack(p, org) \ |
66 | *task_thread_info(p) = *task_thread_info(org); \ | 79 | *task_thread_info(p) = *task_thread_info(org); \ |
67 | task_thread_info(p)->task = (p); | 80 | task_thread_info(p)->task = (p); |
81 | #endif | ||
68 | #define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET) | 82 | #define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET) |
69 | 83 | ||
70 | #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR | 84 | #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR |