From: "Randy.Dunlap" (from Keir:) I have audited the drivers/ and sound/ directories. Most uses of remap_pfn_range are okay, but there are a small handful that are remapping device memory (mostly AGP and DRM drivers). Of particular driver is the HPET driver, whose mmap function is broken even for native (non-Xen) builds. If nothing else, vmalloc_to_phys should be used instead of __pa to convert an ioremapped virtual address to a valid physical address. The fix in this patch is to remember the original bus address as probed at boot time and to pass this to io_remap_pfn_range. Signed-off-by: Keir Fraser Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/agp/frontend.c | 4 ++-- 25-akpm/drivers/char/drm/drm_vm.c | 2 +- 25-akpm/drivers/char/drm/i810_dma.c | 2 +- 25-akpm/drivers/char/drm/i830_dma.c | 2 +- 25-akpm/drivers/char/hpet.c | 6 ++++-- 25-akpm/drivers/sbus/char/flash.c | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) diff -puN drivers/char/agp/frontend.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/agp/frontend.c --- 25/drivers/char/agp/frontend.c~io_remap_pfn_range-fix-some-callers-for-xen 2005-03-18 13:50:54.000000000 -0800 +++ 25-akpm/drivers/char/agp/frontend.c 2005-03-18 13:50:54.000000000 -0800 @@ -628,7 +628,7 @@ static int agp_mmap(struct file *file, s DBG("client vm_ops=%p", kerninfo.vm_ops); if (kerninfo.vm_ops) { vma->vm_ops = kerninfo.vm_ops; - } else if (remap_pfn_range(vma, vma->vm_start, + } else if (io_remap_pfn_range(vma, vma->vm_start, (kerninfo.aper_base + offset) >> PAGE_SHIFT, size, vma->vm_page_prot)) { goto out_again; @@ -644,7 +644,7 @@ static int agp_mmap(struct file *file, s DBG("controller vm_ops=%p", kerninfo.vm_ops); if (kerninfo.vm_ops) { vma->vm_ops = kerninfo.vm_ops; - } else if (remap_pfn_range(vma, vma->vm_start, + } else if (io_remap_pfn_range(vma, vma->vm_start, kerninfo.aper_base >> PAGE_SHIFT, size, vma->vm_page_prot)) { goto out_again; diff -puN drivers/char/drm/drm_vm.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/drm/drm_vm.c --- 25/drivers/char/drm/drm_vm.c~io_remap_pfn_range-fix-some-callers-for-xen 2005-03-18 13:50:54.000000000 -0800 +++ 25-akpm/drivers/char/drm/drm_vm.c 2005-03-18 13:50:54.000000000 -0800 @@ -634,7 +634,7 @@ int drm_mmap(struct file *filp, struct v vma->vm_end - vma->vm_start, vma->vm_page_prot)) #else - if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, + if (io_remap_pfn_range(vma, vma->vm_start, (VM_OFFSET(vma) + offset) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) diff -puN drivers/char/drm/i810_dma.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/drm/i810_dma.c --- 25/drivers/char/drm/i810_dma.c~io_remap_pfn_range-fix-some-callers-for-xen 2005-03-18 13:50:54.000000000 -0800 +++ 25-akpm/drivers/char/drm/i810_dma.c 2005-03-18 13:50:54.000000000 -0800 @@ -119,7 +119,7 @@ int i810_mmap_buffers(struct file *filp, buf_priv->currently_mapped = I810_BUF_MAPPED; unlock_kernel(); - if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, + if (io_remap_pfn_range(vma, vma->vm_start, VM_OFFSET(vma) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; diff -puN drivers/char/drm/i830_dma.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/drm/i830_dma.c --- 25/drivers/char/drm/i830_dma.c~io_remap_pfn_range-fix-some-callers-for-xen 2005-03-18 13:50:54.000000000 -0800 +++ 25-akpm/drivers/char/drm/i830_dma.c 2005-03-18 13:50:54.000000000 -0800 @@ -121,7 +121,7 @@ int i830_mmap_buffers(struct file *filp, buf_priv->currently_mapped = I830_BUF_MAPPED; unlock_kernel(); - if (remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, + if (io_remap_pfn_range(vma, vma->vm_start, VM_OFFSET(vma) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; diff -puN drivers/char/hpet.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/char/hpet.c --- 25/drivers/char/hpet.c~io_remap_pfn_range-fix-some-callers-for-xen 2005-03-18 13:50:54.000000000 -0800 +++ 25-akpm/drivers/char/hpet.c 2005-03-18 13:50:54.000000000 -0800 @@ -76,6 +76,7 @@ struct hpet_dev { struct hpets { struct hpets *hp_next; struct hpet __iomem *hp_hpet; + unsigned long hp_hpet_phys; struct time_interpolator *hp_interpolator; unsigned long hp_period; unsigned long hp_delta; @@ -265,7 +266,7 @@ static int hpet_mmap(struct file *file, return -EINVAL; devp = file->private_data; - addr = (unsigned long)devp->hd_hpet; + addr = devp->hd_hpets->hp_hpet_phys; if (addr & (PAGE_SIZE - 1)) return -ENOSYS; @@ -274,7 +275,7 @@ static int hpet_mmap(struct file *file, vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); addr = __pa(addr); - if (remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, + if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot)) { printk(KERN_ERR "remap_pfn_range failed in hpet.c\n"); return -EAGAIN; @@ -795,6 +796,7 @@ int hpet_alloc(struct hpet_data *hdp) hpetp->hp_which = hpet_nhpet++; hpetp->hp_hpet = hdp->hd_address; + hpetp->hp_hpet_phys = hdp->hd_phys_address; hpetp->hp_ntimer = hdp->hd_nirqs; diff -puN drivers/sbus/char/flash.c~io_remap_pfn_range-fix-some-callers-for-xen drivers/sbus/char/flash.c --- 25/drivers/sbus/char/flash.c~io_remap_pfn_range-fix-some-callers-for-xen 2005-03-18 13:50:54.000000000 -0800 +++ 25-akpm/drivers/sbus/char/flash.c 2005-03-18 13:50:54.000000000 -0800 @@ -75,7 +75,7 @@ flash_mmap(struct file *file, struct vm_ pgprot_val(vma->vm_page_prot) |= _PAGE_E; vma->vm_flags |= (VM_SHM | VM_LOCKED); - if (remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot)) + if (io_remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot)) return -EAGAIN; return 0; _