From d8f94e1bb275ab6a14a15220fd6afd0d04324aeb Mon Sep 17 00:00:00 2001 From: John Snow Date: Wed, 1 Oct 2014 14:19:27 -0400 Subject: [PATCH] ide: Update ide_drive_get to be HBA agnostic Instead of duplicating the logic for the if_ide (bus,unit) mappings, rely on the blockdev layer for managing those mappings for us, and use the drive_get_by_index call instead. This allows ide_drive_get to work for AHCI HBAs as well, and can be used in the Q35 initialization. Lastly, change the nature of the argument to ide_drive_get so that represents the number of total drives we can support, and not the total number of buses. This will prevent array overflows if the units-per-default-bus property ever needs to be adjusted for compatibility reasons. Signed-off-by: John Snow Reviewed-by: Markus Armbruster Reviewed-by: Michael S. Tsirkin Message-id: 1412187569-23452-5-git-send-email-jsnow@redhat.com Signed-off-by: Stefan Hajnoczi --- blockdev.c | 17 +++++++++++++++++ hw/alpha/dp264.c | 2 +- hw/i386/pc_piix.c | 2 +- hw/ide/core.c | 22 +++++++++++++++++----- hw/mips/mips_fulong2e.c | 2 +- hw/mips/mips_malta.c | 2 +- hw/mips/mips_r4k.c | 2 +- hw/ppc/mac_newworld.c | 2 +- hw/ppc/mac_oldworld.c | 2 +- hw/ppc/prep.c | 2 +- hw/sparc64/sun4u.c | 2 +- include/sysemu/blockdev.h | 1 + 12 files changed, 44 insertions(+), 14 deletions(-) diff --git a/blockdev.c b/blockdev.c index 1780d7723a..e595910476 100644 --- a/blockdev.c +++ b/blockdev.c @@ -135,6 +135,23 @@ void blockdev_auto_del(BlockDriverState *bs) } } +/** + * Returns the current mapping of how many units per bus + * a particular interface can support. + * + * A positive integer indicates n units per bus. + * 0 implies the mapping has not been established. + * -1 indicates an invalid BlockInterfaceType was given. + */ +int drive_get_max_devs(BlockInterfaceType type) +{ + if (type >= IF_IDE && type < IF_COUNT) { + return if_max_devs[type]; + } + + return -1; +} + static int drive_index_to_bus_id(BlockInterfaceType type, int index) { int max_devs = if_max_devs[type]; diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index b178a03604..84a55e41a2 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -97,7 +97,7 @@ static void clipper_init(MachineState *machine) /* IDE disk setup. */ { DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); pci_cmd646_ide_init(pci_bus, hd, 0); } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 103d756a72..43846339bc 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -239,7 +239,7 @@ static void pc_init1(MachineState *machine, pc_nic_init(isa_bus, pci_bus); - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); if (pci_enabled) { PCIDevice *dev; if (xen_enabled()) { diff --git a/hw/ide/core.c b/hw/ide/core.c index 190700ac74..ae85428864 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2558,16 +2558,28 @@ const VMStateDescription vmstate_ide_bus = { } }; -void ide_drive_get(DriveInfo **hd, int max_bus) +void ide_drive_get(DriveInfo **hd, int n) { int i; + int highest_bus = drive_get_max_bus(IF_IDE) + 1; + int max_devs = drive_get_max_devs(IF_IDE); + int n_buses = max_devs ? (n / max_devs) : n; - if (drive_get_max_bus(IF_IDE) >= max_bus) { - fprintf(stderr, "qemu: too many IDE bus: %d\n", max_bus); + /* + * Note: The number of actual buses available is not known. + * We compute this based on the size of the DriveInfo* array, n. + * If it is less than max_devs * , + * We will stop looking for drives prematurely instead of overfilling + * the array. + */ + + if (highest_bus > n_buses) { + error_report("Too many IDE buses defined (%d > %d)", + highest_bus, n_buses); exit(1); } - for(i = 0; i < max_bus * MAX_IDE_DEVS; i++) { - hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); + for (i = 0; i < n; i++) { + hd[i] = drive_get_by_index(IF_IDE, i); } } diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index be286da18b..29cd708e07 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -350,7 +350,7 @@ static void mips_fulong2e_init(MachineState *machine) pci_bus = bonito_init((qemu_irq *)&(env->irq[2])); /* South bridge */ - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); isa_bus = vt82c686b_init(pci_bus, PCI_DEVFN(FULONG2E_VIA_SLOT, 0)); if (!isa_bus) { diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 2d87de9ea5..b20807c4e4 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -1147,7 +1147,7 @@ void mips_malta_init(MachineState *machine) pci_bus = gt64120_register(isa_irq); /* Southbridge */ - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); piix4_devfn = piix4_init(pci_bus, &isa_bus, 80); diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index e219766f3e..93606a490c 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -294,7 +294,7 @@ void mips_r4k_init(MachineState *machine) if (nd_table[0].used) isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]); - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); for(i = 0; i < MAX_IDE_BUS; i++) isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i], hd[MAX_IDE_DEVS * i], diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 1626db44ef..4094beb0ed 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -400,7 +400,7 @@ static void ppc_core99_init(MachineState *machine) macio_init(macio, pic_mem, escc_bar); /* We only emulate 2 out of 3 IDE controllers for now */ - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index be9a194038..ebd87fb8f5 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -278,7 +278,7 @@ static void ppc_heathrow_init(MachineState *machine) pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); dev = DEVICE(macio); diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index f0ef1af118..9f484cdcb8 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -519,7 +519,7 @@ static void ppc_prep_init(MachineState *machine) } } - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); for(i = 0; i < MAX_IDE_BUS; i++) { isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i], hd[2 * i], diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index 9c77e18244..871a0ea246 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -864,7 +864,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, for(i = 0; i < nb_nics; i++) pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); - ide_drive_get(hd, MAX_IDE_BUS); + ide_drive_get(hd, ARRAY_SIZE(hd)); pci_cmd646_ide_init(pci_bus, hd, 1); diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index a4033d4c29..09716de809 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -52,6 +52,7 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); bool drive_check_orphaned(void); DriveInfo *drive_get_by_index(BlockInterfaceType type, int index); int drive_get_max_bus(BlockInterfaceType type); +int drive_get_max_devs(BlockInterfaceType type); DriveInfo *drive_get_next(BlockInterfaceType type); DriveInfo *drive_get_by_blockdev(BlockDriverState *bs); -- 2.11.4.GIT