
From: Andi Kleen <ak@suse.de>

This patch has several fixes for serious x86-64 bugs in 2.6.8rc2.

- Fix array overflow in PCI bus checking (Travis Betak) 
- Fix broken pci_map_sg in swiotlb (Suresh B. Siddha) 
- Remove bogus bus check in IOMMU code 

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/x86_64/kernel/mpparse.c  |    2 +-
 25-akpm/arch/x86_64/kernel/pci-gart.c |   33 +++++++++++++++++++++++++--------
 25-akpm/include/asm-x86_64/mpspec.h   |    2 +-
 25-akpm/include/asm-x86_64/topology.h |    6 +++---
 4 files changed, 30 insertions(+), 13 deletions(-)

diff -puN arch/x86_64/kernel/mpparse.c~critical-x86-64-patches-for-268rc2 arch/x86_64/kernel/mpparse.c
--- 25/arch/x86_64/kernel/mpparse.c~critical-x86-64-patches-for-268rc2	2004-07-27 23:15:38.813793992 -0700
+++ 25-akpm/arch/x86_64/kernel/mpparse.c	2004-07-27 23:15:38.824792320 -0700
@@ -44,7 +44,7 @@ int acpi_found_madt;
 int apic_version [MAX_APICS];
 unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-cpumask_t mp_bus_to_cpumask [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = CPU_MASK_ALL };
+cpumask_t pci_bus_to_cpumask [256] = { [0 ... 255] = CPU_MASK_ALL };
 
 int mp_current_pci_id = 0;
 /* I/O APIC entries */
diff -puN arch/x86_64/kernel/pci-gart.c~critical-x86-64-patches-for-268rc2 arch/x86_64/kernel/pci-gart.c
--- 25/arch/x86_64/kernel/pci-gart.c~critical-x86-64-patches-for-268rc2	2004-07-27 23:15:38.815793688 -0700
+++ 25-akpm/arch/x86_64/kernel/pci-gart.c	2004-07-27 23:15:38.826792016 -0700
@@ -70,6 +70,8 @@ int iommu_fullflush = 1;
 static spinlock_t iommu_bitmap_lock = SPIN_LOCK_UNLOCKED;
 static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */
 
+static u32 gart_unmapped_entry;
+
 #define GPTE_VALID    1
 #define GPTE_COHERENT 2
 #define GPTE_ENCODE(x) \
@@ -147,8 +149,6 @@ static void free_iommu(unsigned long off
 static void flush_gart(struct pci_dev *dev)
 { 
 	unsigned long flags;
-	int bus = dev ? dev->bus->number : -1;
-	cpumask_t bus_cpumask = pcibus_to_cpumask(bus);
 	int flushed = 0;
 	int i;
 
@@ -158,8 +158,6 @@ static void flush_gart(struct pci_dev *d
 			u32 w;
 			if (!northbridges[i]) 
 				continue;
-			if (bus >= 0 && !(cpu_isset(i, bus_cpumask)))
-				continue;
 			pci_write_config_dword(northbridges[i], 0x9c, 
 					       northbridge_flush_word[i] | 1); 
 			/* Make sure the hardware actually executed the flush. */
@@ -169,7 +167,7 @@ static void flush_gart(struct pci_dev *d
 			flushed++;
 		} 
 		if (!flushed) 
-			printk("nothing to flush? %d\n", bus);
+			printk("nothing to flush?\n");
 		need_flush = 0;
 	} 
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
@@ -479,6 +477,11 @@ int pci_map_sg(struct pci_dev *dev, stru
 	unsigned long pages = 0;
 	int need = 0, nextneed;
 
+#ifdef CONFIG_SWIOTLB
+	if (swiotlb)
+		return swiotlb_map_sg(&dev->dev,sg,nents,dir);
+#endif
+
 	BUG_ON(dir == PCI_DMA_NONE);
 	if (nents == 0) 
 		return 0;
@@ -562,7 +565,7 @@ void pci_unmap_single(struct pci_dev *hw
 	iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;	
 	npages = to_pages(dma_addr, size);
 	for (i = 0; i < npages; i++) { 
-		iommu_gatt_base[iommu_page + i] = 0; 
+		iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
 		CLEAR_LEAK(iommu_page + i);
 	}
 	free_iommu(iommu_page, npages);
@@ -729,7 +732,8 @@ static int __init pci_iommu_init(void)
 	unsigned long aper_size;
 	unsigned long iommu_start;
 	struct pci_dev *dev;
-		
+	unsigned long scratch;
+	long i;
 
 #ifndef CONFIG_AGP_AMD64
 	no_agp = 1; 
@@ -766,7 +770,7 @@ static int __init pci_iommu_init(void)
 			return -1;
 		}
 	} 
-	
+
 	aper_size = info.aper_size * 1024 * 1024;	
 	iommu_size = check_iommu_size(info.aper_base, aper_size); 
 	iommu_pages = iommu_size >> PAGE_SHIFT; 
@@ -815,6 +819,19 @@ static int __init pci_iommu_init(void)
 	 */
 	clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size);
 
+	/*
+	 * Try to workaround a bug (thanks to BenH)
+	 * Set unmapped entries to a scratch page instead of 0.
+	 * Any prefetches that hit unmapped entries won't get an bus abort
+	 * then.
+	 */
+	scratch = get_zeroed_page(GFP_KERNEL);
+	if (!scratch)
+		panic("Cannot allocate iommu scratch page");
+	gart_unmapped_entry = GPTE_ENCODE(__pa(scratch));
+	for (i = EMERGENCY_PAGES; i < iommu_pages; i++)
+		iommu_gatt_base[i] = gart_unmapped_entry;
+
 	for_all_nb(dev) {
 		u32 flag; 
 		int cpu = PCI_SLOT(dev->devfn) - 24;
diff -puN include/asm-x86_64/mpspec.h~critical-x86-64-patches-for-268rc2 include/asm-x86_64/mpspec.h
--- 25/include/asm-x86_64/mpspec.h~critical-x86-64-patches-for-268rc2	2004-07-27 23:15:38.817793384 -0700
+++ 25-akpm/include/asm-x86_64/mpspec.h	2004-07-27 23:15:38.826792016 -0700
@@ -166,7 +166,7 @@ enum mp_bustype {
 };
 extern unsigned char mp_bus_id_to_type [MAX_MP_BUSSES];
 extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
-extern cpumask_t mp_bus_to_cpumask [MAX_MP_BUSSES];
+extern cpumask_t pci_bus_to_cpumask [256];
 
 extern unsigned int boot_cpu_physical_apicid;
 extern int smp_found_config;
diff -puN include/asm-x86_64/topology.h~critical-x86-64-patches-for-268rc2 include/asm-x86_64/topology.h
--- 25/include/asm-x86_64/topology.h~critical-x86-64-patches-for-268rc2	2004-07-27 23:15:38.819793080 -0700
+++ 25-akpm/include/asm-x86_64/topology.h	2004-07-27 23:15:38.827791864 -0700
@@ -22,9 +22,9 @@ extern cpumask_t     node_to_cpumask[];
 
 static inline cpumask_t pcibus_to_cpumask(int bus)
 {
-	cpumask_t tmp;
-	cpus_and(tmp, mp_bus_to_cpumask[bus], cpu_online_map);
-	return tmp;
+	cpumask_t res;
+	cpus_and(res,  pci_bus_to_cpumask[bus], cpu_online_map);
+	return res;
 }
 
 #define NODE_BALANCE_RATE 30	/* CHECKME */ 
_
