All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Larsson <andreas@gaisler.com>
To: Magnus Lindholm <linmag7@gmail.com>, sparclinux@vger.kernel.org
Cc: davem@davemloft.net, linux-kernel@vger.kernel.org,
	sam@ravnborg.org, glaubitz@physik.fu-berlin.de
Subject: Re: [PATCH v3 5/6] sparc32: move early memory setup to setup_arch
Date: Fri, 25 Sep 2026 17:58:12 +0200	[thread overview]
Message-ID: <01904ae2-ed8e-487e-80f7-540b4d06b55d@gaisler.com> (raw)
In-Reply-To: <20260901214611.60560-6-linmag7@gmail.com>

On 2026-09-01 23:45, Magnus Lindholm wrote:
> Move the early memory configuration out of SRMMU paging setup and next to
> the rest of setup_arch(). Derive the PFN limits from memblock, reserve the
> kernel and initrd there, and retain mem= support with
> memblock_enforce_memory_limit().
> 
> Use for_each_mem_pfn_range() to find the lowmem boundary and replace
> last_valid_pfn with the standard max_low_pfn variable. Set the standard
> max_pfn variable to the end of physical memory and use it as the highmem
> zone limit. This tightens LEON's _pfn_valid() upper bound from all RAM to
> the lowmem limit, with no functional change because LEON does not use
> highmem.

It is not at all true that LEON systems do not use highmem. Rather, they
can make heavy use of highmen. Continued further down.


> The removed bootmem code also printed a private HIGHMEM summary. Generic
> memory initialization already reports the highmem zone, so do not retain
> the duplicate message.
> 
> When PAGE_OFFSET maps a relocated kernel, remove memory below phys_base
> from memblock because it cannot be reached through the linear map. This
> replaces the equivalent trimming of sp_banks.
> 
> Suggested-by: Sam Ravnborg <sam@ravnborg.org>
> Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
> ---
>  arch/sparc/include/asm/highmem.h    |   3 -
>  arch/sparc/include/asm/leon.h       |   2 +-
>  arch/sparc/include/asm/pgtable_32.h |   3 +-
>  arch/sparc/include/asm/pgtsrmmu.h   |   1 -
>  arch/sparc/kernel/setup_32.c        | 112 ++++++++++++-----------
>  arch/sparc/mm/init_32.c             | 132 +---------------------------
>  arch/sparc/mm/leon_mm.c             |   1 +
>  arch/sparc/mm/srmmu.c               |   8 +-
>  8 files changed, 67 insertions(+), 195 deletions(-)
> 
> diff --git a/arch/sparc/include/asm/highmem.h b/arch/sparc/include/asm/highmem.h
> index c7b2e208328b..b1b915ac604d 100644
> --- a/arch/sparc/include/asm/highmem.h
> +++ b/arch/sparc/include/asm/highmem.h
> @@ -26,9 +26,6 @@
>  #include <asm/vaddrs.h>
>  #include <asm/pgtsrmmu.h>
>  
> -/* declarations for highmem.c */
> -extern unsigned long highstart_pfn, highend_pfn;
> -
>  #define kmap_prot __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE)
>  extern pte_t *pkmap_page_table;
>  
> diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
> index 053a24b67aed..815131c77ed7 100644
> --- a/arch/sparc/include/asm/leon.h
> +++ b/arch/sparc/include/asm/leon.h
> @@ -251,7 +251,7 @@ extern int leon_ipi_irq;
>  
>  /* macros used in leon_mm.c */
>  #define PFN(x)           ((x) >> PAGE_SHIFT)
> -#define _pfn_valid(pfn)	 ((pfn < last_valid_pfn) && (pfn >= PFN(phys_base)))
> +#define _pfn_valid(pfn)	 ((pfn < max_low_pfn) && (pfn >= PFN(phys_base)))

What is the reason for doing this change? When leon_swprobe() is called
max_pfn has already been set up. Is there a reason for not using that?


However, in the scope of the calls to leon_swprobe(), no parts of the
inherited MMU table's PTDs/PTEs are outside of lowmem. If there indeed
is some technical reason for needing to do this change I suggest that
you, in a separate patch before this one:

- Remove PFN() and replace the callers in leon_mm.c with the standard
  PFN_DOWN() instead, as also Sam lifted as "future work", and

- Move the _pfn_valid define to leon_mm.c, make it only check for lowmem
  pfns and rename it to _pfn_lowmem() or something like that.

>  #define _SRMMU_PTE_PMASK_LEON 0xffffffff
>  
>  /*
> diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
> index f89b1250661d..91a6032cf6a2 100644
> --- a/arch/sparc/include/asm/pgtable_32.h
> +++ b/arch/sparc/include/asm/pgtable_32.h
> @@ -37,8 +37,7 @@ struct vm_area_struct;
>  struct page;
>  
>  void load_mmu(void);
> -unsigned long calc_highpages(void);
> -unsigned long __init bootmem_init(unsigned long *pages_avail);
> +void __init find_ramdisk(unsigned long end_of_phys_memory);
>  
>  #define pte_ERROR(e)   __builtin_trap()
>  #define pmd_ERROR(e)   __builtin_trap()
> diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h
> index a265822a475e..a2a6c8564c3e 100644
> --- a/arch/sparc/include/asm/pgtsrmmu.h
> +++ b/arch/sparc/include/asm/pgtsrmmu.h
> @@ -98,7 +98,6 @@
>  	 restore %g0, %g0, %g0;
>  
>  #ifndef __ASSEMBLER__
> -extern unsigned long last_valid_pfn;
>  
>  /* This makes sense. Honest it does - Anton */
>  /* XXX Yes but it's ugly as sin.  FIXME. -KMW */
> diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
> index 795714959da6..6ad85538964d 100644
> --- a/arch/sparc/kernel/setup_32.c
> +++ b/arch/sparc/kernel/setup_32.c
> @@ -23,6 +23,7 @@
>  #include <linux/syscalls.h>
>  #include <linux/kdev_t.h>
>  #include <linux/major.h>
> +#include <linux/memblock.h>
>  #include <linux/string.h>
>  #include <linux/init.h>
>  #include <linux/interrupt.h>
> @@ -254,28 +255,71 @@ static __init void leon_patch(void)
>  
>  struct tt_entry *sparc_ttable;
>  
> -/* Drop RAM below the kernel; the linear map runs upward from phys_base
> - * and cannot reach it.
> - */
> -static void __init trim_sp_banks_below(unsigned long base)
> +unsigned long phys_base;
> +EXPORT_SYMBOL(phys_base);
> +
> +unsigned long pfn_base;
> +EXPORT_SYMBOL(pfn_base);
> +
> +static unsigned long __init calc_max_low_pfn(void)
>  {
> -	int i, j = 0;
> +	unsigned long limit = pfn_base + PHYS_PFN(SRMMU_MAXMEM);
> +	unsigned long start_pfn, end_pfn;
> +	unsigned long last_pfn = 0;
> +	int i;
> +
> +	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, NULL) {
> +		if (start_pfn >= limit) {
> +			if (last_pfn < limit)
> +				limit = last_pfn;
> +			break;
> +		}
>  
> -	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
> -		unsigned long start = sp_banks[i].base_addr;
> -		unsigned long end = start + sp_banks[i].num_bytes;
> +		last_pfn = end_pfn;
> +	}
>  
> -		if (end <= base)
> -			continue;		/* wholly below - drop it */
> -		if (start < base)
> -			start = base;		/* straddles - trim the front */
> +	return limit;
> +}
>  
> -		sp_banks[j].base_addr = start;
> -		sp_banks[j].num_bytes = end - start;
> -		j++;
> +static void __init setup_memory(void)
> +{
> +	unsigned long ram_base = memblock_start_of_DRAM();
> +	unsigned long real_base = __get_phys(PAGE_OFFSET);
> +	unsigned long size;
> +
> +	memblock_set_bottom_up(true);
> +	memblock_allow_resize();
> +
> +	phys_base = ram_base;
> +	if (real_base && real_base != phys_base) {
> +		prom_printf("phys_base: RAM starts 0x%x but kernel is at 0x%x\n",
> +			    (unsigned int)phys_base, (unsigned int)real_base);
> +		phys_base = real_base;
> +		memblock_remove(0, phys_base);
> +		prom_printf("phys_base: adopted 0x%x, RAM below it dropped\n",
> +			    (unsigned int)phys_base);
>  	}
> -	sp_banks[j].base_addr = 0;
> -	sp_banks[j].num_bytes = 0;
> +
> +	if (cmdline_memory_size)
> +		memblock_enforce_memory_limit(cmdline_memory_size);
> +
> +	min_low_pfn = PFN_DOWN(memblock_start_of_DRAM());
> +	pfn_base = PHYS_PFN(phys_base);
> +	max_pfn = PFN_DOWN(memblock_end_of_DRAM());
> +	max_low_pfn = max_pfn;
> +
> +	if (max_low_pfn > pfn_base + PHYS_PFN(SRMMU_MAXMEM))
> +		max_low_pfn = calc_max_low_pfn();
> +
> +	find_ramdisk(memblock_end_of_DRAM());
> +
> +	/* Reserve the kernel text/data/bss. */
> +	size = __pa(PAGE_ALIGN((unsigned long)&_end)) - phys_base;
> +	memblock_reserve(phys_base, size);
> +	memblock_add(phys_base, size);
> +
> +	/* Only allow low memory to be allocated by memblock. */
> +	memblock_set_current_limit(PFN_PHYS(max_low_pfn));
>  }
>  
>  /* Called from head_32.S - before we have setup anything
> @@ -306,9 +350,6 @@ void __init sparc32_start_kernel(struct linux_romvec *rp)
>  
>  void __init setup_arch(char **cmdline_p)
>  {
> -	int i;
> -	unsigned long highest_paddr;
> -
>  	sparc_ttable = &trapbase[0];
>  
>  	/* Initialize PROM console and command line. */
> @@ -343,36 +384,7 @@ void __init setup_arch(char **cmdline_p)
>  
>  	idprom_init();
>  	load_mmu();
> -
> -	phys_base = 0xffffffffUL;
> -	highest_paddr = 0UL;
> -	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
> -		unsigned long top;
> -
> -		if (sp_banks[i].base_addr < phys_base)
> -			phys_base = sp_banks[i].base_addr;
> -		top = sp_banks[i].base_addr +
> -			sp_banks[i].num_bytes;
> -		if (highest_paddr < top)
> -			highest_paddr = top;
> -	}
> -
> -	/* phys_base must describe what PAGE_OFFSET maps to, not where RAM starts. */
> -	{
> -		unsigned long real_base = __get_phys(PAGE_OFFSET);
> -
> -		if (real_base && real_base != phys_base) {
> -			prom_printf("phys_base: RAM starts 0x%x but kernel is at 0x%x\n",
> -				    (unsigned int)phys_base,
> -				    (unsigned int)real_base);
> -			phys_base = real_base;
> -			trim_sp_banks_below(phys_base);
> -			prom_printf("phys_base: adopted 0x%x, RAM below it dropped\n",
> -				    (unsigned int)phys_base);
> -		}
> -	}
> -
> -	pfn_base = phys_base >> PAGE_SHIFT;
> +	setup_memory();
>  
>  	if (!root_flags)
>  		root_mountflags &= ~MS_RDONLY;
> diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c
> index 6880d9cb30a5..ac4462f1cf76 100644
> --- a/arch/sparc/mm/init_32.c
> +++ b/arch/sparc/mm/init_32.c
> @@ -35,66 +35,13 @@
>  
>  #include "mm_32.h"
>  
> -unsigned long phys_base;
> -EXPORT_SYMBOL(phys_base);
> -
> -unsigned long pfn_base;
> -EXPORT_SYMBOL(pfn_base);
> -
>  struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
>  
>  /* Initial ramdisk setup */
>  extern unsigned int sparc_ramdisk_image;
>  extern unsigned int sparc_ramdisk_size;
>  
> -unsigned long highstart_pfn, highend_pfn;
> -
> -unsigned long last_valid_pfn;
> -
> -unsigned long calc_highpages(void)
> -{
> -	int i;
> -	int nr = 0;
> -
> -	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
> -		unsigned long start_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
> -		unsigned long end_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
> -
> -		if (end_pfn <= max_low_pfn)
> -			continue;
> -
> -		if (start_pfn < max_low_pfn)
> -			start_pfn = max_low_pfn;
> -
> -		nr += end_pfn - start_pfn;
> -	}
> -
> -	return nr;
> -}
> -
> -static unsigned long calc_max_low_pfn(void)
> -{
> -	int i;
> -	unsigned long tmp = pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT);
> -	unsigned long curr_pfn, last_pfn;
> -
> -	last_pfn = (sp_banks[0].base_addr + sp_banks[0].num_bytes) >> PAGE_SHIFT;
> -	for (i = 1; sp_banks[i].num_bytes != 0; i++) {
> -		curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
> -
> -		if (curr_pfn >= tmp) {
> -			if (last_pfn < tmp)
> -				tmp = last_pfn;
> -			break;
> -		}
> -
> -		last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
> -	}
> -
> -	return tmp;
> -}
> -
> -static void __init find_ramdisk(unsigned long end_of_phys_memory)
> +void __init find_ramdisk(unsigned long end_of_phys_memory)
>  {
>  #ifdef CONFIG_BLK_DEV_INITRD
>  	unsigned long size;
> @@ -124,83 +71,6 @@ static void __init find_ramdisk(unsigned long end_of_phys_memory)
>  #endif
>  }
>  
> -unsigned long __init bootmem_init(unsigned long *pages_avail)
> -{
> -	unsigned long start_pfn, bytes_avail, size;
> -	unsigned long end_of_phys_memory = 0;
> -	unsigned long high_pages = 0;
> -	int i;
> -
> -	memblock_set_bottom_up(true);
> -	memblock_allow_resize();
> -
> -	bytes_avail = 0UL;
> -	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
> -		end_of_phys_memory = sp_banks[i].base_addr +
> -			sp_banks[i].num_bytes;
> -		bytes_avail += sp_banks[i].num_bytes;
> -		if (cmdline_memory_size) {
> -			if (bytes_avail > cmdline_memory_size) {
> -				unsigned long slack = bytes_avail - cmdline_memory_size;
> -
> -				bytes_avail -= slack;
> -				end_of_phys_memory -= slack;
> -
> -				sp_banks[i].num_bytes -= slack;
> -				if (sp_banks[i].num_bytes == 0) {
> -					sp_banks[i].base_addr = 0xdeadbeef;
> -				} else {
> -					memblock_add(sp_banks[i].base_addr,
> -						     sp_banks[i].num_bytes);
> -					sp_banks[i+1].num_bytes = 0;
> -					sp_banks[i+1].base_addr = 0xdeadbeef;
> -				}
> -				break;
> -			}
> -		}
> -		memblock_add(sp_banks[i].base_addr, sp_banks[i].num_bytes);
> -	}
> -
> -	if (cmdline_memory_size)
> -		memblock_enforce_memory_limit(cmdline_memory_size);
> -
> -	/* Start with page aligned address of last symbol in kernel
> -	 * image.
> -	 */
> -	start_pfn  = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &_end));
> -
> -	/* Now shift down to get the real physical page frame number. */
> -	start_pfn >>= PAGE_SHIFT;
> -
> -	max_pfn = end_of_phys_memory >> PAGE_SHIFT;
> -
> -	max_low_pfn = max_pfn;
> -	highstart_pfn = highend_pfn = max_pfn;
> -
> -	if (max_low_pfn > pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT)) {
> -		highstart_pfn = pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT);
> -		max_low_pfn = calc_max_low_pfn();
> -		high_pages = calc_highpages();
> -		printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
> -		    high_pages >> (20 - PAGE_SHIFT));
> -	}
> -
> -	find_ramdisk(end_of_phys_memory);
> -
> -	/* Reserve the kernel text/data/bss. */
> -	size = (start_pfn << PAGE_SHIFT) - phys_base;
> -	memblock_reserve(phys_base, size);
> -	memblock_add(phys_base, size);
> -
> -	size = memblock_phys_mem_size() - memblock_reserved_size();
> -	*pages_avail = (size >> PAGE_SHIFT) - high_pages;
> -
> -	/* Only allow low memory to be allocated via memblock allocation */
> -	memblock_set_current_limit(max_low_pfn << PAGE_SHIFT);
> -
> -	return max_pfn;
> -}
> -
>  /*
>   * paging_init() sets up the page tables: We call the MMU specific
>   * init routine based upon the Sun model type on the Sparc.
> diff --git a/arch/sparc/mm/leon_mm.c b/arch/sparc/mm/leon_mm.c
> index 1dc9b3d70eda..a43c5ffbbbe5 100644
> --- a/arch/sparc/mm/leon_mm.c
> +++ b/arch/sparc/mm/leon_mm.c
> @@ -11,6 +11,7 @@
>   */
>  
>  #include <linux/kernel.h>
> +#include <linux/memblock.h>
>  #include <linux/mm.h>
>  #include <asm/asi.h>
>  #include <asm/leon.h>
> diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
> index f094f6c105a2..e333d3eac451 100644
> --- a/arch/sparc/mm/srmmu.c
> +++ b/arch/sparc/mm/srmmu.c
> @@ -59,8 +59,6 @@ int vac_line_size;
>  
>  extern struct resource sparc_iomap;
>  
> -extern unsigned long last_valid_pfn;
> -
>  static pgd_t *srmmu_swapper_pg_dir;
>  
>  const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
> @@ -871,7 +869,7 @@ void __init arch_zone_limits_init(unsigned long *max_zone_pfns)
>  {
>  	max_zone_pfns[ZONE_DMA] = max_low_pfn;
>  	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
> -	max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
> +	max_zone_pfns[ZONE_HIGHMEM] = max_pfn;
>  }
>  
>  void __init srmmu_paging_init(void)
> @@ -884,7 +882,6 @@ void __init srmmu_paging_init(void)
>  	pud_t *pud;
>  	pmd_t *pmd;
>  	pte_t *pte;
> -	unsigned long pages_avail;
>  
>  	init_mm.context = (unsigned long) NO_CONTEXT;
>  	sparc_iomap.start = SUN4M_IOBASE_VADDR;	/* 16MB of IOSPACE on all sun4m's. */
> @@ -910,9 +907,6 @@ void __init srmmu_paging_init(void)
>  		prom_halt();
>  	}
>  
> -	pages_avail = 0;
> -	last_valid_pfn = bootmem_init(&pages_avail);
> -
>  	srmmu_nocache_calcsize();
>  	srmmu_nocache_init();
>  	srmmu_inherit_prom_mappings(0xfe400000, (LINUX_OPPROM_ENDVM - PAGE_SIZE));

Thanks,
Andreas


  parent reply	other threads:[~2026-09-25 15:58 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-01 21:45 [PATCH v3 0/6] sparc32: replace sp_banks with memblock Magnus Lindholm
2026-09-01 21:45 ` [PATCH v3 1/6] sparc32: use memblock when mapping the kernel Magnus Lindholm
2026-09-01 21:45 ` [PATCH v3 2/6] sparc32: use memblock to find available system memory Magnus Lindholm
2026-09-01 21:45 ` [PATCH v3 3/6] sparc32: populate memblock from the PROM memory map Magnus Lindholm
2026-09-01 21:45 ` [PATCH v3 4/6] sparc32: drop unused valid address bitmap Magnus Lindholm
2026-09-01 21:45 ` [PATCH v3 5/6] sparc32: move early memory setup to setup_arch Magnus Lindholm
2026-09-02  5:31   ` Sam Ravnborg
2026-09-25 15:58   ` Andreas Larsson [this message]
2026-09-26 11:18     ` Magnus Lindholm
2026-09-01 21:45 ` [PATCH v3 6/6] sparc32: drop sp_banks Magnus Lindholm
2026-09-02  5:35 ` [PATCH v3 0/6] sparc32: replace sp_banks with memblock Sam Ravnborg
2026-09-02  5:38   ` Magnus Lindholm

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=01904ae2-ed8e-487e-80f7-540b4d06b55d@gaisler.com \
    --to=andreas@gaisler.com \
    --cc=davem@davemloft.net \
    --cc=glaubitz@physik.fu-berlin.de \
    --cc=linmag7@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sam@ravnborg.org \
    --cc=sparclinux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.