git: 06f659c39da1 - main - dmar: Disable PMR in driver attach routine

From: Wojciech Macek <wma_at_FreeBSD.org>
Date: Wed, 20 Apr 2022 07:40:37 UTC
The branch main has been updated by wma:

URL: https://cgit.FreeBSD.org/src/commit/?id=06f659c39da1d1b53f14e4f91d0080170cc608d9

commit 06f659c39da1d1b53f14e4f91d0080170cc608d9
Author:     Kornel Duleba <mindal@semihalf.com>
AuthorDate: 2022-04-14 10:55:53 +0000
Commit:     Wojciech Macek <wma@FreeBSD.org>
CommitDate: 2022-04-20 07:40:28 +0000

    dmar: Disable PMR in driver attach routine
    
    Previously it was disabled right before translation was enabled.
    This way the disable logic is still executed even when translation
    is not be activated, e.g. with hw.iommu.dma=0 tunable set.
    On some platforms we need to disable PMR in order for core dump to work.
    At the same time it was observed that enabling translation has
    a significant impact on network performance.
    With this patch PMR can be disabled, with IOMMU translation not being
    turned on by appending the following to the loader.conf:
    
    hw.dmar.enable=1
    hw.dmar.pmr.disable=1
    hw.dmar.dma=0
    
    Sponsored by: Stormshield
    Obtained from: Semihalf
    Reviewed by: kib
    Differential Revision: https://reviews.freebsd.org/D34907
---
 sys/x86/iommu/intel_drv.c   | 11 +++++++++++
 sys/x86/iommu/intel_utils.c |  3 +++
 2 files changed, 14 insertions(+)

diff --git a/sys/x86/iommu/intel_drv.c b/sys/x86/iommu/intel_drv.c
index 66849dd43053..1d96faf53fec 100644
--- a/sys/x86/iommu/intel_drv.c
+++ b/sys/x86/iommu/intel_drv.c
@@ -405,6 +405,7 @@ dmar_attach(device_t dev)
 	struct dmar_unit *unit;
 	ACPI_DMAR_HARDWARE_UNIT *dmaru;
 	uint64_t timeout;
+	int disable_pmr;
 	int i, error;
 
 	unit = device_get_softc(dev);
@@ -528,6 +529,16 @@ dmar_attach(device_t dev)
 		dmar_release_resources(dev, unit);
 		return (error);
 	}
+
+	disable_pmr = 0;
+	TUNABLE_INT_FETCH("hw.dmar.pmr.disable", &disable_pmr);
+	if (disable_pmr) {
+		error = dmar_disable_protected_regions(unit);
+		if (error != 0)
+			device_printf(dev,
+			    "Failed to disable protected regions\n");
+	}
+
 	error = iommu_init_busdma(&unit->iommu);
 	if (error != 0) {
 		dmar_release_resources(dev, unit);
diff --git a/sys/x86/iommu/intel_utils.c b/sys/x86/iommu/intel_utils.c
index 4511cceb6444..e3ebea648c4c 100644
--- a/sys/x86/iommu/intel_utils.c
+++ b/sys/x86/iommu/intel_utils.c
@@ -508,6 +508,9 @@ dmar_disable_protected_regions(struct dmar_unit *unit)
 		return (0);
 
 	reg = dmar_read4(unit, DMAR_PMEN_REG);
+	if ((reg & DMAR_PMEN_EPM) == 0)
+		return (0);
+
 	reg &= ~DMAR_PMEN_EPM;
 	dmar_write4(unit, DMAR_PMEN_REG, reg);
 	DMAR_WAIT_UNTIL(((dmar_read4(unit, DMAR_PMEN_REG) & DMAR_PMEN_PRS)