On 06/18/2010 04:22 AM, Kenji Kaneshige wrote: > Current x86 ioremap() doesn't handle physical address higher than > 32-bit properly in X86_32 PAE mode. When physical address higher than > 32-bit is passed to ioremap(), higher 32-bits in physical address is > cleared wrongly. Due to this bug, ioremap() can map wrong address to > linear address space. > > In my case, 64-bit MMIO region was assigned to a PCI device (ioat > device) on my system. Because of the ioremap()'s bug, wrong physical > address (instead of MMIO region) was mapped to linear address space. > Because of this, loading ioatdma driver caused unexpected behavior > (kernel panic, kernel hangup, ...). > > Signed-off-by: Kenji Kaneshige <kaneshige.kenji@xxxxxxxxxxxxxx> > > --- > arch/x86/mm/ioremap.c | 12 +++++------- > include/linux/io.h | 4 ++-- > include/linux/vmalloc.h | 2 +- > lib/ioremap.c | 10 +++++----- > mm/vmalloc.c | 2 +- > 5 files changed, 14 insertions(+), 16 deletions(-) > > Index: linux-2.6.34/arch/x86/mm/ioremap.c > =================================================================== > --- linux-2.6.34.orig/arch/x86/mm/ioremap.c > +++ linux-2.6.34/arch/x86/mm/ioremap.c > @@ -62,8 +62,8 @@ int ioremap_change_attr(unsigned long va > static void __iomem *__ioremap_caller(resource_size_t phys_addr, > unsigned long size, unsigned long prot_val, void *caller) > { > - unsigned long pfn, offset, vaddr; > - resource_size_t last_addr; > + unsigned long offset, vaddr; > + resource_size_t pfn, last_pfn, last_addr; > Why is pfn resource_size_t here? Is it to avoid casting, or does it actually need to hold more than 32 bits? I don't see any use of pfn aside from the page_is_ram loop, and I don't think that can go beyond 32 bits. If you're worried about boundary conditions at the 2^44 limit, then you can make last_pfn inclusive, or compute num_pages and use that for the loop condition. > const resource_size_t unaligned_phys_addr = phys_addr; > const unsigned long unaligned_size = size; > struct vm_struct *area; > @@ -100,10 +100,8 @@ static void __iomem *__ioremap_caller(re > /* > * Don't allow anybody to remap normal RAM that we're using.. > */ > - for (pfn = phys_addr >> PAGE_SHIFT; > - (pfn << PAGE_SHIFT) < (last_addr & PAGE_MASK); > - pfn++) { > - > + last_pfn = last_addr >> PAGE_SHIFT; > If last_addr can be non-page aligned, should it be rounding up to the next pfn rather than rounding down? Ah, looks like you fix it in the second patch. J -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html