diff options
author | Muli Ben-Yehuda <muli@il.ibm.com> | 2007-02-13 07:26:24 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-02-13 07:26:24 -0500 |
commit | 310adfdd9153f6ae818981a38a48dd2330990d8d (patch) | |
tree | 6c093730e11bcfe96368db6af86a43e2c4a9abc6 /arch/x86_64/kernel | |
parent | 2fa8a050a0026eadbb39a2f281011991e00fe29a (diff) |
[PATCH] x86-64: robustify bad_dma_address handling
- set bad_dma_address explicitly to 0x0
- reserve 32 pages from bad_dma_address and up
- WARN_ON() a driver feeding us bad_dma_address
Thanks to Leo Duran <leo.duran@amd.com> for the suggestion.
Signed-off-by: Muli Ben-Yehuda <muli@il.ibm.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Cc: Leo Duran <leo.duran@amd.com>
Cc: Job Mason <jdmason@kudzu.us>
Diffstat (limited to 'arch/x86_64/kernel')
-rw-r--r-- | arch/x86_64/kernel/pci-calgary.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c index 3d65b1d4c2b3..04480c3b68f5 100644 --- a/arch/x86_64/kernel/pci-calgary.c +++ b/arch/x86_64/kernel/pci-calgary.c | |||
@@ -138,6 +138,8 @@ static const unsigned long phb_debug_offsets[] = { | |||
138 | 138 | ||
139 | #define PHB_DEBUG_STUFF_OFFSET 0x0020 | 139 | #define PHB_DEBUG_STUFF_OFFSET 0x0020 |
140 | 140 | ||
141 | #define EMERGENCY_PAGES 32 /* = 128KB */ | ||
142 | |||
141 | unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED; | 143 | unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED; |
142 | static int translate_empty_slots __read_mostly = 0; | 144 | static int translate_empty_slots __read_mostly = 0; |
143 | static int calgary_detected __read_mostly = 0; | 145 | static int calgary_detected __read_mostly = 0; |
@@ -296,6 +298,16 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, | |||
296 | { | 298 | { |
297 | unsigned long entry; | 299 | unsigned long entry; |
298 | unsigned long badbit; | 300 | unsigned long badbit; |
301 | unsigned long badend; | ||
302 | |||
303 | /* were we called with bad_dma_address? */ | ||
304 | badend = bad_dma_address + (EMERGENCY_PAGES * PAGE_SIZE); | ||
305 | if (unlikely((dma_addr >= bad_dma_address) && (dma_addr < badend))) { | ||
306 | printk(KERN_ERR "Calgary: driver tried unmapping bad DMA " | ||
307 | "address 0x%Lx\n", dma_addr); | ||
308 | WARN_ON(1); | ||
309 | return; | ||
310 | } | ||
299 | 311 | ||
300 | entry = dma_addr >> PAGE_SHIFT; | 312 | entry = dma_addr >> PAGE_SHIFT; |
301 | 313 | ||
@@ -656,8 +668,8 @@ static void __init calgary_reserve_regions(struct pci_dev *dev) | |||
656 | u64 start; | 668 | u64 start; |
657 | struct iommu_table *tbl = dev->sysdata; | 669 | struct iommu_table *tbl = dev->sysdata; |
658 | 670 | ||
659 | /* reserve bad_dma_address in case it's a legal address */ | 671 | /* reserve EMERGENCY_PAGES from bad_dma_address and up */ |
660 | iommu_range_reserve(tbl, bad_dma_address, 1); | 672 | iommu_range_reserve(tbl, bad_dma_address, EMERGENCY_PAGES); |
661 | 673 | ||
662 | /* avoid the BIOS/VGA first 640KB-1MB region */ | 674 | /* avoid the BIOS/VGA first 640KB-1MB region */ |
663 | start = (640 * 1024); | 675 | start = (640 * 1024); |
@@ -1176,6 +1188,7 @@ int __init calgary_iommu_init(void) | |||
1176 | } | 1188 | } |
1177 | 1189 | ||
1178 | force_iommu = 1; | 1190 | force_iommu = 1; |
1191 | bad_dma_address = 0x0; | ||
1179 | dma_ops = &calgary_dma_ops; | 1192 | dma_ops = &calgary_dma_ops; |
1180 | 1193 | ||
1181 | return 0; | 1194 | return 0; |