Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/cmpxchg: use register pair instead of register asm

Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Heiko Carstens and committed by
Vasily Gorbik
79ee201e 2bd67038

+38 -33
+24 -20
arch/s390/include/asm/cmpxchg.h
··· 169 169 170 170 #define system_has_cmpxchg_double() 1 171 171 172 - #define __cmpxchg_double(p1, p2, o1, o2, n1, n2) \ 173 - ({ \ 174 - register __typeof__(*(p1)) __old1 asm("2") = (o1); \ 175 - register __typeof__(*(p2)) __old2 asm("3") = (o2); \ 176 - register __typeof__(*(p1)) __new1 asm("4") = (n1); \ 177 - register __typeof__(*(p2)) __new2 asm("5") = (n2); \ 178 - int cc; \ 179 - asm volatile( \ 180 - " cdsg %[old],%[new],%[ptr]\n" \ 181 - " ipm %[cc]\n" \ 182 - " srl %[cc],28" \ 183 - : [cc] "=d" (cc), [old] "+d" (__old1), "+d" (__old2) \ 184 - : [new] "d" (__new1), "d" (__new2), \ 185 - [ptr] "Q" (*(p1)), "Q" (*(p2)) \ 186 - : "memory", "cc"); \ 187 - !cc; \ 188 - }) 172 + static __always_inline int __cmpxchg_double(unsigned long p1, unsigned long p2, 173 + unsigned long o1, unsigned long o2, 174 + unsigned long n1, unsigned long n2) 175 + { 176 + union register_pair old = { .even = o1, .odd = o2, }; 177 + union register_pair new = { .even = n1, .odd = n2, }; 178 + int cc; 179 + 180 + asm volatile( 181 + " cdsg %[old],%[new],%[ptr]\n" 182 + " ipm %[cc]\n" 183 + " srl %[cc],28\n" 184 + : [cc] "=&d" (cc), [old] "+&d" (old.pair) 185 + : [new] "d" (new.pair), 186 + [ptr] "QS" (*(unsigned long *)p1), "Q" (*(unsigned long *)p2) 187 + : "memory", "cc"); 188 + return !cc; 189 + } 189 190 190 191 #define arch_cmpxchg_double(p1, p2, o1, o2, n1, n2) \ 191 192 ({ \ 192 - __typeof__(p1) __p1 = (p1); \ 193 - __typeof__(p2) __p2 = (p2); \ 193 + typeof(p1) __p1 = (p1); \ 194 + typeof(p2) __p2 = (p2); \ 195 + \ 194 196 BUILD_BUG_ON(sizeof(*(p1)) != sizeof(long)); \ 195 197 BUILD_BUG_ON(sizeof(*(p2)) != sizeof(long)); \ 196 198 VM_BUG_ON((unsigned long)((__p1) + 1) != (unsigned long)(__p2));\ 197 - __cmpxchg_double(__p1, __p2, o1, o2, n1, n2); \ 199 + __cmpxchg_double((unsigned long)__p1, (unsigned long)__p2, \ 200 + (unsigned long)(o1), (unsigned long)(o2), \ 201 + (unsigned long)(n1), (unsigned long)(n2)); \ 198 202 }) 199 203 200 204 #endif /* __ASM_CMPXCHG_H */
+14 -13
arch/s390/include/asm/percpu.h
··· 164 164 #define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval) 165 165 #define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval) 166 166 167 - #define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2) \ 168 - ({ \ 169 - typeof(pcp1) o1__ = (o1), n1__ = (n1); \ 170 - typeof(pcp2) o2__ = (o2), n2__ = (n2); \ 171 - typeof(pcp1) *p1__; \ 172 - typeof(pcp2) *p2__; \ 173 - int ret__; \ 174 - preempt_disable_notrace(); \ 175 - p1__ = raw_cpu_ptr(&(pcp1)); \ 176 - p2__ = raw_cpu_ptr(&(pcp2)); \ 177 - ret__ = __cmpxchg_double(p1__, p2__, o1__, o2__, n1__, n2__); \ 178 - preempt_enable_notrace(); \ 179 - ret__; \ 167 + #define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2) \ 168 + ({ \ 169 + typeof(pcp1) *p1__; \ 170 + typeof(pcp2) *p2__; \ 171 + int ret__; \ 172 + \ 173 + preempt_disable_notrace(); \ 174 + p1__ = raw_cpu_ptr(&(pcp1)); \ 175 + p2__ = raw_cpu_ptr(&(pcp2)); \ 176 + ret__ = __cmpxchg_double((unsigned long)p1__, (unsigned long)p2__, \ 177 + (unsigned long)(o1), (unsigned long)(o2), \ 178 + (unsigned long)(n1), (unsigned long)(n2)); \ 179 + preempt_enable_notrace(); \ 180 + ret__; \ 180 181 }) 181 182 182 183 #define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double