Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144317333
D30827.id91997.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D30827.id91997.diff
View Options
Index: sys/amd64/vmm/amd/amdvi_hw.c
===================================================================
--- sys/amd64/vmm/amd/amdvi_hw.c
+++ sys/amd64/vmm/amd/amdvi_hw.c
@@ -809,11 +809,11 @@
cfg = softc->dev_cfg;
for (i = 0; i < softc->dev_cfg_cnt; i++) {
- device_printf(softc->dev, "device [0x%x - 0x%x]"
+ device_printf(softc->dev, "device [0x%x - 0x%x] "
"config:%b%s\n", cfg->start_id, cfg->end_id,
cfg->data,
"\020\001INIT\002ExtInt\003NMI"
- "\007LINT0\008LINT1",
+ "\007LINT0\010LINT1",
cfg->enable_ats ? "ATS enabled" : "");
cfg++;
}
@@ -874,10 +874,6 @@
&softc->total_cmd, "Command submitted count");
SYSCTL_ADD_U16(ctx, child, OID_AUTO, "pci_rid", CTLFLAG_RD,
&softc->pci_rid, 0, "IOMMU RID");
- SYSCTL_ADD_U16(ctx, child, OID_AUTO, "start_dev_rid", CTLFLAG_RD,
- &softc->start_dev_rid, 0, "Start of device under this IOMMU");
- SYSCTL_ADD_U16(ctx, child, OID_AUTO, "end_dev_rid", CTLFLAG_RD,
- &softc->end_dev_rid, 0, "End of device under this IOMMU");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "command_head",
CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 0,
amdvi_handle_sysctl, "IU", "Command head");
@@ -1204,22 +1200,17 @@
amdvi_find_iommu(uint16_t devid)
{
struct amdvi_softc *softc;
- int i;
+ int i, j;
for (i = 0; i < ivhd_count; i++) {
softc = device_get_softc(ivhd_devs[i]);
- if ((devid >= softc->start_dev_rid) &&
- (devid <= softc->end_dev_rid))
- return (softc);
+ for (j = 0; j < softc->dev_cfg_cnt; j++)
+ if ((devid >= softc->dev_cfg[j].start_id) &&
+ (devid <= softc->dev_cfg[j].end_id))
+ return (softc);
}
- /*
- * XXX: BIOS bug, device not in IVRS table, assume its from first IOMMU.
- */
- printf("BIOS bug device(%d.%d.%d) doesn't have IVHD entry.\n",
- RID2PCI_STR(devid));
-
- return (device_get_softc(ivhd_devs[0]));
+ return (NULL);
}
/*
@@ -1228,14 +1219,12 @@
* be set concurrently, e.g. read and write bits.
*/
static void
-amdvi_set_dte(struct amdvi_domain *domain, uint16_t devid, bool enable)
+amdvi_set_dte(struct amdvi_domain *domain, struct amdvi_softc *softc,
+ uint16_t devid, bool enable)
{
- struct amdvi_softc *softc;
struct amdvi_dte* temp;
KASSERT(domain, ("domain is NULL for pci_rid:0x%x\n", devid));
-
- softc = amdvi_find_iommu(devid);
KASSERT(softc, ("softc is NULL for pci_rid:0x%x\n", devid));
temp = &amdvi_dte[devid];
@@ -1269,11 +1258,8 @@
}
static void
-amdvi_inv_device(uint16_t devid)
+amdvi_inv_device(struct amdvi_softc *softc, uint16_t devid)
{
- struct amdvi_softc *softc;
-
- softc = amdvi_find_iommu(devid);
KASSERT(softc, ("softc is NULL"));
amdvi_cmd_inv_dte(softc, devid);
@@ -1288,6 +1274,7 @@
amdvi_add_device(void *arg, uint16_t devid)
{
struct amdvi_domain *domain;
+ struct amdvi_softc *softc;
domain = (struct amdvi_domain *)arg;
KASSERT(domain != NULL, ("domain is NULL"));
@@ -1295,22 +1282,29 @@
printf("Assigning device(%d.%d.%d) to domain:%d\n",
RID2PCI_STR(devid), domain->id);
#endif
- amdvi_set_dte(domain, devid, true);
- amdvi_inv_device(devid);
+ softc = amdvi_find_iommu(devid);
+ if (softc == NULL)
+ return;
+ amdvi_set_dte(domain, softc, devid, true);
+ amdvi_inv_device(softc, devid);
}
static void
amdvi_remove_device(void *arg, uint16_t devid)
{
struct amdvi_domain *domain;
+ struct amdvi_softc *softc;
domain = (struct amdvi_domain *)arg;
#ifdef AMDVI_DEBUG_CMD
printf("Remove device(0x%x) from domain:%d\n",
devid, domain->id);
#endif
- amdvi_set_dte(domain, devid, false);
- amdvi_inv_device(devid);
+ softc = amdvi_find_iommu(devid);
+ if (softc == NULL)
+ return;
+ amdvi_set_dte(domain, softc, devid, false);
+ amdvi_inv_device(softc, devid);
}
static void
Index: sys/amd64/vmm/amd/amdvi_priv.h
===================================================================
--- sys/amd64/vmm/amd/amdvi_priv.h
+++ sys/amd64/vmm/amd/amdvi_priv.h
@@ -2,7 +2,10 @@
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2016 Anish Gupta (anish@freebsd.org)
- * All rights reserved.
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Ka Ho Ng
+ * under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -392,13 +395,11 @@
uint8_t pci_cap; /* PCI capability. */
uint16_t pci_seg; /* IOMMU PCI domain/segment. */
uint16_t pci_rid; /* PCI BDF of IOMMU */
- /* Device range under this IOMMU. */
- uint16_t start_dev_rid; /* First device under this IOMMU. */
- uint16_t end_dev_rid; /* Last device under this IOMMU. */
- /* BIOS provided device configuration for end points. */
- struct ivhd_dev_cfg dev_cfg[10];
+ /* ACPI device configuration for end points. */
+ struct ivhd_dev_cfg *dev_cfg;
int dev_cfg_cnt;
+ int dev_cfg_cap;
/* Software statistics. */
uint64_t event_intr_cnt; /* Total event INTR count. */
Index: sys/amd64/vmm/amd/ivrs_drv.c
===================================================================
--- sys/amd64/vmm/amd/ivrs_drv.c
+++ sys/amd64/vmm/amd/ivrs_drv.c
@@ -184,9 +184,17 @@
{
struct ivhd_dev_cfg *dev_cfg;
- /* If device doesn't have special data, don't add it. */
- if (!cfg)
- return;
+ KASSERT(softc->dev_cfg_cap <= softc->dev_cfg_cnt,
+ ("Impossible case: number of dev_cfg exceeding capacity"));
+ if (softc->dev_cfg_cap == softc->dev_cfg_cnt) {
+ if (softc->dev_cfg_cap == 0)
+ softc->dev_cfg_cap <<= 2;
+ else
+ softc->dev_cfg_cap = 1;
+ softc->dev_cfg = realloc(softc->dev_cfg,
+ sizeof(*softc->dev_cfg) * softc->dev_cfg_cap, M_DEVBUF,
+ M_WAITOK);
+ }
dev_cfg = &softc->dev_cfg[softc->dev_cfg_cnt++];
dev_cfg->start_id = start_id;
@@ -203,14 +211,11 @@
{
ACPI_IVRS_DE_HEADER *de;
uint8_t *p, *end;
- int range_start_id = 0, range_end_id = 0;
+ int range_start_id = -1, range_end_id = -1, i;
uint32_t *extended;
uint8_t all_data = 0, range_data = 0;
bool range_enable_ats = false, enable_ats;
- softc->start_dev_rid = ~0;
- softc->end_dev_rid = 0;
-
switch (ivhd->Header.Type) {
case IVRS_TYPE_HARDWARE_LEGACY:
p = (uint8_t *)ivhd + sizeof(ACPI_IVRS_HARDWARE1);
@@ -231,11 +236,11 @@
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) {
case ACPI_IVRS_TYPE_ALL:
all_data = de->DataSetting;
+ for (i = 0; i < softc->dev_cfg_cnt; i++)
+ softc->dev_cfg[i].data |= all_data;
break;
case ACPI_IVRS_TYPE_SELECT:
@@ -255,6 +260,11 @@
case ACPI_IVRS_TYPE_START:
case ACPI_IVRS_TYPE_ALIAS_START:
case ACPI_IVRS_TYPE_EXT_START:
+ if (range_start_id != -1) {
+ device_printf(softc->dev,
+ "Unexpected start-of-range device entry\n");
+ return (EINVAL);
+ }
range_start_id = de->Id;
range_data = de->DataSetting;
if (de->Type == ACPI_IVRS_TYPE_EXT_START) {
@@ -266,10 +276,20 @@
break;
case ACPI_IVRS_TYPE_END:
+ if (range_start_id == -1) {
+ device_printf(softc->dev,
+ "Unexpected end-of-range device entry\n");
+ return (EINVAL);
+ }
range_end_id = de->Id;
+ if (range_end_id < range_start_id) {
+ device_printf(softc->dev,
+ "Device entry range going backward\n");
+ return (EINVAL);
+ }
ivhd_dev_add_entry(softc, range_start_id, range_end_id,
- range_data | all_data, range_enable_ats);
- range_start_id = range_end_id = 0;
+ range_data | all_data, range_enable_ats);
+ range_start_id = range_end_id = -1;
range_data = 0;
all_data = 0;
break;
@@ -287,12 +307,6 @@
"Unknown dev entry:0x%x\n", de->Type);
}
- if (softc->dev_cfg_cnt >
- (sizeof(softc->dev_cfg) / sizeof(softc->dev_cfg[0]))) {
- device_printf(softc->dev,
- "WARN Too many device entries.\n");
- return (EINVAL);
- }
if (de->Type < 0x40)
p += sizeof(ACPI_IVRS_DEVICE4);
else if (de->Type < 0x80)
@@ -304,10 +318,6 @@
}
}
- KASSERT((softc->end_dev_rid >= softc->start_dev_rid),
- ("Device end[0x%x] < start[0x%x.\n",
- softc->end_dev_rid, softc->start_dev_rid));
-
return (0);
}
@@ -619,9 +629,6 @@
max_ptp_level, amdvi_ptp_level);
}
- device_printf(softc->dev, "device range: 0x%x - 0x%x\n",
- softc->start_dev_rid, softc->end_dev_rid);
-
return (0);
}
@@ -679,21 +686,25 @@
if (status != 0) {
device_printf(dev,
"endpoint device parsing error=%d\n", status);
+ goto fail;
}
status = ivhd_print_cap(softc, ivhd);
- if (status != 0) {
- return (status);
- }
+ if (status != 0)
+ goto fail;
status = amdvi_setup_hw(softc);
if (status != 0) {
device_printf(dev, "couldn't be initialised, error=%d\n",
status);
- return (status);
+ goto fail;
}
return (0);
+
+fail:
+ free(softc->dev_cfg, M_DEVBUF);
+ return (status);
}
static int
@@ -704,6 +715,7 @@
softc = device_get_softc(dev);
amdvi_teardown_hw(softc);
+ free(softc->dev_cfg, M_DEVBUF);
/*
* XXX: delete the device.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 8, 7:47 PM (1 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28491106
Default Alt Text
D30827.id91997.diff (8 KB)
Attached To
Mode
D30827: vmm: Fix AMD-vi using wrong rid range
Attached
Detach File
Event Timeline
Log In to Comment