The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM
@ 2026-08-14 10:52 Magnus Lindholm
  2026-08-14 10:52 ` [PATCH 1/3] sparc32: honour phys_base in the viking cache flush routines Magnus Lindholm
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Magnus Lindholm @ 2026-08-14 10:52 UTC (permalink / raw)
  To: davem, andreas; +Cc: sparclinux, linux-kernel, Magnus Lindholm

Many years ago I ran Linux on my SPARCstation hardware and tried to keep
up with new releases, but somewhere around 3.x I hit a wall, sooner for
SMP builds since they are larger. As the kernel grew it simply became too
big for SILO to load. On this machine the last one that fit was 2.6.32,
at 2598956 bytes against a 2605056 byte window: six kilobytes to spare.
3.12 was 184KB over. Fixing it turned out to need more than SILO changes,
the kernel side needed work too, and I never got around to giving it
serious thought. I recently dusted off my old SPARCs and picked the
journey back up.

A current sparc32 kernel no longer fits in the window SILO loads into:
0x4000 up to SILO's own text at 0x280000, about 2.5MB. Loading it higher
instead exposes two places that assume the kernel sits at the start of
RAM.

Patch 1 is an independent pre-existing bug. viking_flush_page() and
viking_mxcc_flush_page() compute a physical address as vaddr -
PAGE_OFFSET, which is __pa() without phys_base. It is wrong regardless of
the rest of this series; it simply cannot be observed while phys_base is
zero. When it is not, iommu_flush_iotlb() flushes the wrong page, the
IOMMU walks stale IOPTEs and every DMA transfer fails. It comes first so
that no commit in the series leaves Viking DMA broken.

Patch 2 makes setup_arch() discover a non-zero phys_base. It takes it from
the lowest sp_banks[] entry today, and phys_base is the offset __pa() and
__va() are defined in terms of, so once the kernel is loaded elsewhere
every early translation is wrong by the difference, including the physical
addresses written into page table descriptors. The tablewalker then
follows pointers into pages holding nothing, while the same tables read
back correctly through the nocache view, and the machine stops right after
the context table pointer is installed with no console left to say why.
The probe is the architecture's existing __get_phys(), which already
implements it for sun4m and sun4d and returns zero elsewhere.

Patch 3 sets HdrS to 0x0300, the protocol level that tells a boot loader
the kernel supports being located somewhere other than physical 0x4000.

No change in behaviour when phys_base is zero.

Tested on a SPARCstation 20 booting from SCSI to a full userspace, with
and without an initramfs, using a SILO carrying the matching loader
changes. Tested with both CPU module types this machine accepts, single
and dual:

  SuperSPARC-II, TI Viking/MXCC   the path patch 1 corrects
  HyperSPARC RT625, ROSS SRMMU    the only variant whose DVMA mappings
                                  are page coloured

With two SuperSPARC modules fitted the flushes patch 1 corrects are
reached through cross calls; 400MB of concurrent raw block reads on both
CPUs completed with no DMA errors, where a single transfer failed
immediately without the patch. HyperSPARC, which takes a different flush
path entirely, boots and runs DMA with no errors and no change in disk
throughput.

Also boot tested under qemu-system-sparc -M SS-5, and build tested for
LEON and plain sparc32_defconfig. Each commit builds on its own.
Emulation cannot exercise patch 1: microSPARC-II takes a different cache
flush path, and qemu models no write-back cache, so a missed flush has no
consequence there.

The cost is the RAM below the load address, which the loader chooses.

Magnus Lindholm (3):
  sparc32: honour phys_base in the viking cache flush routines
  sparc32: derive phys_base from the PAGE_OFFSET mapping
  sparc32: advertise relocatable kernel with HdrS 0x0300

 arch/sparc/kernel/head_32.S  |  2 +-
 arch/sparc/kernel/setup_32.c | 40 ++++++++++++++++++++++++++++++++++++
 arch/sparc/mm/viking.S       |  6 ++++++
 3 files changed, 47 insertions(+), 1 deletion(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/3] sparc32: honour phys_base in the viking cache flush routines
  2026-08-14 10:52 [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM Magnus Lindholm
@ 2026-08-14 10:52 ` Magnus Lindholm
  2026-08-14 20:43   ` Sam Ravnborg
  2026-08-14 10:52 ` [PATCH 2/3] sparc32: derive phys_base from the PAGE_OFFSET mapping Magnus Lindholm
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Magnus Lindholm @ 2026-08-14 10:52 UTC (permalink / raw)
  To: davem, andreas; +Cc: sparclinux, linux-kernel, Magnus Lindholm

viking_flush_page() and viking_mxcc_flush_page() derive the physical
address of the page they are asked to flush by subtracting PAGE_OFFSET
from the kernel virtual address:

	sethi	%hi(PAGE_OFFSET), %g2
	sub	%o0, %g2, %g3

That is only the physical address when phys_base is zero. The C side spells
the same conversion __pa(), which adds phys_base, and every caller passes a
kernel virtual address expecting exactly that.

With a kernel loaded away from the start of RAM the two disagree by
phys_base. viking_flush_page() then compares cache tags against the wrong
page and flushes nothing, and viking_mxcc_flush_page() streams a page that
is phys_base lower than the one it was given, so the intended lines stay
dirty in the cache while unrelated ones are pushed out.

The visible effect is that anything relying on a flush to make memory
visible to another bus master silently keeps working from stale data. On a
SPARCstation 20 this shows up as every SCSI transfer failing with a DMA
error: iommu_flush_iotlb() cannot get the IOPTEs out to RAM, so the IOMMU
walks stale entries and the ESP DMA faults.

Add phys_base, so these agree with __pa() again. No change when phys_base
is zero, which is why this went unnoticed.

Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
---
 arch/sparc/mm/viking.S | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/sparc/mm/viking.S b/arch/sparc/mm/viking.S
index 48f062de7a7f..8b4e251bbba2 100644
--- a/arch/sparc/mm/viking.S
+++ b/arch/sparc/mm/viking.S
@@ -38,6 +38,9 @@ sun4dsmp_flush_tlb_spin:
 viking_flush_page:
 	sethi	%hi(PAGE_OFFSET), %g2
 	sub	%o0, %g2, %g3
+	sethi	%hi(phys_base), %g2
+	ld	[%g2 + %lo(phys_base)], %g2
+	add	%g3, %g2, %g3		! + phys_base = physical address
 	srl	%g3, 12, %g1		! ppage >> 12
 
 	clr	%o1			! set counter, 0 - 127
@@ -91,6 +94,9 @@ viking_flush_page:
 viking_mxcc_flush_page:
 	sethi	%hi(PAGE_OFFSET), %g2
 	sub	%o0, %g2, %g3
+	sethi	%hi(phys_base), %g2
+	ld	[%g2 + %lo(phys_base)], %g2
+	add	%g3, %g2, %g3			! + phys_base = physical address
 	sub	%g3, -PAGE_SIZE, %g3		! ppage + PAGE_SIZE
 	sethi	%hi(MXCC_SRCSTREAM), %o3	! assume %hi(MXCC_SRCSTREAM) == %hi(MXCC_DESTSTREAM)
 	mov	0x10, %g2			! set cacheable bit
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/3] sparc32: derive phys_base from the PAGE_OFFSET mapping
  2026-08-14 10:52 [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM Magnus Lindholm
  2026-08-14 10:52 ` [PATCH 1/3] sparc32: honour phys_base in the viking cache flush routines Magnus Lindholm
@ 2026-08-14 10:52 ` Magnus Lindholm
  2026-08-14 20:46   ` Sam Ravnborg
  2026-08-14 10:52 ` [PATCH 3/3] sparc32: advertise relocatable kernel with HdrS 0x0300 Magnus Lindholm
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Magnus Lindholm @ 2026-08-14 10:52 UTC (permalink / raw)
  To: davem, andreas; +Cc: sparclinux, linux-kernel, Magnus Lindholm

setup_arch() computes phys_base as the base of the lowest sp_banks[]
entry, that is, where RAM starts, and assumes the kernel image was loaded
there. That holds for the traditional boot path, where SILO places the
image at physical 0x4000 and PAGE_OFFSET is mapped to physical 0.

It stops holding once the image no longer fits there. SILO loads a kernel
between physical 0x4000 and its own text at 0x280000, a window of 2605056
bytes; a current sparc32 kernel is roughly twice that. The loader must
then place the image elsewhere in physical memory and map PAGE_OFFSET to
it, at which point phys_base describes where RAM begins rather than what
PAGE_OFFSET maps to, and the two disagree.

phys_base is the offset __pa() and __va() are defined in terms of, so once
it is wrong every early translation is wrong by the difference, including
the physical addresses written into page table descriptors. The
tablewalker then follows pointers into pages that hold nothing while the
same tables read back correctly through the nocache view. The failure
surfaces as a hang right after the context table pointer is installed and
the TLB flushed, with nothing on the console to explain it, since the PROM
mappings the early console depends on have become just as unreachable.

Ask the MMU what PAGE_OFFSET actually translates to and adopt that.
__get_phys() already implements this probe for sun4m and sun4d and returns
zero elsewhere, so no new low level MMU access is introduced and machines
without an SRMMU are unaffected.

Memory below the kernel cannot be reached through the linear map, which
runs upward from PAGE_OFFSET, so drop the banks that fall below it rather
than leave entries that __va() would translate to below PAGE_OFFSET.

With this a 6MB kernel loaded at physical 0x03000000 boots on sun4m: the
context table lands at its true physical address,
srmmu_inherit_prom_mappings() preserves the PROM console mappings, and
srmmu.c needs no change at all, since map_kernel() already handles a
non-zero phys_base via do_large_mapping().

The cost is the RAM below the load address the loader chose. SILO's
memory_find() picks 48MB on machines with 64MB or more.

Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
---
 arch/sparc/kernel/setup_32.c | 40 ++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index 1b0db16cd37b..795714959da6 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -254,6 +254,30 @@ 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)
+{
+	int i, j = 0;
+
+	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;
+
+		if (end <= base)
+			continue;		/* wholly below - drop it */
+		if (start < base)
+			start = base;		/* straddles - trim the front */
+
+		sp_banks[j].base_addr = start;
+		sp_banks[j].num_bytes = end - start;
+		j++;
+	}
+	sp_banks[j].base_addr = 0;
+	sp_banks[j].num_bytes = 0;
+}
+
 /* Called from head_32.S - before we have setup anything
  * in the kernel. Be very careful with what you do here.
  */
@@ -332,6 +356,22 @@ void __init setup_arch(char **cmdline_p)
 		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;
 
 	if (!root_flags)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/3] sparc32: advertise relocatable kernel with HdrS 0x0300
  2026-08-14 10:52 [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM Magnus Lindholm
  2026-08-14 10:52 ` [PATCH 1/3] sparc32: honour phys_base in the viking cache flush routines Magnus Lindholm
  2026-08-14 10:52 ` [PATCH 2/3] sparc32: derive phys_base from the PAGE_OFFSET mapping Magnus Lindholm
@ 2026-08-14 10:52 ` Magnus Lindholm
  2026-08-14 20:48   ` Sam Ravnborg
  2026-08-14 11:25 ` [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM John Paul Adrian Glaubitz
  2026-08-14 20:53 ` Sam Ravnborg
  4 siblings, 1 reply; 12+ messages in thread
From: Magnus Lindholm @ 2026-08-14 10:52 UTC (permalink / raw)
  To: davem, andreas; +Cc: sparclinux, linux-kernel, Magnus Lindholm

HdrS version 0x0300 tells the boot loader that the kernel supports being
located somewhere other than physical 0x4000, which is where SILO places
the image on the traditional path. Anything older is copied back down
there, and refused outright when it no longer fits.

sparc32 could not make that claim before, because setup_arch() took
phys_base from the lowest memory bank rather than from what PAGE_OFFSET
maps to. It can now, so say so.

Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
---
 arch/sparc/kernel/head_32.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S
index 8c320fa25a67..11a1746829a4 100644
--- a/arch/sparc/kernel/head_32.S
+++ b/arch/sparc/kernel/head_32.S
@@ -69,7 +69,7 @@ sun4e_notsup:
  */
 	.ascii	"HdrS"
 	.word	LINUX_VERSION_CODE
-	.half	0x0203		/* HdrS version */
+	.half	0x0300		/* HdrS version */
 root_flags:
 	.half	1
 root_dev:
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM
  2026-08-14 10:52 [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM Magnus Lindholm
                   ` (2 preceding siblings ...)
  2026-08-14 10:52 ` [PATCH 3/3] sparc32: advertise relocatable kernel with HdrS 0x0300 Magnus Lindholm
@ 2026-08-14 11:25 ` John Paul Adrian Glaubitz
  2026-08-14 14:18   ` Magnus Lindholm
  2026-08-14 20:53 ` Sam Ravnborg
  4 siblings, 1 reply; 12+ messages in thread
From: John Paul Adrian Glaubitz @ 2026-08-14 11:25 UTC (permalink / raw)
  To: Magnus Lindholm, davem, andreas; +Cc: sparclinux, linux-kernel

Hi Magnus,

On Fri, 2026-08-14 at 12:52 +0200, Magnus Lindholm wrote:
> Many years ago I ran Linux on my SPARCstation hardware and tried to keep
> up with new releases, but somewhere around 3.x I hit a wall, sooner for
> SMP builds since they are larger. As the kernel grew it simply became too
> big for SILO to load. On this machine the last one that fit was 2.6.32,
> at 2598956 bytes against a 2605056 byte window: six kilobytes to spare.
> 3.12 was 184KB over. Fixing it turned out to need more than SILO changes,
> the kernel side needed work too, and I never got around to giving it
> serious thought. I recently dusted off my old SPARCs and picked the
> journey back up.

Awesome, thanks a lot for working on this!

Do you know whether GRUB would work on these machines as well or is there
anything that blocks the use on 32-bit machines. I'm currently not sure
whether there was any show-stopper.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM
  2026-08-14 11:25 ` [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM John Paul Adrian Glaubitz
@ 2026-08-14 14:18   ` Magnus Lindholm
  0 siblings, 0 replies; 12+ messages in thread
From: Magnus Lindholm @ 2026-08-14 14:18 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz; +Cc: davem, andreas, sparclinux, linux-kernel

On Fri, Aug 14, 2026 at 1:25 PM John Paul Adrian Glaubitz
<glaubitz@physik.fu-berlin.de> wrote:

>
> Awesome, thanks a lot for working on this!
>
> Do you know whether GRUB would work on these machines as well or is there
> anything that blocks the use on 32-bit machines. I'm currently not sure
> whether there was any show-stopper.
>

Thanks!

I have plenty of sparc32 hardware sitting around, and this lets me run current
kernels on it again.

GRUB is not an option as far as I can tell: there is no 32-bit SPARC target in
it at all. configure.ac maps target_cpu sparc to sparc64, and the only SPARC
platform is sparc64-ieee1275, so sun4c/sun4m machines have never been covered.
Happy to be corrected if anyone has got it running.

SILO still works, but it needs the loader side fixed too. A current kernel
does not fit in the 2.5MB window it loads into. I have a patch series for that
here:

https://github.com/linmag7/silo/tree/big_load-pr

Magnus

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/3] sparc32: honour phys_base in the viking cache flush routines
  2026-08-14 10:52 ` [PATCH 1/3] sparc32: honour phys_base in the viking cache flush routines Magnus Lindholm
@ 2026-08-14 20:43   ` Sam Ravnborg
  0 siblings, 0 replies; 12+ messages in thread
From: Sam Ravnborg @ 2026-08-14 20:43 UTC (permalink / raw)
  To: Magnus Lindholm; +Cc: davem, andreas, sparclinux, linux-kernel

Hi Magnus.

On Fri, Aug 14, 2026 at 12:52:32PM +0200, Magnus Lindholm wrote:
> viking_flush_page() and viking_mxcc_flush_page() derive the physical
> address of the page they are asked to flush by subtracting PAGE_OFFSET
> from the kernel virtual address:
> 
> 	sethi	%hi(PAGE_OFFSET), %g2
> 	sub	%o0, %g2, %g3
> 
> That is only the physical address when phys_base is zero. The C side spells
> the same conversion __pa(), which adds phys_base, and every caller passes a
> kernel virtual address expecting exactly that.
> 
> With a kernel loaded away from the start of RAM the two disagree by
> phys_base. viking_flush_page() then compares cache tags against the wrong
> page and flushes nothing, and viking_mxcc_flush_page() streams a page that
> is phys_base lower than the one it was given, so the intended lines stay
> dirty in the cache while unrelated ones are pushed out.
> 
> The visible effect is that anything relying on a flush to make memory
> visible to another bus master silently keeps working from stale data. On a
> SPARCstation 20 this shows up as every SCSI transfer failing with a DMA
> error: iommu_flush_iotlb() cannot get the IOPTEs out to RAM, so the IOMMU
> walks stale entries and the ESP DMA faults.
> 
> Add phys_base, so these agree with __pa() again. No change when phys_base
> is zero, which is why this went unnoticed.
> 
> Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
Looks good, I checked and as the other variants are coherent this
should be the only place we need this.

Reviewed-by: Sam Ravnborg <sam@ravnborg.org>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/3] sparc32: derive phys_base from the PAGE_OFFSET mapping
  2026-08-14 10:52 ` [PATCH 2/3] sparc32: derive phys_base from the PAGE_OFFSET mapping Magnus Lindholm
@ 2026-08-14 20:46   ` Sam Ravnborg
  2026-08-14 21:58     ` Magnus Lindholm
  0 siblings, 1 reply; 12+ messages in thread
From: Sam Ravnborg @ 2026-08-14 20:46 UTC (permalink / raw)
  To: Magnus Lindholm; +Cc: davem, andreas, sparclinux, linux-kernel

Hi Magnus.

On Fri, Aug 14, 2026 at 12:52:33PM +0200, Magnus Lindholm wrote:
> setup_arch() computes phys_base as the base of the lowest sp_banks[]
> entry, that is, where RAM starts, and assumes the kernel image was loaded
> there. That holds for the traditional boot path, where SILO places the
> image at physical 0x4000 and PAGE_OFFSET is mapped to physical 0.
> 
> It stops holding once the image no longer fits there. SILO loads a kernel
> between physical 0x4000 and its own text at 0x280000, a window of 2605056
> bytes; a current sparc32 kernel is roughly twice that. The loader must
> then place the image elsewhere in physical memory and map PAGE_OFFSET to
> it, at which point phys_base describes where RAM begins rather than what
> PAGE_OFFSET maps to, and the two disagree.
> 
> phys_base is the offset __pa() and __va() are defined in terms of, so once
> it is wrong every early translation is wrong by the difference, including
> the physical addresses written into page table descriptors. The
> tablewalker then follows pointers into pages that hold nothing while the
> same tables read back correctly through the nocache view. The failure
> surfaces as a hang right after the context table pointer is installed and
> the TLB flushed, with nothing on the console to explain it, since the PROM
> mappings the early console depends on have become just as unreachable.
> 
> Ask the MMU what PAGE_OFFSET actually translates to and adopt that.
> __get_phys() already implements this probe for sun4m and sun4d and returns
> zero elsewhere, so no new low level MMU access is introduced and machines
> without an SRMMU are unaffected.
> 
> Memory below the kernel cannot be reached through the linear map, which
> runs upward from PAGE_OFFSET, so drop the banks that fall below it rather
> than leave entries that __va() would translate to below PAGE_OFFSET.
> 
> With this a 6MB kernel loaded at physical 0x03000000 boots on sun4m: the
> context table lands at its true physical address,
> srmmu_inherit_prom_mappings() preserves the PROM console mappings, and
> srmmu.c needs no change at all, since map_kernel() already handles a
> non-zero phys_base via do_large_mapping().
> 
> The cost is the RAM below the load address the loader chose. SILO's
> memory_find() picks 48MB on machines with 64MB or more.
> 
> Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
> ---
>  arch/sparc/kernel/setup_32.c | 40 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
> index 1b0db16cd37b..795714959da6 100644
> --- a/arch/sparc/kernel/setup_32.c
> +++ b/arch/sparc/kernel/setup_32.c
> @@ -254,6 +254,30 @@ 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)
> +{
> +	int i, j = 0;
> +
> +	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;
> +
> +		if (end <= base)
> +			continue;		/* wholly below - drop it */
> +		if (start < base)
> +			start = base;		/* straddles - trim the front */
> +
> +		sp_banks[j].base_addr = start;
> +		sp_banks[j].num_bytes = end - start;
> +		j++;
> +	}
> +	sp_banks[j].base_addr = 0;
> +	sp_banks[j].num_bytes = 0;
> +}
OK

> +
>  /* Called from head_32.S - before we have setup anything
>   * in the kernel. Be very careful with what you do here.
>   */
> @@ -332,6 +356,22 @@ void __init setup_arch(char **cmdline_p)
>  		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);
Use 0x%xl to avoid the casts?
If we are noisy like this it would be nice to always print the RAM start
and kernel start.

The logic looks fine, just the few nits.

	Sam

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/3] sparc32: advertise relocatable kernel with HdrS 0x0300
  2026-08-14 10:52 ` [PATCH 3/3] sparc32: advertise relocatable kernel with HdrS 0x0300 Magnus Lindholm
@ 2026-08-14 20:48   ` Sam Ravnborg
  0 siblings, 0 replies; 12+ messages in thread
From: Sam Ravnborg @ 2026-08-14 20:48 UTC (permalink / raw)
  To: Magnus Lindholm; +Cc: davem, andreas, sparclinux, linux-kernel

Hi Magnus.

On Fri, Aug 14, 2026 at 12:52:34PM +0200, Magnus Lindholm wrote:
> HdrS version 0x0300 tells the boot loader that the kernel supports being
> located somewhere other than physical 0x4000, which is where SILO places
> the image on the traditional path. Anything older is copied back down
> there, and refused outright when it no longer fits.
OK, if I knew this it was paged out a long time ago.

> 
> sparc32 could not make that claim before, because setup_arch() took
> phys_base from the lowest memory bank rather than from what PAGE_OFFSET
> maps to. It can now, so say so.
> 
> Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM
  2026-08-14 10:52 [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM Magnus Lindholm
                   ` (3 preceding siblings ...)
  2026-08-14 11:25 ` [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM John Paul Adrian Glaubitz
@ 2026-08-14 20:53 ` Sam Ravnborg
  2026-08-14 22:05   ` Magnus Lindholm
  4 siblings, 1 reply; 12+ messages in thread
From: Sam Ravnborg @ 2026-08-14 20:53 UTC (permalink / raw)
  To: Magnus Lindholm; +Cc: davem, andreas, sparclinux, linux-kernel

Hi Magnus.

On Fri, Aug 14, 2026 at 12:52:31PM +0200, Magnus Lindholm wrote:
> Many years ago I ran Linux on my SPARCstation hardware and tried to keep
> up with new releases, but somewhere around 3.x I hit a wall, sooner for
> SMP builds since they are larger. As the kernel grew it simply became too
> big for SILO to load. On this machine the last one that fit was 2.6.32,
> at 2598956 bytes against a 2605056 byte window: six kilobytes to spare.
> 3.12 was 184KB over. Fixing it turned out to need more than SILO changes,
> the kernel side needed work too, and I never got around to giving it
> serious thought. I recently dusted off my old SPARCs and picked the
> journey back up.
> 
> A current sparc32 kernel no longer fits in the window SILO loads into:
> 0x4000 up to SILO's own text at 0x280000, about 2.5MB. Loading it higher
> instead exposes two places that assume the kernel sits at the start of
> RAM.
> 
> Patch 1 is an independent pre-existing bug. viking_flush_page() and
> viking_mxcc_flush_page() compute a physical address as vaddr -
> PAGE_OFFSET, which is __pa() without phys_base. It is wrong regardless of
> the rest of this series; it simply cannot be observed while phys_base is
> zero. When it is not, iommu_flush_iotlb() flushes the wrong page, the
> IOMMU walks stale IOPTEs and every DMA transfer fails. It comes first so
> that no commit in the series leaves Viking DMA broken.
> 
> Patch 2 makes setup_arch() discover a non-zero phys_base. It takes it from
> the lowest sp_banks[] entry today, and phys_base is the offset __pa() and
> __va() are defined in terms of, so once the kernel is loaded elsewhere
> every early translation is wrong by the difference, including the physical
> addresses written into page table descriptors. The tablewalker then
> follows pointers into pages holding nothing, while the same tables read
> back correctly through the nocache view, and the machine stops right after
> the context table pointer is installed with no console left to say why.
> The probe is the architecture's existing __get_phys(), which already
> implements it for sun4m and sun4d and returns zero elsewhere.
> 
> Patch 3 sets HdrS to 0x0300, the protocol level that tells a boot loader
> the kernel supports being located somewhere other than physical 0x4000.
> 
> No change in behaviour when phys_base is zero.
> 
> Tested on a SPARCstation 20 booting from SCSI to a full userspace, with
> and without an initramfs, using a SILO carrying the matching loader
> changes. Tested with both CPU module types this machine accepts, single
> and dual:
> 
>   SuperSPARC-II, TI Viking/MXCC   the path patch 1 corrects
>   HyperSPARC RT625, ROSS SRMMU    the only variant whose DVMA mappings
>                                   are page coloured

I thought Viking was only used by the large sun4d machine.
Good to learn something new here.

Nice to see someone having fun with these Sun machines.
I gave up and have actually tried to have the support for sun4m and
sun4d removed from the kernel.

	Sam

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/3] sparc32: derive phys_base from the PAGE_OFFSET mapping
  2026-08-14 20:46   ` Sam Ravnborg
@ 2026-08-14 21:58     ` Magnus Lindholm
  0 siblings, 0 replies; 12+ messages in thread
From: Magnus Lindholm @ 2026-08-14 21:58 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: davem, andreas, sparclinux, linux-kernel

Hi Sam,

On Fri, Aug 14, 2026 at 10:46 PM Sam Ravnborg <sam@ravnborg.org> wrote:

> Use 0x%xl to avoid the casts?
> If we are noisy like this it would be nice to always print the RAM start
> and kernel start.

I've taken that as making the first print unconditional so both values
always show, and leaving the "adopted" line only for when they actually
differ - is that what you meant?

One wrinkle: __get_phys() returns 0 on anything but sun4m/sun4d, so on LEON
it would read "kernel is at 0x0" - happy to gate the whole thing on those
two if you'd prefer that, and I'll send a v2 either way.


Magnus

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM
  2026-08-14 20:53 ` Sam Ravnborg
@ 2026-08-14 22:05   ` Magnus Lindholm
  0 siblings, 0 replies; 12+ messages in thread
From: Magnus Lindholm @ 2026-08-14 22:05 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: davem, andreas, sparclinux, linux-kernel

Hi Sam,

On Fri, Aug 14, 2026 at 10:53 PM Sam Ravnborg <sam@ravnborg.org> wrote:
>
>
> I thought Viking was only used by the large sun4d machine.
> Good to learn something new here.
>
> Nice to see someone having fun with these Sun machines.
> I gave up and have actually tried to have the support for sun4m and
> sun4d removed from the kernel.
>

I think I remember some of those discussions on the mailing list. I'm glad
the code was kept, the old sparcs still have a few cpu cycles to give.


Magnus

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-08-14 22:05 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-14 10:52 [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM Magnus Lindholm
2026-08-14 10:52 ` [PATCH 1/3] sparc32: honour phys_base in the viking cache flush routines Magnus Lindholm
2026-08-14 20:43   ` Sam Ravnborg
2026-08-14 10:52 ` [PATCH 2/3] sparc32: derive phys_base from the PAGE_OFFSET mapping Magnus Lindholm
2026-08-14 20:46   ` Sam Ravnborg
2026-08-14 21:58     ` Magnus Lindholm
2026-08-14 10:52 ` [PATCH 3/3] sparc32: advertise relocatable kernel with HdrS 0x0300 Magnus Lindholm
2026-08-14 20:48   ` Sam Ravnborg
2026-08-14 11:25 ` [PATCH 0/3] sparc32: allow a kernel loaded away from the start of RAM John Paul Adrian Glaubitz
2026-08-14 14:18   ` Magnus Lindholm
2026-08-14 20:53 ` Sam Ravnborg
2026-08-14 22:05   ` Magnus Lindholm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox