From 274074708455b25cf05df3ef745d8db7270b9901 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 28 Jan 2025 16:11:24 +0100 Subject: [PATCH 1/6] hw/char: Add emulation of Diva GSP PCI management boards The Diva GSP ("Guardian Service Processor") PCI boards are Remote Management cards for PA-RISC machines. They come with built-in 16550A UARTs for serial consoles and modem functionalities, as well as a mailbox-like memory area for hardware auto-reboot functionality. Latest generation HP PA-RISC server machines use those Diva cards for console output. Signed-off-by: Helge Deller --- MAINTAINERS | 1 + hw/char/Kconfig | 3 + hw/char/diva-gsp.c | 297 ++++++++++++++++++++++++++++++++++++++++++++ hw/char/meson.build | 1 + 4 files changed, 302 insertions(+) create mode 100644 hw/char/diva-gsp.c diff --git a/MAINTAINERS b/MAINTAINERS index bf737eb6db..e09a8d2791 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1193,6 +1193,7 @@ M: Richard Henderson M: Helge Deller S: Maintained F: configs/devices/hppa-softmmu/default.mak +F: hw/char/diva-gsp.c F: hw/display/artist.c F: hw/hppa/ F: hw/input/lasips2.c diff --git a/hw/char/Kconfig b/hw/char/Kconfig index 1dc20ee4c2..3f702565e6 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig @@ -66,6 +66,9 @@ config RENESAS_SCI config AVR_USART bool +config DIVA_GSP + bool + config MCHP_PFSOC_MMUART bool select SERIAL diff --git a/hw/char/diva-gsp.c b/hw/char/diva-gsp.c new file mode 100644 index 0000000000..ecec1f7bb1 --- /dev/null +++ b/hw/char/diva-gsp.c @@ -0,0 +1,297 @@ +/* + * HP Diva GSP controller + * + * The Diva PCI boards are Remote Management cards for PA-RISC machines. + * They come with built-in 16550A multi UARTs for serial consoles + * and a mailbox-like memory area for hardware auto-reboot functionality. + * GSP stands for "Guardian Service Processor". Later products were marketed + * "Management Processor" (MP). + * + * Diva cards are multifunctional cards. The first part, the aux port, + * is on physical machines not useable but we still try to mimic it here. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2025 Helge Deller + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "hw/char/serial.h" +#include "hw/irq.h" +#include "hw/pci/pci_device.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "migration/vmstate.h" + +#define PCI_DEVICE_ID_HP_DIVA 0x1048 +/* various DIVA GSP cards: */ +#define PCI_DEVICE_ID_HP_DIVA_TOSCA1 0x1049 +#define PCI_DEVICE_ID_HP_DIVA_TOSCA2 0x104A +#define PCI_DEVICE_ID_HP_DIVA_MAESTRO 0x104B +#define PCI_DEVICE_ID_HP_REO_IOC 0x10f1 +#define PCI_DEVICE_ID_HP_DIVA_HALFDOME 0x1223 +#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE 0x1226 +#define PCI_DEVICE_ID_HP_DIVA_POWERBAR 0x1227 +#define PCI_DEVICE_ID_HP_DIVA_EVEREST 0x1282 +#define PCI_DEVICE_ID_HP_DIVA_AUX 0x1290 +#define PCI_DEVICE_ID_HP_DIVA_RMP3 0x1301 +#define PCI_DEVICE_ID_HP_DIVA_HURRICANE 0x132a + + +#define PCI_SERIAL_MAX_PORTS 4 + +typedef struct PCIDivaSerialState { + PCIDevice dev; + MemoryRegion membar; /* for serial ports */ + MemoryRegion mailboxbar; /* for hardware mailbox */ + uint32_t subvendor; + uint32_t ports; + char *name[PCI_SERIAL_MAX_PORTS]; + SerialState state[PCI_SERIAL_MAX_PORTS]; + uint32_t level[PCI_SERIAL_MAX_PORTS]; + qemu_irq *irqs; + uint8_t prog_if; + bool disable; +} PCIDivaSerialState; + +static void diva_pci_exit(PCIDevice *dev) +{ + PCIDivaSerialState *pci = DO_UPCAST(PCIDivaSerialState, dev, dev); + SerialState *s; + int i; + + for (i = 0; i < pci->ports; i++) { + s = pci->state + i; + qdev_unrealize(DEVICE(s)); + memory_region_del_subregion(&pci->membar, &s->io); + g_free(pci->name[i]); + } + qemu_free_irqs(pci->irqs, pci->ports); +} + +static void multi_serial_irq_mux(void *opaque, int n, int level) +{ + PCIDivaSerialState *pci = opaque; + int i, pending = 0; + + pci->level[n] = level; + for (i = 0; i < pci->ports; i++) { + if (pci->level[i]) { + pending = 1; + } + } + pci_set_irq(&pci->dev, pending); +} + +struct diva_info { + unsigned int nports:4; /* number of serial ports */ + unsigned int omask:12; /* offset mask: BIT(1) -> offset 8 */ +}; + +static struct diva_info diva_get_diva_info(PCIDeviceClass *pc) +{ + switch (pc->subsystem_id) { + case PCI_DEVICE_ID_HP_DIVA_POWERBAR: + case PCI_DEVICE_ID_HP_DIVA_HURRICANE: + return (struct diva_info) { .nports = 1, + .omask = BIT(0) }; + case PCI_DEVICE_ID_HP_DIVA_TOSCA2: + return (struct diva_info) { .nports = 2, + .omask = BIT(0) | BIT(1) }; + case PCI_DEVICE_ID_HP_DIVA_TOSCA1: + case PCI_DEVICE_ID_HP_DIVA_HALFDOME: + case PCI_DEVICE_ID_HP_DIVA_KEYSTONE: + return (struct diva_info) { .nports = 3, + .omask = BIT(0) | BIT(1) | BIT(2) }; + case PCI_DEVICE_ID_HP_DIVA_EVEREST: /* e.g. in rp3410 */ + return (struct diva_info) { .nports = 3, + .omask = BIT(0) | BIT(2) | BIT(7) }; + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + return (struct diva_info) { .nports = 4, + .omask = BIT(0) | BIT(1) | BIT(2) | BIT(7) }; + } + g_assert_not_reached(); +} + + +static void diva_pci_realize(PCIDevice *dev, Error **errp) +{ + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); + PCIDivaSerialState *pci = DO_UPCAST(PCIDivaSerialState, dev, dev); + SerialState *s; + struct diva_info di = diva_get_diva_info(pc); + size_t i, offset = 0; + size_t portmask = di.omask; + + pci->dev.config[PCI_CLASS_PROG] = pci->prog_if; + pci->dev.config[PCI_INTERRUPT_PIN] = 0x01; + memory_region_init(&pci->membar, OBJECT(pci), "serial_ports", 4096); + pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &pci->membar); + pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci, di.nports); + + for (i = 0; i < di.nports; i++) { + s = pci->state + i; + if (!qdev_realize(DEVICE(s), NULL, errp)) { + diva_pci_exit(dev); + return; + } + s->irq = pci->irqs[i]; + pci->name[i] = g_strdup_printf("uart #%zu", i + 1); + memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, + pci->name[i], 8); + + /* calculate offset of given port based on bitmask */ + while ((portmask & BIT(0)) == 0) { + offset += 8; + portmask >>= 1; + } + memory_region_add_subregion(&pci->membar, offset, &s->io); + offset += 8; + portmask >>= 1; + pci->ports++; + } + + /* mailbox bar */ + memory_region_init(&pci->mailboxbar, OBJECT(pci), "mailbox", 128 * KiB); + pci_register_bar(&pci->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_PREFETCH, &pci->mailboxbar); +} + +static const VMStateDescription vmstate_pci_diva = { + .name = "pci-diva-serial", + .version_id = 1, + .minimum_version_id = 1, + .fields = (const VMStateField[]) { + VMSTATE_PCI_DEVICE(dev, PCIDivaSerialState), + VMSTATE_STRUCT_ARRAY(state, PCIDivaSerialState, PCI_SERIAL_MAX_PORTS, + 0, vmstate_serial, SerialState), + VMSTATE_UINT32_ARRAY(level, PCIDivaSerialState, PCI_SERIAL_MAX_PORTS), + VMSTATE_BOOL(disable, PCIDivaSerialState), + VMSTATE_END_OF_LIST() + } +}; + +static const Property diva_serial_properties[] = { + DEFINE_PROP_BOOL("disable", PCIDivaSerialState, disable, false), + DEFINE_PROP_CHR("chardev1", PCIDivaSerialState, state[0].chr), + DEFINE_PROP_CHR("chardev2", PCIDivaSerialState, state[1].chr), + DEFINE_PROP_CHR("chardev3", PCIDivaSerialState, state[2].chr), + DEFINE_PROP_CHR("chardev4", PCIDivaSerialState, state[3].chr), + DEFINE_PROP_UINT8("prog_if", PCIDivaSerialState, prog_if, 0x02), + DEFINE_PROP_UINT32("subvendor", PCIDivaSerialState, subvendor, + PCI_DEVICE_ID_HP_DIVA_TOSCA1), +}; + +static void diva_serial_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); + pc->realize = diva_pci_realize; + pc->exit = diva_pci_exit; + pc->vendor_id = PCI_VENDOR_ID_HP; + pc->device_id = PCI_DEVICE_ID_HP_DIVA; + pc->subsystem_vendor_id = PCI_VENDOR_ID_HP; + pc->subsystem_id = PCI_DEVICE_ID_HP_DIVA_TOSCA1; + pc->revision = 3; + pc->class_id = PCI_CLASS_COMMUNICATION_SERIAL; + dc->vmsd = &vmstate_pci_diva; + device_class_set_props(dc, diva_serial_properties); + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); +} + +static void diva_serial_init(Object *o) +{ + PCIDevice *dev = PCI_DEVICE(o); + PCIDivaSerialState *pms = DO_UPCAST(PCIDivaSerialState, dev, dev); + struct diva_info di = diva_get_diva_info(PCI_DEVICE_GET_CLASS(dev)); + size_t i; + + for (i = 0; i < di.nports; i++) { + object_initialize_child(o, "serial[*]", &pms->state[i], TYPE_SERIAL); + } +} + + +/* Diva-aux is the driver for portion 0 of the multifunction PCI device */ + +struct DivaAuxState { + PCIDevice dev; + MemoryRegion mem; + qemu_irq irq; +}; + +#define TYPE_DIVA_AUX "diva-aux" +OBJECT_DECLARE_SIMPLE_TYPE(DivaAuxState, DIVA_AUX) + +static void diva_aux_realize(PCIDevice *dev, Error **errp) +{ + DivaAuxState *pci = DO_UPCAST(DivaAuxState, dev, dev); + + pci->dev.config[PCI_CLASS_PROG] = 0x02; + pci->dev.config[PCI_INTERRUPT_PIN] = 0x01; + pci->irq = pci_allocate_irq(&pci->dev); + + memory_region_init(&pci->mem, OBJECT(pci), "mem", 16); + pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &pci->mem); +} + +static void diva_aux_exit(PCIDevice *dev) +{ + DivaAuxState *pci = DO_UPCAST(DivaAuxState, dev, dev); + qemu_free_irq(pci->irq); +} + +static void diva_aux_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); + pc->realize = diva_aux_realize; + pc->exit = diva_aux_exit; + pc->vendor_id = PCI_VENDOR_ID_HP; + pc->device_id = PCI_DEVICE_ID_HP_DIVA_AUX; + pc->subsystem_vendor_id = PCI_VENDOR_ID_HP; + pc->subsystem_id = 0x1291; + pc->revision = 1; + pc->class_id = PCI_CLASS_COMMUNICATION_MULTISERIAL; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->user_creatable = false; +} + +static void diva_aux_init(Object *o) +{ +} + +static const TypeInfo diva_aux_info = { + .name = TYPE_DIVA_AUX, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(DivaAuxState), + .instance_init = diva_aux_init, + .class_init = diva_aux_class_initfn, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + + + +static const TypeInfo diva_serial_pci_info = { + .name = "diva-gsp", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(PCIDivaSerialState), + .instance_init = diva_serial_init, + .class_init = diva_serial_class_initfn, + .interfaces = (InterfaceInfo[]) { + { INTERFACE_CONVENTIONAL_PCI_DEVICE }, + { }, + }, +}; + +static void diva_pci_register_type(void) +{ + type_register_static(&diva_serial_pci_info); + type_register_static(&diva_aux_info); +} + +type_init(diva_pci_register_type) diff --git a/hw/char/meson.build b/hw/char/meson.build index ed3529cbbb..86ee808cae 100644 --- a/hw/char/meson.build +++ b/hw/char/meson.build @@ -20,6 +20,7 @@ system_ss.add(when: 'CONFIG_SHAKTI_UART', if_true: files('shakti_uart.c')) system_ss.add(when: 'CONFIG_VIRTIO_SERIAL', if_true: files('virtio-console.c')) system_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen_console.c')) system_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_uartlite.c')) +system_ss.add(when: 'CONFIG_DIVA_GSP', if_true: files('diva-gsp.c')) system_ss.add(when: 'CONFIG_AVR_USART', if_true: files('avr_usart.c')) system_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_uart.c')) From c061efca0b6ea6d11a1d29a8d48835146fec10f7 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 28 Jan 2025 16:18:20 +0100 Subject: [PATCH 2/6] hw/hppa: Wire up Diva GSP card Until now we used a standard serial-pci device to emulate a HP serial console. This worked nicely with 32-bit Linux and 32-bit HP-UX, but 64-bit HP-UX crashes with it and expects either a Diva GSP card, or a real 64-bit capable PCI graphic card (which we don't have yet). In order to continue with 64-bit HP-UX, switch over to the recently added Diva GSP card emulation. Signed-off-by: Helge Deller --- hw/hppa/Kconfig | 1 + hw/hppa/machine.c | 31 +++++++++++-------------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/hw/hppa/Kconfig b/hw/hppa/Kconfig index 9312c4294a..cab21045de 100644 --- a/hw/hppa/Kconfig +++ b/hw/hppa/Kconfig @@ -11,6 +11,7 @@ config HPPA_B160L select LASI select SERIAL_MM select SERIAL_PCI + select DIVA_GSP select ISA_BUS select I8259 select IDE_CMD646 diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index b6135d9526..9c98b4c229 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -383,26 +383,17 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus, pci_init_nic_devices(pci_bus, mc->default_nic); - /* BMC board: HP Powerbar SP2 Diva (with console only) */ - pci_dev = pci_new(-1, "pci-serial"); - if (!lasi_dev) { - /* bind default keyboard/serial to Diva card */ - qdev_prop_set_chr(DEVICE(pci_dev), "chardev", serial_hd(0)); - } - qdev_prop_set_uint8(DEVICE(pci_dev), "prog_if", 0); - pci_realize_and_unref(pci_dev, pci_bus, &error_fatal); - pci_config_set_vendor_id(pci_dev->config, PCI_VENDOR_ID_HP); - pci_config_set_device_id(pci_dev->config, 0x1048); - pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_VENDOR_ID], PCI_VENDOR_ID_HP); - pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */ - - /* create a second serial PCI card when running Astro */ - if (serial_hd(1) && !lasi_dev) { - pci_dev = pci_new(-1, "pci-serial-4x"); - qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1)); - qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2)); - qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(3)); - qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(4)); + /* BMC board: HP Diva GSP */ + dev = qdev_new("diva-gsp"); + if (!object_property_get_bool(OBJECT(dev), "disable", NULL)) { + pci_dev = pci_new_multifunction(PCI_DEVFN(2, 0), "diva-gsp"); + if (!lasi_dev) { + /* bind default keyboard/serial to Diva card */ + qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(0)); + qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(1)); + qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(2)); + qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(3)); + } pci_realize_and_unref(pci_dev, pci_bus, &error_fatal); } From d4b3c927909c9e3cb687d2d4b0d7f26b63d1f7e9 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 4 Feb 2025 20:55:18 +0100 Subject: [PATCH 3/6] artist: Allow disabling artist on command line Allow users to disable the artist graphic card on the command line with the option "-global artist.disable=true". This change allows to use other graphic cards when using Linux, e.g. by adding "-device ati-vga". Signed-off-by: Helge Deller --- hw/display/artist.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/display/artist.c b/hw/display/artist.c index 8b719b11ed..f24c1d83dd 100644 --- a/hw/display/artist.c +++ b/hw/display/artist.c @@ -48,6 +48,7 @@ struct ARTISTState { struct vram_buffer vram_buffer[16]; + bool disable; uint16_t width; uint16_t height; uint16_t depth; @@ -1211,8 +1212,8 @@ static uint64_t artist_reg_read(void *opaque, hwaddr addr, unsigned size) break; case 0x380004: - /* 0x02000000 Buserror */ - val = 0x6dc20006; + /* magic number detected by SeaBIOS-hppa */ + val = s->disable ? 0 : 0x6dc20006; break; default: @@ -1432,7 +1433,7 @@ static int vmstate_artist_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_artist = { .name = "artist", - .version_id = 2, + .version_id = 3, .minimum_version_id = 2, .post_load = vmstate_artist_post_load, .fields = (const VMStateField[]) { @@ -1470,6 +1471,7 @@ static const VMStateDescription vmstate_artist = { VMSTATE_UINT32(font_write1, ARTISTState), VMSTATE_UINT32(font_write2, ARTISTState), VMSTATE_UINT32(font_write_pos_y, ARTISTState), + VMSTATE_BOOL(disable, ARTISTState), VMSTATE_END_OF_LIST() } }; @@ -1478,6 +1480,7 @@ static const Property artist_properties[] = { DEFINE_PROP_UINT16("width", ARTISTState, width, 1280), DEFINE_PROP_UINT16("height", ARTISTState, height, 1024), DEFINE_PROP_UINT16("depth", ARTISTState, depth, 8), + DEFINE_PROP_BOOL("disable", ARTISTState, disable, false), }; static void artist_reset(DeviceState *qdev) From b6247273fb6f53c94794444f9385029488bcb6fb Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 4 Feb 2025 21:04:39 +0100 Subject: [PATCH 4/6] hw/hppa: Avoid creation of artist if disabled on command line Do not create the artist graphic card if the user disabled it with "-global artist.disable=true" on the command line. Signed-off-by: Helge Deller --- hw/hppa/machine.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 9c98b4c229..c5f247633e 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -366,12 +366,15 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus, /* Graphics setup. */ if (machine->enable_graphics && vga_interface_type != VGA_NONE) { - vga_interface_created = true; dev = qdev_new("artist"); s = SYS_BUS_DEVICE(dev); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA)); - sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR)); + bool disabled = object_property_get_bool(OBJECT(dev), "disable", NULL); + if (!disabled) { + sysbus_realize_and_unref(s, &error_fatal); + vga_interface_created = true; + sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA)); + sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR)); + } } /* Network setup. */ From 5bef80106fcf1c60eeacfb50250f0624950af225 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 4 Feb 2025 21:10:08 +0100 Subject: [PATCH 5/6] hw/pci-host/astro: Add LMMIO range support Each Astro on 64-bit machines supports up to four LMMIO regions. Those regions are used by graphic cards and other PCI devices which need to map huge memory areas. The LMMIO regions are configured and set up by SeaBIOS-hppa and then used as-is by the operating systems (Linux, HP-UX). With this addition it's now possible to add other PCI graphic cards on the command line, e.g. with "-device ati-vga". Signed-off-by: Helge Deller --- hw/pci-host/astro.c | 52 +++++++++++++++++++++++++++++++++++++ include/hw/pci-host/astro.h | 6 ++--- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/hw/pci-host/astro.c b/hw/pci-host/astro.c index 62e9c8acbf..039cc3ad01 100644 --- a/hw/pci-host/astro.c +++ b/hw/pci-host/astro.c @@ -521,6 +521,53 @@ static ElroyState *elroy_init(int num) * Astro Runway chip. */ +static void adjust_LMMIO_DIRECT_mapping(AstroState *s, unsigned int reg_index) +{ + MemoryRegion *lmmio_alias; + unsigned int lmmio_index, map_route; + hwaddr map_addr; + uint32_t map_size; + struct ElroyState *elroy; + + /* pointer to LMMIO_DIRECT entry */ + lmmio_index = reg_index / 3; + lmmio_alias = &s->lmmio_direct[lmmio_index]; + + map_addr = s->ioc_ranges[3 * lmmio_index + 0]; + map_size = s->ioc_ranges[3 * lmmio_index + 1]; + map_route = s->ioc_ranges[3 * lmmio_index + 2]; + + /* find elroy to which this address is routed */ + map_route &= (ELROY_NUM - 1); + elroy = s->elroy[map_route]; + + if (lmmio_alias->enabled) { + memory_region_set_enabled(lmmio_alias, false); + } + + map_addr = F_EXTEND(map_addr); + map_addr &= TARGET_PAGE_MASK; + map_size = (~map_size) + 1; + map_size &= TARGET_PAGE_MASK; + + /* exit if disabled or zero map size */ + if (!(map_addr & 1) || !map_size) { + return; + } + + if (!memory_region_size(lmmio_alias)) { + memory_region_init_alias(lmmio_alias, OBJECT(elroy), + "pci-lmmmio-alias", &elroy->pci_mmio, + (uint32_t) map_addr, map_size); + memory_region_add_subregion(get_system_memory(), map_addr, + lmmio_alias); + } else { + memory_region_set_alias_offset(lmmio_alias, map_addr); + memory_region_set_size(lmmio_alias, map_size); + memory_region_set_enabled(lmmio_alias, true); + } +} + static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr, uint64_t *data, unsigned size, MemTxAttrs attrs) @@ -628,6 +675,11 @@ static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr, break; case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */ put_val_in_arrary(s->ioc_ranges, 0x300, addr, size, val); + unsigned int index = (addr - 0x300) / 8; + /* check if one of the 4 LMMIO_DIRECT regs, each using 3 entries. */ + if (index < LMMIO_DIRECT_RANGES * 3) { + adjust_LMMIO_DIRECT_mapping(s, index); + } break; case 0x10200: case 0x10220: diff --git a/include/hw/pci-host/astro.h b/include/hw/pci-host/astro.h index e2966917cd..832125a05a 100644 --- a/include/hw/pci-host/astro.h +++ b/include/hw/pci-host/astro.h @@ -24,6 +24,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(ElroyState, ELROY_PCI_HOST_BRIDGE) #define LMMIO_DIST_BASE_ADDR 0xf4000000ULL #define LMMIO_DIST_BASE_SIZE 0x4000000ULL +#define LMMIO_DIRECT_RANGES 4 + #define IOS_DIST_BASE_ADDR 0xfffee00000ULL #define IOS_DIST_BASE_SIZE 0x10000ULL @@ -83,9 +85,7 @@ struct AstroState { struct ElroyState *elroy[ELROY_NUM]; MemoryRegion this_mem; - - MemoryRegion pci_mmio; - MemoryRegion pci_io; + MemoryRegion lmmio_direct[LMMIO_DIRECT_RANGES]; IOMMUMemoryRegion iommu; AddressSpace iommu_as; From 3dc340f8a7cfbc30193ab269aad1a5a6026365a6 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 4 Feb 2025 23:07:05 +0100 Subject: [PATCH 6/6] target/hppa: Update SeaBIOS-hppa Update to lastest SeaBIOS-hppa which sets up the LMMIO range for the internal artist graphic card. Signed-off-by: Helge Deller --- roms/seabios-hppa | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roms/seabios-hppa b/roms/seabios-hppa index 1c516b4813..3391c58096 160000 --- a/roms/seabios-hppa +++ b/roms/seabios-hppa @@ -1 +1 @@ -Subproject commit 1c516b481339f511d83a4afba9a48d1ac904e93e +Subproject commit 3391c580960febcb9fa8f686f9666adaa462c349