Skip to content

Commit

Permalink
hw/i386/pc_piix: Make PIIX4 south bridge usable in PC machine
Browse files Browse the repository at this point in the history
QEMU's PIIX3 implementation actually models the real PIIX4, but with different
PCI IDs. Usually, guests deal just fine with it. Still, in order to provide a
more consistent illusion to guests, allow QEMU's PIIX4 implementation to be used
in the PC machine.

Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Message-Id: <20231007123843.127151-30-shentey@gmail.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
shentok authored and mstsirkin committed Oct 18, 2023
1 parent 461585e commit 8b15292
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 1 deletion.
8 changes: 8 additions & 0 deletions docs/system/target-i386-desc.rst.inc
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,11 @@ machine property, i.e.
|qemu_system_x86| some.img \
-audiodev <backend>,id=<name> \
-machine pcspk-audiodev=<name>

Machine-specific options
~~~~~~~~~~~~~~~~~~~~~~~~

It supports the following machine-specific options:

- ``x-south-bridge=PIIX3|piix4-isa`` (Experimental option to select a particular
south bridge. Default: ``PIIX3``)
1 change: 1 addition & 0 deletions hw/i386/pc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1706,6 +1706,7 @@ static void pc_machine_initfn(Object *obj)
#endif /* CONFIG_VMPORT */
pcms->max_ram_below_4g = 0; /* use default */
pcms->smbios_entry_point_type = pcmc->default_smbios_ep_type;
pcms->south_bridge = pcmc->default_south_bridge;

/* acpi build is enabled by default if machine supports it */
pcms->acpi_build_enabled = pcmc->has_acpi_build;
Expand Down
61 changes: 60 additions & 1 deletion hw/i386/pc_piix.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ static void pc_init1(MachineState *machine,
DeviceState *dev;
size_t i;

pci_dev = pci_new_multifunction(-1, TYPE_PIIX3_DEVICE);
pci_dev = pci_new_multifunction(-1, pcms->south_bridge);
object_property_set_bool(OBJECT(pci_dev), "has-usb",
machine_usb(machine), &error_abort);
object_property_set_bool(OBJECT(pci_dev), "has-acpi",
Expand Down Expand Up @@ -394,6 +394,56 @@ static void pc_init1(MachineState *machine,
}
}

typedef enum PCSouthBridgeOption {
PC_SOUTH_BRIDGE_OPTION_PIIX3,
PC_SOUTH_BRIDGE_OPTION_PIIX4,
PC_SOUTH_BRIDGE_OPTION_MAX,
} PCSouthBridgeOption;

static const QEnumLookup PCSouthBridgeOption_lookup = {
.array = (const char *const[]) {
[PC_SOUTH_BRIDGE_OPTION_PIIX3] = TYPE_PIIX3_DEVICE,
[PC_SOUTH_BRIDGE_OPTION_PIIX4] = TYPE_PIIX4_PCI_DEVICE,
},
.size = PC_SOUTH_BRIDGE_OPTION_MAX
};

#define NotifyVmexitOption_str(val) \
qapi_enum_lookup(&NotifyVmexitOption_lookup, (val))

static int pc_get_south_bridge(Object *obj, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
int i;

for (i = 0; i < PCSouthBridgeOption_lookup.size; i++) {
if (g_strcmp0(PCSouthBridgeOption_lookup.array[i],
pcms->south_bridge) == 0) {
return i;
}
}

error_setg(errp, "Invalid south bridge value set");
return 0;
}

static void pc_set_south_bridge(Object *obj, int value, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);

if (value < 0) {
error_setg(errp, "Value can't be negative");
return;
}

if (value >= PCSouthBridgeOption_lookup.size) {
error_setg(errp, "Value too big");
return;
}

pcms->south_bridge = PCSouthBridgeOption_lookup.array[value];
}

/* Looking for a pc_compat_2_4() function? It doesn't exist.
* pc_compat_*() functions that run on machine-init time and
* change global QEMU state are deprecated. Please don't create
Expand Down Expand Up @@ -473,6 +523,8 @@ static void pc_xen_hvm_init(MachineState *machine)
static void pc_i440fx_machine_options(MachineClass *m)
{
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
ObjectClass *oc = OBJECT_CLASS(m);
pcmc->default_south_bridge = TYPE_PIIX3_DEVICE;
pcmc->pci_root_uid = 0;
pcmc->default_cpu_version = 1;

Expand All @@ -484,6 +536,13 @@ static void pc_i440fx_machine_options(MachineClass *m)
m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL);
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);

object_class_property_add_enum(oc, "x-south-bridge", "PCSouthBridgeOption",
&PCSouthBridgeOption_lookup,
pc_get_south_bridge,
pc_set_south_bridge);
object_class_property_set_description(oc, "x-south-bridge",
"Use a different south bridge than PIIX3");
}

static void pc_i440fx_8_2_machine_options(MachineClass *m)
Expand Down
2 changes: 2 additions & 0 deletions include/hw/i386/pc.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ typedef struct PCMachineState {
uint64_t max_ram_below_4g;
OnOffAuto vmport;
SmbiosEntryPointType smbios_entry_point_type;
const char *south_bridge;

bool acpi_build_enabled;
bool smbus_enabled;
Expand Down Expand Up @@ -92,6 +93,7 @@ struct PCMachineClass {
/* Device configuration: */
bool pci_enabled;
bool kvmclock_enabled;
const char *default_south_bridge;

/* Compat options: */

Expand Down

0 comments on commit 8b15292

Please sign in to comment.