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(-)
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
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
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
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
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
© 2016 - 2026 Red Hat, Inc.