mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-29 02:14:03 -04:00
s390/preempt: Enable HAS_SEPARATE_PREEMPT_RESCHED_BITS
Convert s390's preempt_count to 64 bit, and change the preempt primitives accordingly. [boqun: Apply the corrected comment for asm block] Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Boqun Feng <boqun@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20260804161447.84806-13-boqun@kernel.org
This commit is contained in:
committed by
Peter Zijlstra
parent
264bbd32a3
commit
3484440a7b
@@ -273,6 +273,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
|
||||
|
||||
@@ -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 percpu_register; /* 0x03c0 */
|
||||
__u8 pad_0x03c1[0x0400-0x03c1]; /* 0x03c1 */
|
||||
|
||||
@@ -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);
|
||||
/* READ_ONCE(get_lowcore()->preempt_count) & ~PREEMPT_NEED_RESCHED */
|
||||
lc_preempt = offsetof(struct lowcore, preempt.count);
|
||||
/* READ_ONCE(get_lowcore()->preempt.count) (without 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)
|
||||
|
||||
Reference in New Issue
Block a user