From: Heiko Carstens <[email protected]>

Convert s390's preempt_count to 64 bit, and change the preempt
primitives accordingly.

Signed-off-by: Heiko Carstens <[email protected]>
Signed-off-by: Boqun Feng <[email protected]>
Link: https://patch.msgid.link/[email protected]
---
 arch/s390/Kconfig               |  1 +
 arch/s390/include/asm/lowcore.h | 13 +++++++----
 arch/s390/include/asm/preempt.h | 41 +++++++++++++++------------------
 3 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index ecbcbb781e40..cbbca82f8443 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -276,6 +276,7 @@ config S390
        select PCI_MSI                  if PCI
        select PCI_MSI_ARCH_FALLBACKS   if PCI_MSI
        select PCI_QUIRKS               if PCI
+       select HAS_SEPARATE_PREEMPT_RESCHED_BITS
        select SPARSE_IRQ
        select SWIOTLB
        select SYSCTL_EXCEPTION_TRACE
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index 50ffe75adeb4..0974ab278169 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -160,10 +160,15 @@ struct lowcore {
        /* SMP info area */
        __u32   cpu_nr;                         /* 0x03a0 */
        __u32   softirq_pending;                /* 0x03a4 */
-       __s32   preempt_count;                  /* 0x03a8 */
-       __u32   spinlock_lockval;               /* 0x03ac */
-       __u32   spinlock_index;                 /* 0x03b0 */
-       __u8    pad_0x03b4[0x03b8-0x03b4];      /* 0x03b4 */
+       union {
+               struct {
+                       __u32   need_resched;   /* 0x03a8 */
+                       __u32   count;          /* 0x03ac */
+               } preempt;
+               __u64   preempt_count;          /* 0x03a8 */
+       };
+       __u32   spinlock_lockval;               /* 0x03b0 */
+       __u32   spinlock_index;                 /* 0x03b4 */
        __u64   percpu_offset;                  /* 0x03b8 */
        __u8    pad_0x03c0[0x0400-0x03c0];      /* 0x03c0 */
 
diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h
index 0a25d4648b4c..1d5e4d7e9e1b 100644
--- a/arch/s390/include/asm/preempt.h
+++ b/arch/s390/include/asm/preempt.h
@@ -8,11 +8,8 @@
 #include <asm/cmpxchg.h>
 #include <asm/march.h>
 
-/*
- * Use MSB so it is possible to read preempt_count with LLGT which
- * reads the least significant 31 bits with a single instruction.
- */
-#define PREEMPT_NEED_RESCHED   0x80000000
+/* Use MSB for PREEMPT_NEED_RESCHED mostly because it is available. */
+#define PREEMPT_NEED_RESCHED   0x8000000000000000UL
 
 /*
  * We use the PREEMPT_NEED_RESCHED bit as an inverted NEED_RESCHED such
@@ -26,25 +23,25 @@
  */
 static __always_inline int preempt_count(void)
 {
-       unsigned long lc_preempt, count;
+       unsigned long lc_preempt;
+       int count;
 
-       BUILD_BUG_ON(sizeof_field(struct lowcore, preempt_count) != 
sizeof(int));
-       lc_preempt = offsetof(struct lowcore, preempt_count);
+       lc_preempt = offsetof(struct lowcore, preempt.count);
        /* READ_ONCE(get_lowcore()->preempt_count) & ~PREEMPT_NEED_RESCHED */
        asm_inline(
-               ALTERNATIVE("llgt       %[count],%[offzero](%%r0)\n",
-                           "llgt       %[count],%[offalt](%%r0)\n",
+               ALTERNATIVE("ly         %[count],%[offzero](%%r0)\n",
+                           "ly         %[count],%[offalt](%%r0)\n",
                            ALT_FEATURE(MFEATURE_LOWCORE))
                : [count] "=d" (count)
                : [offzero] "i" (lc_preempt),
                  [offalt] "i" (lc_preempt + LOWCORE_ALT_ADDRESS),
-                 "m" (((struct lowcore *)0)->preempt_count));
+                 "m" (((struct lowcore *)0)->preempt.count));
        return count;
 }
 
-static __always_inline void preempt_count_set(int pc)
+static __always_inline void preempt_count_set(unsigned long pc)
 {
-       int old, new;
+       unsigned long old, new;
 
        old = READ_ONCE(get_lowcore()->preempt_count);
        do {
@@ -63,12 +60,12 @@ static __always_inline void preempt_count_set(int pc)
 
 static __always_inline void set_preempt_need_resched(void)
 {
-       __atomic_and(~PREEMPT_NEED_RESCHED, &get_lowcore()->preempt_count);
+       __atomic64_and(~PREEMPT_NEED_RESCHED, (long 
*)&get_lowcore()->preempt_count);
 }
 
 static __always_inline void clear_preempt_need_resched(void)
 {
-       __atomic_or(PREEMPT_NEED_RESCHED, &get_lowcore()->preempt_count);
+       __atomic64_or(PREEMPT_NEED_RESCHED, (long 
*)&get_lowcore()->preempt_count);
 }
 
 static __always_inline bool test_preempt_need_resched(void)
@@ -88,8 +85,8 @@ static __always_inline void __preempt_count_add(int val)
 
                        lc_preempt = offsetof(struct lowcore, preempt_count);
                        asm_inline(
-                               ALTERNATIVE("asi        
%[offzero](%%r0),%[val]\n",
-                                           "asi        
%[offalt](%%r0),%[val]\n",
+                               ALTERNATIVE("agsi       
%[offzero](%%r0),%[val]\n",
+                                           "agsi       
%[offalt](%%r0),%[val]\n",
                                            ALT_FEATURE(MFEATURE_LOWCORE))
                                : "+m" (((struct lowcore *)0)->preempt_count)
                                : [offzero] "i" (lc_preempt), [val] "i" (val),
@@ -98,7 +95,7 @@ static __always_inline void __preempt_count_add(int val)
                        return;
                }
        }
-       __atomic_add(val, &get_lowcore()->preempt_count);
+       __atomic64_add(val, (long *)&get_lowcore()->preempt_count);
 }
 
 static __always_inline void __preempt_count_sub(int val)
@@ -119,15 +116,15 @@ static __always_inline bool 
__preempt_count_dec_and_test(void)
 
        lc_preempt = offsetof(struct lowcore, preempt_count);
        asm_inline(
-               ALTERNATIVE("alsi       %[offzero](%%r0),%[val]\n",
-                           "alsi       %[offalt](%%r0),%[val]\n",
+               ALTERNATIVE("algsi      %[offzero](%%r0),%[val]\n",
+                           "algsi      %[offalt](%%r0),%[val]\n",
                            ALT_FEATURE(MFEATURE_LOWCORE))
                : "=@cc" (cc), "+m" (((struct lowcore *)0)->preempt_count)
                : [offzero] "i" (lc_preempt), [val] "i" (-1),
                [offalt] "i" (lc_preempt + LOWCORE_ALT_ADDRESS));
        return (cc == 0) || (cc == 2);
 #else
-       return __atomic_add_const_and_test(-1, &get_lowcore()->preempt_count);
+       return __atomic64_add_const_and_test(-1, (long 
*)&get_lowcore()->preempt_count);
 #endif
 }
 
@@ -141,7 +138,7 @@ static __always_inline bool should_resched(int 
preempt_offset)
 
 static __always_inline int __preempt_count_add_return(int val)
 {
-       return val + __atomic_add(val, &get_lowcore()->preempt_count);
+       return val + __atomic64_add(val, (long *)&get_lowcore()->preempt_count);
 }
 
 static __always_inline int __preempt_count_sub_return(int val)
-- 
2.50.1 (Apple Git-155)


Reply via email to