The branch stable/15 has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=1bb1d38e4160836c048b79b922a1a3f980e9128b

commit 1bb1d38e4160836c048b79b922a1a3f980e9128b
Author:     Mark Johnston <[email protected]>
AuthorDate: 2026-08-24 17:05:28 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2026-08-24 17:06:24 +0000

    Revert "atomic: Implement atomic_{set,clear}_8 in _atomic_subword.h"
    
    This commit fails to compile for powerpc64le.  Just revert it as it's
    only a cleanup motivated by adding support for KASAN to riscv.
    
    This is a direct commit to stable/15.
    
    This reverts commit 318915568443f1fdb65faab0f559c872f09628c6.
    
    Reported by:    jenkins
---
 sys/sys/_atomic_subword.h | 54 ++++++++++-----------------------
 sys/vm/vm_page.c          | 76 +++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 82 insertions(+), 48 deletions(-)

diff --git a/sys/sys/_atomic_subword.h b/sys/sys/_atomic_subword.h
index 907fef0bb193..284e2bfa340f 100644
--- a/sys/sys/_atomic_subword.h
+++ b/sys/sys/_atomic_subword.h
@@ -201,42 +201,21 @@ atomic_load_acq_16(const volatile uint16_t *p)
 }
 #endif
 
-#ifndef atomic_set_8
-static __inline void
-atomic_set_8(volatile uint8_t *p, uint8_t bit)
-{
-       uint32_t *addr;
-       int shift;
-
-       addr = _ATOMIC_WORD_ALIGNED(p);
-       shift = _ATOMIC_BYTE_SHIFT(p);
-       atomic_set_32(addr, (uint32_t)bit << shift);
-}
-#endif
+#undef _ATOMIC_WORD_ALIGNED
+#undef _ATOMIC_BYTE_SHIFT
+#undef _ATOMIC_HWORD_SHIFT
 
 #ifndef atomic_set_16
 static __inline void
 atomic_set_16(volatile uint16_t *p, uint16_t bit)
 {
-       uint32_t *addr;
-       int shift;
-
-       addr = _ATOMIC_WORD_ALIGNED(p);
-       shift = _ATOMIC_HWORD_SHIFT(p);
-       atomic_set_32(addr, (uint32_t)bit << shift);
-}
-#endif
-
-#ifndef atomic_clear_8
-static __inline void
-atomic_clear_8(volatile uint8_t *p, uint8_t bit)
-{
-       uint32_t *addr;
-       int shift;
+       uint16_t v;
 
-       addr = _ATOMIC_WORD_ALIGNED(p);
-       shift = _ATOMIC_BYTE_SHIFT(p);
-       atomic_clear_32(addr, (uint32_t)bit << shift);
+       v = atomic_load_16(p);
+       for (;;) {
+               if (atomic_fcmpset_16(p, &v, v | bit))
+                       break;
+       }
 }
 #endif
 
@@ -244,17 +223,14 @@ atomic_clear_8(volatile uint8_t *p, uint8_t bit)
 static __inline void
 atomic_clear_16(volatile uint16_t *p, uint16_t bit)
 {
-       uint32_t *addr;
-       int shift;
+       uint16_t v;
 
-       addr = _ATOMIC_WORD_ALIGNED(p);
-       shift = _ATOMIC_HWORD_SHIFT(p);
-       atomic_clear_32(addr, (uint32_t)bit << shift);
+       v = atomic_load_16(p);
+       for (;;) {
+               if (atomic_fcmpset_16(p, &v, v & ~bit))
+                       break;
+       }
 }
 #endif
 
-#undef _ATOMIC_WORD_ALIGNED
-#undef _ATOMIC_BYTE_SHIFT
-#undef _ATOMIC_HWORD_SHIFT
-
 #endif /* _SYS__ATOMIC_SUBWORD_H_ */
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index fdf63b2160f6..ce5748bd5f33 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -5363,33 +5363,67 @@ vm_page_bits(int base, int size)
 void
 vm_page_bits_set(vm_page_t m, vm_page_bits_t *bits, vm_page_bits_t set)
 {
+
 #if PAGE_SIZE == 32768
        atomic_set_64((uint64_t *)bits, set);
 #elif PAGE_SIZE == 16384
        atomic_set_32((uint32_t *)bits, set);
-#elif PAGE_SIZE == 8192
+#elif (PAGE_SIZE == 8192) && defined(atomic_set_16)
        atomic_set_16((uint16_t *)bits, set);
-#elif PAGE_SIZE == 4096
+#elif (PAGE_SIZE == 4096) && defined(atomic_set_8)
        atomic_set_8((uint8_t *)bits, set);
+#else          /* PAGE_SIZE <= 8192 */
+       uintptr_t addr;
+       int shift;
+
+       addr = (uintptr_t)bits;
+       /*
+        * Use a trick to perform a 32-bit atomic on the
+        * containing aligned word, to not depend on the existence
+        * of atomic_{set, clear}_{8, 16}.
+        */
+       shift = addr & (sizeof(uint32_t) - 1);
+#if BYTE_ORDER == BIG_ENDIAN
+       shift = (sizeof(uint32_t) - sizeof(vm_page_bits_t) - shift) * NBBY;
 #else
-#error unhandled page size
+       shift *= NBBY;
 #endif
+       addr &= ~(sizeof(uint32_t) - 1);
+       atomic_set_32((uint32_t *)addr, set << shift);
+#endif         /* PAGE_SIZE */
 }
 
 static inline void
 vm_page_bits_clear(vm_page_t m, vm_page_bits_t *bits, vm_page_bits_t clear)
 {
+
 #if PAGE_SIZE == 32768
        atomic_clear_64((uint64_t *)bits, clear);
 #elif PAGE_SIZE == 16384
        atomic_clear_32((uint32_t *)bits, clear);
-#elif PAGE_SIZE == 8192
+#elif (PAGE_SIZE == 8192) && defined(atomic_clear_16)
        atomic_clear_16((uint16_t *)bits, clear);
-#elif PAGE_SIZE == 4096
+#elif (PAGE_SIZE == 4096) && defined(atomic_clear_8)
        atomic_clear_8((uint8_t *)bits, clear);
+#else          /* PAGE_SIZE <= 8192 */
+       uintptr_t addr;
+       int shift;
+
+       addr = (uintptr_t)bits;
+       /*
+        * Use a trick to perform a 32-bit atomic on the
+        * containing aligned word, to not depend on the existence
+        * of atomic_{set, clear}_{8, 16}.
+        */
+       shift = addr & (sizeof(uint32_t) - 1);
+#if BYTE_ORDER == BIG_ENDIAN
+       shift = (sizeof(uint32_t) - sizeof(vm_page_bits_t) - shift) * NBBY;
 #else
-#error unhandled page size
+       shift *= NBBY;
 #endif
+       addr &= ~(sizeof(uint32_t) - 1);
+       atomic_clear_32((uint32_t *)addr, clear << shift);
+#endif         /* PAGE_SIZE */
 }
 
 static inline vm_page_bits_t
@@ -5407,21 +5441,45 @@ vm_page_bits_swap(vm_page_t m, vm_page_bits_t *bits, 
vm_page_bits_t newbits)
        old = *bits;
        while (atomic_fcmpset_32(bits, &old, newbits) == 0);
        return (old);
-#elif PAGE_SIZE == 8192
+#elif (PAGE_SIZE == 8192) && defined(atomic_fcmpset_16)
        uint16_t old;
 
        old = *bits;
        while (atomic_fcmpset_16(bits, &old, newbits) == 0);
        return (old);
-#elif PAGE_SIZE == 4096
+#elif (PAGE_SIZE == 4096) && defined(atomic_fcmpset_8)
        uint8_t old;
 
        old = *bits;
        while (atomic_fcmpset_8(bits, &old, newbits) == 0);
        return (old);
+#else          /* PAGE_SIZE <= 4096*/
+       uintptr_t addr;
+       uint32_t old, new, mask;
+       int shift;
+
+       addr = (uintptr_t)bits;
+       /*
+        * Use a trick to perform a 32-bit atomic on the
+        * containing aligned word, to not depend on the existence
+        * of atomic_{set, swap, clear}_{8, 16}.
+        */
+       shift = addr & (sizeof(uint32_t) - 1);
+#if BYTE_ORDER == BIG_ENDIAN
+       shift = (sizeof(uint32_t) - sizeof(vm_page_bits_t) - shift) * NBBY;
 #else
-#error unhandled page size
+       shift *= NBBY;
 #endif
+       addr &= ~(sizeof(uint32_t) - 1);
+       mask = VM_PAGE_BITS_ALL << shift;
+
+       old = *bits;
+       do {
+               new = old & ~mask;
+               new |= newbits << shift;
+       } while (atomic_fcmpset_32((uint32_t *)addr, &old, new) == 0);
+       return (old >> shift);
+#endif         /* PAGE_SIZE */
 }
 
 /*

Reply via email to