lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20250903203502.1155-2-linmag7@gmail.com>
Date: Wed,  3 Sep 2025 22:29:44 +0200
From: Magnus Lindholm <linmag7@...il.com>
To: linux-kernel@...r.kernel.org,
	linux-alpha@...r.kernel.org,
	hch@...radead.org,
	macro@...am.me.uk,
	glaubitz@...sik.fu-berlin.de,
	mattst88@...il.com,
	richard.henderson@...aro.org
Cc: Magnus Lindholm <linmag7@...il.com>
Subject: [PATCH 1/1] alpha: disable DAC for 32-bit PCI on tsunami

Disable DAC for 32-bit PCI cards on Tsunami.
This patch will effectively disable DAC for 32-bit PCI cards on
Tsunami based Alphas. This is done by setting bus_dma_limit to 32 bits
for devices that have no 64-bit memory BARs. Relevant functions in
pci_iommu.c are modified to take 'dev->bus_dma_limit' into
account.

Suggested-by: Maciej Rozycki <macro@...am.me.uk>
Signed-off-by: Magnus Lindholm <linmag7@...il.com>
---
 arch/alpha/kernel/pci.c       | 25 +++++++++++++++++++++++++
 arch/alpha/kernel/pci_iommu.c | 18 ++++++++++++------
 2 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 8e9b4ac86b7e..5b1e4782294b 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -117,6 +117,31 @@ static void pcibios_fixup_final(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
 
+static void tsunami_dac_quirk(struct pci_dev *pdev)
+{
+	unsigned long flags;
+	int i;
+	bool mem64 = false;
+
+	/* If we're not on a Tsunami based system, do nothing */
+	if (hwrpb->sys_type != 34)
+		return;
+
+	for (i = 0; i < PCI_STD_RESOURCE_END + 1; i++) {
+		flags = pci_resource_flags(pdev, i);
+		if (flags & IORESOURCE_MEM)
+			mem64 |= flags & IORESOURCE_MEM_64;
+	}
+
+	/* Limit DMA to 32 bits effectively disabling DAC */
+	if (!mem64) {
+		pdev->dev.bus_dma_limit = DMA_BIT_MASK(32);
+		dev_dbg(&pdev->dev, "disabling DAC for device");
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tsunami_dac_quirk);
+
+
 /* Just declaring that the power-of-ten prefixes are actually the
    power-of-two ones doesn't make it true :) */
 #define KB			1024
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index dc91de50f906..caf2407f80d3 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -208,7 +208,8 @@ static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
 		ok = 0;
 
 	/* The device has to be able to address our DAC bit.  */
-	if ((dac_offset & dev->dma_mask) != dac_offset)
+	if ((dac_offset & min_not_zero(mask,
+		dev->dev.bus_dma_limit)) != dac_offset)
 		ok = 0;
 
 	/* If both conditions above are met, we are fine. */
@@ -228,7 +229,8 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
 		 int dac_allowed)
 {
 	struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
-	dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
+	dma_addr_t max_dma = pdev ? min_not_zero(pdev->dma_mask,
+		pdev->dev.bus_dma_limit) : ISA_DMA_MASK;
 	struct pci_iommu_arena *arena;
 	long npages, dma_ofs, i;
 	unsigned long paddr;
@@ -332,7 +334,8 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
 
 	BUG_ON(dir == DMA_NONE);
 
-	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0; 
+	dac_allowed = pdev ? pci_dac_dma_supported(pdev,
+		min_not_zero(pdev->dma_mask, pdev->dev.bus_dma_limit)) : 0;
 	return pci_map_single_1(pdev, (char *)page_address(page) + offset, 
 				size, dac_allowed);
 }
@@ -638,7 +641,8 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
 
 	BUG_ON(dir == DMA_NONE);
 
-	dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+	dac_allowed = dev ? pci_dac_dma_supported(pdev,
+		min_not_zero(pdev->dma_mask, pdev->dev.bus_dma_limit)) : 0;
 
 	/* Fast path single entry scatterlists.  */
 	if (nents == 1) {
@@ -660,7 +664,8 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
 	/* Second, figure out where we're going to map things.  */
 	if (alpha_mv.mv_pci_tbi) {
 		hose = pdev ? pdev->sysdata : pci_isa_hose;
-		max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
+		max_dma = pdev ? min_not_zero(pdev->dma_mask,
+			pdev->dev.bus_dma_limit) : ISA_DMA_MASK;
 		arena = hose->sg_pci;
 		if (!arena || arena->dma_base + arena->size - 1 > max_dma)
 			arena = hose->sg_isa;
@@ -725,7 +730,8 @@ static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
 		return;
 
 	hose = pdev ? pdev->sysdata : pci_isa_hose;
-	max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
+	max_dma = pdev ? min_not_zero(pdev->dma_mask,
+		pdev->dev.bus_dma_limit) : ISA_DMA_MASK;
 	arena = hose->sg_pci;
 	if (!arena || arena->dma_base + arena->size - 1 > max_dma)
 		arena = hose->sg_isa;
-- 
2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ