On Mon, 2014-04-07 at 09:31 +0200, Christophe Leroy wrote:
> This patch provides VIRT_CPU_ACCOUTING to PPC32 architecture.
> Unlike PPC64, PPC32 doesn't use the PACA convention. Therefore the
> implementation is taken from the IA64 architecture.
> It is based on additional information added to the Task Info structure.
> 
> Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr>

Scott, Can you review/ack this (or get somebody to) ?

It looks like a great idea but I really don't have the bandwidth to
review in detail and test right now.

(Adding Alister as well who maintains our 4xx 32-bit stuff nowadays).

Cheers,
Ben.

> Index: b/arch/powerpc/Kconfig
> ===================================================================
> --- a/arch/powerpc/Kconfig    (revision 5607)
> +++ b/arch/powerpc/Kconfig    (revision 5611)
> @@ -138,6 +138,7 @@
>       select OLD_SIGSUSPEND
>       select OLD_SIGACTION if PPC32
>       select HAVE_DEBUG_STACKOVERFLOW
> +     select HAVE_VIRT_CPU_ACCOUNTING
>  
>  config EARLY_PRINTK
>       bool
> Index: a/arch/powerpc/kernel/time.c
> ===================================================================
> --- a/arch/powerpc/kernel/time.c      (revision 5607)
> +++ b/arch/powerpc/kernel/time.c      (revision 5611)
> @@ -162,7 +162,9 @@
>  
>  cputime_t cputime_one_jiffy;
>  
> +#ifdef CONFIG_PPC_SPLPAR
>  void (*dtl_consumer)(struct dtl_entry *, u64);
> +#endif
>  
>  static void calc_cputime_factors(void)
>  {
> @@ -178,6 +180,7 @@
>       __cputime_clockt_factor = res.result_low;
>  }
>  
> +#ifdef CONFIG_PPC64
>  /*
>   * Read the SPURR on systems that have it, otherwise the PURR,
>   * or if that doesn't exist return the timebase value passed in.
> @@ -190,6 +193,7 @@
>               return mfspr(SPRN_PURR);
>       return tb;
>  }
> +#endif
>  
>  #ifdef CONFIG_PPC_SPLPAR
>  
> @@ -291,6 +295,7 @@
>   * Account time for a transition between system, hard irq
>   * or soft irq state.
>   */
> +#ifdef CONFIG_PPC64
>  static u64 vtime_delta(struct task_struct *tsk,
>                       u64 *sys_scaled, u64 *stolen)
>  {
> @@ -377,7 +382,70 @@
>       get_paca()->utime_sspurr = 0;
>       account_user_time(tsk, utime, utimescaled);
>  }
> +#else
>  
> +void vtime_account_user(struct task_struct *tsk)
> +{
> +     cputime_t delta_utime;
> +     struct thread_info *ti = task_thread_info(tsk);
> +
> +     if (ti->ac_utime) {
> +             delta_utime = ti->ac_utime;
> +             account_user_time(tsk, delta_utime, delta_utime);
> +             ti->ac_utime = 0;
> +     }
> +}
> +
> +/*
> + * Called from the context switch with interrupts disabled, to charge all
> + * accumulated times to the current process, and to prepare accounting on
> + * the next process.
> + */
> +void arch_vtime_task_switch(struct task_struct *prev)
> +{
> +     struct thread_info *pi = task_thread_info(prev);
> +     struct thread_info *ni = task_thread_info(current);
> +
> +     ni->ac_stamp = pi->ac_stamp;
> +     ni->ac_stime = ni->ac_utime = 0;
> +}
> +
> +/*
> + * Account time for a transition between system, hard irq or soft irq state.
> + * Note that this function is called with interrupts enabled.
> + */
> +static cputime_t vtime_delta(struct task_struct *tsk)
> +{
> +     struct thread_info *ti = task_thread_info(tsk);
> +     __u32 delta_stime;
> +     __u32 now;
> +
> +     WARN_ON_ONCE(!irqs_disabled());
> +
> +     now = mftbl();
> +
> +     delta_stime = ti->ac_stime + (now - ti->ac_stamp);
> +     ti->ac_stime = 0;
> +     ti->ac_stamp = now;
> +
> +     return (cputime_t)delta_stime;
> +}
> +
> +void vtime_account_system(struct task_struct *tsk)
> +{
> +     cputime_t delta = vtime_delta(tsk);
> +
> +     account_system_time(tsk, 0, delta, delta);
> +}
> +EXPORT_SYMBOL_GPL(vtime_account_system);
> +
> +void vtime_account_idle(struct task_struct *tsk)
> +{
> +     account_idle_time(vtime_delta(tsk));
> +}
> +
> +#endif
> +
>  #else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
>  #define calc_cputime_factors()
>  #endif
> @@ -871,6 +939,8 @@
>                      ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
>       }
>  
> +     mttbl(0);
> +     mttbu(0);
>       tb_ticks_per_jiffy = ppc_tb_freq / HZ;
>       tb_ticks_per_sec = ppc_tb_freq;
>       tb_ticks_per_usec = ppc_tb_freq / 1000000;
> Index: b/arch/powerpc/kernel/entry_32.S
> ===================================================================
> --- a/arch/powerpc/kernel/entry_32.S  (revision 5607)
> +++ b/arch/powerpc/kernel/entry_32.S  (revision 5611)
> @@ -177,6 +177,12 @@
>       addi    r12,r12,-1
>       stw     r12,4(r11)
>  #endif
> +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
> +     CURRENT_THREAD_INFO(r9, r1)
> +     tophys(r9, r9)
> +     ACCOUNT_CPU_USER_ENTRY(r9, r11, r12)
> +#endif
> +
>       b       3f
>  
>  2:   /* if from kernel, check interrupted DOZE/NAP mode and
> @@ -406,6 +412,13 @@
>       lwarx   r7,0,r1
>  END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
>       stwcx.  r0,0,r1                 /* to clear the reservation */
> +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
> +     andi.   r4,r8,MSR_PR
> +     beq     3f
> +     CURRENT_THREAD_INFO(r4, r1)
> +     ACCOUNT_CPU_USER_EXIT(r4, r5, r7)
> +3:
> +#endif
>       lwz     r4,_LINK(r1)
>       lwz     r5,_CCR(r1)
>       mtlr    r4
> @@ -841,6 +854,10 @@
>       andis.  r10,r0,DBCR0_IDM@h
>       bnel-   load_dbcr0
>  #endif
> +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
> +     CURRENT_THREAD_INFO(r9, r1)
> +     ACCOUNT_CPU_USER_EXIT(r9, r10, r11)
> +#endif
>  
>       b       restore
>  
> Index: b/arch/powerpc/kernel/asm-offsets.c
> ===================================================================
> --- a/arch/powerpc/kernel/asm-offsets.c       (revision 5607)
> +++ b/arch/powerpc/kernel/asm-offsets.c       (revision 5611)
> @@ -167,6 +167,12 @@
>       DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
>       DEFINE(TI_TASK, offsetof(struct thread_info, task));
>       DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
> +#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32)
> +     DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp));
> +     DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave));
> +     DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime));
> +     DEFINE(TI_AC_UTIME, offsetof(struct thread_info, ac_utime));
> +#endif
>  
>  #ifdef CONFIG_PPC64
>       DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size));
> Index: b/arch/powerpc/include/asm/thread_info.h
> ===================================================================
> --- a/arch/powerpc/include/asm/thread_info.h  (revision 5607)
> +++ b/arch/powerpc/include/asm/thread_info.h  (revision 5611)
> @@ -43,6 +43,12 @@
>       int             cpu;                    /* cpu we're on */
>       int             preempt_count;          /* 0 => preemptable,
>                                                  <0 => BUG */
> +#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32)
> +     u32 ac_stamp;
> +     u32 ac_leave;
> +     u32 ac_stime;
> +     u32 ac_utime;
> +#endif
>       struct restart_block restart_block;
>       unsigned long   local_flags;            /* private flags for thread */
>  
> Index: b/arch/powerpc/include/asm/cputime.h
> ===================================================================
> --- a/arch/powerpc/include/asm/cputime.h      (revision 5607)
> +++ b/arch/powerpc/include/asm/cputime.h      (revision 5611)
> @@ -228,7 +228,11 @@
>  
>  #define cputime64_to_clock_t(ct)     cputime_to_clock_t((cputime_t)(ct))
>  
> +#ifdef CONFIG_PPC64
>  static inline void arch_vtime_task_switch(struct task_struct *tsk) { }
> +#else
> +extern void arch_vtime_task_switch(struct task_struct *tsk);
> +#endif
>  
>  #endif /* __KERNEL__ */
>  #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
> Index: b/arch/powerpc/include/asm/ppc_asm.h
> ===================================================================
> --- a/arch/powerpc/include/asm/ppc_asm.h      (revision 5607)
> +++ b/arch/powerpc/include/asm/ppc_asm.h      (revision 5611)
> @@ -25,10 +25,16 @@
>   */
>  
>  #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
> +#ifdef CONFIG_PPC64
>  #define ACCOUNT_CPU_USER_ENTRY(ra, rb)
>  #define ACCOUNT_CPU_USER_EXIT(ra, rb)
> +#else /* CONFIG_PPC64 */
> +#define ACCOUNT_CPU_USER_ENTRY(ti, ra, rb)
> +#define ACCOUNT_CPU_USER_EXIT(ti, ra, rb)
> +#endif /* CONFIG_PPC64 */
>  #define ACCOUNT_STOLEN_TIME
> -#else
> +#else /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
> +#ifdef CONFIG_PPC64
>  #define ACCOUNT_CPU_USER_ENTRY(ra, rb)                                       
> \
>       MFTB(ra);                       /* get timebase */              \
>       ld      rb,PACA_STARTTIME_USER(r13);                            \
> @@ -68,7 +74,27 @@
>  #define ACCOUNT_STOLEN_TIME
>  
>  #endif /* CONFIG_PPC_SPLPAR */
> +#else /* CONFIG_PPC64 */
> +#define ACCOUNT_CPU_USER_ENTRY(ti, ra, rb)                           \
> +     MFTB(ra);                                                       \
> +     lwz rb, TI_AC_LEAVE(ti);                                        \
> +     stw ra, TI_AC_STAMP(ti);        /* AC_STAMP = NOW */            \
> +     subf rb, rb, ra;                /* R = NOW - AC_LEAVE */        \
> +     lwz ra, TI_AC_UTIME(ti);                                        \
> +     add ra, rb, ra;                 /* AC_UTIME += R */             \
> +     stw ra, TI_AC_UTIME(ti);                                        \
>  
> +#define ACCOUNT_CPU_USER_EXIT(ti, ra, rb)                            \
> +     MFTB(ra);                                                       \
> +     lwz rb, TI_AC_STAMP(ti);                                        \
> +     stw ra, TI_AC_LEAVE(ti);                                        \
> +     subf rb, rb, ra;                /* R = NOW - AC_STAMP */        \
> +     lwz ra, TI_AC_STIME(ti);                                        \
> +     add ra, rb, ra;                 /* AC_STIME += R */             \
> +     stw ra, TI_AC_STIME(ti);                                        \
> +
> +#endif /* CONFIG_PPC64 */
> +
>  #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
>  
>  /*
> Index: b/arch/powerpc/platforms/Kconfig.cputype
> ===================================================================
> --- a/arch/powerpc/platforms/Kconfig.cputype  (revision 5607)
> +++ b/arch/powerpc/platforms/Kconfig.cputype  (revision 5611)
> @@ -1,7 +1,6 @@
>  config PPC64
>       bool "64-bit kernel"
>       default n
> -     select HAVE_VIRT_CPU_ACCOUNTING
>       help
>         This option selects whether a 32-bit or a 64-bit kernel
>         will be built.


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to