Commit bb639f82 authored by Alistair Francis's avatar Alistair Francis Committed by Peter Maydell
Browse files

ahci.c: Don't assume AHCIState's parent is AHCIPCIState



The AHCIState struct can either have AHCIPCIState or SysbusAHCIState
as a parent. The ahci_irq_lower() and ahci_irq_raise() functions
assume that it is always AHCIPCIState, which is not always the
case, which causes a seg fault. Verify what the container of AHCIState
is before setting the PCIDevice struct.

Signed-off-by: default avatarAlistair Francis <alistair.francis@xilinx.com>
Acked-by: default avatarJohn Snow <jsnow@redhat.com>
Reviewed-by: default avatarPeter Crosthwaite <crosthwaite.peter@gmail.com>
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 5ea8b9c5
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -121,9 +121,9 @@ static uint32_t ahci_port_read(AHCIState *s, int port, int offset)

static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
{
    AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
    PCIDevice *pci_dev =
        (PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
    DeviceState *dev_state = s->container;
    PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
                                                           TYPE_PCI_DEVICE);

    DPRINTF(0, "raise irq\n");

@@ -136,9 +136,9 @@ static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)

static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
{
    AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
    PCIDevice *pci_dev =
        (PCIDevice *)object_dynamic_cast(OBJECT(d), TYPE_PCI_DEVICE);
    DeviceState *dev_state = s->container;
    PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state),
                                                           TYPE_PCI_DEVICE);

    DPRINTF(0, "lower irq\n");

@@ -1436,6 +1436,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
    s->as = as;
    s->ports = ports;
    s->dev = g_new0(AHCIDevice, ports);
    s->container = qdev;
    ahci_reg_init(s);
    /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
    memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s,
+2 −0
Original line number Diff line number Diff line
@@ -287,6 +287,8 @@ struct AHCIDevice {
};

typedef struct AHCIState {
    DeviceState *container;

    AHCIDevice *dev;
    AHCIControlRegs control_regs;
    MemoryRegion mem;