Re: [PATCH 15/21] mm: memmap_init: iterate over memblock regions rather that check each PFN
> On Apr 12, 2020, at 3:48 PM, Mike Rapoport wrote: > > From: Baoquan He > > When called during boot the memmap_init_zone() function checks if each PFN > is valid and actually belongs to the node being initialized using > early_pfn_valid() and early_pfn_in_nid(). > > Each such check may cost up to O(log(n)) where n is the number of memory > banks, so for large amount of memory overall time spent in early_pfn*() > becomes substantial. > > Since the information is anyway present in memblock, we can iterate over > memblock memory regions in memmap_init() and only call memmap_init_zone() > for PFN ranges that are know to be valid and in the appropriate node. > > Signed-off-by: Baoquan He > Signed-off-by: Mike Rapoport > --- > mm/page_alloc.c | 26 -- > 1 file changed, 16 insertions(+), 10 deletions(-) > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 7f6a3081edb8..c43ce8709457 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -5995,14 +5995,6 @@ void __meminit memmap_init_zone(unsigned long size, > int nid, unsigned long zone, >* function. They do not exist on hotplugged memory. >*/ > if (context == MEMMAP_EARLY) { > - if (!early_pfn_valid(pfn)) { > - pfn = next_pfn(pfn); > - continue; > - } > - if (!early_pfn_in_nid(pfn, nid)) { > - pfn++; > - continue; > - } This causes a compilation warning from Clang, mm/page_alloc.c:5917:39: warning: unused function 'next_pfn' [-Wunused-function] static inline __meminit unsigned long next_pfn(unsigned long pfn) This should fix it, diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d469384c9ca7..b48336e20bdc 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5912,23 +5912,6 @@ overlap_memmap_init(unsigned long zone, unsigned long *pfn) return false; } -#ifdef CONFIG_SPARSEMEM -/* Skip PFNs that belong to non-present sections */ -static inline __meminit unsigned long next_pfn(unsigned long pfn) -{ - const unsigned long section_nr = pfn_to_section_nr(++pfn); - - if (present_section_nr(section_nr)) - return pfn; - return section_nr_to_pfn(next_present_section_nr(section_nr)); -} -#else -static inline __meminit unsigned long next_pfn(unsigned long pfn) -{ - return pfn++; -} -#endif - /* * Initially all pages are reserved - free ones are freed * up by memblock_free_all() once the early boot process is > if (overlap_memmap_init(zone, &pfn)) > continue; > if (defer_init(nid, pfn, end_pfn)) > @@ -6118,9 +6110,23 @@ static void __meminit zone_init_free_lists(struct zone > *zone) > } > > void __meminit __weak memmap_init(unsigned long size, int nid, > - unsigned long zone, unsigned long start_pfn) > + unsigned long zone, > + unsigned long range_start_pfn) > { > - memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY, NULL); > + unsigned long start_pfn, end_pfn; > + unsigned long range_end_pfn = range_start_pfn + size; > + int i; > + > + for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) { > + start_pfn = clamp(start_pfn, range_start_pfn, range_end_pfn); > + end_pfn = clamp(end_pfn, range_start_pfn, range_end_pfn); > + > + if (end_pfn > start_pfn) { > + size = end_pfn - start_pfn; > + memmap_init_zone(size, nid, zone, start_pfn, > + MEMMAP_EARLY, NULL); > + } > + } > } > > static int zone_batchsize(struct zone *zone) > -- > 2.25.1 > > ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Re: [PATCH v5 06/14] ARC: hardware floating point support
On Fri, 17 Apr 2020, Vineet Gupta via Libc-alpha wrote: > > My suggestion would be to define the > > macro (using do { ... } while (0)) to copy the argument to a temporary > > variable, and do the bit-set operation in C code on that temporary > > variable rather than as part of the asm. > > I can certainly do that if you think so. As a general principle, if an operation is something that can readily be expressed in ordinary C code (and setting a bit certainly is), it's best to express it in ordinary C code, and make the inline asm something as short as possible only doing what ordinary C code cannot, so giving the compiler freedom in how it generates the code (unless the compiler e.g. generates bad code for something performance-critical, but that shouldn't be an issue here). -- Joseph S. Myers jos...@codesourcery.com ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Re: [PATCH v5 11/14] ARC: Update syscall-names.list for ARC specific syscalls
On Fri, 17 Apr 2020, Vineet Gupta via Libc-alpha wrote: > On 4/17/20 4:05 PM, Joseph Myers wrote: > > This patch is OK. > > So when the rest of port is ready, this will be part of main commit ? I think it's reasonable to commit this patch before then, much like the relocations in elf.h, so making the main commit and future submissions of the port smaller. -- Joseph S. Myers jos...@codesourcery.com ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Re: [PATCH 2/2] mm/thp: Rename pmd_mknotpresent() as pmd_mknotvalid()
On Fri, Mar 20, 2020 at 10:24:17AM +0530, Anshuman Khandual wrote: > pmd_present() is expected to test positive after pmdp_mknotpresent() as the > PMD entry still points to a valid huge page in memory. pmdp_mknotpresent() > implies that given PMD entry is just invalidated from MMU perspective while > still holding on to pmd_page() referred valid huge page thus also clearing > pmd_present() test. This creates the following situation which is counter > intuitive. > > [pmd_present(pmd_mknotpresent(pmd)) = true] > > This renames pmd_mknotpresent() as pmd_mknotvalid() reflecting the helper's > functionality more accurately while changing the above mentioned situation > as follows. This does not create any functional change. > > [pmd_present(pmd_mknotvalid(pmd)) = true] > > This is not applicable for platforms that define own pmdp_invalidate() via > __HAVE_ARCH_PMDP_INVALIDATE. Suggestion for renaming came during a previous > discussion here. Bikeshed alert: maybe pmd_mkinvalid() would be better, given that this is a one-trick pony for pmdp_invalidate()? Will ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Re: [PATCH v3 2/2] dt-bindings: Document the Synopsys ARC HDMI TX bindings
On Wed, Apr 15, 2020 at 02:29:29AM +0300, Eugeniy Paltsev wrote: > This patch adds documentation of device tree bindings for the Synopsys > HDMI 2.0 TX encoder driver for ARC SoCs. You're going to need to base this on top of Laurent's conversion of dw_hdmi.txt to schema. > > Acked-by: Sam Ravnborg > Signed-off-by: Eugeniy Paltsev > --- > .../display/bridge/snps,arc-dw-hdmi.yaml | 136 ++ > 1 file changed, 136 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/bridge/snps,arc-dw-hdmi.yaml > > diff --git > a/Documentation/devicetree/bindings/display/bridge/snps,arc-dw-hdmi.yaml > b/Documentation/devicetree/bindings/display/bridge/snps,arc-dw-hdmi.yaml > new file mode 100644 > index ..9b2fdfecd5b3 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/bridge/snps,arc-dw-hdmi.yaml > @@ -0,0 +1,136 @@ > +# SPDX-License-Identifier: GPL-2.0 Dual license new bindings please: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/bridge/snps,arc-dw-hdmi.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Synopsys DesignWare HDMI 2.0 TX encoder driver Bindings are for h/w blocks, not drivers. > + > +maintainers: > + - Eugeniy Paltsev > + > +description: | > + The HDMI transmitter is a Synopsys DesignWare HDMI 2.0 TX controller IP > + with a companion of Synopsys DesignWare HDMI 2.0 TX PHY IP. Sounds like 2 blocks? > + > + These DT bindings follow the Synopsys DWC HDMI TX bindings defined in > + Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt > + with the following device-specific properties. > + > +properties: > + compatible: > +const: snps,arc-dw-hdmi-hsdk > + > + reg: > +maxItems: 1 > +description: | > + Memory mapped base address and length of the DWC HDMI TX registers. Can drop. > + > + clocks: > +items: > + - description: The bus clock for AHB / APB > + - description: The internal register configuration clock > + > + clock-names: > +items: > + - const: iahb > + - const: isfr > + > + interrupts: > +maxItems: 1 > +description: Reference to the DWC HDMI TX interrupt Can drop. > + > + reg-io-width: > +allOf: > + - $ref: /schemas/types.yaml#/definitions/uint32 > + - enum: [1, 4] > +description: | > + Width of the registers specified by the reg property. The > + value is expressed in bytes and must be equal to 1 or 4 if > specified. > + The register width defaults to 1 if the property is not present. default: 1 The description is pretty much a plain text version of the constraints, so all but the first sentence can be dropped. > + > + ports: > +type: object > +description: | > + A ports node with endpoint definitions as defined in > + Documentation/devicetree/bindings/media/video-interfaces.txt Can drop. That's all 'ports'. > + > +properties: > + "#address-cells": > +const: 1 > + > + "#size-cells": > +const: 0 > + > + port@0: > +type: object > +description: | > + Video input endpoints of the controller. > + Usually it is associated with ARC PGU. > + > + port@1: > +type: object > +description: | > + Output endpoints of the controller. HDMI connector. > + > +required: > + - "#address-cells" > + - "#size-cells" > + - port@0 > + - port@1 > + > +required: > + - compatible > + - reg > + - clocks > + - clock-names > + - interrupts > + - ports > + > +additionalProperties: false > + > +examples: > + - | > +hdmi@1 { > +compatible = "snps,arc-dw-hdmi-hsdk"; > +reg = <0x1 0x1>; > +reg-io-width = <4>; > +interrupts = <14>; > +clocks = <&apbclk>, <&hdmi_pix_clk>; > +clock-names = "iahb", "isfr"; > + > +ports { > +#address-cells = <1>; > +#size-cells = <0>; > + > +port@0 { > +reg = <0>; > +hdmi_enc_input: endpoint { > +remote-endpoint = <&pgu_output>; > +}; > +}; > + > +port@1 { > +reg = <1>; > +hdmi_enc_out: endpoint { > +remote-endpoint = <&hdmi_con>; > +}; > +}; > +}; > +}; > + > +hdmi-out { > +port { > +hdmi_con: endpoint { > +remote-endpoint = <&hdmi_enc_out>; > +}; > +}; > +}; > + > +pgu { > +port_o: port { > +pgu_output: endpoint { > +remote-endpoint = <&hdmi_enc_input>; > +}; > +}; > +}; > -- > 2.21.1 > ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Re: [PATCH 2/2] mm/thp: Rename pmd_mknotpresent() as pmd_mknotvalid()
On 04/21/2020 02:33 AM, Will Deacon wrote: > On Fri, Mar 20, 2020 at 10:24:17AM +0530, Anshuman Khandual wrote: >> pmd_present() is expected to test positive after pmdp_mknotpresent() as the >> PMD entry still points to a valid huge page in memory. pmdp_mknotpresent() >> implies that given PMD entry is just invalidated from MMU perspective while >> still holding on to pmd_page() referred valid huge page thus also clearing >> pmd_present() test. This creates the following situation which is counter >> intuitive. >> >> [pmd_present(pmd_mknotpresent(pmd)) = true] >> >> This renames pmd_mknotpresent() as pmd_mknotvalid() reflecting the helper's >> functionality more accurately while changing the above mentioned situation >> as follows. This does not create any functional change. >> >> [pmd_present(pmd_mknotvalid(pmd)) = true] >> >> This is not applicable for platforms that define own pmdp_invalidate() via >> __HAVE_ARCH_PMDP_INVALIDATE. Suggestion for renaming came during a previous >> discussion here. > > Bikeshed alert: maybe pmd_mkinvalid() would be better, given that this is > a one-trick pony for pmdp_invalidate()? I had thought about making it pmd_mkinvalid() earlier. But as we were replacing pmd_mknotpresent(), hence went with similar pattern pmd_mknotvalid() which was originally suggested by Catalin. There is an existing pte_mknotpresent() in arc platform as well. I dont have a very strong opinion either way, will be happy to rename. But then still wondering if we really need to. > > Will > ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Re: [PATCH 01/21] mm: memblock: replace dereferences of memblock_region.nid with API calls
On 04/12/20 at 10:48pm, Mike Rapoport wrote: > From: Mike Rapoport > > There are several places in the code that directly dereference > memblock_region.nid despite this field being defined only when > CONFIG_HAVE_MEMBLOCK_NODE_MAP=y. > > Replace these with calls to memblock_get_region_nid() to improve code > robustness and to avoid possible breakage when > CONFIG_HAVE_MEMBLOCK_NODE_MAP will be removed. > > Signed-off-by: Mike Rapoport > --- > arch/arm64/mm/numa.c | 9 ++--- > arch/x86/mm/numa.c | 6 -- > mm/memblock.c| 8 +--- > mm/page_alloc.c | 4 ++-- > 4 files changed, 17 insertions(+), 10 deletions(-) > > diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c > index 4decf1659700..aafcee3e3f7e 100644 > --- a/arch/arm64/mm/numa.c > +++ b/arch/arm64/mm/numa.c > @@ -350,13 +350,16 @@ static int __init numa_register_nodes(void) > struct memblock_region *mblk; > > /* Check that valid nid is set to memblks */ > - for_each_memblock(memory, mblk) > - if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) { > + for_each_memblock(memory, mblk) { > + int mblk_nid = memblock_get_region_node(mblk); > + > + if (mblk_nid == NUMA_NO_NODE || mblk_nid >= MAX_NUMNODES) { > pr_warn("Warning: invalid memblk node %d [mem > %#010Lx-%#010Lx]\n", > - mblk->nid, mblk->base, > + mblk_nid, mblk->base, > mblk->base + mblk->size - 1); > return -EINVAL; > } > + } > > /* Finally register nodes. */ > for_each_node_mask(nid, numa_nodes_parsed) { > diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c > index 59ba008504dc..fe024b2ac796 100644 > --- a/arch/x86/mm/numa.c > +++ b/arch/x86/mm/numa.c > @@ -517,8 +517,10 @@ static void __init numa_clear_kernel_node_hotplug(void) >* reserve specific pages for Sandy Bridge graphics. ] >*/ > for_each_memblock(reserved, mb_region) { > - if (mb_region->nid != MAX_NUMNODES) > - node_set(mb_region->nid, reserved_nodemask); > + int nid = memblock_get_region_node(mb_region); > + > + if (nid != MAX_NUMNODES) > + node_set(nid, reserved_nodemask); > } > > /* > diff --git a/mm/memblock.c b/mm/memblock.c > index c79ba6f9920c..43e2fd3006c1 100644 > --- a/mm/memblock.c > +++ b/mm/memblock.c > @@ -1207,13 +1207,15 @@ void __init_memblock __next_mem_pfn_range(int *idx, > int nid, > { > struct memblock_type *type = &memblock.memory; > struct memblock_region *r; > + int r_nid; > > while (++*idx < type->cnt) { > r = &type->regions[*idx]; > + r_nid = memblock_get_region_node(r); > > if (PFN_UP(r->base) >= PFN_DOWN(r->base + r->size)) > continue; > - if (nid == MAX_NUMNODES || nid == r->nid) > + if (nid == MAX_NUMNODES || nid == r_nid) > break; > } > if (*idx >= type->cnt) { > @@ -1226,7 +1228,7 @@ void __init_memblock __next_mem_pfn_range(int *idx, int > nid, > if (out_end_pfn) > *out_end_pfn = PFN_DOWN(r->base + r->size); > if (out_nid) > - *out_nid = r->nid; > + *out_nid = r_nid; > } > > /** > @@ -1810,7 +1812,7 @@ int __init_memblock memblock_search_pfn_nid(unsigned > long pfn, > *start_pfn = PFN_DOWN(type->regions[mid].base); > *end_pfn = PFN_DOWN(type->regions[mid].base + type->regions[mid].size); > > - return type->regions[mid].nid; > + return memblock_get_region_node(&type->regions[mid]); > } > #endif > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 69827d4fa052..0d012eda1694 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -7208,7 +7208,7 @@ static void __init > find_zone_movable_pfns_for_nodes(void) > if (!memblock_is_hotpluggable(r)) > continue; > > - nid = r->nid; > + nid = memblock_get_region_node(r); > > usable_startpfn = PFN_DOWN(r->base); > zone_movable_pfn[nid] = zone_movable_pfn[nid] ? > @@ -7229,7 +7229,7 @@ static void __init > find_zone_movable_pfns_for_nodes(void) > if (memblock_is_mirror(r)) > continue; > > - nid = r->nid; > + nid = memblock_get_region_node(r); > > usable_startpfn = memblock_region_memory_base_pfn(r); Looks good to me. Reviewed-by: Baoquan He ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Re: [PATCH 02/21] mm: make early_pfn_to_nid() and related defintions close to each other
On 04/12/20 at 10:48pm, Mike Rapoport wrote: > From: Mike Rapoport > > The early_pfn_to_nid() and it's helper __early_pfn_to_nid() are spread > around include/linux/mm.h, include/linux/mmzone.h and mm/page_alloc.c. > > Drop unused stub for __early_pfn_to_nid() and move its actual generic > implementation close to its users. > > Signed-off-by: Mike Rapoport > --- > include/linux/mm.h | 4 ++-- > include/linux/mmzone.h | 9 > mm/page_alloc.c| 51 +- > 3 files changed, 27 insertions(+), 37 deletions(-) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 5a323422d783..a404026d14d4 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2388,9 +2388,9 @@ extern void > sparse_memory_present_with_active_regions(int nid); > > #if !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) && \ > !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) > -static inline int __early_pfn_to_nid(unsigned long pfn, > - struct mminit_pfnnid_cache *state) > +static inline int early_pfn_to_nid(unsigned long pfn) > { > + BUILD_BUG_ON(IS_ENABLED(CONFIG_NUMA)); > return 0; > } It's better to make a separate patch to drop __early_pfn_to_nid() here. > #else > diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h > index 1b9de7d220fb..7b5b6eba402f 100644 > --- a/include/linux/mmzone.h > +++ b/include/linux/mmzone.h > @@ -1078,15 +1078,6 @@ static inline struct zoneref > *first_zones_zonelist(struct zonelist *zonelist, > #include > #endif > > -#if !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) && \ > - !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) > -static inline unsigned long early_pfn_to_nid(unsigned long pfn) > -{ > - BUILD_BUG_ON(IS_ENABLED(CONFIG_NUMA)); > - return 0; > -} > -#endif > - > #ifdef CONFIG_FLATMEM > #define pfn_to_nid(pfn) (0) > #endif > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 0d012eda1694..1ac775bfc9cf 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -1504,6 +1504,31 @@ void __free_pages_core(struct page *page, unsigned int > order) #if defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) || \ defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) This is the upper layer of ifdeffery scope. > > static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; > > +#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID Moving __early_pfn_to_nid() here makes the upper layer of ifdeferry scope a little werid. But seems no better way to optimize it. Otherwise, this patch looks good to me. Reviewed-by: Baoquan He > + > +/* > + * Required by SPARSEMEM. Given a PFN, return what node the PFN is on. > + */ > +int __meminit __early_pfn_to_nid(unsigned long pfn, > + struct mminit_pfnnid_cache *state) > +{ > + unsigned long start_pfn, end_pfn; > + int nid; > + > + if (state->last_start <= pfn && pfn < state->last_end) > + return state->last_nid; > + > + nid = memblock_search_pfn_nid(pfn, &start_pfn, &end_pfn); > + if (nid != NUMA_NO_NODE) { > + state->last_start = start_pfn; > + state->last_end = end_pfn; > + state->last_nid = nid; > + } > + > + return nid; > +} > +#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */ > + > int __meminit early_pfn_to_nid(unsigned long pfn) > { > static DEFINE_SPINLOCK(early_pfn_lock); > @@ -6298,32 +6323,6 @@ void __meminit init_currently_empty_zone(struct zone > *zone, > zone->initialized = 1; > } > > -#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP > -#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID > - > -/* > - * Required by SPARSEMEM. Given a PFN, return what node the PFN is on. > - */ > -int __meminit __early_pfn_to_nid(unsigned long pfn, > - struct mminit_pfnnid_cache *state) > -{ > - unsigned long start_pfn, end_pfn; > - int nid; > - > - if (state->last_start <= pfn && pfn < state->last_end) > - return state->last_nid; > - > - nid = memblock_search_pfn_nid(pfn, &start_pfn, &end_pfn); > - if (nid != NUMA_NO_NODE) { > - state->last_start = start_pfn; > - state->last_end = end_pfn; > - state->last_nid = nid; > - } > - > - return nid; > -} > -#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */ > - > /** > * free_bootmem_with_active_regions - Call memblock_free_early_nid for each > active range > * @nid: The node to free memory on. If MAX_NUMNODES, all nodes are freed. > -- > 2.25.1 > ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
[PATCH V17 0/2] mm/debug: Add tests validating architecture page table helpers
This adds a test validation for architecture exported page table helpers. Patch adds basic transformation tests at various levels of the page table. This test was originally suggested by Catalin during arm64 THP migration RFC discussion earlier. Going forward it can include more specific tests with respect to various generic MM functions like THP, HugeTLB etc and platform specific tests. https://lore.kernel.org/linux-mm/20190628102003.ga56...@arrakis.emea.arm.com/ Needs to be applied on linux V5.7-rc2 Changes in V17: - debug_vm_pgtable() is now called from late_initcall() per Linus - Explicitly enable DEBUG_VM_PGTABLE when ARCH_HAS_DEBUG_VM_PGTABLE and DEBUG_VM - Added #ifdef documentation per Gerald - Dropped page table helper semantics documentation (will be added via later patches) - Split the X86 changes defining mm_p4d_folded() into a new prerequisite patch Changes in V16: (https://patchwork.kernel.org/patch/11431277/) - Replaced WRITE_ONCE() with set_pte_at() with a new barrier() in pte_clear_tests() per Qian - Enabled all powerpc platforms and updated the feature list Changes in V15: (https://patchwork.kernel.org/patch/11422803/) - Replaced __pa() with __pa_symbol() (https://patchwork.kernel.org/patch/11407715/) - Replaced pte_alloc_map() with pte_alloc_map_lock() per Qian - Replaced pte_unmap() with pte_unmap_unlock() per Qian - Added address to pte_clear_tests() and passed it down till pte_clear() per Qian Changes in V14: (https://patchwork.kernel.org/project/linux-mm/list/?series=242305) - Disabled DEBUG_VM_PGTABLE for IA64 and ARM (32 Bit) per Andrew and Christophe - Updated DEBUG_VM_PGTABLE documentation wrt EXPERT and disabled platforms - Updated RANDOM_[OR|NZ]VALUE open encodings with GENMASK() per Catalin - Updated s390 constraint bits from 12 to 4 (S390_MASK_BITS) per Gerald - Updated in-code documentation for RANDOM_ORVALUE per Gerald - Updated pxx_basic_tests() to use invert functions first per Catalin - Dropped ARCH_HAS_4LEVEL_HACK check from pud_basic_tests() - Replaced __ARCH_HAS_[4|5]LEVEL_HACK with __PAGETABLE_[PUD|P4D]_FOLDED per Catalin - Trimmed the CC list on the commit message per Catalin Changes in V13: (https://patchwork.kernel.org/project/linux-mm/list/?series=237125) - Subscribed s390 platform and updated debug-vm-pgtable/arch-support.txt per Gerald - Dropped keyword 'extern' from debug_vm_pgtable() declaration per Christophe - Moved debug_vm_pgtable() declarations to per Christophe - Moved debug_vm_pgtable() call site into kernel_init() per Christophe - Changed CONFIG_DEBUG_VM_PGTABLE rules per Christophe - Updated commit to include new supported platforms and changed config selection Changes in V12: (https://patchwork.kernel.org/project/linux-mm/list/?series=233905) - Replaced __mmdrop() with mmdrop() - Enable ARCH_HAS_DEBUG_VM_PGTABLE on X86 for non CONFIG_X86_PAE platforms as the test procedure interfere with pre-allocated PMDs attached to the PGD resulting in runtime failures with VM_BUG_ON() Changes in V11: (https://patchwork.kernel.org/project/linux-mm/list/?series=221135) - Rebased the patch on V5.4 Changes in V10: (https://patchwork.kernel.org/project/linux-mm/list/?series=205529) - Always enable DEBUG_VM_PGTABLE when DEBUG_VM is enabled per Ingo - Added tags from Ingo Changes in V9: (https://patchwork.kernel.org/project/linux-mm/list/?series=201429) - Changed feature support enumeration for powerpc platforms per Christophe - Changed config wrapper for basic_[pmd|pud]_tests() to enable ARC platform - Enabled the test on ARC platform Changes in V8: (https://patchwork.kernel.org/project/linux-mm/list/?series=194297) - Enabled ARCH_HAS_DEBUG_VM_PGTABLE on PPC32 platform per Christophe - Updated feature documentation as DEBUG_VM_PGTABLE is now enabled on PPC32 platform - Moved ARCH_HAS_DEBUG_VM_PGTABLE earlier to indent it with DEBUG_VM per Christophe - Added an information message in debug_vm_pgtable() per Christophe - Dropped random_vaddr boundary condition checks per Christophe and Qian - Replaced virt_addr_valid() check with pfn_valid() check in debug_vm_pgtable() - Slightly changed pr_fmt(fmt) information Changes in V7: (https://patchwork.kernel.org/project/linux-mm/list/?series=193051) - Memory allocation and free routines for mapped pages have been droped - Mapped pfns are derived from standard kernel text symbol per Matthew - Moved debug_vm_pgtaable() after page_alloc_init_late() per Michal and Qian - Updated the commit message per Michal - Updated W=1 GCC warning problem on x86 per Qian Cai - Addition of new alloc_contig_pages() helper has been submitted separately Changes in V6: (https://patchwork.kernel.org/project/linux-mm/list/?series=187589) - Moved alloc_gigantic_page_order() into mm/page_alloc.c per Michal - Moved alloc_gigantic_page_order() within CONFIG_CONTIG_ALLOC in the test - Folded Andrew's include/asm-generic/pgtable.h fix into the test patch 2/2 Changes in V5: (https://patchwork.kernel.org/pr
[PATCH V17 2/2] mm/debug: Add tests validating architecture page table helpers
This adds tests which will validate architecture page table helpers and other accessors in their compliance with expected generic MM semantics. This will help various architectures in validating changes to existing page table helpers or addition of new ones. This test covers basic page table entry transformations including but not limited to old, young, dirty, clean, write, write protect etc at various level along with populating intermediate entries with next page table page and validating them. Test page table pages are allocated from system memory with required size and alignments. The mapped pfns at page table levels are derived from a real pfn representing a valid kernel text symbol. This test gets called via late_initcall(). This test gets built and run when CONFIG_DEBUG_VM_PGTABLE is selected. Any architecture, which is willing to subscribe this test will need to select ARCH_HAS_DEBUG_VM_PGTABLE. For now this is limited to arc, arm64, x86, s390 and powerpc platforms where the test is known to build and run successfully Going forward, other architectures too can subscribe the test after fixing any build or runtime problems with their page table helpers. Meanwhile for better platform coverage, the test can also be enabled with CONFIG_EXPERT even without ARCH_HAS_DEBUG_VM_PGTABLE. Folks interested in making sure that a given platform's page table helpers conform to expected generic MM semantics should enable the above config which will just trigger this test during boot. Any non conformity here will be reported as an warning which would need to be fixed. This test will help catch any changes to the agreed upon semantics expected from generic MM and enable platforms to accommodate it thereafter. Cc: Andrew Morton Cc: Mike Rapoport Cc: Vineet Gupta Cc: Catalin Marinas Cc: Will Deacon Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Heiko Carstens Cc: Vasily Gorbik Cc: Christian Borntraeger Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: Kirill A. Shutemov Cc: Paul Walmsley Cc: Palmer Dabbelt Cc: linux-snps-arc@lists.infradead.org Cc: linux-arm-ker...@lists.infradead.org Cc: linuxppc-...@lists.ozlabs.org Cc: linux-s...@vger.kernel.org Cc: linux-ri...@lists.infradead.org Cc: x...@kernel.org Cc: linux-a...@vger.kernel.org Cc: linux-ker...@vger.kernel.org Suggested-by: Catalin Marinas Reviewed-by: Ingo Molnar Tested-by: Gerald Schaefer # s390 Tested-by: Christophe Leroy# ppc32 Signed-off-by: Qian Cai Signed-off-by: Andrew Morton Signed-off-by: Christophe Leroy Signed-off-by: Anshuman Khandual --- .../debug/debug-vm-pgtable/arch-support.txt | 34 ++ arch/arc/Kconfig | 1 + arch/arm64/Kconfig| 1 + arch/powerpc/Kconfig | 1 + arch/s390/Kconfig | 1 + arch/x86/Kconfig | 1 + lib/Kconfig.debug | 25 ++ mm/Makefile | 1 + mm/debug_vm_pgtable.c | 382 ++ 9 files changed, 447 insertions(+) create mode 100644 Documentation/features/debug/debug-vm-pgtable/arch-support.txt create mode 100644 mm/debug_vm_pgtable.c diff --git a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt new file mode 100644 index ..c527d05c0459 --- /dev/null +++ b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt @@ -0,0 +1,34 @@ +# +# Feature name: debug-vm-pgtable +# Kconfig: ARCH_HAS_DEBUG_VM_PGTABLE +# description: arch supports pgtable tests for semantics compliance +# +--- +| arch |status| +--- +| alpha: | TODO | +| arc: | ok | +| arm: | TODO | +| arm64: | ok | +| c6x: | TODO | +|csky: | TODO | +| h8300: | TODO | +| hexagon: | TODO | +|ia64: | TODO | +|m68k: | TODO | +| microblaze: | TODO | +|mips: | TODO | +| nds32: | TODO | +| nios2: | TODO | +|openrisc: | TODO | +| parisc: | TODO | +| powerpc: | ok | +| riscv: | TODO | +|s390: | ok | +| sh: | TODO | +| sparc: | TODO | +| um: | TODO | +| unicore32: | TODO | +| x86: | ok | +| xtensa: | TODO | +--- diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index ff306246d0f8..471ef22216c4 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -6,6 +6,7 @@ config ARC def_bool y select ARC_TIMERS + select ARCH_HAS_DEBUG_VM_PGTABLE select ARCH_HAS_DMA_PREP_COHERENT select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_SETUP_DMA_OPS diff --git
Re: [PATCH 02/21] mm: make early_pfn_to_nid() and related defintions close to each other
On 04/12/20 at 10:48pm, Mike Rapoport wrote: > From: Mike Rapoport > > The early_pfn_to_nid() and it's helper __early_pfn_to_nid() are spread > around include/linux/mm.h, include/linux/mmzone.h and mm/page_alloc.c. > > Drop unused stub for __early_pfn_to_nid() and move its actual generic > implementation close to its users. > > Signed-off-by: Mike Rapoport > --- > include/linux/mm.h | 4 ++-- > include/linux/mmzone.h | 9 > mm/page_alloc.c| 51 +- > 3 files changed, 27 insertions(+), 37 deletions(-) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 5a323422d783..a404026d14d4 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2388,9 +2388,9 @@ extern void > sparse_memory_present_with_active_regions(int nid); > > #if !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) && \ > !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) > -static inline int __early_pfn_to_nid(unsigned long pfn, > - struct mminit_pfnnid_cache *state) > +static inline int early_pfn_to_nid(unsigned long pfn) > { > + BUILD_BUG_ON(IS_ENABLED(CONFIG_NUMA)); > return 0; > } > #else > diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h > index 1b9de7d220fb..7b5b6eba402f 100644 > --- a/include/linux/mmzone.h > +++ b/include/linux/mmzone.h > @@ -1078,15 +1078,6 @@ static inline struct zoneref > *first_zones_zonelist(struct zonelist *zonelist, > #include > #endif > > -#if !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) && \ > - !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) > -static inline unsigned long early_pfn_to_nid(unsigned long pfn) > -{ > - BUILD_BUG_ON(IS_ENABLED(CONFIG_NUMA)); > - return 0; > -} > -#endif > - > #ifdef CONFIG_FLATMEM > #define pfn_to_nid(pfn) (0) > #endif > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 0d012eda1694..1ac775bfc9cf 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -1504,6 +1504,31 @@ void __free_pages_core(struct page *page, unsigned int > order) > > static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; > > +#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID > + > +/* > + * Required by SPARSEMEM. Given a PFN, return what node the PFN is on. > + */ > +int __meminit __early_pfn_to_nid(unsigned long pfn, > + struct mminit_pfnnid_cache *state) > +{ > + unsigned long start_pfn, end_pfn; > + int nid; > + > + if (state->last_start <= pfn && pfn < state->last_end) > + return state->last_nid; > + > + nid = memblock_search_pfn_nid(pfn, &start_pfn, &end_pfn); > + if (nid != NUMA_NO_NODE) { > + state->last_start = start_pfn; > + state->last_end = end_pfn; > + state->last_nid = nid; > + } > + > + return nid; > +} > +#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */ > + > int __meminit early_pfn_to_nid(unsigned long pfn) > { > static DEFINE_SPINLOCK(early_pfn_lock); > @@ -6298,32 +6323,6 @@ void __meminit init_currently_empty_zone(struct zone > *zone, > zone->initialized = 1; > } > > -#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP Here it's apparently removing CONFIG_HAVE_MEMBLOCK_NODE_MAP too early, it should be done in patch 3, and its #end is kept there. I just found it when I almost became dizzy in reviewing patch 3. > -#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID > - > -/* > - * Required by SPARSEMEM. Given a PFN, return what node the PFN is on. > - */ > -int __meminit __early_pfn_to_nid(unsigned long pfn, > - struct mminit_pfnnid_cache *state) > -{ > - unsigned long start_pfn, end_pfn; > - int nid; > - > - if (state->last_start <= pfn && pfn < state->last_end) > - return state->last_nid; > - > - nid = memblock_search_pfn_nid(pfn, &start_pfn, &end_pfn); > - if (nid != NUMA_NO_NODE) { > - state->last_start = start_pfn; > - state->last_end = end_pfn; > - state->last_nid = nid; > - } > - > - return nid; > -} > -#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */ > - > /** > * free_bootmem_with_active_regions - Call memblock_free_early_nid for each > active range > * @nid: The node to free memory on. If MAX_NUMNODES, all nodes are freed. > -- > 2.25.1 > ___ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc
Re: [PATCH 03/21] mm: remove CONFIG_HAVE_MEMBLOCK_NODE_MAP option
On 04/12/20 at 10:48pm, Mike Rapoport wrote: > From: Mike Rapoport > > The CONFIG_HAVE_MEMBLOCK_NODE_MAP is used to differentiate initialization > of nodes and zones structures between the systems that have region to node > mapping in memblock and those that don't. > > Currently all the NUMA architectures enable this option and for the > non-NUMA systems we can presume that all the memory belongs to node 0 and > therefore the compile time configuration option is not required. > > The remaining few architectures that use DISCONTIGMEM without NUMA are > easily updated to use memblock_add_node() instead of memblock_add() and > thus have proper correspondence of memblock regions to NUMA nodes. > > Still, free_area_init_node() must have a backward compatible version > because its semantics with and without CONFIG_HAVE_MEMBLOCK_NODE_MAP is > different. Once all the architectures will use the new semantics, the > entire compatibility layer can be dropped. > > To avoid addition of extra run time memory to store node id for > architectures that keep memblock but have only a single node, the node id > field of the memblock_region is guarded by CONFIG_NEED_MULTIPLE_NODES and > the corresponding accessors presume that in those cases it is always 0. > > Signed-off-by: Mike Rapoport > --- ... > diff --git a/include/linux/memblock.h b/include/linux/memblock.h > index 6bc37a731d27..45abfc54da37 100644 > --- a/include/linux/memblock.h > +++ b/include/linux/memblock.h > @@ -50,7 +50,7 @@ struct memblock_region { > phys_addr_t base; > phys_addr_t size; > enum memblock_flags flags; > -#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP > +#ifdef CONFIG_NEED_MULTIPLE_NODES > int nid; > #endif > }; > @@ -215,7 +215,6 @@ static inline bool memblock_is_nomap(struct > memblock_region *m) > return m->flags & MEMBLOCK_NOMAP; > } > > -#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP > int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn, > unsigned long *end_pfn); > void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, > @@ -234,7 +233,6 @@ void __next_mem_pfn_range(int *idx, int nid, unsigned > long *out_start_pfn, > #define for_each_mem_pfn_range(i, nid, p_start, p_end, p_nid) > \ > for (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid); \ >i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid)) > -#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ > > #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT > void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone, > @@ -310,10 +308,10 @@ void __next_mem_pfn_range_in_zone(u64 *idx, struct zone > *zone, > for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved, \ > nid, flags, p_start, p_end, p_nid) > > -#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP > int memblock_set_node(phys_addr_t base, phys_addr_t size, > struct memblock_type *type, int nid); > > +#ifdef CONFIG_NEED_MULTIPLE_NODES > static inline void memblock_set_region_node(struct memblock_region *r, int > nid) > { > r->nid = nid; > @@ -332,7 +330,7 @@ static inline int memblock_get_region_node(const struct > memblock_region *r) > { > return 0; > } > -#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ > +#endif /* CONFIG_NEED_MULTIPLE_NODES */ > > /* Flags for memblock allocation APIs */ > #define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0) > diff --git a/include/linux/mm.h b/include/linux/mm.h > index a404026d14d4..5903bbbdb336 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2344,9 +2344,8 @@ static inline unsigned long get_num_physpages(void) > return phys_pages; > } > > -#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP > /* > - * With CONFIG_HAVE_MEMBLOCK_NODE_MAP set, an architecture may initialise its > + * Using memblock node mappings, an architecture may initialise its > * zones, allocate the backing mem_map and account for memory holes in a more > * architecture independent manner. This is a substitute for creating the > * zone_sizes[] and zholes_size[] arrays and passing them to > @@ -2367,9 +2366,6 @@ static inline unsigned long get_num_physpages(void) > * registered physical page range. Similarly > * sparse_memory_present_with_active_regions() calls memory_present() for > * each range when SPARSEMEM is enabled. > - * > - * See mm/page_alloc.c for more information on each function exposed by > - * CONFIG_HAVE_MEMBLOCK_NODE_MAP. > */ > extern void free_area_init_nodes(unsigned long *max_zone_pfn); > unsigned long node_map_pfn_alignment(void); > @@ -2384,13 +2380,9 @@ extern void free_bootmem_with_active_regions(int nid, > unsigned long max_low_pfn); > extern void sparse_memory_present_with_active_regions(int nid); > > -#endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ > - > -#if !defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) && \ > -!defined(CONFIG