*参照元 [#s3213880] #backlinks *説明 [#l6834610] -パス: 複数あり --CONFIG_MMU 有効: [[linux-4.4.1/mm/memory.c]] --CONFIG_MMU 無効: [[linux-4.4.1/mm/nommu.c]] -FIXME: これは何? --説明 **引数 [#pcaff14b] -struct vm_area_struct *vma -- --[[linux-4.4.1/vm_area_struct]] -unsigned long addr -- -unsigned long pfn -- -unsigned long size -- -pgprot_t prot -- --[[linux-4.4.1/pgprot_t]] **返り値 [#o1f4aebe] -int -- **参考 [#t4cd3c58] *実装 [#s5a5b93b] **CONFIG_MMU 有効: mm/memory.c [#j68c4666] /** * remap_pfn_range - remap kernel memory to userspace * @vma: user vma to map to * @addr: target user address to start at * @pfn: physical address of kernel memory * @size: size of map area * @prot: page protection flags for this mapping * * Note: this is only safe if the mm semaphore is held when called. */ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot) { pgd_t *pgd; unsigned long next; unsigned long end = addr + PAGE_ALIGN(size); struct mm_struct *mm = vma->vm_mm; int err; - --[[linux-4.4.1/PAGE_ALIGN()]] --[[linux-4.4.1/mm_struct]] /* * Physically remapped pages are special. Tell the * rest of the world about it: * VM_IO tells people not to look at these pages * (accesses can have side effects). * VM_PFNMAP tells the core MM that the base pages are just * raw PFN mappings, and do not have a "struct page" associated * with them. * VM_DONTEXPAND * Disable vma merging and expanding with mremap(). * VM_DONTDUMP * Omit vma from core dump, even when VM_IO turned off. * * There's a horrible special case to handle copy-on-write * behaviour that some programs depend on. We mark the "original" * un-COW'ed pages by matching them up with "vma->vm_pgoff". * See vm_normal_page() for details. */ if (is_cow_mapping(vma->vm_flags)) { if (addr != vma->vm_start || end != vma->vm_end) return -EINVAL; vma->vm_pgoff = pfn; } - --[[linux-4.4.1/is_cow_mapping()]] err = track_pfn_remap(vma, &prot, pfn, addr, PAGE_ALIGN(size)); if (err) return -EINVAL; - --[[linux-4.4.1/track_pfn_remap()]] vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; BUG_ON(addr >= end); pfn -= addr >> PAGE_SHIFT; pgd = pgd_offset(mm, addr); flush_cache_range(vma, addr, end); - --[[linux-4.4.1/BUG_ON()]] --[[linux-4.4.1/pgd_offset()]] --[[linux-4.4.1/flush_cache_range()]] do { next = pgd_addr_end(addr, end); err = remap_pud_range(mm, pgd, addr, next, pfn + (addr >> PAGE_SHIFT), prot); if (err) break; - --[[linux-4.4.1/pgd_addr_end()]] --[[linux-4.4.1/remap_pud_range()]] } while (pgd++, addr = next, addr != end); if (err) untrack_pfn(vma, pfn, PAGE_ALIGN(size)); - --[[linux-4.4.1/untrack_pfn()]] return err; } EXPORT_SYMBOL(remap_pfn_range); - --[[linux-4.4.1/EXPORT_SYMBOL()]] **ONFIG_MMU 無効: mm/nommu.c [#ff4b047d] int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot) { if (addr != (pfn << PAGE_SHIFT)) return -EINVAL; vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; return 0; } EXPORT_SYMBOL(remap_pfn_range); *コメント [#zbb21cd8]