vmm/amd: improve iteration over IVHD (type 10h) entries in IVRS table
Many 8-byte entries have zero at byte 4, so the second 4-byte part is skipped as a 4-byte padding entry. But not all 8-byte entries have that property and they get misinterpreted. A real example: 48 00 00 00 ff 01 00 01 This an 8-byte ACPI_IVRS_TYPE_SPECIAL entry for IOAPIC with ID 255 (bogus). It is reported as: ivhd0: Unknown dev entry:0xff Fortunately, it was completely harmless. Also, bail out early if we encounter an entry of a variable length type. We do not have proper handling for those yet. Reviewed by: anish
This commit is contained in:
parent
d72d8662c0
commit
58c07c5a95
@ -186,7 +186,8 @@ ivhd_dev_add_entry(struct amdvi_softc *softc, uint32_t start_id,
|
||||
static int
|
||||
ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi_softc *softc)
|
||||
{
|
||||
ACPI_IVRS_DE_HEADER *de, *end;
|
||||
ACPI_IVRS_DE_HEADER *de;
|
||||
uint8_t *p, *end;
|
||||
int range_start_id = 0, range_end_id = 0;
|
||||
uint32_t *extended;
|
||||
uint8_t all_data = 0, range_data = 0;
|
||||
@ -195,12 +196,15 @@ ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi_softc *softc)
|
||||
softc->start_dev_rid = ~0;
|
||||
softc->end_dev_rid = 0;
|
||||
|
||||
de = (ACPI_IVRS_DE_HEADER *) ((uint8_t *)ivhd +
|
||||
sizeof(ACPI_IVRS_HARDWARE));
|
||||
end = (ACPI_IVRS_DE_HEADER *) ((uint8_t *)ivhd +
|
||||
ivhd->Header.Length);
|
||||
/*
|
||||
* XXX The following actually depends on Header.Type and
|
||||
* is only true for 0x10.
|
||||
*/
|
||||
p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE);
|
||||
end = (uint8_t *)ivhd + ivhd->Header.Length;
|
||||
|
||||
while (de < (ACPI_IVRS_DE_HEADER *) end) {
|
||||
while (p < end) {
|
||||
de = (ACPI_IVRS_DE_HEADER *)p;
|
||||
softc->start_dev_rid = MIN(softc->start_dev_rid, de->Id);
|
||||
softc->end_dev_rid = MAX(softc->end_dev_rid, de->Id);
|
||||
switch (de->Type) {
|
||||
@ -263,7 +267,15 @@ ivhd_dev_parse(ACPI_IVRS_HARDWARE * ivhd, struct amdvi_softc *softc)
|
||||
"WARN Too many device entries.\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
de++;
|
||||
if (de->Type < 0x40)
|
||||
p += sizeof(ACPI_IVRS_DEVICE4);
|
||||
else if (de->Type < 0x80)
|
||||
p += sizeof(ACPI_IVRS_DEVICE8A);
|
||||
else {
|
||||
printf("Variable size IVHD type 0x%x not supported\n",
|
||||
de->Type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
KASSERT((softc->end_dev_rid >= softc->start_dev_rid),
|
||||
|
Loading…
Reference in New Issue
Block a user