Commit 628505a0 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86-64 fixes

This fixes several small but 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: default avatarLinus Torvalds <torvalds@osdl.org>
parent 9b10dbb5
......@@ -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 */
......
......@@ -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 offset, int size)
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 *dev)
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 *dev)
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, struct scatterlist *sg, int nents, int dir)
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 *hwdev, dma_addr_t dma_addr,
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;
......
......@@ -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;
......
......@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment