diff options
| author | Tony Luck <tony.luck@intel.com> | 2008-04-17 13:12:27 -0400 |
|---|---|---|
| committer | Tony Luck <tony.luck@intel.com> | 2008-04-17 13:12:27 -0400 |
| commit | 14d0647c98f52e2d76113d44de6b771ec87a934f (patch) | |
| tree | 4b9407b00ad0b5baf5ee6245a4157a07062680b5 | |
| parent | 2a467d5f7d6bdc90c365db167a10022dd8351894 (diff) | |
| parent | b64f34cdfe5bef9dfed1304c513220b0f2862eca (diff) | |
Pull virt-cpu-accounting into release branch
| -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 8fa3faf5ef1b..eef457fda08f 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
| @@ -283,6 +283,17 @@ config FORCE_MAX_ZONEORDER | |||
| 283 | default "17" if HUGETLB_PAGE | 283 | default "17" if HUGETLB_PAGE |
| 284 | default "11" | 284 | default "11" |
| 285 | 285 | ||
| 286 | config VIRT_CPU_ACCOUNTING | ||
| 287 | bool "Deterministic task and CPU time accounting" | ||
| 288 | default n | ||
| 289 | help | ||
| 290 | Select this option to enable more accurate task and CPU time | ||
| 291 | accounting. This is done by reading a CPU counter on each | ||
| 292 | kernel entry and exit and on transitions within the kernel | ||
| 293 | between system, softirq and hardirq state, so there is a | ||
| 294 | small performance impact. | ||
| 295 | If in doubt, say N here. | ||
| 296 | |||
| 286 | config SMP | 297 | config SMP |
| 287 | bool "Symmetric multi-processing support" | 298 | bool "Symmetric multi-processing support" |
| 288 | help | 299 | 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 6a72db7ddecc..357b7e2adc63 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
| @@ -656,7 +656,11 @@ GLOBAL_ENTRY(fsys_bubble_down) | |||
| 656 | nop.i 0 | 656 | nop.i 0 |
| 657 | ;; | 657 | ;; |
| 658 | mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0 | 658 | mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0 |
| 659 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
| 660 | mov.m r30=ar.itc // M get cycle for accounting | ||
| 661 | #else | ||
| 659 | nop.m 0 | 662 | nop.m 0 |
| 663 | #endif | ||
| 660 | nop.i 0 | 664 | nop.i 0 |
| 661 | ;; | 665 | ;; |
| 662 | mov r23=ar.bspstore // M2 (12 cyc) save ar.bspstore | 666 | mov r23=ar.bspstore // M2 (12 cyc) save ar.bspstore |
| @@ -678,6 +682,28 @@ GLOBAL_ENTRY(fsys_bubble_down) | |||
| 678 | cmp.ne pKStk,pUStk=r0,r0 // A set pKStk <- 0, pUStk <- 1 | 682 | cmp.ne pKStk,pUStk=r0,r0 // A set pKStk <- 0, pUStk <- 1 |
| 679 | br.call.sptk.many b7=ia64_syscall_setup // B | 683 | br.call.sptk.many b7=ia64_syscall_setup // B |
| 680 | ;; | 684 | ;; |
| 685 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
| 686 | // mov.m r30=ar.itc is called in advance | ||
| 687 | add r16=TI_AC_STAMP+IA64_TASK_SIZE,r2 | ||
| 688 | add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r2 | ||
| 689 | ;; | ||
| 690 | ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel | ||
| 691 | ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at leave kernel | ||
| 692 | ;; | ||
| 693 | ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime | ||
| 694 | ld8 r21=[r17] // cumulated utime | ||
| 695 | sub r22=r19,r18 // stime before leave kernel | ||
| 696 | ;; | ||
| 697 | st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // update stamp | ||
| 698 | sub r18=r30,r19 // elapsed time in user mode | ||
| 699 | ;; | ||
| 700 | add r20=r20,r22 // sum stime | ||
| 701 | add r21=r21,r18 // sum utime | ||
| 702 | ;; | ||
| 703 | st8 [r16]=r20 // update stime | ||
| 704 | st8 [r17]=r21 // update utime | ||
| 705 | ;; | ||
| 706 | #endif | ||
| 681 | mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 | 707 | mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 |
| 682 | mov rp=r14 // I0 set the real return addr | 708 | mov rp=r14 // I0 set the real return addr |
| 683 | and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A | 709 | 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 |
