qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]