On 2/11/16, Christophe Leroy <christophe.le...@c-s.fr> wrote:
> This patch provides VIRT_CPU_ACCOUTING to PPC32 architecture.
> PPC32 doesn't have the PACA structure, so we use the task_info
> structure to store the accounting data.
>
> In order to reuse on PPC32 the PPC64 functions, all u64 data has
> been replaced by 'unsigned long' so that it is u32 on PPC32 and
> u64 on PPC64
>
> Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr>

I'll try it out on my ppc32 machines.

Thanks!

> ---
> Changes in v3: unlike previous version of the patch that was inspired
> from IA64 architecture, this new version tries to reuse as much as
> possible the PPC64 implementation.
>
> PPC32 doesn't have PACA and past discusion on v2 version has shown
> that it is not worth implementing a PACA in PPC32 architecture
> (see below benh opinion)
>
> benh: PACA is actually a data structure and you really really don't want it
> on ppc32 :-) Having a register point to current works, having a register
> point to per-cpu data instead works too (ie, change what we do today),
> but don't introduce a PACA *please* :-)
>
> Changes in v4: ACCOUNT_CPU_USER_ENTRY/EXIT() needed updates in other
> places than entry_32.S and entry_64.S (reported by kbuild-robot)
> Related defines in asm-offset.c need to be conditional to
> CONFIG_VIRT_CPU_ACCOUNTING_NATIVE (reported by kbuild-robot)
>
> Changes in v5: Using PPC_LL et PPC_STL instead of defining new macros
> AC_LD and AC_STD
>
>  arch/powerpc/Kconfig                     |  1 +
>  arch/powerpc/include/asm/cputime.h       |  4 ++++
>  arch/powerpc/include/asm/exception-64s.h |  2 +-
>  arch/powerpc/include/asm/ppc_asm.h       | 24 ++++++++++----------
>  arch/powerpc/include/asm/reg.h           |  1 +
>  arch/powerpc/include/asm/thread_info.h   | 11 +++++++++
>  arch/powerpc/kernel/asm-offsets.c        |  7 ++++++
>  arch/powerpc/kernel/entry_32.S           | 17 ++++++++++++++
>  arch/powerpc/kernel/entry_64.S           |  6 ++---
>  arch/powerpc/kernel/exceptions-64e.S     |  4 ++--
>  arch/powerpc/kernel/time.c               | 38
> ++++++++++++++++++++++++++------
>  arch/powerpc/platforms/Kconfig.cputype   |  1 -
>  12 files changed, 90 insertions(+), 26 deletions(-)
>
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 3a557be..57ce4ff 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -159,6 +159,7 @@ config PPC
>       select ARCH_HAS_DEVMEM_IS_ALLOWED
>       select HAVE_ARCH_SECCOMP_FILTER
>       select ARCH_HAS_UBSAN_SANITIZE_ALL
> +     select HAVE_VIRT_CPU_ACCOUNTING
>
>  config GENERIC_CSUM
>       def_bool CPU_LITTLE_ENDIAN
> diff --git a/arch/powerpc/include/asm/cputime.h
> b/arch/powerpc/include/asm/cputime.h
> index e245255..c4c33be 100644
> --- a/arch/powerpc/include/asm/cputime.h
> +++ b/arch/powerpc/include/asm/cputime.h
> @@ -230,7 +230,11 @@ static inline cputime_t clock_t_to_cputime(const
> unsigned long clk)
>
>  #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
> +void arch_vtime_task_switch(struct task_struct *tsk);
> +#endif
>
>  #endif /* __KERNEL__ */
>  #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
> diff --git a/arch/powerpc/include/asm/exception-64s.h
> b/arch/powerpc/include/asm/exception-64s.h
> index 93ae809..8bc38d1 100644
> --- a/arch/powerpc/include/asm/exception-64s.h
> +++ b/arch/powerpc/include/asm/exception-64s.h
> @@ -287,7 +287,7 @@ do_kvm_##n:                                               
>                 \
>       std     r0,GPR0(r1);            /* save r0 in stackframe        */ \
>       std     r10,GPR1(r1);           /* save r1 in stackframe        */ \
>       beq     4f;                     /* if from kernel mode          */ \
> -     ACCOUNT_CPU_USER_ENTRY(r9, r10);                                   \
> +     ACCOUNT_CPU_USER_ENTRY(r13, r9, r10);                              \
>       SAVE_PPR(area, r9, r10);                                           \
>  4:   EXCEPTION_PROLOG_COMMON_2(area)                                    \
>       EXCEPTION_PROLOG_COMMON_3(n)                                       \
> diff --git a/arch/powerpc/include/asm/ppc_asm.h
> b/arch/powerpc/include/asm/ppc_asm.h
> index 499d9f8..07d1bfc 100644
> --- a/arch/powerpc/include/asm/ppc_asm.h
> +++ b/arch/powerpc/include/asm/ppc_asm.h
> @@ -24,27 +24,27 @@
>   */
>
>  #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
> -#define ACCOUNT_CPU_USER_ENTRY(ra, rb)
> -#define ACCOUNT_CPU_USER_EXIT(ra, rb)
> +#define ACCOUNT_CPU_USER_ENTRY(ptr, ra, rb)
> +#define ACCOUNT_CPU_USER_EXIT(ptr, ra, rb)
>  #define ACCOUNT_STOLEN_TIME
>  #else
> -#define ACCOUNT_CPU_USER_ENTRY(ra, rb)                                       
> \
> +#define ACCOUNT_CPU_USER_ENTRY(ptr, ra, rb)                          \
>       MFTB(ra);                       /* get timebase */              \
> -     ld      rb,PACA_STARTTIME_USER(r13);                            \
> -     std     ra,PACA_STARTTIME(r13);                                 \
> +     PPC_LL  rb, PACA_STARTTIME_USER(ptr);                           \
> +     PPC_STL ra, PACA_STARTTIME(ptr);                                \
>       subf    rb,rb,ra;               /* subtract start value */      \
> -     ld      ra,PACA_USER_TIME(r13);                                 \
> +     PPC_LL  ra, PACA_USER_TIME(ptr);                                \
>       add     ra,ra,rb;               /* add on to user time */       \
> -     std     ra,PACA_USER_TIME(r13);                                 \
> +     PPC_STL ra, PACA_USER_TIME(ptr);                                \
>
> -#define ACCOUNT_CPU_USER_EXIT(ra, rb)                                        
> \
> +#define ACCOUNT_CPU_USER_EXIT(ptr, ra, rb)                           \
>       MFTB(ra);                       /* get timebase */              \
> -     ld      rb,PACA_STARTTIME(r13);                                 \
> -     std     ra,PACA_STARTTIME_USER(r13);                            \
> +     PPC_LL  rb, PACA_STARTTIME(ptr);                                \
> +     PPC_STL ra, PACA_STARTTIME_USER(ptr);                           \
>       subf    rb,rb,ra;               /* subtract start value */      \
> -     ld      ra,PACA_SYSTEM_TIME(r13);                               \
> +     PPC_LL  ra, PACA_SYSTEM_TIME(ptr);                              \
>       add     ra,ra,rb;               /* add on to system time */     \
> -     std     ra,PACA_SYSTEM_TIME(r13)
> +     PPC_STL ra, PACA_SYSTEM_TIME(ptr)
>
>  #ifdef CONFIG_PPC_SPLPAR
>  #define ACCOUNT_STOLEN_TIME                                          \
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
> index c4cb2ff..ff6b591 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -1275,6 +1275,7 @@ static inline unsigned long mfvtb (void)
>                       asm volatile("mfspr %0, %1" : "=r" (rval) : \
>                               "i" (SPRN_TBRU)); rval;})
>  #endif
> +#define mftb()               mftbl()
>  #endif /* !__powerpc64__ */
>
>  #define mttbl(v)     asm volatile("mttbl %0":: "r"(v))
> diff --git a/arch/powerpc/include/asm/thread_info.h
> b/arch/powerpc/include/asm/thread_info.h
> index 7efee4a..4f19e96 100644
> --- a/arch/powerpc/include/asm/thread_info.h
> +++ b/arch/powerpc/include/asm/thread_info.h
> @@ -44,6 +44,17 @@ struct thread_info {
>                                                  <0 => BUG */
>       unsigned long   local_flags;            /* private flags for thread */
>
> +#if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32)
> +     /* Stuff for accurate time accounting */
> +     unsigned long user_time;        /* accumulated usermode TB ticks */
> +     unsigned long system_time;      /* accumulated system TB ticks */
> +     unsigned long user_time_scaled; /* accumulated usermode SPURR ticks */
> +     unsigned long starttime;        /* TB value snapshot */
> +     unsigned long starttime_user;   /* TB value on exit to usermode */
> +     unsigned long startspurr;       /* SPURR value snapshot */
> +     unsigned long utime_sspurr;     /* ->user_time when ->startspurr set */
> +#endif
> +
>       /* low level flags - has atomic operations done on it */
>       unsigned long   flags ____cacheline_aligned_in_smp;
>  };
> diff --git a/arch/powerpc/kernel/asm-offsets.c
> b/arch/powerpc/kernel/asm-offsets.c
> index 07cebc3..b04b957 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -256,6 +256,13 @@ int main(void)
>       DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
>       DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost));
>       DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso));
> +#else /* CONFIG_PPC64 */
> +#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
> +     DEFINE(PACA_STARTTIME, offsetof(struct thread_info, starttime));
> +     DEFINE(PACA_STARTTIME_USER, offsetof(struct thread_info, 
> starttime_user));
> +     DEFINE(PACA_USER_TIME, offsetof(struct thread_info, user_time));
> +     DEFINE(PACA_SYSTEM_TIME, offsetof(struct thread_info, system_time));
> +#endif
>  #endif /* CONFIG_PPC64 */
>
>       /* RTAS */
> diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
> index 2405631..9899032 100644
> --- a/arch/powerpc/kernel/entry_32.S
> +++ b/arch/powerpc/kernel/entry_32.S
> @@ -175,6 +175,12 @@ transfer_to_handler:
>       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
> @@ -398,6 +404,13 @@ BEGIN_FTR_SECTION
>       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
> @@ -769,6 +782,10 @@ restore_user:
>       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
>
> diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
> index 0d525ce..d9bf82b 100644
> --- a/arch/powerpc/kernel/entry_64.S
> +++ b/arch/powerpc/kernel/entry_64.S
> @@ -70,7 +70,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM)
>       std     r0,GPR0(r1)
>       std     r10,GPR1(r1)
>       beq     2f                      /* if from kernel mode */
> -     ACCOUNT_CPU_USER_ENTRY(r10, r11)
> +     ACCOUNT_CPU_USER_ENTRY(r13, r10, r11)
>  2:   std     r2,GPR2(r1)
>       std     r3,GPR3(r1)
>       mfcr    r2
> @@ -222,7 +222,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
>       ld      r4,_LINK(r1)
>
>       beq-    1f
> -     ACCOUNT_CPU_USER_EXIT(r11, r12)
> +     ACCOUNT_CPU_USER_EXIT(r13, r11, r12)
>
>  BEGIN_FTR_SECTION
>       HMT_MEDIUM_LOW
> @@ -822,7 +822,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
>  BEGIN_FTR_SECTION
>       mtspr   SPRN_PPR,r2     /* Restore PPR */
>  END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
> -     ACCOUNT_CPU_USER_EXIT(r2, r4)
> +     ACCOUNT_CPU_USER_EXIT(r13, r2, r4)
>       REST_GPR(13, r1)
>  1:
>       mtspr   SPRN_SRR1,r3
> diff --git a/arch/powerpc/kernel/exceptions-64e.S
> b/arch/powerpc/kernel/exceptions-64e.S
> index 488e631..a9bc548 100644
> --- a/arch/powerpc/kernel/exceptions-64e.S
> +++ b/arch/powerpc/kernel/exceptions-64e.S
> @@ -386,7 +386,7 @@ exc_##n##_common:                                         
>             \
>       std     r10,_NIP(r1);           /* save SRR0 to stackframe */       \
>       std     r11,_MSR(r1);           /* save SRR1 to stackframe */       \
>       beq     2f;                     /* if from kernel mode */           \
> -     ACCOUNT_CPU_USER_ENTRY(r10,r11);/* accounting (uses cr0+eq) */      \
> +     ACCOUNT_CPU_USER_ENTRY(r13,r10,r11);/* accounting (uses cr0+eq) */ \
>  2:   ld      r3,excf+EX_R10(r13);    /* get back r10 */                  \
>       ld      r4,excf+EX_R11(r13);    /* get back r11 */                  \
>       mfspr   r5,scratch;             /* get back r13 */                  \
> @@ -1059,7 +1059,7 @@ fast_exception_return:
>       andi.   r6,r10,MSR_PR
>       REST_2GPRS(6, r1)
>       beq     1f
> -     ACCOUNT_CPU_USER_EXIT(r10, r11)
> +     ACCOUNT_CPU_USER_EXIT(r13, r10, r11)
>       ld      r0,GPR13(r1)
>
>  1:   stdcx.  r0,0,r1         /* to clear the reservation */
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index 81b0900..6307b09 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -165,7 +165,13 @@ DEFINE_PER_CPU(unsigned long,
> cputime_scaled_last_delta);
>
>  cputime_t cputime_one_jiffy;
>
> +#ifdef CONFIG_PPC_SPLPAR
>  void (*dtl_consumer)(struct dtl_entry *, u64);
> +#endif
> +
> +#ifdef CONFIG_PPC32
> +#define get_paca()   task_thread_info(tsk)
> +#endif
>
>  static void calc_cputime_factors(void)
>  {
> @@ -185,7 +191,7 @@ static void calc_cputime_factors(void)
>   * Read the SPURR on systems that have it, otherwise the PURR,
>   * or if that doesn't exist return the timebase value passed in.
>   */
> -static u64 read_spurr(u64 tb)
> +static unsigned long read_spurr(unsigned long tb)
>  {
>       if (cpu_has_feature(CPU_FTR_SPURR))
>               return mfspr(SPRN_SPURR);
> @@ -294,11 +300,12 @@ static inline u64 calculate_stolen_time(u64 stop_tb)
>   * Account time for a transition between system, hard irq
>   * or soft irq state.
>   */
> -static u64 vtime_delta(struct task_struct *tsk,
> -                     u64 *sys_scaled, u64 *stolen)
> +static unsigned long vtime_delta(struct task_struct *tsk,
> +                              unsigned long *sys_scaled,
> +                              unsigned long *stolen)
>  {
> -     u64 now, nowscaled, deltascaled;
> -     u64 udelta, delta, user_scaled;
> +     unsigned long now, nowscaled, deltascaled;
> +     unsigned long udelta, delta, user_scaled;
>
>       WARN_ON_ONCE(!irqs_disabled());
>
> @@ -343,7 +350,7 @@ static u64 vtime_delta(struct task_struct *tsk,
>
>  void vtime_account_system(struct task_struct *tsk)
>  {
> -     u64 delta, sys_scaled, stolen;
> +     unsigned long delta, sys_scaled, stolen;
>
>       delta = vtime_delta(tsk, &sys_scaled, &stolen);
>       account_system_time(tsk, 0, delta, sys_scaled);
> @@ -354,7 +361,7 @@ EXPORT_SYMBOL_GPL(vtime_account_system);
>
>  void vtime_account_idle(struct task_struct *tsk)
>  {
> -     u64 delta, sys_scaled, stolen;
> +     unsigned long delta, sys_scaled, stolen;
>
>       delta = vtime_delta(tsk, &sys_scaled, &stolen);
>       account_idle_time(delta + stolen);
> @@ -381,6 +388,23 @@ void vtime_account_user(struct task_struct *tsk)
>       account_user_time(tsk, utime, utimescaled);
>  }
>
> +#ifdef CONFIG_PPC32
> +/*
> + * 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->starttime = pi->starttime;
> +     ni->system_time = 0;
> +     ni->user_time = 0;
> +}
> +#endif /* CONFIG_PPC32 */
> +
>  #else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
>  #define calc_cputime_factors()
>  #endif
> diff --git a/arch/powerpc/platforms/Kconfig.cputype
> b/arch/powerpc/platforms/Kconfig.cputype
> index 142dff5..54b8043 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -1,7 +1,6 @@
>  config PPC64
>       bool "64-bit kernel"
>       default n
> -     select HAVE_VIRT_CPU_ACCOUNTING
>       select ZLIB_DEFLATE
>       help
>         This option selects whether a 32-bit or a 64-bit kernel
> --
> 2.1.0
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to