[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Changes to support booting NetBSD/alpha
From: |
Jason Thorpe |
Subject: |
[PATCH] Changes to support booting NetBSD/alpha |
Date: |
Tue, 6 Oct 2020 20:24:17 -0700 |
Along with the previous patch set for qemu-palcode, these changes
allow NetBSD/alpha to run in qemu-system-alpha.
- Allow a the minimum PCI device number to be passed to typhoon_init().
Use this to specify a minimum PCI device number of 1 in the Clipper
system emulation, since that's the lowest PCI device number with
valid interrupt mappings on that system.
- Instead of passing just the CPU count in trap_arg2, also pass other
configuration information. Define the first config bit (bit 6) to
reflect the "-nographic" option; PALcode will use this to initialize
the Console Terminal Block to specify serial console.
- Attach a minimal i82378 SIO PCI node; some operating systems won't
scan for ISA devices unless a PCI-ISA bridge is detected. Real hardware
would have had a Cypress or ALI bridge, but many Alpha models shipped
with a i82378, and most operating sytems are not picky about the specific
model.
- Modify the mc146818rtc emulation to ensure the timer is started as soon
as the device is realized, and update the PF bit in REG_C even if it is
not going to result in raising an interrupt, as the real hardware does.
Signed-off-by: Jason Thorpe <thorpej@me.com>
---
hw/alpha/alpha_sys.h | 2 +-
hw/alpha/dp264.c | 16 ++++++-
hw/alpha/typhoon.c | 104 +++++++++++++++++++++++++++++++++++++++++--
hw/rtc/mc146818rtc.c | 7 +++
4 files changed, 123 insertions(+), 6 deletions(-)
diff --git a/hw/alpha/alpha_sys.h b/hw/alpha/alpha_sys.h
index e2c02e2bbe..4835b3d5ee 100644
--- a/hw/alpha/alpha_sys.h
+++ b/hw/alpha/alpha_sys.h
@@ -11,7 +11,7 @@
PCIBus *typhoon_init(MemoryRegion *, ISABus **, qemu_irq *, AlphaCPU *[4],
- pci_map_irq_fn);
+ pci_map_irq_fn, uint8_t devfn_min);
/* alpha_pci.c. */
extern const MemoryRegionOps alpha_pci_ignore_ops;
diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index 4d24518d1d..de59ae78cb 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -72,13 +72,25 @@ static void clipper_init(MachineState *machine)
cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type));
}
+ /* arg0 -> memory size
+ arg1 -> kernel entry point
+ arg2 -> config word
+
+ Config word: bits 0-5 -> ncpus
+ bit 6 -> nographics option (for HWRPB CTB)
+
+ See init_hwrpb() in the PALcode. */
+
cpus[0]->env.trap_arg0 = ram_size;
cpus[0]->env.trap_arg1 = 0;
cpus[0]->env.trap_arg2 = smp_cpus;
+ if (!machine->enable_graphics)
+ cpus[0]->env.trap_arg2 |= (1 << 6);
- /* Init the chipset. */
+ /* Init the chipset. Because we're using CLIPPER IRQ mappings,
+ the minimum PCI device IdSel is 1. */
pci_bus = typhoon_init(machine->ram, &isa_bus, &rtc_irq, cpus,
- clipper_pci_map_irq);
+ clipper_pci_map_irq, PCI_DEVFN(1, 0));
/* Since we have an SRM-compatible PALcode, use the SRM epoch. */
mc146818_rtc_init(isa_bus, 1900, rtc_irq);
diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index a42b319812..cfe7fd5098 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -817,7 +817,8 @@ static void typhoon_alarm_timer(void *opaque)
}
PCIBus *typhoon_init(MemoryRegion *ram, ISABus **isa_bus, qemu_irq *p_rtc_irq,
- AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
+ AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq,
+ uint8_t devfn_min)
{
MemoryRegion *addr_space = get_system_memory();
DeviceState *dev;
@@ -887,7 +888,7 @@ PCIBus *typhoon_init(MemoryRegion *ram, ISABus **isa_bus,
qemu_irq *p_rtc_irq,
b = pci_register_root_bus(dev, "pci",
typhoon_set_irq, sys_map_irq, s,
&s->pchip.reg_mem, &s->pchip.reg_io,
- 0, 64, TYPE_PCI_BUS);
+ devfn_min, 64, TYPE_PCI_BUS);
phb->bus = b;
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
@@ -921,10 +922,21 @@ PCIBus *typhoon_init(MemoryRegion *ram, ISABus **isa_bus,
qemu_irq *p_rtc_irq,
/* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB. */
/* Init the ISA bus. */
- /* ??? Technically there should be a cy82c693ub pci-isa bridge. */
+ /* Init the PCI-ISA bridge. Technically, this would have been
+ a cy82c693ub, but a i82378 SIO was also used on many Alpha
+ systems and is close enough.
+
+ ??? We are using a private, stripped down implementation of i82378
+ so that we can handle the way the ISA interrupts are wired up on
+ Tsunami-type systems. We're leaving that (and the rest of the board
+ peripheral setup) untoucned; we merely need to instantiate the PCI
+ device node for the bridge, so that operating systems that expect
+ it to be there will see it. */
{
qemu_irq *isa_irqs;
+ pci_create_simple(b, PCI_DEVFN(7, 0), "i82378-typhoon");
+
*isa_bus = isa_bus_new(NULL, get_system_memory(), &s->pchip.reg_io,
&error_abort);
isa_irqs = i8259_init(*isa_bus,
@@ -955,10 +967,96 @@ static const TypeInfo typhoon_iommu_memory_region_info = {
.class_init = typhoon_iommu_memory_region_class_init,
};
+/* The following was copied from hw/isa/i82378.c and modified to provide
+ only the minimal PCI device node. */
+
+/*
+ * QEMU Intel i82378 emulation (PCI to ISA bridge)
+ *
+ * Copyright (c) 2010-2011 Herv\xc3\xa9 Poussineau
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "migration/vmstate.h"
+
+#define TYPE_I82378 "i82378-typhoon"
+#define I82378(obj) \
+ OBJECT_CHECK(I82378State, (obj), TYPE_I82378)
+
+typedef struct I82378State {
+ PCIDevice parent_obj;
+} I82378State;
+
+static const VMStateDescription vmstate_i82378 = {
+ .name = "pci-i82378-typhoon",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_PCI_DEVICE(parent_obj, I82378State),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void i82378_realize(PCIDevice *pci, Error **errp)
+{
+ uint8_t *pci_conf;
+
+ pci_conf = pci->config;
+ pci_set_word(pci_conf + PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ pci_set_word(pci_conf + PCI_STATUS,
+ PCI_STATUS_DEVSEL_MEDIUM);
+
+ pci_config_set_interrupt_pin(pci_conf, 1); /* interrupt pin 0 */
+}
+
+static void i82378_init(Object *obj)
+{
+}
+
+static void i82378_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ k->realize = i82378_realize;
+ k->vendor_id = PCI_VENDOR_ID_INTEL;
+ k->device_id = PCI_DEVICE_ID_INTEL_82378;
+ k->revision = 0x03;
+ k->class_id = PCI_CLASS_BRIDGE_ISA;
+ dc->vmsd = &vmstate_i82378;
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+}
+
+static const TypeInfo i82378_typhoon_type_info = {
+ .name = TYPE_I82378,
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(I82378State),
+ .instance_init = i82378_init,
+ .class_init = i82378_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { },
+ },
+};
+
static void typhoon_register_types(void)
{
type_register_static(&typhoon_pcihost_info);
type_register_static(&typhoon_iommu_memory_region_info);
+ type_register_static(&i82378_typhoon_type_info);
}
type_init(typhoon_register_types)
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index 7a38540cb9..596876cb43 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -155,9 +155,15 @@ static uint32_t rtc_periodic_clock_ticks(RTCState *s)
{
int period_code;
+#if 0
+ /*
+ * Real hardware sets the PF bit rergardless if it actually
+ * raises an interrupt.
+ */
if (!(s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
return 0;
}
+#endif
period_code = s->cmos_data[RTC_REG_A] & 0x0f;
@@ -944,6 +950,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
}
s->periodic_timer = timer_new_ns(rtc_clock, rtc_periodic_timer, s);
+ periodic_timer_update(s, qemu_clock_get_ns(rtc_clock), 0, true);
s->update_timer = timer_new_ns(rtc_clock, rtc_update_timer, s);
check_update_timer(s);
--
2.28.0
- [PATCH] Changes to support booting NetBSD/alpha,
Jason Thorpe <=