LCOV - code coverage report
Current view: top level - arch/arm64/include/asm - percpu.h (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-djwa @ Mon Jul 31 20:08:17 PDT 2023 Lines: 6 7 85.7 %
Date: 2023-07-31 20:08:17 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0-only */
       2             : /*
       3             :  * Copyright (C) 2013 ARM Ltd.
       4             :  */
       5             : #ifndef __ASM_PERCPU_H
       6             : #define __ASM_PERCPU_H
       7             : 
       8             : #include <linux/preempt.h>
       9             : 
      10             : #include <asm/alternative.h>
      11             : #include <asm/cmpxchg.h>
      12             : #include <asm/stack_pointer.h>
      13             : #include <asm/sysreg.h>
      14             : 
      15             : static inline void set_my_cpu_offset(unsigned long off)
      16             : {
      17             :         asm volatile(ALTERNATIVE("msr tpidr_el1, %0",
      18             :                                  "msr tpidr_el2, %0",
      19             :                                  ARM64_HAS_VIRT_HOST_EXTN)
      20             :                         :: "r" (off) : "memory");
      21             : }
      22             : 
      23             : static inline unsigned long __hyp_my_cpu_offset(void)
      24             : {
      25             :         /*
      26             :          * Non-VHE hyp code runs with preemption disabled. No need to hazard
      27             :          * the register access against barrier() as in __kern_my_cpu_offset.
      28             :          */
      29             :         return read_sysreg(tpidr_el2);
      30             : }
      31             : 
      32 >50763*10^7 : static inline unsigned long __kern_my_cpu_offset(void)
      33             : {
      34 >50763*10^7 :         unsigned long off;
      35             : 
      36             :         /*
      37             :          * We want to allow caching the value, so avoid using volatile and
      38             :          * instead use a fake stack read to hazard against barrier().
      39             :          */
      40 >50763*10^7 :         asm(ALTERNATIVE("mrs %0, tpidr_el1",
      41             :                         "mrs %0, tpidr_el2",
      42             :                         ARM64_HAS_VIRT_HOST_EXTN)
      43             :                 : "=r" (off) :
      44 >50763*10^7 :                 "Q" (*(const unsigned long *)current_stack_pointer));
      45             : 
      46 >50763*10^7 :         return off;
      47             : }
      48             : 
      49             : #ifdef __KVM_NVHE_HYPERVISOR__
      50             : #define __my_cpu_offset __hyp_my_cpu_offset()
      51             : #else
      52             : #define __my_cpu_offset __kern_my_cpu_offset()
      53             : #endif
      54             : 
      55             : #define PERCPU_RW_OPS(sz)                                               \
      56             : static inline unsigned long __percpu_read_##sz(void *ptr)               \
      57             : {                                                                       \
      58             :         return READ_ONCE(*(u##sz *)ptr);                                \
      59             : }                                                                       \
      60             :                                                                         \
      61             : static inline void __percpu_write_##sz(void *ptr, unsigned long val)    \
      62             : {                                                                       \
      63             :         WRITE_ONCE(*(u##sz *)ptr, (u##sz)val);                          \
      64             : }
      65             : 
      66             : #define __PERCPU_OP_CASE(w, sfx, name, sz, op_llsc, op_lse)             \
      67             : static inline void                                                      \
      68             : __percpu_##name##_case_##sz(void *ptr, unsigned long val)               \
      69             : {                                                                       \
      70             :         unsigned int loop;                                              \
      71             :         u##sz tmp;                                                      \
      72             :                                                                         \
      73             :         asm volatile (ARM64_LSE_ATOMIC_INSN(                            \
      74             :         /* LL/SC */                                                     \
      75             :         "1:        ldxr" #sfx "\t%" #w "[tmp], %[ptr]\n"                  \
      76             :                 #op_llsc "\t%" #w "[tmp], %" #w "[tmp], %" #w "[val]\n" \
      77             :         "  stxr" #sfx "\t%w[loop], %" #w "[tmp], %[ptr]\n"                \
      78             :         "  cbnz    %w[loop], 1b",                                     \
      79             :         /* LSE atomics */                                               \
      80             :                 #op_lse "\t%" #w "[val], %[ptr]\n"                  \
      81             :                 __nops(3))                                              \
      82             :         : [loop] "=&r" (loop), [tmp] "=&r" (tmp),                   \
      83             :           [ptr] "+Q"(*(u##sz *)ptr)                                   \
      84             :         : [val] "r" ((u##sz)(val)));                                  \
      85             : }
      86             : 
      87             : #define __PERCPU_RET_OP_CASE(w, sfx, name, sz, op_llsc, op_lse)         \
      88             : static inline u##sz                                                     \
      89             : __percpu_##name##_return_case_##sz(void *ptr, unsigned long val)        \
      90             : {                                                                       \
      91             :         unsigned int loop;                                              \
      92             :         u##sz ret;                                                      \
      93             :                                                                         \
      94             :         asm volatile (ARM64_LSE_ATOMIC_INSN(                            \
      95             :         /* LL/SC */                                                     \
      96             :         "1:        ldxr" #sfx "\t%" #w "[ret], %[ptr]\n"                  \
      97             :                 #op_llsc "\t%" #w "[ret], %" #w "[ret], %" #w "[val]\n" \
      98             :         "  stxr" #sfx "\t%w[loop], %" #w "[ret], %[ptr]\n"                \
      99             :         "  cbnz    %w[loop], 1b",                                     \
     100             :         /* LSE atomics */                                               \
     101             :                 #op_lse "\t%" #w "[val], %" #w "[ret], %[ptr]\n"  \
     102             :                 #op_llsc "\t%" #w "[ret], %" #w "[ret], %" #w "[val]\n" \
     103             :                 __nops(2))                                              \
     104             :         : [loop] "=&r" (loop), [ret] "=&r" (ret),                   \
     105             :           [ptr] "+Q"(*(u##sz *)ptr)                                   \
     106             :         : [val] "r" ((u##sz)(val)));                                  \
     107             :                                                                         \
     108             :         return ret;                                                     \
     109             : }
     110             : 
     111             : #define PERCPU_OP(name, op_llsc, op_lse)                                \
     112             :         __PERCPU_OP_CASE(w, b, name,  8, op_llsc, op_lse)               \
     113             :         __PERCPU_OP_CASE(w, h, name, 16, op_llsc, op_lse)               \
     114             :         __PERCPU_OP_CASE(w,  , name, 32, op_llsc, op_lse)               \
     115             :         __PERCPU_OP_CASE( ,  , name, 64, op_llsc, op_lse)
     116             : 
     117             : #define PERCPU_RET_OP(name, op_llsc, op_lse)                            \
     118             :         __PERCPU_RET_OP_CASE(w, b, name,  8, op_llsc, op_lse)           \
     119             :         __PERCPU_RET_OP_CASE(w, h, name, 16, op_llsc, op_lse)           \
     120             :         __PERCPU_RET_OP_CASE(w,  , name, 32, op_llsc, op_lse)           \
     121             :         __PERCPU_RET_OP_CASE( ,  , name, 64, op_llsc, op_lse)
     122             : 
     123             : PERCPU_RW_OPS(8)
     124             : PERCPU_RW_OPS(16)
     125             : PERCPU_RW_OPS(32)
     126           0 : PERCPU_RW_OPS(64)
     127 21340693420 : PERCPU_OP(add, add, stadd)
     128             : PERCPU_OP(andnot, bic, stclr)
     129             : PERCPU_OP(or, orr, stset)
     130             : PERCPU_RET_OP(add, add, ldadd)
     131             : 
     132             : #undef PERCPU_RW_OPS
     133             : #undef __PERCPU_OP_CASE
     134             : #undef __PERCPU_RET_OP_CASE
     135             : #undef PERCPU_OP
     136             : #undef PERCPU_RET_OP
     137             : 
     138             : /*
     139             :  * It would be nice to avoid the conditional call into the scheduler when
     140             :  * re-enabling preemption for preemptible kernels, but doing that in a way
     141             :  * which builds inside a module would mean messing directly with the preempt
     142             :  * count. If you do this, peterz and tglx will hunt you down.
     143             :  *
     144             :  * Not to mention it'll break the actual preemption model for missing a
     145             :  * preemption point when TIF_NEED_RESCHED gets set while preemption is
     146             :  * disabled.
     147             :  */
     148             : 
     149             : #define _pcp_protect(op, pcp, ...)                                      \
     150             : ({                                                                      \
     151             :         preempt_disable_notrace();                                      \
     152             :         op(raw_cpu_ptr(&(pcp)), __VA_ARGS__);                               \
     153             :         preempt_enable_notrace();                                       \
     154             : })
     155             : 
     156             : #define _pcp_protect_return(op, pcp, args...)                           \
     157             : ({                                                                      \
     158             :         typeof(pcp) __retval;                                           \
     159             :         preempt_disable_notrace();                                      \
     160             :         __retval = (typeof(pcp))op(raw_cpu_ptr(&(pcp)), ##args);    \
     161             :         preempt_enable_notrace();                                       \
     162             :         __retval;                                                       \
     163             : })
     164             : 
     165             : #define this_cpu_read_1(pcp)            \
     166             :         _pcp_protect_return(__percpu_read_8, pcp)
     167             : #define this_cpu_read_2(pcp)            \
     168             :         _pcp_protect_return(__percpu_read_16, pcp)
     169             : #define this_cpu_read_4(pcp)            \
     170             :         _pcp_protect_return(__percpu_read_32, pcp)
     171             : #define this_cpu_read_8(pcp)            \
     172             :         _pcp_protect_return(__percpu_read_64, pcp)
     173             : 
     174             : #define this_cpu_write_1(pcp, val)      \
     175             :         _pcp_protect(__percpu_write_8, pcp, (unsigned long)val)
     176             : #define this_cpu_write_2(pcp, val)      \
     177             :         _pcp_protect(__percpu_write_16, pcp, (unsigned long)val)
     178             : #define this_cpu_write_4(pcp, val)      \
     179             :         _pcp_protect(__percpu_write_32, pcp, (unsigned long)val)
     180             : #define this_cpu_write_8(pcp, val)      \
     181             :         _pcp_protect(__percpu_write_64, pcp, (unsigned long)val)
     182             : 
     183             : #define this_cpu_add_1(pcp, val)        \
     184             :         _pcp_protect(__percpu_add_case_8, pcp, val)
     185             : #define this_cpu_add_2(pcp, val)        \
     186             :         _pcp_protect(__percpu_add_case_16, pcp, val)
     187             : #define this_cpu_add_4(pcp, val)        \
     188             :         _pcp_protect(__percpu_add_case_32, pcp, val)
     189             : #define this_cpu_add_8(pcp, val)        \
     190             :         _pcp_protect(__percpu_add_case_64, pcp, val)
     191             : 
     192             : #define this_cpu_add_return_1(pcp, val) \
     193             :         _pcp_protect_return(__percpu_add_return_case_8, pcp, val)
     194             : #define this_cpu_add_return_2(pcp, val) \
     195             :         _pcp_protect_return(__percpu_add_return_case_16, pcp, val)
     196             : #define this_cpu_add_return_4(pcp, val) \
     197             :         _pcp_protect_return(__percpu_add_return_case_32, pcp, val)
     198             : #define this_cpu_add_return_8(pcp, val) \
     199             :         _pcp_protect_return(__percpu_add_return_case_64, pcp, val)
     200             : 
     201             : #define this_cpu_and_1(pcp, val)        \
     202             :         _pcp_protect(__percpu_andnot_case_8, pcp, ~val)
     203             : #define this_cpu_and_2(pcp, val)        \
     204             :         _pcp_protect(__percpu_andnot_case_16, pcp, ~val)
     205             : #define this_cpu_and_4(pcp, val)        \
     206             :         _pcp_protect(__percpu_andnot_case_32, pcp, ~val)
     207             : #define this_cpu_and_8(pcp, val)        \
     208             :         _pcp_protect(__percpu_andnot_case_64, pcp, ~val)
     209             : 
     210             : #define this_cpu_or_1(pcp, val)         \
     211             :         _pcp_protect(__percpu_or_case_8, pcp, val)
     212             : #define this_cpu_or_2(pcp, val)         \
     213             :         _pcp_protect(__percpu_or_case_16, pcp, val)
     214             : #define this_cpu_or_4(pcp, val)         \
     215             :         _pcp_protect(__percpu_or_case_32, pcp, val)
     216             : #define this_cpu_or_8(pcp, val)         \
     217             :         _pcp_protect(__percpu_or_case_64, pcp, val)
     218             : 
     219             : #define this_cpu_xchg_1(pcp, val)       \
     220             :         _pcp_protect_return(xchg_relaxed, pcp, val)
     221             : #define this_cpu_xchg_2(pcp, val)       \
     222             :         _pcp_protect_return(xchg_relaxed, pcp, val)
     223             : #define this_cpu_xchg_4(pcp, val)       \
     224             :         _pcp_protect_return(xchg_relaxed, pcp, val)
     225             : #define this_cpu_xchg_8(pcp, val)       \
     226             :         _pcp_protect_return(xchg_relaxed, pcp, val)
     227             : 
     228             : #define this_cpu_cmpxchg_1(pcp, o, n)   \
     229             :         _pcp_protect_return(cmpxchg_relaxed, pcp, o, n)
     230             : #define this_cpu_cmpxchg_2(pcp, o, n)   \
     231             :         _pcp_protect_return(cmpxchg_relaxed, pcp, o, n)
     232             : #define this_cpu_cmpxchg_4(pcp, o, n)   \
     233             :         _pcp_protect_return(cmpxchg_relaxed, pcp, o, n)
     234             : #define this_cpu_cmpxchg_8(pcp, o, n)   \
     235             :         _pcp_protect_return(cmpxchg_relaxed, pcp, o, n)
     236             : 
     237             : #define this_cpu_cmpxchg64(pcp, o, n)   this_cpu_cmpxchg_8(pcp, o, n)
     238             : 
     239             : #define this_cpu_cmpxchg128(pcp, o, n)                                  \
     240             : ({                                                                      \
     241             :         typedef typeof(pcp) pcp_op_T__;                                 \
     242             :         u128 old__, new__, ret__;                                       \
     243             :         pcp_op_T__ *ptr__;                                              \
     244             :         old__ = o;                                                      \
     245             :         new__ = n;                                                      \
     246             :         preempt_disable_notrace();                                      \
     247             :         ptr__ = raw_cpu_ptr(&(pcp));                                        \
     248             :         ret__ = cmpxchg128_local((void *)ptr__, old__, new__);          \
     249             :         preempt_enable_notrace();                                       \
     250             :         ret__;                                                          \
     251             : })
     252             : 
     253             : #ifdef __KVM_NVHE_HYPERVISOR__
     254             : extern unsigned long __hyp_per_cpu_offset(unsigned int cpu);
     255             : #define __per_cpu_offset
     256             : #define per_cpu_offset(cpu)     __hyp_per_cpu_offset((cpu))
     257             : #endif
     258             : 
     259             : #include <asm-generic/percpu.h>
     260             : 
     261             : /* Redefine macros for nVHE hyp under DEBUG_PREEMPT to avoid its dependencies. */
     262             : #if defined(__KVM_NVHE_HYPERVISOR__) && defined(CONFIG_DEBUG_PREEMPT)
     263             : #undef  this_cpu_ptr
     264             : #define this_cpu_ptr            raw_cpu_ptr
     265             : #undef  __this_cpu_read
     266             : #define __this_cpu_read         raw_cpu_read
     267             : #undef  __this_cpu_write
     268             : #define __this_cpu_write        raw_cpu_write
     269             : #endif
     270             : 
     271             : #endif /* __ASM_PERCPU_H */

Generated by: LCOV version 1.14