Do not give false expectations, as this machine only
uses 64MB of RAM.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/sh4/r2d.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 010be6d5394..56da48f64cb 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -251,6 +251,14 @@ static void r2d_init(MachineState *machine)
USBBus *usb_bus;
r2d_fpga_t *fpga;
+ switch (machine->ram_size) {
+ case 64 * MiB:
+ break;
+ default:
+ error_report("This machine can only use 64M of memory");
+ exit(EXIT_FAILURE);
+ }
+
cpu = SUPERH_CPU(cpu_create(machine->cpu_type));
env = &cpu->env;
--
2.51.0
On 11/24/25 03:50, Philippe Mathieu-Daudé wrote: > Do not give false expectations, as this machine only > uses 64MB of RAM. This broke my https://landley.net/bin/mkroot/0.8.13/sh4.tgz because every target in that directory does -m 256 as part of the template from https://github.com/landley/toybox/blob/0.8.13/mkroot/mkroot.sh#L333 which worked until now. I can special case qemu-system-sh4 but that won't fix compatibility with existing shipped instances. Could you maybe just turn this into a warning instead of -Werror in production? I fixed it up by hand for testing in the meantime, and it loaded the kernel with -m 192 but then initramfs couldn't find init. Without the patch series the same git version (942b0d378a1d) booted to a shell prompt. I can try to track down what happened in the morning... Sorry if I missed newer stuff I should be testing instead, I've been a bit distracted. Thanks, Rob
On 12/31/25 01:32, Rob Landley wrote: > I fixed it up by hand for testing in the meantime, and it loaded the > kernel with -m 192 but then initramfs couldn't find init. Without the > patch series the same git version (942b0d378a1d) booted to a shell > prompt. I can try to track down what happened in the morning... Ah, it boots with the full patch stack applied for -m 64 but not -m 128. It's mapping in the extra memory that breaks it. The initramfs doesn't seem to be extracting with the second memory block enabled? What's the diff in the output... --- out.txt 2025-12-31 01:42:33.487421358 -0600 +++ out2.txt 2025-12-31 01:42:47.359676340 -0600 @@ -105,7 +105,6 @@ NET: Registered PF_UNIX/PF_LOCAL protocol family PCI: CLS 0 bytes, default 32 Unpacking initramfs... -Freeing initrd memory: 528K workingset: timestamp_bits=30 max_order=14 bucket_order=0 squashfs: version 4.0 (2009/01/31) Phillip Lougher SuperH (H)SCI(F) driver initialized @@ -121,50 +120,14 @@ Segment Routing with IPv6 In-situ OAM (IOAM) with IPv6 NET: Registered PF_PACKET protocol family +Freeing initrd memory: 528K netconsole: network logging started -check access for rdinit=/init failed: -2, ignoring -/dev/root: Can't open blockdev -VFS: Cannot open root device "" or unknown-block(1,0): error -6 ... [filesystem list and panic dump elided] - [<8c3d0e24>] kernel_init+0x0/0x104 - -Rebooting in 1 seconds.. +devtmpfs: mounted +Freeing unused kernel image (initmem) memory: 132K +This architecture does not have kernel memory protection. +Run /init as init process +8139cp 0000:00:02.0 eth0: link up, 100Mbps, full-duplex, lpa 0x05E1 +ESC[?7hType exit when done. +$ exit +reboot: Restarting system Why on earth did the "freeing initrd memory" move? (Interrupts shouldn't be enabled until right before it spawns PID 1, unless they rewrote that part when I wasn't looking...) Ah, the - is the fail and the + is the success, I'm guessing the extract failed and the error path freed it early. Possibly the new memory block is either overwriting the cpio.gz or changing where it lives in a way the kernel isn't finding it. Anyway, you've got the tarball if you want to smoketest it yourself. Unless this is expected and we need kernel tweaks just to boot even when not using the new memory, in which case -m 256 warning and dropping down to 192 would _still_ lose backwards compatibility. (If there's an address range conflict, could the -initrd loaded contents be IN the new memory block, as if it had been loaded rather than a mapped in ROM?) Thanks, Rob
On Wed, 31 Dec 2025, Rob Landley wrote: > On 12/31/25 01:32, Rob Landley wrote: >> I fixed it up by hand for testing in the meantime, and it loaded the kernel >> with -m 192 but then initramfs couldn't find init. Without the patch series >> the same git version (942b0d378a1d) booted to a shell prompt. I can try to >> track down what happened in the morning... > > Ah, it boots with the full patch stack applied for -m 64 but not -m 128. It's > mapping in the extra memory that breaks it. > > The initramfs doesn't seem to be extracting with the second memory block > enabled? What's the diff in the output... > > --- out.txt 2025-12-31 01:42:33.487421358 -0600 > +++ out2.txt 2025-12-31 01:42:47.359676340 -0600 > @@ -105,7 +105,6 @@ > NET: Registered PF_UNIX/PF_LOCAL protocol family > PCI: CLS 0 bytes, default 32 > Unpacking initramfs... > -Freeing initrd memory: 528K > workingset: timestamp_bits=30 max_order=14 bucket_order=0 > squashfs: version 4.0 (2009/01/31) Phillip Lougher > SuperH (H)SCI(F) driver initialized > @@ -121,50 +120,14 @@ > Segment Routing with IPv6 > In-situ OAM (IOAM) with IPv6 > NET: Registered PF_PACKET protocol family > +Freeing initrd memory: 528K > netconsole: network logging started > -check access for rdinit=/init failed: -2, ignoring > -/dev/root: Can't open blockdev > -VFS: Cannot open root device "" or unknown-block(1,0): error -6 > ... [filesystem list and panic dump elided] > - [<8c3d0e24>] kernel_init+0x0/0x104 > - > -Rebooting in 1 seconds.. > +devtmpfs: mounted > +Freeing unused kernel image (initmem) memory: 132K > +This architecture does not have kernel memory protection. > +Run /init as init process > +8139cp 0000:00:02.0 eth0: link up, 100Mbps, full-duplex, lpa 0x05E1 > +ESC[?7hType exit when done. > +$ exit > +reboot: Restarting system > > Why on earth did the "freeing initrd memory" move? (Interrupts shouldn't be > enabled until right before it spawns PID 1, unless they rewrote that part > when I wasn't looking...) > > Ah, the - is the fail and the + is the success, I'm guessing the extract > failed and the error path freed it early. Possibly the new memory block is > either overwriting the cpio.gz or changing where it lives in a way the kernel > isn't finding it. I don't know anything about this but have you tried comparing 'info mtree' output from QEMU Monitor to see what changed? That may show if some memory block moved or overlaps something now. > Anyway, you've got the tarball if you want to smoketest it yourself. Unless > this is expected and we need kernel tweaks just to boot even when not using > the new memory, in which case -m 256 warning and dropping down to 192 would > _still_ lose backwards compatibility. (If there's an address range conflict, > could the -initrd loaded contents be IN the new memory block, as if it had > been loaded rather than a mapped in ROM?) The SH in QEMU is not much maintained and maybe there aren't many people to look at it so don't expect much help with it. Regards, BALATON Zoltan
On 12/31/25 06:01, BALATON Zoltan wrote:
>> Ah, the - is the fail and the + is the success, I'm guessing the
>> extract failed and the error path freed it early. Possibly the new
>> memory block is either overwriting the cpio.gz or changing where it
>> lives in a way the kernel isn't finding it.
>
> I don't know anything about this
Unfortunately I know about it less than I like, but I'm digging into the
code in the absence of further replies from people who presumably do know...
> but have you tried comparing 'info
> mtree' output from QEMU Monitor to see what changed? That may show if
> some memory block moved or overlaps something now.
I said "Possibly the new memory block is..." because the purpose of the
patch series I was replying to was adding more memory blocks to the r2d
board so it could have more than 64 megs ram. (Seems like this is like a
10 line change not a big series, but...) I was regression testing to see
if unchanged kernels still worked fine, hence finding (what seems to be)
a conflict with qemu's command line initrd loader. (Sorry for the delay
following up, a dementia patient declared war on the city I live in.)
Alas "info mtree" is a bit verbose to wade through, although I'll
probably take a swing at it if I can't parse the rest of this. (It would
be nice if it WASN'T always printing 8 leading zeroes for every number
on a 32 bit platform.) What I'd really like to get out of the monitor is
the device tree, but that doesn't seem to be an option...
https://qemu-project.gitlab.io/qemu/system/monitor.html said that "info
mem" is an option, but my qemu build disagred, so I did:
(qemu) info roms
info roms
addr=000000000c010000 size=0x000200 mem=ram name="boot_params"
addr=000000000c800000 size=0x31e020 mem=ram name="./linux-kernel"
addr=000000000d800000 size=0x084411 mem=ram name="./initramfs.cpio.gz"
(qemu) info ramblock
Block Name PSize Offset
Used Total HVA RO
r2d.sdram 4 KiB 0x0000000000000000
0x0000000004000000 0x0000000004000000 0x00007fd6d7e00000 rw
r2d.flash 4 KiB 0x0000000004800000
0x0000000001000000 0x0000000001000000 0x00007fd6e2e00000 rw
sm501.local 4 KiB 0x0000000004000000
0x0000000000800000 0x0000000000800000 0x00007fd728c00000 rw
pci:02.0/rtl8139.rom 4 KiB 0x0000000005800000
0x0000000000040000 0x0000000000040000 0x00007fd728a00000 ro
Which SEEMS to say that the 64m of sram is at offset ZERO, despite
hw/sh4/rd2.c (before all these patches) doing:
#define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
#define SDRAM_SIZE 0x04000000
/* Allocate memory space */
memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE,
&error_fatal);
memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
And then the boot params, kernel, and initrd.cpio.gz are loaded as
_roms_ in what would otherwise be the ram area...? (Again, the docs are
pointing me at nonexistent commands, so...)
I've just been reading the qemu source, but it's a bit eldritch in
places and has bloated by about 3x since I last went through it...
You're right the mtree subset for "memory" shows things in the expected
places, or at least sort of. (There's also address-space: I/O,
cpu-memory-0, rtl8139, sh_pci_host, intc, timer, sh_pci, ANOTHER one
called "memory", timer, sci, scif, rtl8139 _again_, I/O again, and then
"system" seems to be "memory" again...)
"What does a kernel running on this emulated hardware see" would be a
nice thing to get an answer to, but that doesn't appear to have occurred
to the people who wrote "monitor". Or if it did, it's like -hda where
the simple interface was deprecated, and it's one of the:
(qemu) info memdev
info memdev
(qemu) info memory-devices
info memory-devices
(qemu) info memory_size_summary
info memory_size_summary
base memory: 67108864
(Don't ask me why the first one has a blank line and the others don't.
The third one doesn't say WHERE the memory is, or what mapping holes I
could put more memory in...)
Hmmm... ah, this ALMOST seems to do what I want:
(qemu) info mtree -f
info mtree -f
FlatView #0
AS "memory", root: system
AS "cpu-memory-0", root: system
AS "sh_pci_host", root: bus master container
AS "rtl8139", root: bus master container
Root memory region: system
0000000000000000-0000000000ffffff (prio 0, romd): r2d.flash
0000000004000000-000000000400003f (prio 0, i/o): r2d-fpga
000000000c000000-000000000fffffff (prio 0, ram): r2d.sdram
0000000010000000-00000000107fffff (prio 0, ram): sm501.local
0000000013e00000-0000000013e0006b (prio 0, i/o): sm501-system-config
0000000013e10040-0000000013e10053 (prio 0, i/o): sm501-i2c
0000000013e30000-0000000013e3001f (prio 0, i/o): serial
0000000013e40000-0000000013e400ff (prio 0, i/o): ohci
0000000013e80000-0000000013e80fff (prio 0, i/o): sm501-disp-ctrl
0000000013f00000-0000000013f00053 (prio 0, i/o): sm501-2d-engine
000000001400080c-000000001400080f (prio 0, i/o): ide-mmio.2
0000000014001000-000000001400101f (prio 0, i/o): ide-mmio.1
000000001e080000-000000001e080003 (prio 0, i/o): intc @000000001e080000
000000001e080040-000000001e080043 (prio 0, i/o): intc @000000001e080040
000000001e080060-000000001e080063 (prio 0, i/o): intc @000000001e080060
000000001e100000-000000001e10002f (prio 0, i/o): timer
000000001e200000-000000001e200223 (prio 0, i/o): sh_pci
000000001f000000-000000001f000fff (prio 0, i/o): memory @000000001f000000
000000001f800000-000000001f800fff (prio 0, i/o): memory @000000001f800000
000000001fc00000-000000001fc00fff (prio 0, i/o): memory @000000001fc00000
000000001fd00004-000000001fd00013 (prio 0, i/o): intc @000000001fd00004
000000001fd80000-000000001fd8002f (prio 0, i/o): timer
000000001fe00000-000000001fe00027 (prio 0, i/o): sci
000000001fe80000-000000001fe80027 (prio 0, i/o): scif
00000000f0000000-00000000f7ffffff (prio 0, i/o): cache-and-tlb
00000000fd040000-00000000fd0400ff (prio 1, i/o): rtl8139
00000000fe080000-00000000fe080003 (prio 0, i/o): intc @000000001e080000
00000000fe080040-00000000fe080043 (prio 0, i/o): intc @000000001e080040
00000000fe080060-00000000fe080063 (prio 0, i/o): intc @000000001e080060
00000000fe100000-00000000fe10002f (prio 0, i/o): timer
00000000fe200000-00000000fe200223 (prio 0, i/o): sh_pci
00000000fe240000-00000000fe240fff (prio 0, i/o): io
00000000fe241000-00000000fe2410ff (prio 1, i/o): rtl8139
00000000fe241100-00000000fe24ffff (prio 0, i/o): io @0000000000001100
00000000ff000000-00000000ff000fff (prio 0, i/o): memory @000000001f000000
00000000ff800000-00000000ff800fff (prio 0, i/o): memory @000000001f800000
00000000ffc00000-00000000ffc00fff (prio 0, i/o): memory @000000001fc00000
00000000ffd00004-00000000ffd00013 (prio 0, i/o): intc @000000001fd00004
00000000ffd80000-00000000ffd8002f (prio 0, i/o): timer
00000000ffe00000-00000000ffe00027 (prio 0, i/o): sci
00000000ffe80000-00000000ffe80027 (prio 0, i/o): scif
FlatView #1
AS "I/O", root: io
Root memory region: io
0000000000000000-0000000000000fff (prio 0, i/o): io
0000000000001000-00000000000010ff (prio 1, i/o): rtl8139
0000000000001100-000000000000ffff (prio 0, i/o): io @0000000000001100
Except for the "FlatView #1" part at the end? (Define "flat" if there's
two of them...)
> The SH in QEMU is not much maintained
The subject says "Re: [PATCH... 01/13] because I was replying to a patch
in a series to update sh in qemu.
Here's me first getting an sh4 kernel booted under qemu a couple decades
ago now:
https://lists.gnu.org/archive/html/qemu-devel/2009-02/msg00961.html
I've regression tested both current linux/arch/sh and qemu-system-sh4 at
least a couple times a year ever since:
https://landley.net/bin/mkroot/latest/sh4.tgz is linux-6.17 because that
was current at the time.
> and maybe there aren't many people
> to look at it so don't expect much help with it.
Other than the people I cc'd on the email, including the patch's author,
the linux arch/sh maintainer, a previous linux arch/sh maintainer...
(Who were all cc'd on the original patch series.)
Rob
On 1/26/26 11:17, Rob Landley wrote:
> On 12/31/25 06:01, BALATON Zoltan wrote:
> Which SEEMS to say that the 64m of sram is at offset ZERO, despite hw/
> sh4/rd2.c (before all these patches) doing:
>
> #define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
> #define SDRAM_SIZE 0x04000000
>
> /* Allocate memory space */
> memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE,
> &error_fatal);
> memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram);
Right, it looks like if I don't care what the real hardware is doing but
just want to mangle the emulation to gimme a native build environment
with enough ram to build linux from scratch etc in for the architecture,
I can tweak hw/sh4/r2d2.c to have SDRAM_BASE of 0x4100000 and SDRAM_SIZE
of 0xbf00000 which gives me ~200 megs, and then in the linux kernel
config set CONFIG_MEMORY_START and CONFIG_MEMORY_SIZE to match and I
don't even need a kernel patch, just a config change...
And yes!
Freeing unused kernel image (initmem) memory: 132K
This architecture does not have kernel memory protection.
Run /init as init process
8139cp 0000:00:02.0 eth0: link up, 100Mbps, full-duplex, lpa 0x05E1
Type exit when done.
$ head /proc/cpuinfo
machine : RTS7751R2D
processor : 0
cpu family : sh4
cpu type : SH7751R
cut : unknown
cpu flags : fpu ptea
cache type : split (harvard)
icache size : 4KiB (2-way)
dcache size : 4KiB (2-way)
address sizes : 29 bits physical
$ head /proc/meminfo
MemTotal: 188356 kB
MemFree: 182852 kB
MemAvailable: 180324 kB
Buffers: 0 kB
Cached: 724 kB
SwapCached: 0 kB
Active: 620 kB
Inactive: 292 kB
Active(anon): 620 kB
Inactive(anon): 292 kB
The kernel and qemu have to agree where the memory base is or the
-kernel -initrd and -append can't hand off their blobs (which are
relative to the start of the big SRAM block), but it works.
Sigh, I wouldn't need to patch qemu either if -m argument's csv format
wasn't pointless. Instead of letting me specify address ranges (ala -m
64m@c0000000,16m@2000000), it's got:
-m [size=]megs[,slots=n,maxmem=size]
configure guest RAM
size: initial amount of guest memory
slots: number of hotplug slots (default: none)
maxmem: maximum amount of guest memory (default: none)
Which makes NO sense to me. (What's the point of specifying hotplug
slots if I can't say what's IN each hotplug slot? Something somewhere in
the board had to DEFINE the hardware slots, so what is the point of this
slots= thing? You're just reiterating.)
Oh well. If I wanted to get clever I could read the -m 123 value, do a
floor at the exiting 64 and a ceiling at 200, and subtract from the
starting address to provide the requested amount of memory. So if you
DON'T specify -m (or -m 64 the existing value), it works with existing
kernels. And then you can just -m a different number and use a matching
kernel .config to get more memory up to the "one bit contiguous block" size.
In theory with device tree support I wouldn't have to recompile the
kernel to tell it about the extra memory. We did device tree support in
the new j-core board, I wonder what it would take to use that as a model
to port r2d...
(Alas I have NO IDEA how to add such support to qemu. Or how to teach
its -kernel to load a vmlinux instead of mandating a zImage...)
But if I _did_ have device tree support there's a lot more places to
shove ram into:
> Root memory region: system
> 0000000000000000-0000000000ffffff (prio 0, romd): r2d.flash
1000000-4000000 is a 64 meg gap
> 0000000004000000-000000000400003f (prio 0, i/o): r2d-fpga
The one it's using above.
> 000000000c000000-000000000fffffff (prio 0, ram): r2d.sdram
> 0000000010000000-00000000107fffff (prio 0, ram): sm501.local
11000000-13e00000 is ~48 meg gap
> 0000000013e00000-0000000013e0006b (prio 0, i/o): sm501-system-config
> 0000000013e10040-0000000013e10053 (prio 0, i/o): sm501-i2c
> 0000000013e30000-0000000013e3001f (prio 0, i/o): serial
> 0000000013e40000-0000000013e400ff (prio 0, i/o): ohci
> 0000000013e80000-0000000013e80fff (prio 0, i/o): sm501-disp-ctrl
> 0000000013f00000-0000000013f00053 (prio 0, i/o): sm501-2d-engine
> 000000001400080c-000000001400080f (prio 0, i/o): ide-mmio.2
> 0000000014001000-000000001400101f (prio 0, i/o): ide-mmio.1
14100000-1e000000 is 128+48 meg gap.
> 000000001e080000-000000001e080003 (prio 0, i/o): intc @000000001e080000
> 000000001e080040-000000001e080043 (prio 0, i/o): intc @000000001e080040
> 000000001e080060-000000001e080063 (prio 0, i/o): intc @000000001e080060
> 000000001e100000-000000001e10002f (prio 0, i/o): timer
> 000000001e200000-000000001e200223 (prio 0, i/o): sh_pci
> 000000001f000000-000000001f000fff (prio 0, i/o): memory
> @000000001f000000
> 000000001f800000-000000001f800fff (prio 0, i/o): memory
> @000000001f800000
> 000000001fc00000-000000001fc00fff (prio 0, i/o): memory
> @000000001fc00000
> 000000001fd00004-000000001fd00013 (prio 0, i/o): intc @000000001fd00004
> 000000001fd80000-000000001fd8002f (prio 0, i/o): timer
> 000000001fe00000-000000001fe00027 (prio 0, i/o): sci
> 000000001fe80000-000000001fe80027 (prio 0, i/o): scif
This one's huge but I vaguely recall some hardware limitations in the
TLB or something? (I should ask.)
Still, the above adds up somewhere near 500 megs and that's PLENTY for
doing real work on a 32 bit headless build node. (Honestly in mkroot I
set even the 64 bit targets to 256 megs by default. When I do heavy
lifting I run distcc hooked up to a cross compiler and have it move the
heavy lifting of compilation outside the emulator while the build still
_acts_ fully native, since there's only one set of headers, one set of
libraries, and you can run anything you build and all the questions
configure asks from uname and sysinfo and /proc and such get the right
answers. The virtual network card becomes the bottleneck somewhere
around -j3, not counting that "autoconf is always the bottleneck" even
on -j32 build native machines. You can sing "autoconf is useless" to
"every sperm is sacred", and I often do while it's endlessly running to
ask three different ways if this system is compliant with posix-2008...)
And yes, I've been doing this for a while:
https://landley.net/aboriginal/about.html
https://landley.net/aboriginal/control-images/
Haven't learned how to set up a debian build node yet, but it's on the
todo list. :)
Rob
On 1/26/26 12:26, Rob Landley wrote: > Right, it looks like if I don't care what the real hardware is doing but > just want to mangle the emulation to gimme a native build environment > with enough ram to build linux from scratch etc in for the architecture, > I can tweak hw/sh4/r2d2.c to have SDRAM_BASE of 0x4100000 and SDRAM_SIZE > of 0xbf00000 which gives me ~200 megs, and then in the linux kernel > config set CONFIG_MEMORY_START and CONFIG_MEMORY_SIZE to match and I > don't even need a kernel patch, just a config change... > > And yes! ... > $ head /proc/cpuinfo > machine : RTS7751R2D ... > $ head /proc/meminfo > MemTotal: 188356 kB > MemFree: 182852 kB > MemAvailable: 180324 kB > > The kernel and qemu have to agree where the memory base is or the - > kernel -initrd and -append can't hand off their blobs (which are > relative to the start of the big SRAM block), but it works. Here's a QEMU patch that Does The Thing, with -m wired up. Rob
© 2016 - 2026 Red Hat, Inc.