* [PATCH v3 3/3] mm/armv6: work around armv6 cmpxchg support issue
[not found] <1598928612-68996-1-git-send-email-alex.shi@linux.alibaba.com>
@ 2020-09-01 2:50 ` Alex Shi
2020-09-01 6:30 ` Alex Shi
0 siblings, 1 reply; 4+ messages in thread
From: Alex Shi @ 2020-09-01 2:50 UTC (permalink / raw)
To: Anshuman Khandual, David Hildenbrand, Matthew Wilcox
Cc: Russell King, linux-kernel, linux-mm, Baolin Wang, Andrew Morton,
linux-arm-kernel
Armv6 can not simulate cmpxchg1 func, so we have to use cmpxchg4 on it.
arm-linux-gnueabi-ld: mm/page_alloc.o: in function `set_pfnblock_flags_mask':
(.text+0x32b4): undefined reference to `__bad_cmpxchg'
arm-linux-gnueabi-ld: (.text+0x32e0): undefined reference to `__bad_cmpxchg'
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Alex Shi <alex.shi@linux.alibaba.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
---
include/linux/mmzone.h | 15 ++++++++++++---
mm/page_alloc.c | 24 ++++++++++++------------
2 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index be676e659fb7..4c91ca807473 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -406,6 +406,15 @@ enum zone_type {
#ifndef __GENERATING_BOUNDS_H
+/* cmpxchg only support 32-bits operands on ARMv6. */
+#ifdef CONFIG_CPU_V6
+#define BITS_PER_FLAGS BITS_PER_LONG
+typedef unsigned long pageblockflags_t;
+#else
+#define BITS_PER_FLAGS BITS_PER_BYTE
+typedef unsigned char pageblockflags_t;
+#endif
+
struct zone {
/* Read-mostly fields */
@@ -437,7 +446,7 @@ struct zone {
* Flags for a pageblock_nr_pages block. See pageblock-flags.h.
* In SPARSEMEM, this map is stored in struct mem_section
*/
- unsigned char *pageblock_flags;
+ pageblockflags_t *pageblock_flags;
#endif /* CONFIG_SPARSEMEM */
/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
@@ -1159,7 +1168,7 @@ struct mem_section_usage {
DECLARE_BITMAP(subsection_map, SUBSECTIONS_PER_SECTION);
#endif
/* See declaration of similar field in struct zone */
- unsigned char pageblock_flags[0];
+ pageblockflags_t pageblock_flags[0];
};
void subsection_map_init(unsigned long pfn, unsigned long nr_pages);
@@ -1212,7 +1221,7 @@ struct mem_section {
extern struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT];
#endif
-static inline unsigned char *section_to_usemap(struct mem_section *ms)
+static inline pageblockflags_t *section_to_usemap(struct mem_section *ms)
{
return ms->usage->pageblock_flags;
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 60342e764090..9a41c5dc78eb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -445,7 +445,7 @@ static inline bool defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
#endif
/* Return a pointer to the bitmap storing bits affecting a block of pages */
-static inline unsigned char *get_pageblock_bitmap(struct page *page,
+static inline pageblockflags_t *get_pageblock_bitmap(struct page *page,
unsigned long pfn)
{
#ifdef CONFIG_SPARSEMEM
@@ -474,24 +474,24 @@ static inline int pfn_to_bitidx(struct page *page, unsigned long pfn)
* Return: pageblock_bits flags
*/
static __always_inline
-unsigned char __get_pfnblock_flags_mask(struct page *page,
+pageblockflags_t __get_pfnblock_flags_mask(struct page *page,
unsigned long pfn,
unsigned long mask)
{
- unsigned char *bitmap;
+ pageblockflags_t *bitmap;
unsigned long bitidx, byte_bitidx;
- unsigned char byte;
+ pageblockflags_t byte;
bitmap = get_pageblock_bitmap(page, pfn);
bitidx = pfn_to_bitidx(page, pfn);
- byte_bitidx = bitidx / BITS_PER_BYTE;
- bitidx &= (BITS_PER_BYTE-1);
+ byte_bitidx = bitidx / BITS_PER_FLAGS;
+ bitidx &= (BITS_PER_FLAGS - 1);
byte = bitmap[byte_bitidx];
return (byte >> bitidx) & mask;
}
-unsigned char get_pfnblock_flags_mask(struct page *page, unsigned long pfn,
+pageblockflags_t get_pfnblock_flags_mask(struct page *page, unsigned long pfn,
unsigned long mask)
{
return __get_pfnblock_flags_mask(page, pfn, mask);
@@ -513,17 +513,17 @@ void set_pfnblock_flags_mask(struct page *page, unsigned long flags,
unsigned long pfn,
unsigned long mask)
{
- unsigned char *bitmap;
+ pageblockflags_t *bitmap;
unsigned long bitidx, byte_bitidx;
- unsigned char old_byte, byte;
+ pageblockflags_t old_byte, byte;
- BUILD_BUG_ON(NR_PAGEBLOCK_BITS != BITS_PER_BYTE);
+ BUILD_BUG_ON(NR_PAGEBLOCK_BITS != BITS_PER_FLAGS);
BUILD_BUG_ON(MIGRATE_TYPES > (1 << PB_migratetype_bits));
bitmap = get_pageblock_bitmap(page, pfn);
bitidx = pfn_to_bitidx(page, pfn);
- byte_bitidx = bitidx / BITS_PER_BYTE;
- bitidx &= (BITS_PER_BYTE-1);
+ byte_bitidx = bitidx / BITS_PER_FLAGS;
+ bitidx &= (BITS_PER_FLAGS - 1);
VM_BUG_ON_PAGE(!zone_spans_pfn(page_zone(page), pfn), page);
--
1.8.3.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 3/3] mm/armv6: work around armv6 cmpxchg support issue
2020-09-01 2:50 ` [PATCH v3 3/3] mm/armv6: work around armv6 cmpxchg support issue Alex Shi
@ 2020-09-01 6:30 ` Alex Shi
2020-09-01 13:17 ` Matthew Wilcox
0 siblings, 1 reply; 4+ messages in thread
From: Alex Shi @ 2020-09-01 6:30 UTC (permalink / raw)
To: Anshuman Khandual, David Hildenbrand, Matthew Wilcox
Cc: Russell King, linux-kernel, linux-mm, Baolin Wang, Andrew Morton,
linux-arm-kernel
seems there are couples archs can not do cmpxchg1
So update the patch here. And it's easy to fix if more arch issue find here.
From cdf98ae7b5e83bb7210c927d4749f62fee4ed115 Mon Sep 17 00:00:00 2001
From: Alex Shi <alex.shi@linux.alibaba.com>
Date: Mon, 31 Aug 2020 15:41:20 +0800
Subject: [PATCH v4 3/3] mm/pageblock: work around multiple arch's cmpxchg
support issue
Armv6, sh2, sparc32 and xtensa can not do cmpxchg1, so we have to use
cmpxchg4 on it.
arm-linux-gnueabi-ld: mm/page_alloc.o: in function `set_pfnblock_flags_mask':
(.text+0x32b4): undefined reference to `__bad_cmpxchg'
arm-linux-gnueabi-ld: (.text+0x32e0): undefined reference to `__bad_cmpxchg'
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Alex Shi <alex.shi@linux.alibaba.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
---
include/linux/mmzone.h | 20 +++++++++++++++++---
mm/page_alloc.c | 24 ++++++++++++------------
2 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index be676e659fb7..364b29ed99b3 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -406,6 +406,20 @@ enum zone_type {
#ifndef __GENERATING_BOUNDS_H
+/*
+ * cmpxchg only support 32-bits operands on the following archs ARMv6, SPARC32
+ * sh2, XTENSA.
+ */
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_SH2) || \
+ defined(CONFIG_SPARC32) || defined(CONFIG_XTENSA)
+
+#define BITS_PER_FLAGS BITS_PER_LONG
+typedef unsigned long pageblockflags_t;
+#else
+#define BITS_PER_FLAGS BITS_PER_BYTE
+typedef unsigned char pageblockflags_t;
+#endif
+
struct zone {
/* Read-mostly fields */
@@ -437,7 +451,7 @@ struct zone {
* Flags for a pageblock_nr_pages block. See pageblock-flags.h.
* In SPARSEMEM, this map is stored in struct mem_section
*/
- unsigned char *pageblock_flags;
+ pageblockflags_t *pageblock_flags;
#endif /* CONFIG_SPARSEMEM */
/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
@@ -1159,7 +1173,7 @@ struct mem_section_usage {
DECLARE_BITMAP(subsection_map, SUBSECTIONS_PER_SECTION);
#endif
/* See declaration of similar field in struct zone */
- unsigned char pageblock_flags[0];
+ pageblockflags_t pageblock_flags[0];
};
void subsection_map_init(unsigned long pfn, unsigned long nr_pages);
@@ -1212,7 +1226,7 @@ struct mem_section {
extern struct mem_section mem_section[NR_SECTION_ROOTS][SECTIONS_PER_ROOT];
#endif
-static inline unsigned char *section_to_usemap(struct mem_section *ms)
+static inline pageblockflags_t *section_to_usemap(struct mem_section *ms)
{
return ms->usage->pageblock_flags;
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 60342e764090..9a41c5dc78eb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -445,7 +445,7 @@ static inline bool defer_init(int nid, unsigned long pfn, unsigned long end_pfn)
#endif
/* Return a pointer to the bitmap storing bits affecting a block of pages */
-static inline unsigned char *get_pageblock_bitmap(struct page *page,
+static inline pageblockflags_t *get_pageblock_bitmap(struct page *page,
unsigned long pfn)
{
#ifdef CONFIG_SPARSEMEM
@@ -474,24 +474,24 @@ static inline int pfn_to_bitidx(struct page *page, unsigned long pfn)
* Return: pageblock_bits flags
*/
static __always_inline
-unsigned char __get_pfnblock_flags_mask(struct page *page,
+pageblockflags_t __get_pfnblock_flags_mask(struct page *page,
unsigned long pfn,
unsigned long mask)
{
- unsigned char *bitmap;
+ pageblockflags_t *bitmap;
unsigned long bitidx, byte_bitidx;
- unsigned char byte;
+ pageblockflags_t byte;
bitmap = get_pageblock_bitmap(page, pfn);
bitidx = pfn_to_bitidx(page, pfn);
- byte_bitidx = bitidx / BITS_PER_BYTE;
- bitidx &= (BITS_PER_BYTE-1);
+ byte_bitidx = bitidx / BITS_PER_FLAGS;
+ bitidx &= (BITS_PER_FLAGS - 1);
byte = bitmap[byte_bitidx];
return (byte >> bitidx) & mask;
}
-unsigned char get_pfnblock_flags_mask(struct page *page, unsigned long pfn,
+pageblockflags_t get_pfnblock_flags_mask(struct page *page, unsigned long pfn,
unsigned long mask)
{
return __get_pfnblock_flags_mask(page, pfn, mask);
@@ -513,17 +513,17 @@ void set_pfnblock_flags_mask(struct page *page, unsigned long flags,
unsigned long pfn,
unsigned long mask)
{
- unsigned char *bitmap;
+ pageblockflags_t *bitmap;
unsigned long bitidx, byte_bitidx;
- unsigned char old_byte, byte;
+ pageblockflags_t old_byte, byte;
- BUILD_BUG_ON(NR_PAGEBLOCK_BITS != BITS_PER_BYTE);
+ BUILD_BUG_ON(NR_PAGEBLOCK_BITS != BITS_PER_FLAGS);
BUILD_BUG_ON(MIGRATE_TYPES > (1 << PB_migratetype_bits));
bitmap = get_pageblock_bitmap(page, pfn);
bitidx = pfn_to_bitidx(page, pfn);
- byte_bitidx = bitidx / BITS_PER_BYTE;
- bitidx &= (BITS_PER_BYTE-1);
+ byte_bitidx = bitidx / BITS_PER_FLAGS;
+ bitidx &= (BITS_PER_FLAGS - 1);
VM_BUG_ON_PAGE(!zone_spans_pfn(page_zone(page), pfn), page);
--
1.8.3.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v3 3/3] mm/armv6: work around armv6 cmpxchg support issue
2020-09-01 6:30 ` Alex Shi
@ 2020-09-01 13:17 ` Matthew Wilcox
2020-09-03 6:47 ` Alex Shi
0 siblings, 1 reply; 4+ messages in thread
From: Matthew Wilcox @ 2020-09-01 13:17 UTC (permalink / raw)
To: Alex Shi
Cc: David Hildenbrand, Anshuman Khandual, Russell King, linux-kernel,
linux-mm, Baolin Wang, Andrew Morton, linux-arm-kernel
On Tue, Sep 01, 2020 at 02:30:51PM +0800, Alex Shi wrote:
> seems there are couples archs can not do cmpxchg1
> So update the patch here. And it's easy to fix if more arch issue find here.
> +/*
> + * cmpxchg only support 32-bits operands on the following archs ARMv6, SPARC32
> + * sh2, XTENSA.
> + */
> +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_SH2) || \
> + defined(CONFIG_SPARC32) || defined(CONFIG_XTENSA)
Looks like we need a HAVE_CMPXCHG_BYTE in Kconfig to parallel
HAVE_CMPXCHG_DOUBLE.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 3/3] mm/armv6: work around armv6 cmpxchg support issue
2020-09-01 13:17 ` Matthew Wilcox
@ 2020-09-03 6:47 ` Alex Shi
0 siblings, 0 replies; 4+ messages in thread
From: Alex Shi @ 2020-09-03 6:47 UTC (permalink / raw)
To: Matthew Wilcox
Cc: David Hildenbrand, Anshuman Khandual, Russell King, linux-kernel,
linux-mm, Baolin Wang, Andrew Morton, linux-arm-kernel
在 2020/9/1 下午9:17, Matthew Wilcox 写道:
> On Tue, Sep 01, 2020 at 02:30:51PM +0800, Alex Shi wrote:
>> seems there are couples archs can not do cmpxchg1
>> So update the patch here. And it's easy to fix if more arch issue find here.
>
>> +/*
>> + * cmpxchg only support 32-bits operands on the following archs ARMv6, SPARC32
>> + * sh2, XTENSA.
>> + */
>> +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_SH2) || \
>> + defined(CONFIG_SPARC32) || defined(CONFIG_XTENSA)
>
> Looks like we need a HAVE_CMPXCHG_BYTE in Kconfig to parallel
> HAVE_CMPXCHG_DOUBLE.
>
Thanks for reminder! Compare the HAVE_CMPXCHG_BYTE, NO_CMPXCHG_BYTE would be
better for less code change.
I will send the v4 for a bit more change on patch 2.
Thanks!
Alex
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2020-09-03 6:48 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1598928612-68996-1-git-send-email-alex.shi@linux.alibaba.com>
2020-09-01 2:50 ` [PATCH v3 3/3] mm/armv6: work around armv6 cmpxchg support issue Alex Shi
2020-09-01 6:30 ` Alex Shi
2020-09-01 13:17 ` Matthew Wilcox
2020-09-03 6:47 ` Alex Shi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).