Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Aug 2021 13:08:18 GMT
From:      Ka Ho Ng <khng@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 6e2fc728d8da - stable/13 - AMD-vi: Fortify IVHD device_identify process
Message-ID:  <202108271308.17RD8IPl087647@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by khng:

URL: https://cgit.FreeBSD.org/src/commit/?id=6e2fc728d8da06d4f849061cce6540fdc2ea6000

commit 6e2fc728d8da06d4f849061cce6540fdc2ea6000
Author:     Ka Ho Ng <khng@FreeBSD.org>
AuthorDate: 2021-04-19 08:07:03 +0000
Commit:     Ka Ho Ng <khng@FreeBSD.org>
CommitDate: 2021-08-27 13:05:58 +0000

    AMD-vi: Fortify IVHD device_identify process
    
    - Use malloc(9) to allocate ivhd_hdrs list. The previous assumption
      that there are at most 10 IVHDs in a system is not true. A counter
      example would be a system with 4 IOMMUs, and each IOMMU is related
      to IVHDs type 10h, 11h and 40h in the ACPI IVRS table.
    - Always scan through the whole ivhd_hdrs list to find IVHDs that has
      the same DeviceId but less prioritized IVHD type.
    
    Sponsored by:   The FreeBSD Foundation
    MFC with:       74ada297e897
    Reviewed by:    grehan
    Approved by:    lwhsu (mentor)
    Differential Revision:  https://reviews.freebsd.org/D29525
    
    (cherry picked from commit 6fe60f1d5c39c94fc87534e9dd4e9630594e0bec)
---
 sys/amd64/vmm/amd/ivrs_drv.c | 47 ++++++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 21 deletions(-)

diff --git a/sys/amd64/vmm/amd/ivrs_drv.c b/sys/amd64/vmm/amd/ivrs_drv.c
index 430d18a059a2..68c31788e29d 100644
--- a/sys/amd64/vmm/amd/ivrs_drv.c
+++ b/sys/amd64/vmm/amd/ivrs_drv.c
@@ -57,7 +57,7 @@ int	ivhd_count;			/* Number of IVHD header. */
  * Cached IVHD header list.
  * Single entry for each IVHD, filtered the legacy one.
  */
-ACPI_IVRS_HARDWARE1 *ivhd_hdrs[10];	
+ACPI_IVRS_HARDWARE1 **ivhd_hdrs;
 
 extern int amdvi_ptp_level;		/* Page table levels. */
 
@@ -134,9 +134,11 @@ ivrs_is_ivhd(UINT8 type)
 static int
 ivhd_count_iter(ACPI_IVRS_HEADER * ivrs_he, void *arg)
 {
+	int *count;
 
+	count = (int *)arg;
 	if (ivrs_is_ivhd(ivrs_he->Type))
-		ivhd_count++;
+		(*count)++;
 
 	return (1);
 }
@@ -349,7 +351,7 @@ ivhd_identify(driver_t *driver, device_t parent)
 	ACPI_TABLE_IVRS *ivrs;
 	ACPI_IVRS_HARDWARE1 *ivhd;
 	ACPI_STATUS status;
-	int i, count = 0;
+	int i, j, count = 0;
 	uint32_t ivrs_ivinfo;
 
 	if (acpi_disabled("ivhd"))
@@ -370,32 +372,35 @@ ivhd_identify(driver_t *driver, device_t parent)
 		REG_BITS(ivrs_ivinfo, 7, 5), REG_BITS(ivrs_ivinfo, 22, 22),
 		"\020\001EFRSup");
 
-	ivrs_hdr_iterate_tbl(ivhd_count_iter, NULL);
-	if (!ivhd_count)
+	ivrs_hdr_iterate_tbl(ivhd_count_iter, &count);
+	if (!count)
 		return;
 
-	for (i = 0; i < ivhd_count; i++) {
+	ivhd_hdrs = malloc(sizeof(void *) * count, M_DEVBUF,
+		M_WAITOK | M_ZERO);
+	for (i = 0; i < count; i++) {
 		ivhd = ivhd_find_by_index(i);
 		KASSERT(ivhd, ("ivhd%d is NULL\n", i));
-		ivhd_hdrs[i] = ivhd;
-	}
 
-        /* 
-	 * Scan for presence of legacy and non-legacy device type
-	 * for same AMD-Vi device and override the old one.
-	 */
-	for (i = ivhd_count - 1 ; i > 0 ; i--){
-       		if (ivhd_is_newer(&ivhd_hdrs[i-1]->Header, 
-			&ivhd_hdrs[i]->Header)) {
-			memmove(&ivhd_hdrs[i-1], &ivhd_hdrs[i],
-			    sizeof(void *) * (ivhd_count - i));
-			ivhd_count--;
+		/*
+		 * Scan for presence of legacy and non-legacy device type
+		 * for same IOMMU device and override the old one.
+		 *
+		 * If there is no existing IVHD to the same IOMMU device,
+		 * the IVHD header pointer is appended.
+		 */
+		for (j = 0; j < ivhd_count; j++) {
+			if (ivhd_is_newer(&ivhd_hdrs[j]->Header, &ivhd->Header))
+				break;
 		}
+		ivhd_hdrs[j] = ivhd;
+		if (j == ivhd_count)
+			ivhd_count++;
 	}
 
 	ivhd_devs = malloc(sizeof(device_t) * ivhd_count, M_DEVBUF,
 		M_WAITOK | M_ZERO);
-	for (i = 0; i < ivhd_count; i++) {
+	for (i = 0, j = 0; i < ivhd_count; i++) {
 		ivhd = ivhd_hdrs[i];
 		KASSERT(ivhd, ("ivhd%d is NULL\n", i));
 
@@ -417,13 +422,13 @@ ivhd_identify(driver_t *driver, device_t parent)
 				break;
 			}
 		}
-		count++;
+		j++;
 	}
 
 	/*
 	 * Update device count in case failed to attach.
 	 */
-	ivhd_count = count;
+	ivhd_count = j;
 }
 
 static int



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202108271308.17RD8IPl087647>