@samitouri / QOSamiQemu / commits / 4a84032a26

hw/hppa: Implement memory ranges

All 64-bit PA-RISC machines split the memory into (up to 3) different memory ranges, which are mapped at specific addresses. This patch mimics the mapping as it's done on physical machines, which includes the 3.75 GB split for C3700, and 1 GB split for newer 64-bit PAT machines like the A400. SeaBIOS-hppa needs to know how the memory split is done, so add a new memsplit_addr variable which stores the specific split address and hand this over to SeaBIOS-hppa via fwcfg. Signed-off-by: Helge Deller <deller@gmx.de>

Helge Deller committed Mar 30, 2026 at 00:11 UTC 4a84032a26811e4f7404625b09c66b468534fdfe
2 files changed +45 -16
hw/hppa/hppa_hardware.h
+2 -1
@@ -8,7 +8,8 @@
8 #define FIRMWARE_END 0xf0100000
9 #define FIRMWARE_HIGH 0xfffffff0 /* upper 32-bits of 64-bit firmware address */
10
11 -#define RAM_MAP_HIGH 0x0100000000 /* memory above 3.75 GB is mapped here */
11 +#define RAM_MAP_HIGH1 0x0100000000 /* memory above 4 GB */
12 +#define RAM_MAP_HIGH2 0x4040000000 /* memory between 1 G and 3.75 GB */
13
14 #define MEM_PDC_ENTRY 0x4800 /* PDC entry address */
15
hw/hppa/machine.c
+43 -15
@@ -43,6 +43,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(HppaMachineState, HPPA_COMMON_MACHINE)
43
44 struct HppaMachineState {
45 MachineState parent_obj;
46 +
47 + uint64_t memsplit_addr;
48 };
49
50 #define MIN_SEABIOS_HPPA_VERSION 22 /* require at least this fw version */
@@ -208,6 +210,7 @@ static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
210 const char qemu_version[] = QEMU_VERSION;
211 MachineClass *mc = MACHINE_GET_CLASS(ms);
212 int btlb_entries = HPPA_BTLB_ENTRIES(&cpu[0]->env);
213 + struct HppaMachineState *hpm = HPPA_COMMON_MACHINE(ms);
214 int len;
215
216 fw_cfg = fw_cfg_init_mem_nodma(addr, addr + 4, 1);
@@ -231,6 +234,10 @@ static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
234 fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
235 g_memdup2(mc->name, len), len);
236
237 + val = cpu_to_le64(hpm->memsplit_addr);
238 + fw_cfg_add_file(fw_cfg, "/etc/hppa/memsplit-addr",
239 + g_memdup2(&val, sizeof(val)), sizeof(val));
240 +
241 val = cpu_to_le64(soft_power_reg);
242 fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
243 g_memdup2(&val, sizeof(val)), sizeof(val));
@@ -287,6 +294,8 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
294 TranslateFn *translate;
295 MemoryRegion *cpu_region;
296 uint64_t ram_max;
297 + struct HppaMachineState *hpm;
298 + hwaddr splitaddr;
299
300 /* Create CPUs. */
301 for (unsigned int i = 0; i < smp_cpus; i++) {
@@ -347,21 +356,36 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
356 info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB);
357 machine->ram_size = ram_max;
358 }
350 - if (machine->ram_size <= FIRMWARE_START) {
351 - /* contiguous memory up to 3.75 GB RAM */
352 - memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
353 - } else {
359 +
360 + hpm = HPPA_COMMON_MACHINE(machine);
361 + if (!hpm->memsplit_addr) {
362 /* non-contiguous: Memory above 3.75 GB is mapped at RAM_MAP_HIGH */
355 - MemoryRegion *mem_region;
356 - mem_region = g_new(MemoryRegion, 2);
357 - memory_region_init_alias(&mem_region[0], &addr_space->parent_obj,
358 - "LowMem", machine->ram, 0, FIRMWARE_START);
359 - memory_region_init_alias(&mem_region[1], &addr_space->parent_obj,
360 - "HighMem", machine->ram, FIRMWARE_START,
361 - machine->ram_size - FIRMWARE_START);
362 - memory_region_add_subregion_overlap(addr_space, 0, &mem_region[0], -1);
363 - memory_region_add_subregion_overlap(addr_space, RAM_MAP_HIGH,
364 - &mem_region[1], -1);
363 + hpm->memsplit_addr = FIRMWARE_START;
364 + }
365 + splitaddr = hpm->memsplit_addr;
366 +
367 + MemoryRegion *mem_region;
368 + mem_region = g_new(MemoryRegion, 1);
369 + memory_region_init_alias(&mem_region[0], &addr_space->parent_obj,
370 + "memory0", machine->ram, 0, splitaddr);
371 + memory_region_add_subregion_overlap(addr_space, 0, &mem_region[0], -1);
372 + if (hppa_is_pa20(&cpu[0]->env)) {
373 + if (machine->ram_size > 4 * GiB) {
374 + mem_region = g_new(MemoryRegion, 1);
375 + memory_region_init_alias(&mem_region[0], &addr_space->parent_obj,
376 + "memory1", machine->ram, 4 * GiB,
377 + machine->ram_size - 4 * GiB);
378 + memory_region_add_subregion_overlap(addr_space, RAM_MAP_HIGH1,
379 + &mem_region[0], -1);
380 + }
381 + if (machine->ram_size > splitaddr) {
382 + mem_region = g_new(MemoryRegion, 1);
383 + memory_region_init_alias(&mem_region[0], &addr_space->parent_obj,
384 + "memory2", machine->ram, splitaddr,
385 + 4 * GiB - splitaddr);
386 + memory_region_add_subregion_overlap(addr_space, RAM_MAP_HIGH2,
387 + &mem_region[0], -1);
388 + }
389 }
390
391 return translate;
@@ -756,6 +780,10 @@ static void machine_HP_C3700_init(MachineState *machine)
780 */
781 static void machine_HP_A400_init(MachineState *machine)
782 {
783 + struct HppaMachineState *hpm;
784 +
785 + hpm = HPPA_COMMON_MACHINE(machine);
786 + hpm->memsplit_addr = 1 * GiB;
787 machine_HP_C3700_init(machine);
788 }
789
@@ -814,7 +842,7 @@ static void hppa_machine_common_class_init(ObjectClass *oc, const void *data)
842 mc->default_cpus = 1;
843 mc->max_cpus = HPPA_MAX_CPUS;
844 mc->default_boot_order = "cd";
817 - mc->default_ram_id = "ram";
845 + mc->default_ram_id = "hppa.ram";
846 mc->default_nic = "tulip";
847
848 nc->nmi_monitor_handler = hppa_nmi;