pc,pci,virtio,qdev fixes, tests

new tests for SMBIOS
 SMBIOS fixes
 pc, pci fixes
 qdev patches stayed on list for a month with no review,
 as I told people on KVM forum I'm merging stuch patches
 if they look fine.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJTkJ2iAAoJECgfDbjSjVRpk4oIALf6RC/Bm3bVaX5TSgqdt8UT
 4vCf10V53KkbfhxN9dGyPluswz/gyY7M/nrOoi0BSbrQndSavgyNRCfMfBfIw1FO
 yvfeyrkBkKBP4ViF6uogcSr79h3vQaXsqZIGmZUsdv3ZfVrLS+7dKsigVI6PumNR
 8YBveGljFjn0nrCC2+M2+LDefcPGSEu9vea9hKER0uPuz1mib8otjm1PAH30QeW/
 9q1bwFEwobFJk32vrayQrwGk5ECXCCHR8LPV1Rv9tyZLEqAbdiNrwGb4MycztLvK
 UHuvNFNqUHKNe/tqvp1RPmWOY2aO8+u0570kc8nhXXq2/tjJTOCmQfmodE6hh8A=
 =bwmA
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

pc,pci,virtio,qdev fixes, tests

new tests for SMBIOS
SMBIOS fixes
pc, pci fixes
qdev patches stayed on list for a month with no review,
as I told people on KVM forum I'm merging stuch patches
if they look fine.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

* remotes/mst/tags/for_upstream:
  qdev: Add test of qdev_prop_check_global
  qdev: Display warning about unused -global
  tests: add smbios testing
  tests: rename acpi-test to bios-tables-test
  virtio-balloon: return empty data when no stats are available
  pcie_host: Turn pcie_host_init() into an instance_init
  SMBIOS: Fix type 17 field sizes
  SMBIOS: Update Type 0 struct generator for machines >= 2.1
  SMBIOS: Fix endian-ness when populating multi-byte fields
  serial-pci: Set prog interface field of pci config to 16550 compatible

Conflicts:
	include/hw/i386/pc.h
[PMM: fixed trivial conflict in pc.h]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-06-05 21:52:37 +01:00
commit 26edf8cc08
18 changed files with 273 additions and 76 deletions

View File

@ -35,7 +35,8 @@ which will return a dictionary containing:
o A key named last-update, which contains the last stats update
timestamp in seconds. Since this timestamp is generated by the host,
a buggy guest can't influence its value
a buggy guest can't influence its value. The value is 0 if the guest
has not updated the stats (yet).
It's also important to note the following:
@ -49,7 +50,7 @@ It's also important to note the following:
- Polling can be enabled even if the guest doesn't have stats support
or the balloon driver wasn't loaded in the guest. If this is the case
and stats are queried, an error will be returned
and stats are queried, last-update will be 0.
- The polling timer is only re-armed when the guest responds to the
statistics request. This means that if a (buggy) guest doesn't ever

View File

@ -34,6 +34,7 @@
typedef struct PCISerialState {
PCIDevice dev;
SerialState state;
uint8_t prog_if;
} PCISerialState;
typedef struct PCIMultiSerialState {
@ -44,6 +45,7 @@ typedef struct PCIMultiSerialState {
SerialState state[PCI_SERIAL_MAX_PORTS];
uint32_t level[PCI_SERIAL_MAX_PORTS];
qemu_irq *irqs;
uint8_t prog_if;
} PCIMultiSerialState;
static int serial_pci_init(PCIDevice *dev)
@ -60,6 +62,7 @@ static int serial_pci_init(PCIDevice *dev)
return -1;
}
pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
s->irq = pci_allocate_irq(&pci->dev);
@ -101,6 +104,7 @@ static int multi_serial_pci_init(PCIDevice *dev)
assert(pci->ports > 0);
assert(pci->ports <= PCI_SERIAL_MAX_PORTS);
pci->dev.config[PCI_CLASS_PROG] = pci->prog_if;
pci->dev.config[PCI_INTERRUPT_PIN] = 0x01;
memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * pci->ports);
pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar);
@ -177,12 +181,14 @@ static const VMStateDescription vmstate_pci_multi_serial = {
static Property serial_pci_properties[] = {
DEFINE_PROP_CHR("chardev", PCISerialState, state.chr),
DEFINE_PROP_UINT8("prog_if", PCISerialState, prog_if, 0x02),
DEFINE_PROP_END_OF_LIST(),
};
static Property multi_2x_serial_pci_properties[] = {
DEFINE_PROP_CHR("chardev1", PCIMultiSerialState, state[0].chr),
DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02),
DEFINE_PROP_END_OF_LIST(),
};
@ -191,6 +197,7 @@ static Property multi_4x_serial_pci_properties[] = {
DEFINE_PROP_CHR("chardev2", PCIMultiSerialState, state[1].chr),
DEFINE_PROP_CHR("chardev3", PCIMultiSerialState, state[2].chr),
DEFINE_PROP_CHR("chardev4", PCIMultiSerialState, state[3].chr),
DEFINE_PROP_UINT8("prog_if", PCIMultiSerialState, prog_if, 0x02),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -439,11 +439,27 @@ PropertyInfo qdev_prop_iothread = {
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
{
GlobalProperty *g;
ObjectClass *oc;
g = g_malloc0(sizeof(*g));
g->driver = qemu_opt_get(opts, "driver");
g->property = qemu_opt_get(opts, "property");
g->value = qemu_opt_get(opts, "value");
oc = object_class_by_name(g->driver);
if (oc) {
DeviceClass *dc = DEVICE_CLASS(oc);
if (dc->hotpluggable) {
/* If hotpluggable then skip not_used checking. */
g->not_used = false;
} else {
/* Maybe a typo. */
g->not_used = true;
}
} else {
/* Maybe a typo. */
g->not_used = true;
}
qdev_prop_register_global(g);
return 0;
}

View File

@ -955,6 +955,23 @@ void qdev_prop_register_global_list(GlobalProperty *props)
}
}
int qdev_prop_check_global(void)
{
GlobalProperty *prop;
int ret = 0;
QTAILQ_FOREACH(prop, &global_props, next) {
if (!prop->not_used) {
continue;
}
ret = 1;
error_report("Warning: \"-global %s.%s=%s\" not used",
prop->driver, prop->property, prop->value);
}
return ret;
}
void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
Error **errp)
{
@ -966,6 +983,7 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
if (strcmp(typename, prop->driver) != 0) {
continue;
}
prop->not_used = false;
object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
if (err != NULL) {
error_propagate(errp, err);

View File

@ -67,7 +67,7 @@ static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1);
static struct {
const char *vendor, *version, *date;
bool have_major_minor;
bool have_major_minor, uefi;
uint8_t major, minor;
} type0;
@ -134,6 +134,10 @@ static const QemuOptDesc qemu_smbios_type0_opts[] = {
.name = "release",
.type = QEMU_OPT_STRING,
.help = "revision number",
},{
.name = "uefi",
.type = QEMU_OPT_BOOL,
.help = "uefi support",
},
{ /* end of list */ }
};
@ -444,7 +448,7 @@ static bool smbios_skip_table(uint8_t type, bool required_table)
\
t->header.type = tbl_type; \
t->header.length = sizeof(*t); \
t->header.handle = tbl_handle; \
t->header.handle = cpu_to_le16(tbl_handle); \
} while (0)
#define SMBIOS_TABLE_SET_STR(tbl_type, field, value) \
@ -491,19 +495,18 @@ static void smbios_build_type_0_table(void)
SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor);
SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version);
t->bios_starting_address_segment = 0xE800; /* hardcoded in SeaBIOS */
t->bios_starting_address_segment = cpu_to_le16(0xE800); /* from SeaBIOS */
SMBIOS_TABLE_SET_STR(0, bios_release_date_str, type0.date);
t->bios_rom_size = 0; /* hardcoded in SeaBIOS with FIXME comment */
/* BIOS characteristics not supported */
memset(t->bios_characteristics, 0, 8);
t->bios_characteristics[0] = 0x08;
/* Enable targeted content distribution (needed for SVVP, per SeaBIOS) */
t->bios_characteristics = cpu_to_le64(0x08); /* Not supported */
t->bios_characteristics_extension_bytes[0] = 0;
t->bios_characteristics_extension_bytes[1] = 4;
t->bios_characteristics_extension_bytes[1] = 0x14; /* TCD/SVVP | VM */
if (type0.uefi) {
t->bios_characteristics_extension_bytes[1] |= 0x08; /* |= UEFI */
}
if (type0.have_major_minor) {
t->system_bios_major_release = type0.major;
@ -551,7 +554,7 @@ static void smbios_build_type_2_table(void)
SMBIOS_TABLE_SET_STR(2, asset_tag_number_str, type2.asset);
t->feature_flags = 0x01; /* Motherboard */
SMBIOS_TABLE_SET_STR(2, location_str, type2.location);
t->chassis_handle = 0x300; /* Type 3 (System enclosure) */
t->chassis_handle = cpu_to_le16(0x300); /* Type 3 (System enclosure) */
t->board_type = 0x0A; /* Motherboard */
t->contained_element_count = 0;
@ -571,7 +574,7 @@ static void smbios_build_type_3_table(void)
t->power_supply_state = 0x03; /* Safe */
t->thermal_state = 0x03; /* Safe */
t->security_status = 0x02; /* Unknown */
t->oem_defined = 0;
t->oem_defined = cpu_to_le32(0);
t->height = 0;
t->number_of_power_cords = 0;
t->contained_element_count = 0;
@ -589,26 +592,27 @@ static void smbios_build_type_4_table(unsigned instance)
snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance);
SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str);
t->processor_type = 0x03; /* CPU */
t->processor_family = 0x01; /* Other */
SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer);
t->processor_id[0] = smbios_cpuid_version;
t->processor_id[1] = smbios_cpuid_features;
t->processor_id[0] = cpu_to_le32(smbios_cpuid_version);
t->processor_id[1] = cpu_to_le32(smbios_cpuid_features);
SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
t->voltage = 0;
t->external_clock = 0; /* Unknown */
t->max_speed = 0; /* Unknown */
t->current_speed = 0; /* Unknown */
t->external_clock = cpu_to_le16(0); /* Unknown */
t->max_speed = cpu_to_le16(0); /* Unknown */
t->current_speed = cpu_to_le16(0); /* Unknown */
t->status = 0x41; /* Socket populated, CPU enabled */
t->processor_upgrade = 0x01; /* Other */
t->l1_cache_handle = 0xFFFF; /* N/A */
t->l2_cache_handle = 0xFFFF; /* N/A */
t->l3_cache_handle = 0xFFFF; /* N/A */
t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
t->l2_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
t->l3_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
SMBIOS_TABLE_SET_STR(4, serial_number_str, type4.serial);
SMBIOS_TABLE_SET_STR(4, asset_tag_number_str, type4.asset);
SMBIOS_TABLE_SET_STR(4, part_number_str, type4.part);
t->core_count = t->core_enabled = smp_cores;
t->thread_count = smp_threads;
t->processor_characteristics = 0x02; /* Unknown */
t->processor_family = t->processor_family2 = 0x01; /* Other */
t->processor_characteristics = cpu_to_le16(0x02); /* Unknown */
t->processor_family2 = cpu_to_le16(0x01); /* Other */
SMBIOS_BUILD_TABLE_POST;
smbios_type4_count++;
@ -631,14 +635,14 @@ static void smbios_build_type_16_table(unsigned dimm_cnt)
t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */
size_kb = QEMU_ALIGN_UP(ram_size, ONE_KB) / ONE_KB;
if (size_kb < MAX_T16_STD_SZ) {
t->maximum_capacity = size_kb;
t->extended_maximum_capacity = 0;
t->maximum_capacity = cpu_to_le32(size_kb);
t->extended_maximum_capacity = cpu_to_le64(0);
} else {
t->maximum_capacity = MAX_T16_STD_SZ;
t->extended_maximum_capacity = ram_size;
t->maximum_capacity = cpu_to_le32(MAX_T16_STD_SZ);
t->extended_maximum_capacity = cpu_to_le64(ram_size);
}
t->memory_error_information_handle = 0xFFFE; /* Not provided */
t->number_of_memory_devices = dimm_cnt;
t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
t->number_of_memory_devices = cpu_to_le16(dimm_cnt);
SMBIOS_BUILD_TABLE_POST;
}
@ -653,18 +657,18 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
t->physical_memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
t->memory_error_information_handle = 0xFFFE; /* Not provided */
t->total_width = 0xFFFF; /* Unknown */
t->data_width = 0xFFFF; /* Unknown */
t->physical_memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
t->total_width = cpu_to_le16(0xFFFF); /* Unknown */
t->data_width = cpu_to_le16(0xFFFF); /* Unknown */
size_mb = QEMU_ALIGN_UP(size, ONE_MB) / ONE_MB;
if (size_mb < MAX_T17_STD_SZ) {
t->size = size_mb;
t->extended_size = 0;
t->size = cpu_to_le16(size_mb);
t->extended_size = cpu_to_le32(0);
} else {
assert(size_mb < MAX_T17_EXT_SZ);
t->size = MAX_T17_STD_SZ;
t->extended_size = size_mb;
t->size = cpu_to_le16(MAX_T17_STD_SZ);
t->extended_size = cpu_to_le32(size_mb);
}
t->form_factor = 0x09; /* DIMM */
t->device_set = 0; /* Not in a set */
@ -672,17 +676,17 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size)
SMBIOS_TABLE_SET_STR(17, device_locator_str, loc_str);
SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank);
t->memory_type = 0x07; /* RAM */
t->type_detail = 0x02; /* Other */
t->speed = 0; /* Unknown */
t->type_detail = cpu_to_le16(0x02); /* Other */
t->speed = cpu_to_le16(0); /* Unknown */
SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer);
SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial);
SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset);
SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part);
t->attributes = 0; /* Unknown */
t->configured_clock_speed = 0; /* Unknown */
t->minimum_voltage = 0; /* Unknown */
t->maximum_voltage = 0; /* Unknown */
t->configured_voltage = 0; /* Unknown */
t->configured_clock_speed = cpu_to_le16(0); /* Unknown */
t->minimum_voltage = cpu_to_le16(0); /* Unknown */
t->maximum_voltage = cpu_to_le16(0); /* Unknown */
t->configured_voltage = cpu_to_le16(0); /* Unknown */
SMBIOS_BUILD_TABLE_POST;
}
@ -699,15 +703,16 @@ static void smbios_build_type_19_table(unsigned instance,
start_kb = start / ONE_KB;
end_kb = end / ONE_KB;
if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) {
t->starting_address = start_kb;
t->ending_address = end_kb;
t->extended_starting_address = t->extended_ending_address = 0;
t->starting_address = cpu_to_le32(start_kb);
t->ending_address = cpu_to_le32(end_kb);
t->extended_starting_address =
t->extended_ending_address = cpu_to_le64(0);
} else {
t->starting_address = t->ending_address = UINT32_MAX;
t->extended_starting_address = start;
t->extended_ending_address = end;
t->starting_address = t->ending_address = cpu_to_le32(UINT32_MAX);
t->extended_starting_address = cpu_to_le64(start);
t->extended_ending_address = cpu_to_le64(end);
}
t->memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */
t->memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
t->partition_width = 1; /* One device per row */
SMBIOS_BUILD_TABLE_POST;
@ -794,14 +799,14 @@ static void smbios_entry_point_setup(void)
ep.smbios_bcd_revision = 0x28;
/* set during table construction, but BIOS may override: */
ep.structure_table_length = smbios_tables_len;
ep.max_structure_size = smbios_table_max;
ep.number_of_structures = smbios_table_cnt;
ep.structure_table_length = cpu_to_le16(smbios_tables_len);
ep.max_structure_size = cpu_to_le16(smbios_table_max);
ep.number_of_structures = cpu_to_le16(smbios_table_cnt);
/* BIOS must recalculate: */
ep.checksum = 0;
ep.intermediate_checksum = 0;
ep.structure_table_address = 0; /* where BIOS has copied smbios_tables */
ep.structure_table_address = cpu_to_le32(0);
}
void smbios_get_tables(uint8_t **tables, size_t *tables_len,
@ -977,6 +982,7 @@ void smbios_entry_add(QemuOpts *opts)
save_opt(&type0.vendor, opts, "vendor");
save_opt(&type0.version, opts, "version");
save_opt(&type0.date, opts, "date");
type0.uefi = qemu_opt_get_bool(opts, "uefi", false);
val = qemu_opt_get(opts, "release");
if (val) {

View File

@ -47,10 +47,6 @@ static void q35_host_realize(DeviceState *dev, Error **errp)
sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
if (pcie_host_init(PCIE_HOST_BRIDGE(s)) < 0) {
error_setg(errp, "failed to initialize pcie host");
return;
}
pci->bus = pci_bus_new(DEVICE(s), "pcie.0",
s->mch.pci_address_space, s->mch.address_space_io,
0, TYPE_PCIE_BUS);

View File

@ -83,11 +83,11 @@ static const MemoryRegionOps pcie_mmcfg_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
int pcie_host_init(PCIExpressHost *e)
static void pcie_host_init(Object *obj)
{
e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
return 0;
e->base_addr = PCIE_BASE_ADDR_UNMAPPED;
}
void pcie_host_mmcfg_unmap(PCIExpressHost *e)
@ -128,6 +128,7 @@ static const TypeInfo pcie_host_type_info = {
.parent = TYPE_PCI_HOST_BRIDGE,
.abstract = true,
.instance_size = sizeof(PCIExpressHost),
.instance_init = pcie_host_init,
};
static void pcie_host_register_types(void)

View File

@ -112,11 +112,6 @@ static void balloon_stats_get_all(Object *obj, struct Visitor *v,
VirtIOBalloon *s = opaque;
int i;
if (!s->stats_last_update) {
error_setg(errp, "guest hasn't updated any stats yet");
return;
}
visit_start_struct(v, NULL, "guest-stats", name, 0, &err);
if (err) {
goto out;
@ -378,6 +373,8 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
s->dvq = virtio_add_queue(vdev, 128, virtio_balloon_handle_output);
s->svq = virtio_add_queue(vdev, 128, virtio_balloon_receive_stats);
reset_stats(s);
register_savevm(dev, "virtio-balloon", -1, 1,
virtio_balloon_save, virtio_balloon_load, s);

View File

@ -275,6 +275,21 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
.driver = "nec-usb-xhci",\
.property = "superspeed-ports-first",\
.value = "off",\
},\
{\
.driver = "pci-serial",\
.property = "prog_if",\
.value = stringify(0),\
},\
{\
.driver = "pci-serial-2x",\
.property = "prof_if",\
.value = stringify(0),\
},\
{\
.driver = "pci-serial-4x",\
.property = "prog_if",\
.value = stringify(0),\
}
#define PC_COMPAT_1_7 \

View File

@ -64,7 +64,7 @@ struct smbios_type_0 {
uint16_t bios_starting_address_segment;
uint8_t bios_release_date_str;
uint8_t bios_rom_size;
uint8_t bios_characteristics[8];
uint64_t bios_characteristics;
uint8_t bios_characteristics_extension_bytes[2];
uint8_t system_bios_major_release;
uint8_t system_bios_minor_release;
@ -182,10 +182,10 @@ struct smbios_type_17 {
uint8_t part_number_str;
uint8_t attributes;
uint32_t extended_size;
uint32_t configured_clock_speed;
uint32_t minimum_voltage;
uint32_t maximum_voltage;
uint32_t configured_voltage;
uint16_t configured_clock_speed;
uint16_t minimum_voltage;
uint16_t maximum_voltage;
uint16_t configured_voltage;
} QEMU_PACKED;
/* SMBIOS type 19 - Memory Array Mapped Address (v2.7) */

View File

@ -49,7 +49,6 @@ struct PCIExpressHost {
MemoryRegion mmio;
};
int pcie_host_init(PCIExpressHost *e);
void pcie_host_mmcfg_unmap(PCIExpressHost *e);
void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, uint32_t size);
void pcie_host_mmcfg_update(PCIExpressHost *e,

View File

@ -239,10 +239,18 @@ struct PropertyInfo {
ObjectPropertyRelease *release;
};
/**
* GlobalProperty:
* @not_used: Track use of a global property. Defaults to false in all C99
* struct initializations.
*
* This prevents reports of .compat_props when they are not used.
*/
typedef struct GlobalProperty {
const char *driver;
const char *property;
const char *value;
bool not_used;
QTAILQ_ENTRY(GlobalProperty) next;
} GlobalProperty;

View File

@ -180,6 +180,7 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
void qdev_prop_register_global(GlobalProperty *prop);
void qdev_prop_register_global_list(GlobalProperty *props);
int qdev_prop_check_global(void);
void qdev_prop_set_globals(DeviceState *dev, Error **errp);
void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
Error **errp);

View File

@ -1341,7 +1341,7 @@ ETEXI
DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
"-smbios file=binary\n"
" load SMBIOS entry from binary file\n"
"-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d]\n"
"-smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d][,uefi=on|off]\n"
" specify SMBIOS type 0 fields\n"
"-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]\n"
" [,uuid=uuid][,sku=str][,family=str]\n"
@ -1351,7 +1351,7 @@ STEXI
@findex -smbios
Load SMBIOS entry from binary file.
@item -smbios type=0[,vendor=@var{str}][,version=@var{str}][,date=@var{str}][,release=@var{%d.%d}]
@item -smbios type=0[,vendor=@var{str}][,version=@var{str}][,date=@var{str}][,release=@var{%d.%d}][,uefi=on|off]
Specify SMBIOS type 0 fields
@item -smbios type=1[,manufacturer=@var{str}][,product=@var{str}] [,version=@var{str}][,serial=@var{str}][,uuid=@var{uuid}][,sku=@var{str}] [,family=@var{str}]

View File

@ -133,7 +133,7 @@ check-qtest-i386-y += tests/ide-test$(EXESUF)
check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
gcov-files-i386-y += hw/block/hd-geometry.c
check-qtest-i386-y += tests/boot-order-test$(EXESUF)
check-qtest-i386-y += tests/acpi-test$(EXESUF)
check-qtest-i386-y += tests/bios-tables-test$(EXESUF)
check-qtest-i386-y += tests/rtc-test$(EXESUF)
check-qtest-i386-y += tests/i440fx-test$(EXESUF)
check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
@ -290,7 +290,7 @@ tests/fdc-test$(EXESUF): tests/fdc-test.o
tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
tests/acpi-test$(EXESUF): tests/acpi-test.o $(libqos-obj-y)
tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)

View File

@ -18,6 +18,8 @@
#include "libqtest.h"
#include "qemu/compiler.h"
#include "hw/i386/acpi-defs.h"
#include "hw/i386/smbios.h"
#include "qemu/bitmap.h"
#define MACHINE_PC "pc"
#define MACHINE_Q35 "q35"
@ -46,6 +48,8 @@ typedef struct {
uint32_t *rsdt_tables_addr;
int rsdt_tables_nr;
GArray *tables;
uint32_t smbios_ep_addr;
struct smbios_entry_point smbios_ep_table;
} test_data;
#define LOW(x) ((x) & 0xff)
@ -581,6 +585,124 @@ static void test_acpi_asl(test_data *data)
free_test_data(&exp_data);
}
static void test_smbios_ep_address(test_data *data)
{
uint32_t off;
/* find smbios entry point structure */
for (off = 0xf0000; off < 0x100000; off += 0x10) {
uint8_t sig[] = "_SM_";
int i;
for (i = 0; i < sizeof sig - 1; ++i) {
sig[i] = readb(off + i);
}
if (!memcmp(sig, "_SM_", sizeof sig)) {
break;
}
}
g_assert_cmphex(off, <, 0x100000);
data->smbios_ep_addr = off;
}
static void test_smbios_ep_table(test_data *data)
{
struct smbios_entry_point *ep_table = &data->smbios_ep_table;
uint32_t addr = data->smbios_ep_addr;
ACPI_READ_ARRAY(ep_table->anchor_string, addr);
g_assert(!memcmp(ep_table->anchor_string, "_SM_", 4));
ACPI_READ_FIELD(ep_table->checksum, addr);
ACPI_READ_FIELD(ep_table->length, addr);
ACPI_READ_FIELD(ep_table->smbios_major_version, addr);
ACPI_READ_FIELD(ep_table->smbios_minor_version, addr);
ACPI_READ_FIELD(ep_table->max_structure_size, addr);
ACPI_READ_FIELD(ep_table->entry_point_revision, addr);
ACPI_READ_ARRAY(ep_table->formatted_area, addr);
ACPI_READ_ARRAY(ep_table->intermediate_anchor_string, addr);
g_assert(!memcmp(ep_table->intermediate_anchor_string, "_DMI_", 5));
ACPI_READ_FIELD(ep_table->intermediate_checksum, addr);
ACPI_READ_FIELD(ep_table->structure_table_length, addr);
g_assert_cmpuint(ep_table->structure_table_length, >, 0);
ACPI_READ_FIELD(ep_table->structure_table_address, addr);
ACPI_READ_FIELD(ep_table->number_of_structures, addr);
g_assert_cmpuint(ep_table->number_of_structures, >, 0);
ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr);
g_assert(!acpi_checksum((uint8_t *)ep_table, sizeof *ep_table));
g_assert(!acpi_checksum((uint8_t *)ep_table + 0x10,
sizeof *ep_table - 0x10));
}
static inline bool smbios_single_instance(uint8_t type)
{
switch (type) {
case 0:
case 1:
case 2:
case 3:
case 16:
case 32:
case 127:
return true;
default:
return false;
}
}
static void test_smbios_structs(test_data *data)
{
DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 };
struct smbios_entry_point *ep_table = &data->smbios_ep_table;
uint32_t addr = ep_table->structure_table_address;
int i, len, max_len = 0;
uint8_t type, prv, crt;
uint8_t required_struct_types[] = {0, 1, 3, 4, 16, 17, 19, 32, 127};
/* walk the smbios tables */
for (i = 0; i < ep_table->number_of_structures; i++) {
/* grab type and formatted area length from struct header */
type = readb(addr);
g_assert_cmpuint(type, <=, SMBIOS_MAX_TYPE);
len = readb(addr + 1);
/* single-instance structs must not have been encountered before */
if (smbios_single_instance(type)) {
g_assert(!test_bit(type, struct_bitmap));
}
set_bit(type, struct_bitmap);
/* seek to end of unformatted string area of this struct ("\0\0") */
prv = crt = 1;
while (prv || crt) {
prv = crt;
crt = readb(addr + len);
len++;
}
/* keep track of max. struct size */
if (max_len < len) {
max_len = len;
g_assert_cmpuint(max_len, <=, ep_table->max_structure_size);
}
/* start of next structure */
addr += len;
}
/* total table length and max struct size must match entry point values */
g_assert_cmpuint(ep_table->structure_table_length, ==,
addr - ep_table->structure_table_address);
g_assert_cmpuint(ep_table->max_structure_size, ==, max_len);
/* required struct types must all be present */
for (i = 0; i < ARRAY_SIZE(required_struct_types); i++) {
g_assert(test_bit(required_struct_types[i], struct_bitmap));
}
}
static void test_acpi_one(const char *params, test_data *data)
{
char *args;
@ -633,6 +755,10 @@ static void test_acpi_one(const char *params, test_data *data)
}
}
test_smbios_ep_address(data);
test_smbios_ep_table(data);
test_smbios_structs(data);
qtest_quit(global_qtest);
g_free(args);
}

View File

@ -150,8 +150,10 @@ static void test_dynamic_globalprop(void)
static GlobalProperty props[] = {
{ TYPE_DYNAMIC_PROPS, "prop1", "101" },
{ TYPE_DYNAMIC_PROPS, "prop2", "102" },
{ TYPE_DYNAMIC_PROPS"-bad", "prop3", "103", true },
{}
};
int all_used;
qdev_prop_register_global_list(props);
@ -160,6 +162,8 @@ static void test_dynamic_globalprop(void)
g_assert_cmpuint(mt->prop1, ==, 101);
g_assert_cmpuint(mt->prop2, ==, 102);
all_used = qdev_prop_check_global();
g_assert_cmpuint(all_used, ==, 1);
}
int main(int argc, char **argv)

2
vl.c
View File

@ -4541,6 +4541,8 @@ int main(int argc, char **argv, char **envp)
}
}
qdev_prop_check_global();
if (incoming) {
Error *local_err = NULL;
qemu_start_incoming_migration(incoming, &local_err);