diff mbox

[SeaBIOS,edk2] (PAM stuff) reset doesn't work on OVMF + SeaBIOS CSM

Message ID 1361228926.2725.14.camel@shinybook.infradead.org
State New
Headers show

Commit Message

David Woodhouse Feb. 18, 2013, 11:08 p.m. UTC
On Mon, 2013-02-18 at 17:37 -0500, Kevin O'Connor wrote:
> On Mon, Feb 18, 2013 at 09:12:46PM +0000, David Woodhouse wrote:
> > The i440fx data sheet (ยง3.0) appears to say that the default values are
> > loaded on a *hard* reset, not a soft reset. And a reset invoked by the
> > keyboard controller (as SeaBIOS does) is a *soft* reset. The only way to
> > do a *hard* reset from software that's mentioned in the datasheet is the
> > PMC turbo/reset control register (port 0x93). And that, presumably, is
> > chipset-dependent and not something we can easily use from the reset
> > vector without doing a bunch of hardware probing.
> 
> The ACPI v2 spec describes a "hard" reset register.  SeaBIOS could
> extract it from the FADT and then use it.  Of course, we'd probably
> want to update the QEMU ACPI tables to implement ACPI v2 then.

Yeah, that makes me somewhat happier about the SeaBIOS side of it being
hardware-specific. That way the code at the reset vector only has to
cope with a single 8-bit write to memory, IO or config space.

Laszlo has hooked up the RCR on the PIIX3 already, so something like
this ought to make it reset the PAM setup *only* if reset via that...
diff mbox

Patch

diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 6c77e49..f4420bd 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -77,6 +77,7 @@  typedef struct PIIX3State {
 
     /* Reset Control Register contents */
     uint8_t rcr;
+    uint8_t rcr_hard_reset;
 
     /* IO memory region for Reset Control Register (RCR_IOPORT) */
     MemoryRegion rcr_mem;
@@ -84,6 +85,7 @@  typedef struct PIIX3State {
 
 struct PCII440FXState {
     PCIDevice dev;
+    PIIX3State *piix3;
     MemoryRegion *system_memory;
     MemoryRegion *pci_address_space;
     MemoryRegion *ram_memory;
@@ -171,6 +173,29 @@  static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
     return 0;
 }
 
+static void i440fx_reset(DeviceState *ds)
+{
+    PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, ds);
+    PCII440FXState *d = DO_UPCAST(PCII440FXState, dev, dev);
+    uint8_t *pci_conf = d->dev.config;
+
+    if (!d->piix3->rcr_hard_reset)
+        return;
+
+    pci_conf[0x59] = 0x00; // Reset PAM setup
+    pci_conf[0x5a] = 0x00;
+    pci_conf[0x5b] = 0x00;
+    pci_conf[0x5c] = 0x00;
+    pci_conf[0x5d] = 0x00;
+    pci_conf[0x5e] = 0x00;
+    pci_conf[0x5f] = 0x00;
+    pci_conf[0x72] = 0x02; // And SMM
+
+    i440fx_update_memory_mappings(d);
+
+    d->piix3->rcr_hard_reset = 0;
+}
+
 static int i440fx_post_load(void *opaque, int version_id)
 {
     PCII440FXState *d = opaque;
@@ -297,6 +322,7 @@  static PCIBus *i440fx_common_init(const char *device_name,
         pci_bus_set_route_irq_fn(b, piix3_route_intx_pin_to_irq);
     }
     piix3->pic = pic;
+    f->piix3 = piix3;
     *isa_bus = DO_UPCAST(ISABus, qbus,
                          qdev_get_child_bus(&piix3->dev.qdev, "isa.0"));
 
@@ -521,6 +547,8 @@  static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
     PIIX3State *d = opaque;
 
     if (val & 4) {
+        if (val & 2)
+            d->rcr_hard_reset = 1;
         qemu_system_reset_request();
         return;
     }
@@ -615,6 +643,7 @@  static void i440fx_class_init(ObjectClass *klass, void *data)
     dc->desc = "Host bridge";
     dc->no_user = 1;
     dc->vmsd = &vmstate_i440fx;
+    dc->reset = i440fx_reset;
 }
 
 static const TypeInfo i440fx_info = {